[logback-dev] svn commit: r1820 - in logback/trunk: logback-core/src/main/java/ch/qos/logback/core/rolling logback-core/src/main/java/ch/qos/logback/core/rolling/helper logback-core/src/test/java/ch/qos/logback/core/rolling logback-core/src/test/java/ch/qos/logback/core/rolling/helper logback-site/src/site/pages/manual

noreply.ceki at qos.ch noreply.ceki at qos.ch
Tue Oct 7 15:23:40 CEST 2008


Author: ceki
Date: Tue Oct  7 15:23:33 2008
New Revision: 1820

Added:
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/PeriodicityType.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/TimeBasedCleaner.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithCleanTest.java
Modified:
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedRollingPolicy.java
   logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/RollingCalendar.java
   logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/RollingCalendarTest.java
   logback/trunk/logback-site/src/site/pages/manual/appenders.html

Log:
Fixing LBCORE-11

- Allow TimeBasedRollingPolicy to delete old files if asked by the user.
- PeriodicityType are now listed in an enum.


Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedRollingPolicy.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedRollingPolicy.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedRollingPolicy.java	Tue Oct  7 15:23:33 2008
@@ -13,6 +13,8 @@
 import java.util.Date;
 import java.util.concurrent.Future;
 
+import sun.misc.Cleaner;
+
 import ch.qos.logback.core.rolling.helper.AsynchronousCompressor;
 import ch.qos.logback.core.rolling.helper.Compressor;
 import ch.qos.logback.core.rolling.helper.CompressionMode;
@@ -20,6 +22,7 @@
 import ch.qos.logback.core.rolling.helper.FileNamePattern;
 import ch.qos.logback.core.rolling.helper.RenameUtil;
 import ch.qos.logback.core.rolling.helper.RollingCalendar;
+import ch.qos.logback.core.rolling.helper.TimeBasedCleaner;
 
 /**
  * <code>TimeBasedRollingPolicy</code> is both easy to configure and quite
@@ -48,6 +51,8 @@
   String lastGeneratedFileName;
   Future<?> future;
 
+  TimeBasedCleaner tbCleaner;
+  
   public void setCurrentTime(long timeInMillis) {
     currentTime = timeInMillis;
     isTimeForced = true;
@@ -109,8 +114,9 @@
 
     // currentTime = System.currentTimeMillis();
     lastCheck.setTime(getCurrentTime());
-    nextCheck = rc.getNextCheckMillis(lastCheck);
+    nextCheck = rc.getNextTriggeringMillis(lastCheck);
 
+    tbCleaner = new TimeBasedCleaner(fileNamePattern, rc, 5);
     // Date nc = new Date();
     // nc.setTime(nextCheck);
   }
@@ -130,6 +136,8 @@
       }
     }
 
+    tbCleaner.clean(new Date(getCurrentTime()));
+    
     // let's update the parent active file name
     setParentFileName(getNewActiveFileName());
 
@@ -172,13 +180,13 @@
    * file equals the file name for the current period as computed by the
    * <b>FileNamePattern</b> option.
    * 
-   * The RollingPolicy must know wether it is responsible for changing the name
+   * <p>The RollingPolicy must know wether it is responsible for changing the name
    * of the active file or not. If the active file name is set by the user via
    * the configuration file, then the RollingPolicy must let it like it is. If
    * the user does not specify an active file name, then the RollingPolicy
    * generates one.
    * 
-   * To be sure that the file name used by the parent class has been generated
+   * <p>To be sure that the file name used by the parent class has been generated
    * by the RollingPolicy and not specified by the user, we keep track of the
    * last generated name object and compare its reference to the parent file
    * name. If they match, then the RollingPolicy knows it's responsible for the
@@ -210,7 +218,7 @@
       // addInfo("elapsedPeriodsFileName set to "+elapsedPeriodsFileName);
 
       lastCheck.setTime(time);
-      nextCheck = rc.getNextCheckMillis(lastCheck);
+      nextCheck = rc.getNextTriggeringMillis(lastCheck);
 
       Date x = new Date();
       x.setTime(nextCheck);

Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/PeriodicityType.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/PeriodicityType.java	Tue Oct  7 15:23:33 2008
@@ -0,0 +1,16 @@
+package ch.qos.logback.core.rolling.helper;
+
+public enum PeriodicityType {
+
+  ERRONEOUS, TOP_OF_SECOND, TOP_OF_MINUTE, TOP_OF_HOUR, HALF_DAY, TOP_OF_DAY, TOP_OF_WEEK, TOP_OF_MONTH;
+
+  // The followed list is assued to be in 
+  static PeriodicityType[] VALID_ORDERED_LIST = new PeriodicityType[] {
+      PeriodicityType.TOP_OF_SECOND, 
+      PeriodicityType.TOP_OF_MINUTE,
+      PeriodicityType.TOP_OF_HOUR, 
+      PeriodicityType.TOP_OF_DAY, 
+      PeriodicityType.TOP_OF_WEEK,
+      PeriodicityType.TOP_OF_MONTH };
+
+}

Modified: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/RollingCalendar.java
==============================================================================
--- logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/RollingCalendar.java	(original)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/RollingCalendar.java	Tue Oct  7 15:23:33 2008
@@ -19,36 +19,23 @@
 
 import ch.qos.logback.core.spi.ContextAwareBase;
 
-
-
 /**
- * RollingCalendar is a helper class to 
- * {@link ch.qos.logback.core.rolling.TimeBasedRollingPolicy } 
- * or similar timed-based rolling policies. Given a periodicity type and the 
- * current time, it computes the start of the next interval.
- *
+ * RollingCalendar is a helper class to
+ * {@link ch.qos.logback.core.rolling.TimeBasedRollingPolicy } or similar
+ * timed-based rolling policies. Given a periodicity type and the current time,
+ * it computes the start of the next interval (i.e. the triggering date).
+ * 
  * @author Ceki G&uuml;lc&uuml;
- *
- * */
+ * 
+ */
 public class RollingCalendar extends GregorianCalendar {
 
   private static final long serialVersionUID = -5937537740925066161L;
 
-
   // The gmtTimeZone is used only in computeCheckPeriod() method.
   static final TimeZone GMT_TIMEZONE = TimeZone.getTimeZone("GMT");
 
-  // The code assumes that the following constants are in a increasing
-  // sequence.
-  public static final int TOP_OF_TROUBLE = -1;
-  public static final int TOP_OF_SECOND = 0;
-  public static final int TOP_OF_MINUTE = 1;
-  public static final int TOP_OF_HOUR = 2;
-  public static final int HALF_DAY = 3;
-  public static final int TOP_OF_DAY = 4;
-  public static final int TOP_OF_WEEK = 5;
-  public static final int TOP_OF_MONTH = 6;
-  int type = TOP_OF_TROUBLE;
+  PeriodicityType type = PeriodicityType.ERRONEOUS;
 
   public RollingCalendar() {
     super();
@@ -59,15 +46,15 @@
   }
 
   public void init(String datePattern) {
-    type = computeTriggeringPeriod(datePattern);
+    type = computePeriodicity(datePattern);
   }
 
-  private void setType(int type) {
+  private void setType(PeriodicityType type) {
     this.type = type;
   }
 
-  public long getNextCheckMillis(Date now) {
-    return getNextCheckDate(now).getTime();
+  public long getNextTriggeringMillis(Date now) {
+    return getNextTriggeringDate(now).getTime();
   }
 
   // This method computes the roll over period by looping over the
@@ -78,32 +65,32 @@
   // formatting is done in GMT and not local format because the test
   // logic is based on comparisons relative to 1970-01-01 00:00:00
   // GMT (the epoch).
-  public int computeTriggeringPeriod(String datePattern) {
-    RollingCalendar rollingCalendar =
-      new RollingCalendar(GMT_TIMEZONE, Locale.getDefault());
+  public PeriodicityType computePeriodicity(String datePattern) {
+    RollingCalendar rollingCalendar = new RollingCalendar(GMT_TIMEZONE, Locale
+        .getDefault());
 
     // set sate to 1970-01-01 00:00:00 GMT
     Date epoch = new Date(0);
 
     if (datePattern != null) {
-      for (int i = TOP_OF_SECOND; i <= TOP_OF_MONTH; i++) {
+      for (PeriodicityType i : PeriodicityType.VALID_ORDERED_LIST) {
         SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
-        simpleDateFormat.setTimeZone(GMT_TIMEZONE); // do all date formatting in GMT
+        simpleDateFormat.setTimeZone(GMT_TIMEZONE); // all date formatting done in GMT
 
         String r0 = simpleDateFormat.format(epoch);
         rollingCalendar.setType(i);
 
-        Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));
+        Date next = new Date(rollingCalendar.getNextTriggeringMillis(epoch));
         String r1 = simpleDateFormat.format(next);
 
-        //System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1);
+        // System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1);
         if ((r0 != null) && (r1 != null) && !r0.equals(r1)) {
           return i;
         }
       }
     }
-
-    return TOP_OF_TROUBLE; // Deliberately head for trouble...
+    // we failed
+    return PeriodicityType.ERRONEOUS; 
   }
 
   public void printPeriodicity(ContextAwareBase cab) {
@@ -148,20 +135,20 @@
     }
   }
 
-  public Date getNextCheckDate(Date now) {
+  public Date getRelativeDate(Date now, int periods) {
     this.setTime(now);
 
     switch (type) {
     case TOP_OF_SECOND:
       this.set(Calendar.MILLISECOND, 0);
-      this.add(Calendar.SECOND, 1);
+      this.add(Calendar.SECOND, periods);
 
       break;
 
     case TOP_OF_MINUTE:
       this.set(Calendar.SECOND, 0);
       this.set(Calendar.MILLISECOND, 0);
-      this.add(Calendar.MINUTE, 1);
+      this.add(Calendar.MINUTE, periods);
 
       break;
 
@@ -169,23 +156,7 @@
       this.set(Calendar.MINUTE, 0);
       this.set(Calendar.SECOND, 0);
       this.set(Calendar.MILLISECOND, 0);
-      this.add(Calendar.HOUR_OF_DAY, 1);
-
-      break;
-
-    case HALF_DAY:
-      this.set(Calendar.MINUTE, 0);
-      this.set(Calendar.SECOND, 0);
-      this.set(Calendar.MILLISECOND, 0);
-
-      int hour = get(Calendar.HOUR_OF_DAY);
-
-      if (hour < 12) {
-        this.set(Calendar.HOUR_OF_DAY, 12);
-      } else {
-        this.set(Calendar.HOUR_OF_DAY, 0);
-        this.add(Calendar.DAY_OF_MONTH, 1);
-      }
+      this.add(Calendar.HOUR_OF_DAY, periods);
 
       break;
 
@@ -194,7 +165,7 @@
       this.set(Calendar.MINUTE, 0);
       this.set(Calendar.SECOND, 0);
       this.set(Calendar.MILLISECOND, 0);
-      this.add(Calendar.DATE, 1);
+      this.add(Calendar.DATE, periods);
 
       break;
 
@@ -204,7 +175,7 @@
       this.set(Calendar.MINUTE, 0);
       this.set(Calendar.SECOND, 0);
       this.set(Calendar.MILLISECOND, 0);
-      this.add(Calendar.WEEK_OF_YEAR, 1);
+      this.add(Calendar.WEEK_OF_YEAR, periods);
 
       break;
 
@@ -214,7 +185,7 @@
       this.set(Calendar.MINUTE, 0);
       this.set(Calendar.SECOND, 0);
       this.set(Calendar.MILLISECOND, 0);
-      this.add(Calendar.MONTH, 1);
+      this.add(Calendar.MONTH, periods);
 
       break;
 
@@ -224,4 +195,8 @@
 
     return getTime();
   }
+  
+  public Date getNextTriggeringDate(Date now) {
+    return getRelativeDate(now, 1);
+  }
 }

Added: logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/TimeBasedCleaner.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/main/java/ch/qos/logback/core/rolling/helper/TimeBasedCleaner.java	Tue Oct  7 15:23:33 2008
@@ -0,0 +1,32 @@
+package ch.qos.logback.core.rolling.helper;
+
+import java.io.File;
+import java.util.Date;
+
+public class TimeBasedCleaner {
+
+  FileNamePattern fileNamePattern;
+  RollingCalendar rc;
+  int numberOfPeriods;
+
+  public TimeBasedCleaner(FileNamePattern fileNamePattern, RollingCalendar rc,
+      int numberOfPeriods) {
+    this.fileNamePattern = fileNamePattern;
+    this.rc = rc;
+    //
+    this.numberOfPeriods = -numberOfPeriods -1;
+  }
+
+  public void clean(Date now) {
+    Date date2delete = rc.getRelativeDate(now, numberOfPeriods);
+
+    String filename = fileNamePattern.convertDate(date2delete);
+
+    File file2Delete = new File(filename);
+
+    if (file2Delete.exists() && file2Delete.isFile()) {
+      file2Delete.delete();
+    }
+  }
+
+}

Added: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithCleanTest.java
==============================================================================
--- (empty file)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/TimeBasedRollingWithCleanTest.java	Tue Oct  7 15:23:33 2008
@@ -0,0 +1,61 @@
+package ch.qos.logback.core.rolling;
+
+
+
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import ch.qos.logback.core.Context;
+import ch.qos.logback.core.ContextBase;
+import ch.qos.logback.core.layout.EchoLayout;
+import ch.qos.logback.core.util.Constants;
+
+public class TimeBasedRollingWithCleanTest {
+
+  Context context = new ContextBase();
+  EchoLayout<Object> layout = new EchoLayout<Object>();
+  
+  static final String DATE_PATTERN = "yyyy-MM-dd_HH_mm_ss";
+  
+  @Before
+  public void setUp() throws Exception {
+    context.setName("test");
+  }
+
+  @After
+  public void tearDown() throws Exception {
+  }
+
+  
+  @Test
+  public void smoke() {
+    long currentTime = System.currentTimeMillis();
+    
+    RollingFileAppender<Object> rfa = new RollingFileAppender<Object>();
+    rfa.setContext(context);
+    rfa.setLayout(layout);
+    rfa.setFile(Constants.OUTPUT_DIR_PREFIX + "clean.txt");
+    TimeBasedRollingPolicy tbrp = new TimeBasedRollingPolicy();
+    tbrp.setContext(context);
+    tbrp.setFileNamePattern(Constants.OUTPUT_DIR_PREFIX + "clean-%d{"
+        + DATE_PATTERN + "}.txt");
+    tbrp.setParent(rfa);
+    tbrp.setCurrentTime(currentTime);
+    tbrp.start();
+    rfa.setRollingPolicy(tbrp);
+    rfa.start();
+   
+    for (int i = 0; i < 10; i++) {
+      rfa.doAppend("Hello---" + i);
+      tbrp.setCurrentTime(addTime(tbrp.getCurrentTime(), 500));      
+    }
+   
+  }
+  
+  static long addTime(long currentTime, long timeToWait) {
+    return currentTime + timeToWait;
+  }
+
+}

Modified: logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/RollingCalendarTest.java
==============================================================================
--- logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/RollingCalendarTest.java	(original)
+++ logback/trunk/logback-core/src/test/java/ch/qos/logback/core/rolling/helper/RollingCalendarTest.java	Tue Oct  7 15:23:33 2008
@@ -9,7 +9,8 @@
  */
 package ch.qos.logback.core.rolling.helper;
 
-import ch.qos.logback.core.rolling.helper.RollingCalendar;
+import java.util.Date;
+
 import junit.framework.TestCase;
 
 public class RollingCalendarTest extends TestCase {
@@ -26,37 +27,65 @@
     super.tearDown();
   }
 
-  public void test() {
+  public void testPeriodicity() {
     {
       RollingCalendar rc = new RollingCalendar();
-      assertEquals(RollingCalendar.TOP_OF_SECOND, rc
-          .computeTriggeringPeriod("yyyy-MM-dd_HH_mm_ss"));
+      assertEquals(PeriodicityType.TOP_OF_SECOND, rc
+          .computePeriodicity("yyyy-MM-dd_HH_mm_ss"));
     }
 
     {
       RollingCalendar rc = new RollingCalendar();
-      assertEquals(RollingCalendar.TOP_OF_MINUTE, rc
-          .computeTriggeringPeriod("yyyy-MM-dd_HH_mm"));
+      assertEquals(PeriodicityType.TOP_OF_MINUTE, rc
+          .computePeriodicity("yyyy-MM-dd_HH_mm"));
     }
-    
+
     {
       RollingCalendar rc = new RollingCalendar();
-      assertEquals(RollingCalendar.TOP_OF_HOUR, rc
-          .computeTriggeringPeriod("yyyy-MM-dd_HH"));
+      assertEquals(PeriodicityType.TOP_OF_HOUR, rc
+          .computePeriodicity("yyyy-MM-dd_HH"));
     }
-    
+
     {
       RollingCalendar rc = new RollingCalendar();
-      assertEquals(RollingCalendar.TOP_OF_DAY, rc
-          .computeTriggeringPeriod("yyyy-MM-dd"));
+      assertEquals(PeriodicityType.TOP_OF_DAY, rc
+          .computePeriodicity("yyyy-MM-dd"));
     }
-    
+
     {
       RollingCalendar rc = new RollingCalendar();
-      assertEquals(RollingCalendar.TOP_OF_MONTH, rc
-          .computeTriggeringPeriod("yyyy-MM"));
+      assertEquals(PeriodicityType.TOP_OF_MONTH, rc
+          .computePeriodicity("yyyy-MM"));
     }
-    
   }
 
+  public void testVaryingNumberOfHourlyPeriods() {
+    RollingCalendar rc = new RollingCalendar();
+    rc.init("yyyy-MM-dd_HH");
+    long MILLIS_IN_HOUR = 3600*1000;
+
+    for (int p = 100; p > -100; p--) {
+      long now = 1223325293589L;  // Mon Oct 06 22:34:53 CEST 2008
+      Date result = rc.getRelativeDate(new Date(now), p);
+      long expected = now - (now % (MILLIS_IN_HOUR)) + p * MILLIS_IN_HOUR;
+      assertEquals(expected, result.getTime());
+    }
+  }
+
+  public void testVaryingNumberOfDailyPeriods() {
+    RollingCalendar rc = new RollingCalendar();
+    rc.init("yyyy-MM-dd");
+    final long MILLIS_IN_DAY = 24*3600*1000;
+    
+    for (int p = 20; p > -100; p--) {
+      long now = 1223325293589L;  // Mon Oct 06 22:34:53 CEST 2008
+      Date nowDate = new Date(now);
+      Date result = rc.getRelativeDate(nowDate, p);
+      long offset = rc.getTimeZone().getRawOffset()+rc.getTimeZone().getDSTSavings();
+    
+      long origin = now - (now % (MILLIS_IN_DAY)) - offset;      
+      long expected = origin + p * MILLIS_IN_DAY;
+      assertEquals("p="+p, expected, result.getTime());
+    }
+  }
 }

Modified: logback/trunk/logback-site/src/site/pages/manual/appenders.html
==============================================================================
--- logback/trunk/logback-site/src/site/pages/manual/appenders.html	(original)
+++ logback/trunk/logback-site/src/site/pages/manual/appenders.html	Tue Oct  7 15:23:33 2008
@@ -925,21 +925,9 @@
 			<em>/wombat/foo.2006-24.log</em> until it is rolled over at the
 			beginning of the next week.
 			</td>
-		</tr>
+		</tr>	
 		<tr class="a">
 			<td class="small">
-				<em>/wombat/foo.  &nbsp;&nbsp; /<br/>%d{yyyy-MM-dd-a}.log</em>
-			</td>
-			<td>Rollover at midnight and midday of each day.</td>
-
-			<td>During the first 12 hours of November 3rd, 2006, the logging
-			will be output to <em>/wombat/foo.2006-11-03-AM.log</em>.  After
-			noon, and until midnight, the logging will be output to
-			<em>/wombat/foo.2006-11-03-PM.log</em>.
-			</td>
-		</tr>
-		<tr class="b">
-			<td class="small">
 				<em>/wombat/foo.  &nbsp;&nbsp;/<br/>%d{yyyy-MM-dd_HH}.log</em>
 			</td>
 			<td>Rollover at the top of each hour.</td>
@@ -950,7 +938,7 @@
 			<em>/wombat/foo.2006-11-03_12.log</em>.
 			</td>
 		</tr>
-		<tr class="a">
+		<tr class="b">
 			<td class="small">
 				<em>/wombat/foo. &nbsp;&nbsp; /<br/>%d{yyyy-MM-dd_HH-mm}.log</em>
 			</td>


More information about the logback-dev mailing list