… | |
… | |
23 | $mid = $digest->hexdigest; |
23 | $mid = $digest->hexdigest; |
24 | }; |
24 | }; |
25 | } |
25 | } |
26 | } |
26 | } |
27 | |
27 | |
28 | sub flushfh { |
28 | sub fflush { |
29 | my $oldfh = select $_[0]; |
29 | my $oldfh = select $_[0]; |
30 | $| = 1; |
30 | $| = 1; $| = 0; |
31 | select $oldfh; |
31 | select $oldfh; |
32 | } |
32 | } |
33 | |
33 | |
34 | # rename a file and fsync the directory |
34 | # rename a file and fsync the directory |
35 | sub replace { |
35 | sub replace { |
… | |
… | |
190 | print $fh "[DIFF $_->[0]]\n"; |
190 | print $fh "[DIFF $_->[0]]\n"; |
191 | print $fh "+$_\n" for @{$_->[1]}; |
191 | print $fh "+$_\n" for @{$_->[1]}; |
192 | print $fh "-$_\n" for @{$_->[2]}; |
192 | print $fh "-$_\n" for @{$_->[2]}; |
193 | } |
193 | } |
194 | |
194 | |
195 | flushfh($fh); |
195 | fflush($fh); |
196 | File::Sync::fsync($fh); |
196 | File::Sync::fsync($fh); |
197 | close $fh |
197 | close $fh |
198 | or die "$path~: unable to create updated .mdif: $!"; |
198 | or die "$path~: unable to create updated .mdif: $!"; |
199 | |
199 | |
200 | replace("$path~", $path); |
200 | replace("$path~", $path); |
… | |
… | |
249 | |
249 | |
250 | sub close { |
250 | sub close { |
251 | my $self = shift; |
251 | my $self = shift; |
252 | |
252 | |
253 | if ($self->{rw} && $self->{fh}) { |
253 | if ($self->{rw} && $self->{fh}) { |
254 | flushfh($self->{fh}); |
254 | fflush($self->{fh}); |
255 | File::Sync::fsync($self->{fh}); |
255 | File::Sync::fsync($self->{fh}); |
256 | } |
256 | } |
257 | |
257 | |
258 | $self->write_mdif; |
258 | $self->write_mdif; |
259 | |
259 | |
… | |
… | |
350 | my $mail; |
350 | my $mail; |
351 | |
351 | |
352 | my $msg = $self->{iidx}{$hash} |
352 | my $msg = $self->{iidx}{$hash} |
353 | or die "$hash: no such message in $self->{path}"; |
353 | or die "$hash: no such message in $self->{path}"; |
354 | |
354 | |
|
|
355 | print STDERR "$self->{fh}, $msg->[0], SEEK_SET\n";#d# |
|
|
356 | |
355 | seek $self->{fh}, $msg->[0], SEEK_SET |
357 | seek $self->{fh}, $msg->[0], SEEK_SET |
356 | or die "$self->{path}: $!"; |
358 | or die "$self->{path}: $!"; |
|
|
359 | |
|
|
360 | print STDERR "$msg->[1] == read $self->{fh}, $msg->[1]\n";#d# |
357 | |
361 | |
358 | $msg->[1] == read $self->{fh}, $mail, $msg->[1] |
362 | $msg->[1] == read $self->{fh}, $mail, $msg->[1] |
359 | or die "$self->{path}: $!"; |
363 | or die "$self->{path}: $!"; |
360 | |
364 | |
361 | $mail =~ /^From \S/ |
365 | $mail =~ /^From \S/ |
… | |
… | |
380 | for (@_) { |
384 | for (@_) { |
381 | if (exists $self->{iidx}{$_}) { # at least one message exists |
385 | if (exists $self->{iidx}{$_}) { # at least one message exists |
382 | my $guard = $::lockdisk->guard; |
386 | my $guard = $::lockdisk->guard; |
383 | my %del; @del{@_} = (); |
387 | my %del; @del{@_} = (); |
384 | my @nidx; |
388 | my @nidx; |
|
|
389 | my $dofs = 0; |
385 | |
390 | |
386 | open my $fh, ">", $temp |
391 | open my $fh, "+>", $temp |
387 | or die "$temp: $!"; |
392 | or die "$temp: $!"; |
388 | |
393 | |
389 | eval { |
394 | eval { |
390 | 0 == setlkw(fileno $fh, 2) |
395 | 0 == setlkw(fileno $fh, 2) |
391 | or die "$self->{path}~: $!"; |
396 | or die "$self->{path}~: $!"; |
392 | |
397 | |
393 | $self->{fsize} = 0; # we virtually truncated the file |
398 | $self->{fsize} = 0; # we virtually truncated the file |
394 | |
399 | |
395 | my $dofs = 0; |
|
|
396 | for (@{delete $self->{idx}}) { |
400 | for (@{delete $self->{idx}}) { |
397 | my $hash = $_->[1]; |
401 | my $hash = $_->[1]; |
398 | my $buf; |
402 | my $buf; |
399 | |
403 | |
400 | unless (exists $del{$hash}) { |
404 | unless (exists $del{$hash}) { |
… | |
… | |
430 | close $fh; |
434 | close $fh; |
431 | unlink $temp; |
435 | unlink $temp; |
432 | die; |
436 | die; |
433 | } |
437 | } |
434 | |
438 | |
|
|
439 | fflush($fh); |
435 | File::Sync::fsync($fh); |
440 | File::Sync::fsync($fh); |
436 | replace $temp, $self->{path}; |
441 | replace $temp, $self->{path}; |
437 | |
442 | |
438 | $self->{fh} = $fh; |
443 | $self->{fh} = $fh; |
439 | $self->{rw} = 1; |
444 | $self->{rw} = 1; |
440 | |
445 | |
441 | delete $self->{iidx}; |
446 | delete $self->{iidx}; |
442 | |
447 | |
443 | $self->{idx} = \@nidx; |
448 | $self->{idx} = \@nidx; |
444 | $self->{fsize} = $ofs; |
449 | $self->{fsize} = $dofs; |
445 | |
450 | |
446 | return; |
451 | return; |
447 | } |
452 | } |
448 | } |
453 | } |
449 | } |
454 | } |
… | |
… | |
466 | } |
471 | } |
467 | |
472 | |
468 | sub end_update { |
473 | sub end_update { |
469 | my $self = shift; |
474 | my $self = shift; |
470 | |
475 | |
471 | $self->gendiff((delete $self->{oidx}, $self->{idx})); |
476 | $self->gendiff((delete $self->{oidx}), $self->{idx}); |
472 | |
477 | |
473 | flushfh($self->{fh}); |
478 | fflush($self->{fh}); |
474 | File::Sync::fsync($self->{fh}); |
479 | File::Sync::fsync($self->{fh}); |
475 | |
480 | |
476 | stat $self->{fh} |
481 | stat $self->{fh} |
477 | or die "$self->{path}: $!"; |
482 | or die "$self->{path}: $!"; |
478 | |
483 | |