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

Comparing syncmail/syncmail (file contents):
Revision 1.6 by root, Sun Oct 28 20:52:25 2001 UTC vs.
Revision 1.7 by root, Mon Oct 29 00:37:41 2001 UTC

73 @folders; 73 @folders;
74} 74}
75 75
76my $sync_folder = new Coro::Semaphore 3; # max 3 folders in parallel 76my $sync_folder = new Coro::Semaphore 3; # max 3 folders in parallel
77 77
78sub sync_offer {
79 my ($folder, $avc, $diff) = @_;
80
81 my $vc = create vc pri => 1;
82 $avc->snd("offer", $vc->{port});
83
84 async {
85 $vc->rcv; # need to synchronize, argl. should open on other side
86 $vc->snd(join "\0", @$diff);
87 my %dup; @dup{split /\0/, $vc->rcv} = ();
88
89 for (@$diff) {
90 $vc->snd($folder->fetch($_)) unless exists $dup{$_};
91 }
92
93 defined $vc->rcv and die "protocol error, expected close";
94 };
95}
96
78sub sync_folder { 97sub sync_folder {
79 my $name = $_[0]; 98 my $name = $_[0];
80 99
81 my $quit_guard = quit_guard; 100 my $quit_guard = quit_guard;
82 async { 101 async {
86 my $folder = new folder name => $name; 105 my $folder = new folder name => $name;
87 106
88 $vc->snd("open", $name); 107 $vc->snd("open", $name);
89 $vc->snd("mtime"); 108 $vc->snd("mtime");
90 109
91 $folder->check;
92 $folder->read_mdif; 110 $folder->read_mdif;
93 111
94 my $ctime = $folder->{host}{$OTHERNAME} || -1; 112 my $ctime = $folder->{host}{$OTHERNAME} || -1;
95 my $rtime = $vc->rcv; 113 my $rtime = $vc->rcv;
96 114
101 # 01 - local add 119 # 01 - local add
102 # 10 - remote del 120 # 10 - remote del
103 # 11 - remote add 121 # 11 - remote add
104 122
105 my @diff = grep { $_->[0] > $ctime } @{$folder->{diff}}; 123 my @diff = grep { $_->[0] > $ctime } @{$folder->{diff}};
124
106 $diff = $vc->rcv; 125 $diff = $vc->rcv;
107
108 while () { 126 while () {
109 if ($diff >= 0 and (!@diff or $diff <= $diff[0][0])) { 127 if ($diff >= 0 and (!@diff or $diff < $diff[0][0])) {
110 slog 0, "applying remote diff $diff (@add, @del)\n";
111 $diff{$_} = 0b01 for split /\0/, $vc->rcv; # add 128 $diff{$_} = 0b01 for split /\0/, $vc->rcv; # add
112 $diff{$_} = 0b00 for split /\0/, $vc->rcv; # del 129 $diff{$_} = 0b00 for split /\0/, $vc->rcv; # del
113 130
114 $diff = $vc->rcv; 131 $diff = $vc->rcv;
115 } elsif (@diff) { 132 } elsif (@diff) {
116 slog 0, "applying local diff $diff[0][0]\n";
117 $diff{$_} = 0b11 for @{$diff[0][1]}; 133 $diff{$_} = 0b11 for @{$diff[0][1]};
118 $diff{$_} = 0b10 for @{$diff[0][2]}; 134 $diff{$_} = 0b10 for @{$diff[0][2]};
119 135
120 shift @diff; 136 shift @diff;
121 } else { 137 } else {
122 slog 0, "no more diffing\n";
123 last; 138 last;
124 } 139 }
125 } 140 }
126 141
127 # append or update, depending on wether there are messages to be deleted 142 # append or update, depending on wether there are messages to be deleted
134 } 149 }
135 150
136 $vc->snd("delete", join "\0", @{$diff[2]}); 151 $vc->snd("delete", join "\0", @{$diff[2]});
137 $folder->delete(@{$diff[0]}); 152 $folder->delete(@{$diff[0]});
138 153
154 # offer ours
155 my $offer_coro = sync_offer($folder, $vc, $diff[3]);
156
157 # request theirs
158 {
159 my @send = grep { !$folder->exists($_) } @{$diff[1]};
160 $vc->snd("send", join "\0", @send);
161 $folder->append($_, $vc->rcv) for @send;
162 $vc->snd("-"); # sync
163 }
164
165 slog 0, "waiting...\n";#d#
166 $offer_coro->join;
167
168 # sanity check
169 $vc->snd("inventory");
170 if ($folder->inventory ne $vc->rcv) {
171 $folder->write_mdif;
172 slog 0, "FATAL: folder inventory mismatch after update\n";
173 }
174
139 $vc->snd("end"); 175 $vc->snd("end");
140 $folder->end_update; 176 $folder->end_update;
141 177
142 $vc->snd("ctime", $folder->{ctime}); 178 $vc->snd("setctime", $folder->{ctime});
179
180 $vc->snd("mtime");
143 $folder->{host}{$OTHERNAME} = $vc->rcv; 181 $folder->{host}{$OTHERNAME} = $vc->rcv;
144 182
145 # sanity check
146 $vc->snd("inventory"); 183 $vc->snd("close");
147 if ($folder->inventory ne $vc->rcv) { 184 $folder->close;
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";
153 185
154 undef $quit_guard; 186 undef $quit_guard;
155 } 187 }
156} 188}
157 189
164 $vc->snd("time"); 196 $vc->snd("time");
165 my $othertime = $vc->rcv; 197 my $othertime = $vc->rcv;
166 abs (($time + time)*0.5 - $othertime) <= $::MAXTIMEDIFF 198 abs (($time + time)*0.5 - $othertime) <= $::MAXTIMEDIFF
167 or die "ERROR: time difference between hosts larger than $::MAXTIMEDIFF"; 199 or die "ERROR: time difference between hosts larger than $::MAXTIMEDIFF";
168 } 200 }
169#Coro::Event::do_timer(after => 60);#d#
170 201
171 $vc->snd("setname", $MYNAME); $OTHERNAME = $vc->rcv; 202 $vc->snd("setname", $MYNAME); $OTHERNAME = $vc->rcv;
172 203
173 if ($SLAVE) { 204 if ($SLAVE) {
174 # 205 #
196 my $name = $vc->rcv; 227 my $name = $vc->rcv;
197 my $folder = new folder name => $name; 228 my $folder = new folder name => $name;
198 229
199 slog 8, "serving folder $name\n"; 230 slog 8, "serving folder $name\n";
200 231
201 $folder->check;
202 $folder->read_mdif; 232 $folder->read_mdif;
203 233
204 while (my $msg = $vc->rcv) { 234 while (my $msg = $vc->rcv) {
205 if ($msg eq "mtime") { 235 if ($msg eq "mtime") {
206 $vc->snd($folder->{mtime}); 236 $vc->snd($folder->{mtime});
216 ); 246 );
217 } 247 }
218 $vc->snd(-1); 248 $vc->snd(-1);
219 } elsif ($msg eq "begin") { 249 } elsif ($msg eq "begin") {
220 $folder->begin_update; 250 $folder->begin_update;
251 } elsif ($msg eq "delete") {
252 $folder->delete(split /\0/, $vc->rcv);
253 } elsif ($msg eq "offer") {
254 my $ovc = catch vc port => $vc->rcv;
255 async {
256 my @offer;
257 {
258 my @dup;
259
260 $ovc->snd("-"); # synchronize
261 for (split /\0/, $ovc->rcv) {
262 if ($folder->exists($_)) {
263 push @dup, $_;
264 } else {
265 push @offer, $_;
266 }
267 }
268
269 $ovc->snd(join "\0", @dup);
270 }
271
272 # now we'll get everything in @offer, in order
273 $folder->append($_, $ovc->rcv) for @offer;
274 $ovc->close;
275 };
276 } elsif ($msg eq "send") {
277 $vc->pri(1);
278 $vc->snd($folder->fetch($_)) for split /\0/, $vc->rcv;
279 $vc->rcv; # sync
280 $vc->pri(0);
221 } elsif ($msg eq "end") { 281 } elsif ($msg eq "end") {
222 $folder->end_update; 282 $folder->end_update;
223 } elsif ($msg eq "mtime") { 283 } elsif ($msg eq "mtime") {
224 $vc->snd($folder->{mtime}); 284 $vc->snd($folder->{mtime});
225 } elsif ($msg eq "setctime") { 285 } elsif ($msg eq "setctime") {
226 $folder->{host}{$OTHERNAME} = $vc->rcv; 286 $folder->{host}{$OTHERNAME} = $vc->rcv;
287 } elsif ($msg eq "close") {
288 $folder->close;
227 } else { 289 } else {
228 die "protocol error, unknown folder command ($msg)\n"; 290 die "protocol error, unknown folder command ($msg)\n";
229 } 291 }
230 } 292 }
231} 293}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines