ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/syncmail/syncmail
(Generate patch)

Comparing syncmail/syncmail (file contents):
Revision 1.5 by root, Sun Oct 28 04:00:59 2001 UTC vs.
Revision 1.6 by root, Sun Oct 28 20:52:25 2001 UTC

10 10
11use Set::Scalar; 11use Set::Scalar;
12 12
13use Fcntl; 13use Fcntl;
14 14
15use constant PROTVERSION => 1;
16
17$VERSION = 0.1; 15our $VERSION = 0.1;
16
17our $NOW = time;
18 18
19require "config.pl"; 19require "config.pl";
20 20
21use folder; 21use folder;
22use vc; 22use vc;
63 opendir my $dh, $PREFIX 63 opendir my $dh, $PREFIX
64 or die "$PREFIX: $!"; 64 or die "$PREFIX: $!";
65 65
66 while (defined (my $folder = readdir $dh)) { 66 while (defined (my $folder = readdir $dh)) {
67 next if $folder =~ /^\./; 67 next if $folder =~ /^\./;
68 next if $folder =~ /~$/;
68 next unless -f "$PREFIX/$folder"; 69 next unless -f "$PREFIX/$folder";
69 push @folders, $folder; 70 push @folders, $folder;
70 } 71 }
71 72
72 @folders; 73 @folders;
78 my $name = $_[0]; 79 my $name = $_[0];
79 80
80 my $quit_guard = quit_guard; 81 my $quit_guard = quit_guard;
81 async { 82 async {
82 my $guard = $sync_folder->guard; 83 my $guard = $sync_folder->guard;
83 my $vc = new vc; 84 my $vc = create vc;
84 85
85 my $folder = new folder name => $name; 86 my $folder = new folder name => $name;
86 87
87 $vc->snd("open", $name); 88 $vc->snd("open", $name);
88 $vc->snd("mtime"); 89 $vc->snd("mtime");
93 my $ctime = $folder->{host}{$OTHERNAME} || -1; 94 my $ctime = $folder->{host}{$OTHERNAME} || -1;
94 my $rtime = $vc->rcv; 95 my $rtime = $vc->rcv;
95 96
96 $vc->snd("diff", $ctime); 97 $vc->snd("diff", $ctime);
97 98
98 my (%ladd, %ldel, %radd, %rdel); 99 my %diff; #
100 # 00 - local del
101 # 01 - local add
102 # 10 - remote del
103 # 11 - remote add
99 104
100 my @diff = grep { $_->[0] > $ctime } @{$folder->{diff}}; 105 my @diff = grep { $_->[0] > $ctime } @{$folder->{diff}};
101 $diff = $vc->rcv; 106 $diff = $vc->rcv;
102 107
103 while () { 108 while () {
104 if ($diff >= 0 and (!@diff or $diff <= $diff[0][0])) { 109 if ($diff >= 0 and (!@diff or $diff <= $diff[0][0])) {
105 my @add = split /\0/, $vc->rcv;
106 my @del = split /\0/, $vc->rcv;
107 slog 0, "applying remote diff $diff\n"; 110 slog 0, "applying remote diff $diff (@add, @del)\n";
108 for (@del) { undef $rdel{$_}; delete $radd{$_}; delete $ladd{$_}; delete $ldel{$_}; } 111 $diff{$_} = 0b01 for split /\0/, $vc->rcv; # add
109 for (@add) { undef $radd{$_}; delete $rdel{$_}; delete $ladd{$_}; delete $ldel{$_}; } 112 $diff{$_} = 0b00 for split /\0/, $vc->rcv; # del
113
110 $diff = $vc->rcv; 114 $diff = $vc->rcv;
111 } elsif (@diff) { 115 } elsif (@diff) {
112 slog 0, "applying local diff $diff[0][0]\n"; 116 slog 0, "applying local diff $diff[0][0]\n";
113 for (@{$diff[0][2]}) { undef $rdel{$_}; delete $radd{$_}; delete $ladd{$_}; delete $ldel{$_}; } 117 $diff{$_} = 0b11 for @{$diff[0][1]};
114 for (@{$diff[0][1]}) { undef $radd{$_}; delete $rdel{$_}; delete $ladd{$_}; delete $ldel{$_}; } 118 $diff{$_} = 0b10 for @{$diff[0][2]};
119
115 shift @diff; 120 shift @diff;
116 } else { 121 } else {
117 slog 0, "no more diffing\n"; 122 slog 0, "no more diffing\n";
118 last; 123 last;
119 } 124 }
120 } 125 }
121 126
122 slog 0, "LADD ".join(" ", keys %ladd)."\n"; 127 # append or update, depending on wether there are messages to be deleted
123 slog 0, "LDEL ".join(" ", keys %ldel)."\n"; 128 $vc->snd("begin");
124 slog 0, "RADD ".join(" ", keys %radd)."\n"; 129 $folder->begin_update;
125 slog 0, "RDEL ".join(" ", keys %rdel)."\n"; 130
131 while (my ($k,$v) = each %diff) {
132 push @{$diff[$v]}, $k;
133 slog 0, "DIFF $k : $v\n";#d#
134 }
135
136 $vc->snd("delete", join "\0", @{$diff[2]});
137 $folder->delete(@{$diff[0]});
138
139 $vc->snd("end");
140 $folder->end_update;
126 141
142 $vc->snd("ctime", $folder->{ctime});
127 #$folder->{host}{$OTHERNAME} = time; 143 $folder->{host}{$OTHERNAME} = $vc->rcv;
128 #$vc->snd("setctime", time); 144
145 # sanity check
146 $vc->snd("inventory");
147 if ($folder->inventory ne $vc->rcv) {
148 slog 0, "FATAL: folder inventory mismatch after update";
149 die;
150 }
151 slog 0, "LINV ".$folder->inventory."\n";
152 slog 0, "RINV ".$vc->rcv."\n";
129 153
130 undef $quit_guard; 154 undef $quit_guard;
131 } 155 }
132} 156}
133 157
134sub main { 158sub main {
135 my $vc = new vc; 159 my $vc = create vc;
136 160
137 # time checking done symmetrically 161 # time checking done symmetrically
138 { 162 {
139 my $time = time; 163 my $time = time;
140 $vc->snd("time"); 164 $vc->snd("time");
142 abs (($time + time)*0.5 - $othertime) <= $::MAXTIMEDIFF 166 abs (($time + time)*0.5 - $othertime) <= $::MAXTIMEDIFF
143 or die "ERROR: time difference between hosts larger than $::MAXTIMEDIFF"; 167 or die "ERROR: time difference between hosts larger than $::MAXTIMEDIFF";
144 } 168 }
145#Coro::Event::do_timer(after => 60);#d# 169#Coro::Event::do_timer(after => 60);#d#
146 170
147 $vc->snd("name"); 171 $vc->snd("setname", $MYNAME); $OTHERNAME = $vc->rcv;
148 $OTHERNAME = $vc->rcv;
149 172
150 if ($SLAVE) { 173 if ($SLAVE) {
151 # 174 #
152 } else { 175 } else {
153 $vc->snd("list"); 176 $vc->snd("list");
179 $folder->read_mdif; 202 $folder->read_mdif;
180 203
181 while (my $msg = $vc->rcv) { 204 while (my $msg = $vc->rcv) {
182 if ($msg eq "mtime") { 205 if ($msg eq "mtime") {
183 $vc->snd($folder->{mtime}); 206 $vc->snd($folder->{mtime});
207 } elsif ($msg eq "inventory") {
208 $vc->snd($folder->inventory);
184 } elsif ($msg eq "diff") { 209 } elsif ($msg eq "diff") {
185 my $time = $vc->rcv; 210 my $time = $vc->rcv;
186 for (@{$folder->{diff}}) { 211 for (@{$folder->{diff}}) {
187 next if $_->[0] <= $time; 212 next if $_->[0] <= $time;
188 $vc->snd($_->[0], 213 $vc->snd($_->[0],
189 (join "\0", @{$_->[1]}), 214 (join "\0", @{$_->[1]}),
190 (join "\0", @{$_->[2]}), 215 (join "\0", @{$_->[2]}),
191 ); 216 );
192 } 217 }
193 $vc->snd(-1); 218 $vc->snd(-1);
219 } elsif ($msg eq "begin") {
220 $folder->begin_update;
221 } elsif ($msg eq "end") {
222 $folder->end_update;
223 } elsif ($msg eq "mtime") {
224 $vc->snd($folder->{mtime});
194 } elsif ($msg eq "setctime") { 225 } elsif ($msg eq "setctime") {
195 $folder->{host}{$OTHERNAME} = $vc->rcv; 226 $folder->{host}{$OTHERNAME} = $vc->rcv;
196 } else { 227 } else {
197 die "protocol error, unknown folder command ($msg)\n"; 228 die "protocol error, unknown folder command ($msg)\n";
198 } 229 }
203 my $vc = shift; 234 my $vc = shift;
204 235
205 slog 8, "new connection $vc->{port}\n"; 236 slog 8, "new connection $vc->{port}\n";
206 237
207 while (my $msg = $vc->rcv) { 238 while (my $msg = $vc->rcv) {
208 if ($msg eq "name") { 239 if ($msg eq "setname") {
209 $vc->snd($::MYNAME); 240 $vc->snd($MYNAME);
241 $OTHERNAME = $vc->rcv;
210 } elsif ($msg eq "pri") { 242 } elsif ($msg eq "pri") {
211 $self->{pri} = $vc->rcv; 243 $vc->{pri} = $vc->rcv;
212 } elsif ($msg eq "time") { 244 } elsif ($msg eq "time") {
213 $vc->snd(time); 245 $vc->snd(time);
214 } elsif ($msg eq "list") { 246 } elsif ($msg eq "list") {
215 $vc->snd(join "\0", find_folders); 247 $vc->snd(join "\0", find_folders);
216 } elsif ($msg eq "open") { 248 } elsif ($msg eq "open") {

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines