Index: src/Appender/RollingFileAppender.cs
===================================================================
--- src/Appender/RollingFileAppender.cs (revision 883140)
+++ src/Appender/RollingFileAppender.cs (working copy)
@@ -318,8 +318,34 @@
get { return m_maxSizeRollBackups; }
set { m_maxSizeRollBackups = value; }
}
-
+
///
+ /// Gets or sets the maximum number of backup files that are kept before
+ /// the oldest is erased.
+ ///
+ ///
+ /// The maximum number of backup files that are kept before the oldest is
+ /// erased.
+ ///
+ ///
+ ///
+ /// If set to zero, then there will be no backup files and the log file
+ /// will be truncated when it reaches .
+ ///
+ ///
+ /// If a negative number is supplied then no deletions will be made. Note
+ /// that this could result in very slow performance as a large number of
+ /// files are rolled over unless is used.
+ ///
+ /// Added by Joshua Masek of RoviSys - see http://issues.apache.org/jira/browse/LOG4NET-27
+ ///
+ public int MaxDateRollBackups
+ {
+ get { return m_maxDateRollBackups; }
+ set { m_maxDateRollBackups = value; }
+ }
+
+ ///
/// Gets or sets the maximum size that the output file is allowed to reach
/// before being rolled over to backup files.
///
@@ -1167,7 +1193,93 @@
RollFile(File, m_scheduledFilename);
}
-
+
+ //delete old backups
+ if (m_rollDate && m_maxDateRollBackups != 0)
+ {
+ FileInfo fi = new FileInfo(m_baseFileName);
+ DateTime currentDate = m_now;
+ string dirName = fi.DirectoryName + Path.DirectorySeparatorChar;
+ int tempMaxDateRollBackups = m_maxDateRollBackups;
+ if (tempMaxDateRollBackups < 0) tempMaxDateRollBackups = 0;
+ int tempMaxSizeRollBackups = m_maxSizeRollBackups;
+ if (tempMaxSizeRollBackups < 0) tempMaxSizeRollBackups = 0;
+
+ // Build all valid file names
+ string[] validFilesName = new string[(tempMaxDateRollBackups + 1) * (tempMaxSizeRollBackups + 1)];
+ for (int iDate = 0; iDate <= tempMaxDateRollBackups; iDate++)
+ {
+ string loopFileNameBase = null;
+ if ((iDate == 0) && m_staticLogFileName)
+ {
+ loopFileNameBase = fi.Name;
+ }
+ else
+ {
+ if (iDate > 0)
+ {
+ currentDate = PreviousCheckDate(currentDate, m_rollPoint);
+ }
+ string loopDateFormat = currentDate.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
+ loopFileNameBase = fi.Name + loopDateFormat;
+ }
+
+ for (int iSize = 0; iSize <= tempMaxSizeRollBackups; iSize++)
+ {
+ int iFileName = (iDate * (tempMaxSizeRollBackups + 1) + iSize);
+ if (iSize == 0)
+ {
+ validFilesName[iFileName] = loopFileNameBase;
+ }
+ else
+ {
+ validFilesName[iFileName] = loopFileNameBase + "." + iSize;
+ }
+ }
+ }
+
+ // Check if existing files are in valid file names list, also delete it
+ foreach (string current in GetExistingFiles(m_baseFileName))
+ {
+ bool valid = false;
+ foreach (string validFileName in validFilesName)
+ {
+ if (validFileName.Equals(current))
+ {
+ valid = true;
+ break;
+ }
+ }
+ if (valid == false)
+ {
+ string filenameToDelete = dirName + current;
+ DateTime fileLastModified = System.IO.File.GetLastWriteTime(filenameToDelete);
+ DateTime previousCheckDateAfterFileModified = PreviousCheckDate(fileLastModified, m_rollPoint);
+ string formattedCurrent = fileLastModified.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
+ string formattedNext = previousCheckDateAfterFileModified.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
+ int lastCharIndexToUse = current.Length - 1;
+ for (int charLoop = current.Length - 1; charLoop >= 0; charLoop--)
+ {
+ byte dummyByte = 0;
+ if ((charLoop < (current.Length - 1)) && (current.Substring(charLoop, 1) == "."))
+ {
+ lastCharIndexToUse = charLoop - 1;
+ break;
+ }
+ else if (!byte.TryParse(current.Substring(charLoop, 1), out dummyByte))
+ {
+ break;
+ }
+ }
+ string currentBase = current.Substring(0, lastCharIndexToUse + 1);
+ if (currentBase.Equals(fi.Name) || currentBase.Equals(fi.Name + formattedCurrent) || currentBase.Equals(fi.Name + formattedNext))
+ {
+ DeleteFile(filenameToDelete);
+ }
+ }
+ }
+ }
+
//We've cleared out the old date and are ready for the new
m_curSizeRollBackups = 0;
@@ -1180,8 +1292,85 @@
SafeOpenFile(m_baseFileName, false);
}
}
-
+
///
+ /// Roll on to the previous interval before the date passed
+ ///
+ /// the current date
+ /// the type of roll point we are working with
+ /// the previous roll point an interval before the currentDateTime date
+ ///
+ /// Advances the date to the previous roll point before the
+ /// currentDateTime date passed to the method.
+ ///
+ protected DateTime PreviousCheckDate(DateTime currentDateTime, RollPoint rollPoint)
+ {
+ // Local variable to work on (this does not look very efficient)
+ DateTime current = currentDateTime;
+
+ // Do different things depending on what the type of roll point we are going for is
+ switch (rollPoint)
+ {
+ case RollPoint.TopOfMinute:
+ current = current.AddMilliseconds(-current.Millisecond);
+ current = current.AddSeconds(-current.Second);
+ current = current.AddMinutes(-1);
+ break;
+
+ case RollPoint.TopOfHour:
+ current = current.AddMilliseconds(-current.Millisecond);
+ current = current.AddSeconds(-current.Second);
+ current = current.AddMinutes(-current.Minute);
+ current = current.AddHours(-1);
+ break;
+
+ case RollPoint.HalfDay:
+ current = current.AddMilliseconds(-current.Millisecond);
+ current = current.AddSeconds(-current.Second);
+ current = current.AddMinutes(-current.Minute);
+
+ if (current.Hour < 12)
+ {
+ current = current.AddHours(-current.Hour - 12);
+ }
+ else
+ {
+ current = current.AddHours(-current.Hour);
+ }
+ break;
+
+ case RollPoint.TopOfDay:
+ current = current.AddMilliseconds(-current.Millisecond);
+ current = current.AddSeconds(-current.Second);
+ current = current.AddMinutes(-current.Minute);
+ current = current.AddHours(-current.Hour);
+ current = current.AddDays(-1);
+ break;
+
+ case RollPoint.TopOfWeek:
+ current = current.AddMilliseconds(-current.Millisecond);
+ current = current.AddSeconds(-current.Second);
+ current = current.AddMinutes(-current.Minute);
+ current = current.AddHours(-current.Hour);
+ current = current.AddDays(-(int)current.DayOfWeek - 7);
+ break;
+
+ case RollPoint.TopOfMonth:
+ current = current.AddMilliseconds(-current.Millisecond);
+ current = current.AddSeconds(-current.Second);
+ current = current.AddMinutes(-current.Minute);
+ current = current.AddHours(-current.Hour);
+ current = current.AddDays(-current.Day);
+ // To be in previous month
+ current = current.AddDays(-1);
+ current = current.AddDays(-DateTime.DaysInMonth(current.Year, current.Month) + 1);
+
+ break;
+ }
+ return current;
+ }
+
+ ///
/// Renames file to file .
///
/// Name of existing file to roll.
@@ -1572,6 +1761,12 @@
private int m_maxSizeRollBackups = 0;
///
+ /// There is zero backup files by default
+ ///
+ /// Added by Joshua Masek of RoviSys - see http://issues.apache.org/jira/browse/LOG4NET-27
+ private int m_maxDateRollBackups = 0;
+
+ ///
/// How many sized based backups have been made so far
///
private int m_curSizeRollBackups = 0;