You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@spamassassin.apache.org by fe...@apache.org on 2004/02/29 21:06:04 UTC

svn commit: rev 6935 - incubator/spamassassin/trunk/lib/Mail/SpamAssassin

Author: felicity
Date: Sun Feb 29 12:06:03 2004
New Revision: 6935

Modified:
   incubator/spamassassin/trunk/lib/Mail/SpamAssassin/BayesStoreDBM.pm
Log:
bug 3100: if the fs fills up, we'll get a partial write failure to the bayes journal.  we used to loop and keep attempting to write out the data, but this would crush systems...  we'll now only try to write out the journal 5 times before failing out, we'll also truncate the journal upon write failure so we don't do a partial journal commit.

Modified: incubator/spamassassin/trunk/lib/Mail/SpamAssassin/BayesStoreDBM.pm
==============================================================================
--- incubator/spamassassin/trunk/lib/Mail/SpamAssassin/BayesStoreDBM.pm	(original)
+++ incubator/spamassassin/trunk/lib/Mail/SpamAssassin/BayesStoreDBM.pm	Sun Feb 29 12:06:03 2004
@@ -861,25 +861,35 @@
   # do not use print() here, it will break up the buffer if it's >8192 bytes,
   # which could result in two sets of tokens getting mixed up and their
   # touches missed.
-  my $writ = 0;
-  while ($writ < $nbytes) {
-    my $len = syswrite (OUT, $self->{string_to_journal}, $nbytes-$writ);
+  my $write_failure = 0;
+  my $original_point = tell OUT;
+  my $len;
+  do {
+    $len = syswrite (OUT, $self->{string_to_journal}, $nbytes);
 
+    # argh, write failure, give up
     if (!defined $len || $len < 0) {
-      # argh, write failure, give up
       $len = 0 unless ( defined $len );
       warn "write failed to Bayes journal $path ($len of $nbytes)!\n";
       last;
     }
 
-    $writ += $len;
-    if ($len < $nbytes) {
-      # this should not happen on filesystem writes!  Still, try to recover
-      # anyway, but be noisy about it so the admin knows
+    # This shouldn't happen, but could if the fs is full...
+    if ($len != $nbytes) {
       warn "partial write to Bayes journal $path ($len of $nbytes), recovering.\n";
-      $self->{string_to_journal} = substr ($self->{string_to_journal}, $len);
+
+      # we want to be atomic, so revert the journal file back to where
+      # we know it's "good".  if we can't truncate the journal, or we've
+      # tried 5 times to do the write, abort!
+      if (!truncate(OUT, $original_point) || ($write_failure++ > 4)) {
+        warn "cannot write to Bayes journal $path, aborting!\n";
+	last;
+      }
+
+      # if the fs is full, let's give the system a break
+      sleep 1;
     }
-  }
+  } while ($len != $nbytes);
 
   if (!close OUT) {
     warn "cannot write to $path, Bayes db update ignored\n";