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]