--- syncmail/syncmail 2001/10/28 04:00:59 1.5 +++ syncmail/syncmail 2001/10/28 20:52:25 1.6 @@ -12,9 +12,9 @@ use Fcntl; -use constant PROTVERSION => 1; +our $VERSION = 0.1; -$VERSION = 0.1; +our $NOW = time; require "config.pl"; @@ -65,6 +65,7 @@ while (defined (my $folder = readdir $dh)) { next if $folder =~ /^\./; + next if $folder =~ /~$/; next unless -f "$PREFIX/$folder"; push @folders, $folder; } @@ -80,7 +81,7 @@ my $quit_guard = quit_guard; async { my $guard = $sync_folder->guard; - my $vc = new vc; + my $vc = create vc; my $folder = new folder name => $name; @@ -95,23 +96,27 @@ $vc->snd("diff", $ctime); - my (%ladd, %ldel, %radd, %rdel); + my %diff; # + # 00 - local del + # 01 - local add + # 10 - remote del + # 11 - remote add my @diff = grep { $_->[0] > $ctime } @{$folder->{diff}}; $diff = $vc->rcv; while () { if ($diff >= 0 and (!@diff or $diff <= $diff[0][0])) { - my @add = split /\0/, $vc->rcv; - my @del = split /\0/, $vc->rcv; - slog 0, "applying remote diff $diff\n"; - for (@del) { undef $rdel{$_}; delete $radd{$_}; delete $ladd{$_}; delete $ldel{$_}; } - for (@add) { undef $radd{$_}; delete $rdel{$_}; delete $ladd{$_}; delete $ldel{$_}; } + slog 0, "applying remote diff $diff (@add, @del)\n"; + $diff{$_} = 0b01 for split /\0/, $vc->rcv; # add + $diff{$_} = 0b00 for split /\0/, $vc->rcv; # del + $diff = $vc->rcv; } elsif (@diff) { slog 0, "applying local diff $diff[0][0]\n"; - for (@{$diff[0][2]}) { undef $rdel{$_}; delete $radd{$_}; delete $ladd{$_}; delete $ldel{$_}; } - for (@{$diff[0][1]}) { undef $radd{$_}; delete $rdel{$_}; delete $ladd{$_}; delete $ldel{$_}; } + $diff{$_} = 0b11 for @{$diff[0][1]}; + $diff{$_} = 0b10 for @{$diff[0][2]}; + shift @diff; } else { slog 0, "no more diffing\n"; @@ -119,20 +124,39 @@ } } - slog 0, "LADD ".join(" ", keys %ladd)."\n"; - slog 0, "LDEL ".join(" ", keys %ldel)."\n"; - slog 0, "RADD ".join(" ", keys %radd)."\n"; - slog 0, "RDEL ".join(" ", keys %rdel)."\n"; + # append or update, depending on wether there are messages to be deleted + $vc->snd("begin"); + $folder->begin_update; + + while (my ($k,$v) = each %diff) { + push @{$diff[$v]}, $k; + slog 0, "DIFF $k : $v\n";#d# + } + + $vc->snd("delete", join "\0", @{$diff[2]}); + $folder->delete(@{$diff[0]}); + + $vc->snd("end"); + $folder->end_update; - #$folder->{host}{$OTHERNAME} = time; - #$vc->snd("setctime", time); + $vc->snd("ctime", $folder->{ctime}); + $folder->{host}{$OTHERNAME} = $vc->rcv; + + # sanity check + $vc->snd("inventory"); + if ($folder->inventory ne $vc->rcv) { + slog 0, "FATAL: folder inventory mismatch after update"; + die; + } + slog 0, "LINV ".$folder->inventory."\n"; + slog 0, "RINV ".$vc->rcv."\n"; undef $quit_guard; } } sub main { - my $vc = new vc; + my $vc = create vc; # time checking done symmetrically { @@ -144,8 +168,7 @@ } #Coro::Event::do_timer(after => 60);#d# - $vc->snd("name"); - $OTHERNAME = $vc->rcv; + $vc->snd("setname", $MYNAME); $OTHERNAME = $vc->rcv; if ($SLAVE) { # @@ -181,6 +204,8 @@ while (my $msg = $vc->rcv) { if ($msg eq "mtime") { $vc->snd($folder->{mtime}); + } elsif ($msg eq "inventory") { + $vc->snd($folder->inventory); } elsif ($msg eq "diff") { my $time = $vc->rcv; for (@{$folder->{diff}}) { @@ -191,6 +216,12 @@ ); } $vc->snd(-1); + } elsif ($msg eq "begin") { + $folder->begin_update; + } elsif ($msg eq "end") { + $folder->end_update; + } elsif ($msg eq "mtime") { + $vc->snd($folder->{mtime}); } elsif ($msg eq "setctime") { $folder->{host}{$OTHERNAME} = $vc->rcv; } else { @@ -205,10 +236,11 @@ slog 8, "new connection $vc->{port}\n"; while (my $msg = $vc->rcv) { - if ($msg eq "name") { - $vc->snd($::MYNAME); + if ($msg eq "setname") { + $vc->snd($MYNAME); + $OTHERNAME = $vc->rcv; } elsif ($msg eq "pri") { - $self->{pri} = $vc->rcv; + $vc->{pri} = $vc->rcv; } elsif ($msg eq "time") { $vc->snd(time); } elsif ($msg eq "list") {