[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ülcü
- *
- * */
+ *
+ */
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. /<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. /<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. /<br/>%d{yyyy-MM-dd_HH-mm}.log</em>
</td>
More information about the logback-dev
mailing list