You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2012/11/19 04:22:58 UTC

svn commit: r1411052 - in /logging/log4j/log4j2/trunk: core/src/main/java/org/apache/logging/log4j/core/appender/ core/src/main/java/org/apache/logging/log4j/core/appender/rolling/ core/src/test/java/org/apache/logging/log4j/core/appender/rolling/ src/...

Author: rgoers
Date: Mon Nov 19 03:22:56 2012
New Revision: 1411052

URL: http://svn.apache.org/viewvc?rev=1411052&view=rev
Log:
LOG4J2-116 - File renaming was using the wrong date value. Enhanced DefaultRolloverStrategy to store newest files in highest index as well as lowest.

Modified:
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/RollingFileAppender.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/PatternProcessor.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/rolling/OnStartupTriggeringPolicyTest.java
    logging/log4j/log4j2/trunk/src/changes/changes.xml
    logging/log4j/log4j2/trunk/src/site/xdoc/manual/appenders.xml

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/RollingFileAppender.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/RollingFileAppender.java?rev=1411052&r1=1411051&r2=1411052&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/RollingFileAppender.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/RollingFileAppender.java Mon Nov 19 03:22:56 2012
@@ -39,18 +39,13 @@ public final class RollingFileAppender e
 
     private final String fileName;
     private final String filePattern;
-    private final TriggeringPolicy policy;
-    private final RolloverStrategy strategy;
 
-    private RollingFileAppender(String name, Layout layout, TriggeringPolicy policy, RolloverStrategy strategy,
-                               Filter filter, RollingFileManager manager, String fileName, String filePattern,
-                               boolean handleException, boolean immediateFlush) {
+
+    private RollingFileAppender(String name, Layout layout, Filter filter, RollingFileManager manager, String fileName,
+                                String filePattern, boolean handleException, boolean immediateFlush) {
         super(name, layout, filter, handleException, immediateFlush, manager);
         this.fileName = fileName;
         this.filePattern = filePattern;
-        this.policy = policy;
-        this.strategy = strategy;
-        policy.initialize(manager);
     }
 
     /**
@@ -60,7 +55,7 @@ public final class RollingFileAppender e
      */
     @Override
     public void append(LogEvent event) {
-        ((RollingFileManager) getManager()).checkRollover(event, policy, strategy);
+        ((RollingFileManager) getManager()).checkRollover(event);
         super.append(event);
     }
 
@@ -138,10 +133,11 @@ public final class RollingFileAppender e
         }
 
         if (strategy == null) {
-            strategy = DefaultRolloverStrategy.createStrategy(null, null, config);
+            strategy = DefaultRolloverStrategy.createStrategy(null, null, "true", config);
         }
 
-        RollingFileManager manager = RollingFileManager.getFileManager(fileName, filePattern, isAppend, isBuffered);
+        RollingFileManager manager = RollingFileManager.getFileManager(fileName, filePattern, isAppend, isBuffered,
+            policy, strategy);
         if (manager == null) {
             return null;
         }
@@ -150,7 +146,7 @@ public final class RollingFileAppender e
             layout = PatternLayout.createLayout(null, null, null, null);
         }
 
-        return new RollingFileAppender(name, layout, policy, strategy, filter, manager, fileName, filePattern,
+        return new RollingFileAppender(name, layout, filter, manager, fileName, filePattern,
             handleExceptions, isFlush);
     }
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java?rev=1411052&r1=1411051&r2=1411052&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/DefaultRolloverStrategy.java Mon Nov 19 03:22:56 2012
@@ -29,22 +29,26 @@ import org.apache.logging.log4j.core.con
 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
 import org.apache.logging.log4j.status.StatusLogger;
 
+import javax.swing.plaf.basic.BasicInternalFrameTitlePane;
 import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 
 /**
- * When rolling over, <code>FixedWindowRollingPolicy</code> renames files
- * according to a fixed window algorithm as described below.
+ * When rolling over, <code>DefaultRolloverStrategy</code> renames files
+ * according to an algorithm as described below.
  * <p/>
- * <p>The <b>ActiveFileName</b> property, which is required, represents the name
- * of the file where current logging output will be written.
- * The <b>FileNamePattern</b>  option represents the file name pattern for the
- * archived (rolled over) log files. If present, the <b>FileNamePattern</b>
- * option must include an integer token, that is the string "%i" somewhere
- * within the pattern.
- * <p/>
- * <p>Let <em>max</em> and <em>min</em> represent the values of respectively
+ * <p>The DefaultRolloverStrategy is a combination of a time-based policy and a fixed-window policy. When
+ * the file name pattern contains a date format then the rollover time interval will be used to calculate the
+ * time to use in the file pattern. When the file pattern contains an integer replacement token one of the
+ * counting techniques will be used.</p>
+ * <p>When the ascending attribute is set to true (the default) then the counter will be incremented and the
+ * current log file will be renamed to include the counter value. If the counter hits the maximum value then
+ * the oldest file, which will have the smallest counter, will be deleted, all other files will be renamed to
+ * have their counter decremented and then the current file will be renamed to have the maximum counter value.
+ * Note that with this counting strategy specifying a large maximum value may entirely avoid renaming files.</p>
+ * <p>When the ascending attribute is false, then the "normal" fixed-window strategy will be used.</p>
+ * Let <em>max</em> and <em>min</em> represent the values of respectively
  * the <b>MaxIndex</b> and <b>MinIndex</b> options. Let "foo.log" be the value
  * of the <b>ActiveFile</b> option and "foo.%i.log" the value of
  * <b>FileNamePattern</b>. Then, when rolling over, the file
@@ -58,9 +62,7 @@ import java.util.List;
  * <code>foo.log</code> will be created.
  * <p/>
  * <p>Given that this rollover algorithm requires as many file renaming
- * operations as the window size, large window sizes are discouraged. The
- * current implementation will automatically reduce the window size to 12 when
- * larger values are specified by the user.
+ * operations as the window size, large window sizes are discouraged.
  */
 @Plugin(name = "DefaultRolloverStrategy", type = "Core", printObject = true)
 public class DefaultRolloverStrategy implements RolloverStrategy {
@@ -82,6 +84,8 @@ public class DefaultRolloverStrategy imp
      */
     private final int minIndex;
 
+    private final boolean useMax;
+
     private final StrSubstitutor subst;
 
     /**
@@ -89,10 +93,11 @@ public class DefaultRolloverStrategy imp
      * @param min The minimum index.
      * @param max The maximum index.
      */
-    protected DefaultRolloverStrategy(int min, int max, StrSubstitutor subst) {
+    protected DefaultRolloverStrategy(int min, int max, boolean useMax, StrSubstitutor subst) {
         minIndex = min;
         maxIndex = max;
         this.subst = subst;
+        this.useMax = useMax;
     }
 
     /**
@@ -103,14 +108,14 @@ public class DefaultRolloverStrategy imp
      */
     public RolloverDescription rollover(RollingFileManager manager) throws SecurityException {
         if (maxIndex >= 0) {
-            int purgeStart = minIndex;
+            int fileIndex;
 
-            if (!purge(purgeStart, maxIndex, manager)) {
+            if ((fileIndex = purge(minIndex, maxIndex, manager)) < 0) {
                 return null;
             }
 
             StringBuilder buf = new StringBuilder();
-            manager.getProcessor().formatFileName(buf, purgeStart);
+            manager.getProcessor().formatFileName(buf, fileIndex);
             String currentFileName = manager.getFileName();
 
             String renameTo = subst.replace(buf);
@@ -134,15 +139,21 @@ public class DefaultRolloverStrategy imp
         return null;
     }
 
+    private int purge(final int lowIndex, final int highIndex, RollingFileManager manager) {
+        return useMax ? purgeAscending(lowIndex, highIndex, manager) :
+            purgeDescending(lowIndex, highIndex, manager);
+    }
+
     /**
-     * Purge and rename old log files in preparation for rollover
+     * Purge and rename old log files in preparation for rollover. The newest file will have the smallest index, the
+     * oldest will have the highest.
      *
      * @param lowIndex  low index
      * @param highIndex high index.  Log file associated with high index will be deleted if needed.
      * @param manager The RollingFileManager
      * @return true if purge was successful and rollover should be attempted.
      */
-    private boolean purge(final int lowIndex, final int highIndex, RollingFileManager manager) {
+    private int purgeDescending(final int lowIndex, final int highIndex, RollingFileManager manager) {
         int suffixLength = 0;
 
         List<FileRenameAction> renames = new ArrayList<FileRenameAction>();
@@ -182,7 +193,7 @@ public class DefaultRolloverStrategy imp
                 //        if that fails then abandon purge
                 if (i == highIndex) {
                     if (!toRename.delete()) {
-                        return false;
+                        return -1;
                     }
 
                     break;
@@ -216,15 +227,123 @@ public class DefaultRolloverStrategy imp
 
             try {
                 if (!action.execute()) {
-                    return false;
+                    return -1;
                 }
             } catch (Exception ex) {
                 LOGGER.warn("Exception during purge in RollingFileAppender", ex);
-                return false;
+                return -1;
             }
         }
 
-        return true;
+        return lowIndex;
+    }
+
+    /**
+     * Purge and rename old log files in preparation for rollover. The oldest file will have the smallest index,
+     * the newest the highest.
+     *
+     * @param lowIndex  low index
+     * @param highIndex high index.  Log file associated with high index will be deleted if needed.
+     * @param manager The RollingFileManager
+     * @return true if purge was successful and rollover should be attempted.
+     */
+    private int purgeAscending(final int lowIndex, final int highIndex, RollingFileManager manager) {
+        int suffixLength = 0;
+
+        List<FileRenameAction> renames = new ArrayList<FileRenameAction>();
+        StringBuilder buf = new StringBuilder();
+        manager.getProcessor().formatFileName(buf, highIndex);
+
+        String highFilename = subst.replace(buf);
+
+        if (highFilename.endsWith(".gz")) {
+            suffixLength = 3;
+        } else if (highFilename.endsWith(".zip")) {
+            suffixLength = 4;
+        }
+
+        int maxIndex = 0;
+
+        for (int i = highIndex; i >= lowIndex; i--) {
+            File toRename = new File(highFilename);
+            if (i == highIndex && toRename.exists()) {
+                maxIndex = highIndex;
+            } else if (maxIndex == 0 && toRename.exists()) {
+                maxIndex = i + 1;
+                break;
+            }
+
+            boolean isBase = false;
+
+            if (suffixLength > 0) {
+                File toRenameBase =
+                    new File(highFilename.substring(0, highFilename.length() - suffixLength));
+
+                if (toRename.exists()) {
+                    if (toRenameBase.exists()) {
+                        toRenameBase.delete();
+                    }
+                } else {
+                    toRename = toRenameBase;
+                    isBase = true;
+                }
+            }
+
+            if (toRename.exists()) {
+                //
+                //    if at lower index and then all slots full
+                //        attempt to delete last file
+                //        if that fails then abandon purge
+                if (i == lowIndex) {
+                    if (!toRename.delete()) {
+                        return -1;
+                    }
+
+                    break;
+                }
+
+                //
+                //   if intermediate index
+                //     add a rename action to the list
+                buf.setLength(0);
+                manager.getProcessor().formatFileName(buf, i - 1);
+
+                String lowFilename = subst.replace(buf);
+                String renameTo = lowFilename;
+
+                if (isBase) {
+                    renameTo = lowFilename.substring(0, lowFilename.length() - suffixLength);
+                }
+
+                renames.add(new FileRenameAction(toRename, new File(renameTo), true));
+                highFilename = lowFilename;
+            } else {
+                buf.setLength(0);
+                manager.getProcessor().formatFileName(buf, i - 1);
+
+                highFilename = subst.replace(buf);
+            }
+        }
+        if (maxIndex == 0) {
+            maxIndex = lowIndex;
+        }
+
+        //
+        //   work renames backwards
+        //
+        for (int i = renames.size() - 1; i >= 0; i--) {
+            Action action = renames.get(i);
+
+            try {
+                if (!action.execute()) {
+                    return -1;
+                }
+            } catch (Exception ex) {
+                LOGGER.warn("Exception during purge in RollingFileAppender", ex);
+                return -1;
+            }
+        }
+        return maxIndex;
     }
 
     @Override
@@ -242,8 +361,9 @@ public class DefaultRolloverStrategy imp
     @PluginFactory
     public static DefaultRolloverStrategy createStrategy(@PluginAttr("max") String max,
                                                          @PluginAttr("min") String min,
+                                                         @PluginAttr("fileIndex") String fileIndex,
                                                          @PluginConfiguration Configuration config) {
-
+        boolean useMax = fileIndex == null ? true : fileIndex.equalsIgnoreCase("max");
         int minIndex;
         if (min != null) {
             minIndex = Integer.parseInt(min);
@@ -264,7 +384,7 @@ public class DefaultRolloverStrategy imp
         } else {
             maxIndex = DEFAULT_WINDOW_SIZE;
         }
-        return new DefaultRolloverStrategy(minIndex, maxIndex, config.getSubst());
+        return new DefaultRolloverStrategy(minIndex, maxIndex, useMax, config.getSubst());
     }
 
 }

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/PatternProcessor.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/PatternProcessor.java?rev=1411052&r1=1411051&r2=1411052&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/PatternProcessor.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/PatternProcessor.java Mon Nov 19 03:22:56 2012
@@ -46,6 +46,9 @@ public class PatternProcessor {
     private final ArrayPatternConverter[] patternConverters;
     private final FormattingInfo[] patternFields;
 
+    private long prevFileTime = 0;
+    private long nextFileTime = 0;
+
     private RolloverFrequency frequency = null;
 
     /**
@@ -74,9 +77,12 @@ public class PatternProcessor {
      * Returns the next potential rollover time.
      * @param current The current time.
      * @param increment The increment to the next time.
-     * @return the next potential rollover time.
+     * @return the next potential rollover time and the timestamp for the target file.
      */
     public long getNextTime(long current, int increment, boolean modulus) {
+        prevFileTime = nextFileTime;
+        long nextTime;
+
         if (frequency == null) {
             throw new IllegalStateException("Pattern does not contain a date");
         }
@@ -87,38 +93,62 @@ public class PatternProcessor {
         cal.set(Calendar.MILLISECOND, 0);
         if (frequency == RolloverFrequency.ANNUALLY) {
             increment(cal, Calendar.YEAR, increment, modulus);
-            return cal.getTimeInMillis();
+            nextTime = cal.getTimeInMillis();
+            cal.add(Calendar.YEAR, -1);
+            nextFileTime = cal.getTimeInMillis();
+            return nextTime;
         }
         if (frequency == RolloverFrequency.MONTHLY) {
             increment(cal, Calendar.MONTH, increment, modulus);
-            return cal.getTimeInMillis();
+            nextTime = cal.getTimeInMillis();
+            cal.add(Calendar.MONTH, -1);
+            nextFileTime = cal.getTimeInMillis();
+            return nextTime;
         }
         if (frequency == RolloverFrequency.WEEKLY) {
             increment(cal, Calendar.WEEK_OF_YEAR, increment, modulus);
-            return cal.getTimeInMillis();
+            nextTime = cal.getTimeInMillis();
+            cal.add(Calendar.WEEK_OF_YEAR, -1);
+            nextFileTime = cal.getTimeInMillis();
+            return nextTime;
         }
         cal.set(Calendar.DAY_OF_YEAR, currentCal.get(Calendar.DAY_OF_YEAR));
         if (frequency == RolloverFrequency.DAILY) {
             increment(cal, Calendar.DAY_OF_YEAR, increment, modulus);
-            return cal.getTimeInMillis();
+            nextTime = cal.getTimeInMillis();
+            cal.add(Calendar.DAY_OF_YEAR, -1);
+            nextFileTime = cal.getTimeInMillis();
+            return nextTime;
         }
         cal.set(Calendar.HOUR, currentCal.get(Calendar.HOUR));
         if (frequency == RolloverFrequency.HOURLY) {
             increment(cal, Calendar.HOUR, increment, modulus);
-            return cal.getTimeInMillis();
+            nextTime = cal.getTimeInMillis();
+            cal.add(Calendar.HOUR, -1);
+            nextFileTime = cal.getTimeInMillis();
+            return nextTime;
         }
         cal.set(Calendar.MINUTE, currentCal.get(Calendar.MINUTE));
         if (frequency == RolloverFrequency.EVERY_MINUTE) {
             increment(cal, Calendar.MINUTE, increment, modulus);
-            return cal.getTimeInMillis();
+            nextTime = cal.getTimeInMillis();
+            cal.add(Calendar.MINUTE, -1);
+            nextFileTime = cal.getTimeInMillis();
+            return nextTime;
         }
         cal.set(Calendar.SECOND, currentCal.get(Calendar.SECOND));
         if (frequency == RolloverFrequency.EVERY_SECOND) {
             increment(cal, Calendar.SECOND, increment, modulus);
-            return cal.getTimeInMillis();
+            nextTime = cal.getTimeInMillis();
+            cal.add(Calendar.SECOND, -1);
+            nextFileTime = cal.getTimeInMillis();
+            return nextTime;
         }
         increment(cal, Calendar.MILLISECOND, increment, modulus);
-        return cal.getTimeInMillis();
+        nextTime = cal.getTimeInMillis();
+        cal.add(Calendar.MILLISECOND, -1);
+        nextFileTime = cal.getTimeInMillis();
+        return nextTime;
     }
 
     private void increment(Calendar cal, int type, int increment, boolean modulate) {
@@ -131,8 +161,9 @@ public class PatternProcessor {
      * @param buf string buffer to which formatted file name is appended, may not be null.
      * @param obj object to be evaluated in formatting, may not be null.
      */
-    protected final void formatFileName(final StringBuilder buf, final Object obj) {
-        formatFileName(buf, new Date(System.currentTimeMillis()), obj);
+    public final void formatFileName(final StringBuilder buf, final Object obj) {
+        long time = prevFileTime == 0 ? System.currentTimeMillis() : prevFileTime;
+        formatFileName(buf, new Date(time), obj);
     }
 
     /**

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java?rev=1411052&r1=1411051&r2=1411052&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/appender/rolling/RollingFileManager.java Mon Nov 19 03:22:56 2012
@@ -41,13 +41,18 @@ public class RollingFileManager extends 
     private long initialTime;
     private final PatternProcessor processor;
     private final Semaphore semaphore = new Semaphore(1);
+    private final TriggeringPolicy policy;
+    private final RolloverStrategy strategy;
 
     protected RollingFileManager(String fileName, String pattern, OutputStream os, boolean append, long size,
-                                 long time) {
+                                 long time, TriggeringPolicy policy, RolloverStrategy strategy) {
         super(fileName, os, append, false);
         this.size = size;
         this.initialTime = time;
+        this.policy = policy;
+        this.strategy = strategy;
         processor = new PatternProcessor(pattern);
+        policy.initialize(this);
     }
 
     /**
@@ -59,10 +64,11 @@ public class RollingFileManager extends 
      * @return A RollingFileManager.
      */
     public static RollingFileManager getFileManager(String fileName, String pattern, boolean append,
-                                                    boolean bufferedIO) {
+                                                    boolean bufferedIO, TriggeringPolicy policy,
+                                                    RolloverStrategy strategy) {
 
         return (RollingFileManager) getManager(fileName, new FactoryData(pattern, append,
-            bufferedIO), factory);
+            bufferedIO, policy, strategy), factory);
     }
 
     @Override
@@ -90,10 +96,8 @@ public class RollingFileManager extends 
     /**
      * Determine if a rollover should occur.
      * @param event The LogEvent.
-     * @param policy The TriggeringPolicy.
-     * @param strategy The RolloverStrategy.
      */
-    public synchronized void checkRollover(LogEvent event, TriggeringPolicy policy, RolloverStrategy strategy) {
+    public synchronized void checkRollover(LogEvent event) {
         if (policy.isTriggeringEvent(event) && rollover(strategy)) {
             try {
                 size = 0;
@@ -219,6 +223,8 @@ public class RollingFileManager extends 
         private String pattern;
         private boolean append;
         private boolean bufferedIO;
+        private TriggeringPolicy policy;
+        private RolloverStrategy strategy;
 
         /**
          * Create the data for the factory.
@@ -226,10 +232,13 @@ public class RollingFileManager extends 
          * @param append The append flag.
          * @param bufferedIO The bufferedIO flag.
          */
-        public FactoryData(String pattern, boolean append, boolean bufferedIO) {
+        public FactoryData(String pattern, boolean append, boolean bufferedIO, TriggeringPolicy policy,
+                           RolloverStrategy strategy) {
             this.pattern = pattern;
             this.append = append;
             this.bufferedIO = bufferedIO;
+            this.policy = policy;
+            this.strategy = strategy;
         }
     }
 
@@ -265,7 +274,8 @@ public class RollingFileManager extends 
                 if (data.bufferedIO) {
                     os = new BufferedOutputStream(os);
                 }
-                return new RollingFileManager(name, data.pattern, os, data.append, size, time);
+                return new RollingFileManager(name, data.pattern, os, data.append, size, time, data.policy,
+                    data.strategy);
             } catch (FileNotFoundException ex) {
                 LOGGER.error("FileManager (" + name + ") " + ex);
             }

Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/rolling/OnStartupTriggeringPolicyTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/rolling/OnStartupTriggeringPolicyTest.java?rev=1411052&r1=1411051&r2=1411052&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/rolling/OnStartupTriggeringPolicyTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/appender/rolling/OnStartupTriggeringPolicyTest.java Mon Nov 19 03:22:56 2012
@@ -33,10 +33,9 @@ public class OnStartupTriggeringPolicyTe
 
     @Test
     public void testPolicy() {
-        MyRollingManager manager = new MyRollingManager();
-        manager.setFileTime(System.currentTimeMillis() - 36000000);
         OnStartupTriggeringPolicy policy = OnStartupTriggeringPolicy.createPolicy();
-        policy.initialize(manager);
+        MyRollingManager manager = new MyRollingManager(policy, null);
+        manager.setFileTime(System.currentTimeMillis() - 36000000);
         LogEvent event = new Log4jLogEvent(null, null, null, Level.ERROR, new SimpleMessage("Test"), null);
         assertTrue("Expected trigger to succeed", policy.isTriggeringEvent(event));
         assertTrue("Expected trigger not to fire", !policy.isTriggeringEvent(event));
@@ -51,9 +50,9 @@ public class OnStartupTriggeringPolicyTe
 
         private long timestamp;
 
-        public MyRollingManager() {
+        public MyRollingManager(TriggeringPolicy policy, RolloverStrategy strategy) {
             super("testfile", "target/rolling1/test1-%i.log.gz", new ByteArrayOutputStream(),
-                false, 0, System.currentTimeMillis());
+                false, 0, System.currentTimeMillis(), policy, strategy);
         }
 
         public void setFileTime(long timestamp) {

Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1411052&r1=1411051&r2=1411052&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/changes/changes.xml (original)
+++ logging/log4j/log4j2/trunk/src/changes/changes.xml Mon Nov 19 03:22:56 2012
@@ -23,6 +23,10 @@
 
   <body>
     <release version="2.0-beta4" date="TBD" description="Bug fixes and enhancements">
+      <action issue="LOG4J2-116" dev="rgoers" type="fix">
+        File renaming was using the wrong date value. Enhanced DefaultRolloverStrategy to store newest files in
+        highest index as well as lowest.
+      </action>
       <action issue="LOG4J2-115" dev="rgoers" type="fix">
         ThreadContext Map elements with null values are now ignored when constructing a Flume event and in the
         RFC5424 Layout.

Modified: logging/log4j/log4j2/trunk/src/site/xdoc/manual/appenders.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/site/xdoc/manual/appenders.xml?rev=1411052&r1=1411051&r2=1411052&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/site/xdoc/manual/appenders.xml (original)
+++ logging/log4j/log4j2/trunk/src/site/xdoc/manual/appenders.xml Mon Nov 19 03:22:56 2012
@@ -1105,9 +1105,100 @@
                 compression scheme that matches the suffix. The pattern may also contain lookup references that
                 can be resolved at runtime such as is shown in the example below.
               </p>
-              <p>The Default rollover strategy also accepts a minimum value and a maximum value. When a minimim
-                value other than 1 is specified than files with an index lower than that value will not be
-                deleted when the maximum value is exceeded.</p>
+              <p>The default rollover strategy supports two variations for incrementing the counter. The first is
+                the "fixed window" strategy. To illustrate how it works, suppose that the min attribute is set to 1,
+                the max attribute is set to 3, the file name is "foo.log", and the file name pattern is "foo-%i.log".
+              </p>
+
+              <table>
+                <tr>
+                  <th>Number of rollovers</th>
+                  <th>Active output target</th>
+                  <th>Archived log files</th>
+                  <th>Description</th>
+                </tr>
+                <tr>
+                  <td>0</td>
+                  <td>foo.log</td>
+                  <td>-</td>
+                  <td>All logging is going to the initial file.</td>
+                </tr>
+                <tr>
+                  <td>1</td>
+                  <td>foo.log</td>
+                  <td>foo-1.log</td>
+                  <td>During the first rollover foo.log is renamed to foo-1.log. A new foo.log file is created and
+                  starts being written to.</td>
+                </tr>
+                <tr>
+                  <td>2</td>
+                  <td>foo.log</td>
+                  <td>foo-1.log, foo-2.log</td>
+                  <td>During the second rollover foo-1.log is renamed to foo-2.log and foo.log is renamed to
+                    foo-1.log. A new foo.log file is created and starts being written to.</td>
+                </tr>
+                <tr>
+                  <td>3</td>
+                  <td>foo.log</td>
+                  <td>foo-1.log, foo-2.log, foo-3.log</td>
+                  <td>During the third rollover foo-2.log is renamed to foo-3.log, foo-1.log is renamed to foo-2.log and
+                    foo.log is renamed to foo-1.log. A new foo.log file is created and starts being written to.</td>
+                </tr>
+                <tr>
+                  <td>4</td>
+                  <td>foo.log</td>
+                  <td>foo-1.log, foo-2.log, foo-3.log</td>
+                  <td>In the fourth and subsequent rollovers, foo-3.log is deleted, foo-2.log is renamed to foo-3.log,
+                    foo-1.log is renamed to foo-2.log and foo.log is renamed to foo-1.log. A new foo.log file is
+                    created and starts being written to.</td>
+                </tr>
+              </table>
+              <p>By way of contrast, when the the fileIndex attribute is set to "max" but all the other settings
+                are the same the following actions will be performed.
+              </p>
+              <table>
+                <tr>
+                  <th>Number of rollovers</th>
+                  <th>Active output target</th>
+                  <th>Archived log files</th>
+                  <th>Description</th>
+                </tr>
+                <tr>
+                  <td>0</td>
+                  <td>foo.log</td>
+                  <td>-</td>
+                  <td>All logging is going to the initial file.</td>
+                </tr>
+                <tr>
+                  <td>1</td>
+                  <td>foo.log</td>
+                  <td>foo-1.log</td>
+                  <td>During the first rollover foo.log is renamed to foo-1.log. A new foo.log file is created and
+                    starts being written to.</td>
+                </tr>
+                <tr>
+                  <td>2</td>
+                  <td>foo.log</td>
+                  <td>foo-1.log, foo-2.log</td>
+                  <td>During the second rollover foo.log is renamed to foo-2.log. A new foo.log file is created
+                    and starts being written to.</td>
+                </tr>
+                <tr>
+                  <td>3</td>
+                  <td>foo.log</td>
+                  <td>foo-1.log, foo-2.log, foo-3.log</td>
+                  <td>During the third rollover foo.log is renamed to foo-3.log. A new foo.log file is created and
+                    starts being written to.</td>
+                </tr>
+                <tr>
+                  <td>4</td>
+                  <td>foo.log</td>
+                  <td>foo-1.log, foo-2.log, foo-3.log</td>
+                  <td>In the fourth and subsequent rollovers, foo-1.log is deleted, foo-2.log is renamed to foo-1.log,
+                    foo-3.log is renamed to foo-2.log and foo.log is renamed to foo-3.log. A new foo.log file is
+                    created and starts being written to.</td>
+                </tr>
+              </table>
               <table>
                 <tr>
                   <th>Parameter Name</th>
@@ -1115,6 +1206,13 @@
                   <th>Description</th>
                 </tr>
                 <tr>
+                  <td>fileIndex</td>
+                  <td>String</td>
+                  <td>If set to "max" (the default), files with a higher index will be newer than files with a
+                    smaller index. If set to "min", file renaming and the counter will follow the Fixed Window strategy
+                    described above.</td>
+                </tr>
+                <tr>
                   <td>min</td>
                   <td>integer</td>
                   <td>The minimum value of the counter. The default value is 1.</td>
@@ -1127,6 +1225,7 @@
                 </tr>
                 <caption align="top">DefaultRolloverStrategy Parameters</caption>
               </table>
+
           <p>
             Below is a sample configuration that uses a RollingFileAppender with both the time and size based
             triggering policies, will create up to 7 archives on the same day (1-7) that are stored in a directory