Author: carnold
Date: Thu Mar  1 22:58:38 2007
New Revision: 513638

URL: http://svn.apache.org/viewvc?view=rev&rev=513638
Log:
Bug 41735: RollingFileAppender may delete files during rollover

Modified:
    logging/log4j/branches/v1_2-branch/docs/HISTORY.txt
    
logging/log4j/branches/v1_2-branch/src/java/org/apache/log4j/RollingFileAppender.java
    logging/log4j/branches/v1_2-branch/src/xdocs/download.xml
    
logging/log4j/branches/v1_2-branch/tests/src/java/org/apache/log4j/RFATestCase.java

Modified: logging/log4j/branches/v1_2-branch/docs/HISTORY.txt
URL: 
http://svn.apache.org/viewvc/logging/log4j/branches/v1_2-branch/docs/HISTORY.txt?view=diff&rev=513638&r1=513637&r2=513638
==============================================================================
--- logging/log4j/branches/v1_2-branch/docs/HISTORY.txt (original)
+++ logging/log4j/branches/v1_2-branch/docs/HISTORY.txt Thu Mar  1 22:58:38 2007
@@ -38,6 +38,7 @@
        41186: AsyncAppender in 1.2.14 DiscardSummary events create 
NullPointerExceptions in layouts
           37864: Add target to generate binary and source compatibility report
           41708: PropertyPrinter.printOptions breaking signature change in 
log4j 1.2.9
+          41735: RollingFileAppender may delete files during rollover
  
  
  September 18th, 2006

Modified: 
logging/log4j/branches/v1_2-branch/src/java/org/apache/log4j/RollingFileAppender.java
URL: 
http://svn.apache.org/viewvc/logging/log4j/branches/v1_2-branch/src/java/org/apache/log4j/RollingFileAppender.java?view=diff&rev=513638&r1=513637&r2=513638
==============================================================================
--- 
logging/log4j/branches/v1_2-branch/src/java/org/apache/log4j/RollingFileAppender.java
 (original)
+++ 
logging/log4j/branches/v1_2-branch/src/java/org/apache/log4j/RollingFileAppender.java
 Thu Mar  1 22:58:38 2007
@@ -47,6 +47,8 @@
    */
   protected int  maxBackupIndex  = 1;
 
+  private long nextRollover = 0;
+
   /**
      The default constructor simply calls its [EMAIL PROTECTED]
      FileAppender#FileAppender parents constructor}.  */
@@ -120,27 +122,33 @@
     File file;
 
     if (qw != null) {
-       LogLog.debug("rolling over count=" + ((CountingQuietWriter) 
qw).getCount());
+        long size = ((CountingQuietWriter) qw).getCount();
+        LogLog.debug("rolling over count=" + size);
+        //   if operation fails, do not roll again until
+        //      maxFileSize more bytes are written
+        nextRollover = size + maxFileSize;
     }
     LogLog.debug("maxBackupIndex="+maxBackupIndex);
 
+    boolean renameSucceeded = true;
     // If maxBackups <= 0, then there is no file renaming to be done.
     if(maxBackupIndex > 0) {
       // Delete the oldest file, to keep Windows happy.
       file = new File(fileName + '.' + maxBackupIndex);
       if (file.exists())
-       file.delete();
+       renameSucceeded = file.delete();
 
       // Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2}
-      for (int i = maxBackupIndex - 1; i >= 1; i--) {
+      for (int i = maxBackupIndex - 1; i >= 1 && renameSucceeded; i--) {
        file = new File(fileName + "." + i);
        if (file.exists()) {
          target = new File(fileName + '.' + (i + 1));
          LogLog.debug("Renaming file " + file + " to " + target);
-         file.renameTo(target);
+         renameSucceeded = file.renameTo(target);
        }
       }
 
+    if(renameSucceeded) {
       // Rename fileName to fileName.1
       target = new File(fileName + "." + 1);
 
@@ -148,17 +156,35 @@
 
       file = new File(fileName);
       LogLog.debug("Renaming file " + file + " to " + target);
-      file.renameTo(target);
+      renameSucceeded = file.renameTo(target);
+      //
+      //   if file rename failed, reopen file with append = true
+      //
+      if (!renameSucceeded) {
+          try {
+            this.setFile(fileName, true, bufferedIO, bufferSize);
+          }
+          catch(IOException e) {
+            LogLog.error("setFile("+fileName+", true) call failed.", e);
+          }
+      }
+    }
     }
 
+    //
+    //   if all renames were successful, then
+    //
+    if (renameSucceeded) {
     try {
       // This will also close the file. This is OK since multiple
       // close operations are safe.
       this.setFile(fileName, false, bufferedIO, bufferSize);
+      nextRollover = 0;
     }
     catch(IOException e) {
       LogLog.error("setFile("+fileName+", false) call failed.", e);
     }
+    }
   }
 
   public
@@ -235,8 +261,11 @@
   protected
   void subAppend(LoggingEvent event) {
     super.subAppend(event);
-    if((fileName != null) &&
-                     ((CountingQuietWriter) qw).getCount() >= maxFileSize)
-      this.rollOver();
+    if(fileName != null && qw != null) {
+        long size = ((CountingQuietWriter) qw).getCount();
+        if (size >= maxFileSize && size >= nextRollover) {
+            rollOver();
+        }
+    }
    }
 }

Modified: logging/log4j/branches/v1_2-branch/src/xdocs/download.xml
URL: 
http://svn.apache.org/viewvc/logging/log4j/branches/v1_2-branch/src/xdocs/download.xml?view=diff&rev=513638&r1=513637&r2=513638
==============================================================================
--- logging/log4j/branches/v1_2-branch/src/xdocs/download.xml (original)
+++ logging/log4j/branches/v1_2-branch/src/xdocs/download.xml Thu Mar  1 
22:58:38 2007
@@ -63,6 +63,7 @@
        <li><a 
href="http://issues.apache.org/bugzilla/show_bug.cgi?id=41186";>41186</a>: 
AsyncAppender in 1.2.14 DiscardSummary events create NullPointerExceptions in 
layouts</li>
        <li><a 
href="http://issues.apache.org/bugzilla/show_bug.cgi?id=37864";>37864</a>: Add 
target to generate binary and source compatibility report</li>
        <li><a 
href="http://issues.apache.org/bugzilla/show_bug.cgi?id=41708";>41708</a>: 
PropertyPrinter.printOptions breaking signature change in log4j 1.2.9</li>
+       <li><a 
href="http://issues.apache.org/bugzilla/show_bug.cgi?id=41735";>41735</a>: 
RollingFileAppender may delete files during rollover</li>
       </ul>
    </li>
     </ul>

Modified: 
logging/log4j/branches/v1_2-branch/tests/src/java/org/apache/log4j/RFATestCase.java
URL: 
http://svn.apache.org/viewvc/logging/log4j/branches/v1_2-branch/tests/src/java/org/apache/log4j/RFATestCase.java?view=diff&rev=513638&r1=513637&r2=513638
==============================================================================
--- 
logging/log4j/branches/v1_2-branch/tests/src/java/org/apache/log4j/RFATestCase.java
 (original)
+++ 
logging/log4j/branches/v1_2-branch/tests/src/java/org/apache/log4j/RFATestCase.java
 Thu Mar  1 22:58:38 2007
@@ -20,6 +20,7 @@
 import junit.framework.TestCase;
 
 import java.io.File;
+import java.io.FileWriter;
 import java.io.IOException;
 
 /**
@@ -112,5 +113,125 @@
                 new RollingFileAppender(layout,"output/rfa_3param.log", false);
         assertEquals(1, appender.getMaxBackupIndex());
     }
+
+    /**
+     * Test locking of .1 file.
+     */
+    public void testLockDotOne() throws Exception {
+      Logger logger = Logger.getLogger(RFATestCase.class);
+      Logger root = Logger.getRootLogger();
+      PatternLayout layout = new PatternLayout("%m\n");
+      org.apache.log4j.RollingFileAppender rfa =
+        new org.apache.log4j.RollingFileAppender();
+      rfa.setName("ROLLING");
+      rfa.setLayout(layout);
+      rfa.setAppend(false);
+      rfa.setMaxBackupIndex(10);
+      rfa.setMaximumFileSize(100);
+      rfa.setFile("output/RFA-dot1.log");
+      rfa.activateOptions();
+      root.addAppender(rfa);
+
+      new File("output/RFA-dot1.log.2").delete();
+
+      FileWriter dot1 = new FileWriter("output/RFA-dot1.log.1");
+      dot1.write("Locked file");
+      FileWriter dot5 = new FileWriter("output/RFA-dot1.log.5");
+      dot5.write("Unlocked file");
+      dot5.close();
+
+      // Write exactly 10 bytes with each log
+      for (int i = 0; i < 15; i++) {
+        if (i < 10) {
+          logger.debug("Hello---" + i);
+        } else if (i < 100) {
+          logger.debug("Hello--" + i);
+        }
+      }
+      dot1.close();
+
+      for (int i = 15; i < 25; i++) {
+            logger.debug("Hello--" + i);
+      }
+      rfa.close();
+
+
+      assertTrue(new File("output/RFA-dot1.log.7").exists());
+      //
+      //     if .2 is the locked file then
+      //       renaming wasn't successful until the file was closed
+      if (new File("output/RFA-dot1.log.2").length() < 15) {
+          assertEquals(50, new File("output/RFA-dot1.log").length());
+          assertEquals(200, new File("output/RFA-dot1.log.1").length());
+      } else {
+          assertTrue(new File("output/RFA-dot1.log").exists());
+          assertTrue(new File("output/RFA-dot1.log.1").exists());
+          assertTrue(new File("output/RFA-dot1.log.2").exists());
+          assertTrue(new File("output/RFA-dot1.log.3").exists());
+          assertFalse(new File("output/RFA-dot1.log.4").exists());
+      }
+    }
+
+
+    /**
+     * Test locking of .3 file.
+     */
+    public void testLockDotThree() throws Exception {
+      Logger logger = Logger.getLogger(RFATestCase.class);
+      Logger root = Logger.getRootLogger();
+      PatternLayout layout = new PatternLayout("%m\n");
+      org.apache.log4j.RollingFileAppender rfa =
+        new org.apache.log4j.RollingFileAppender();
+      rfa.setName("ROLLING");
+      rfa.setLayout(layout);
+      rfa.setAppend(false);
+      rfa.setMaxBackupIndex(10);
+      rfa.setMaximumFileSize(100);
+      rfa.setFile("output/RFA-dot3.log");
+      rfa.activateOptions();
+      root.addAppender(rfa);
+
+      new File("output/RFA-dot3.log.1").delete();
+      new File("output/RFA-dot3.log.2").delete();
+      new File("output/RFA-dot3.log.4").delete();
+
+      FileWriter dot3 = new FileWriter("output/RFA-dot3.log.3");
+      dot3.write("Locked file");
+      FileWriter dot5 = new FileWriter("output/RFA-dot3.log.5");
+      dot5.write("Unlocked file");
+      dot5.close();
+
+      // Write exactly 10 bytes with each log
+      for (int i = 0; i < 15; i++) {
+        if (i < 10) {
+          logger.debug("Hello---" + i);
+        } else if (i < 100) {
+          logger.debug("Hello--" + i);
+        }
+      }
+      dot3.close();
+
+      for (int i = 15; i < 35; i++) {
+          logger.debug("Hello--" + i);
+      }
+      rfa.close();
+
+      assertTrue(new File("output/RFA-dot3.log.8").exists());
+      //
+      //     if .3 is the locked file then
+      //       renaming wasn't successful until file was closed
+      if (new File("output/RFA-dot3.log.5").exists()) {
+          assertEquals(50, new File("output/RFA-dot3.log").length());
+          assertEquals(100, new File("output/RFA-dot3.log.1").length());
+          assertEquals(200, new File("output/RFA-dot3.log.2").length());
+      } else {
+          assertTrue(new File("output/RFA-dot3.log").exists());
+          assertTrue(new File("output/RFA-dot3.log.1").exists());
+          assertTrue(new File("output/RFA-dot3.log.2").exists());
+          assertTrue(new File("output/RFA-dot3.log.3").exists());
+          assertFalse(new File("output/RFA-dot3.log.4").exists());
+      }
+    }
+
 
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to