Index: RollingFileAppender.cs
===================================================================
--- RollingFileAppender.cs (revision 425395)
+++ RollingFileAppender.cs (working copy)
@@ -477,6 +477,26 @@
set { m_staticLogFileName = value; }
}
+ ///
+ /// Gets or sets a value indicating whether to preserve the file name extension when rolling.
+ ///
+ ///
+ /// true if the file name extension should be preserved.
+ ///
+ ///
+ ///
+ /// By default file.log is rolled to file.log.yyyy-mm-dd or file.log.curSizeRollBackup.
+ /// However, under Windows the new file name will loose any program associations as the
+ /// extension is changed. Optionally file.log can be renamed to file.yyyy-mm-dd.log or
+ /// file.curSizeRollBackup.log to maintain any program associations.
+ ///
+ ///
+ public bool PreserveLogFileNameExtension
+ {
+ get { return m_preserveLogFileNameExtension; }
+ set { m_preserveLogFileNameExtension = value; }
+ }
+
#endregion Public Instance Properties
#region Override implementation of FileAppender
@@ -679,9 +699,15 @@
/// that are similar to the base file name.
///
///
+ ///
///
- private static string GetWildcardPatternForFile(string baseFileName)
+ private static string GetWildcardPatternForFile(string baseFileName, bool preserveLogFileNameExtension)
{
+ if (preserveLogFileNameExtension == true)
+ {
+ string pp = Path.GetFileNameWithoutExtension(baseFileName) + "*" + Path.GetExtension(baseFileName);
+ return (pp);
+ }
return baseFileName + '*';
}
@@ -691,9 +717,10 @@
///
///
///
- private ArrayList GetExistingFiles(string baseFilePath)
+ private ArrayList GetExistingFiles(string baseFilePath)
{
ArrayList alFiles = new ArrayList();
+ string bfn = "";
string directory = null;
@@ -706,25 +733,65 @@
{
string baseFileName = Path.GetFileName(fullPath);
- string[] files = Directory.GetFiles(directory, GetWildcardPatternForFile(baseFileName));
-
- if (files != null)
- {
- for (int i = 0; i < files.Length; i++)
- {
- string curFileName = Path.GetFileName(files[i]);
- if (curFileName.StartsWith(baseFileName))
- {
- alFiles.Add(curFileName);
- }
- }
- }
+ string t = GetWildcardPatternForFile(baseFileName, PreserveLogFileNameExtension);
+ string[] files = Directory.GetFiles(directory, GetWildcardPatternForFile(baseFileName, PreserveLogFileNameExtension));
+
+ if (files != null)
+ {
+ if (PreserveLogFileNameExtension)
+ {
+ bfn = Path.GetFileNameWithoutExtension(baseFileName);
+ }
+ for (int i = 0; i < files.Length; i++)
+ {
+ string curFileName = Path.GetFileName(files[i]);
+ if (PreserveLogFileNameExtension)
+ {
+ string fnext = Path.GetFileNameWithoutExtension(curFileName);
+
+ // if it's a log file we've generated, the name from the directory will either be
+ // the basefilename (with extension)
+ // or will end with a period followed by the file's serial number
+ // followed by the basefilename's extension
+ // the last point is guaranteed by the wild card pattern used to look for files
+
+ if ((fnext==bfn)
+ || (fnext.LastIndexOf(".") >0) && (IsNumber(fnext.Substring(fnext.LastIndexOf(".")+1))))
+ {
+ alFiles.Add(curFileName);
+ }
+ }
+ else
+ {
+ if (curFileName.StartsWith(baseFileName))
+ {
+ alFiles.Add(curFileName);
+ }
+ }
+ }
+ }
}
}
LogLog.Debug("RollingFileAppender: Searched for existing files in ["+directory+"]");
return alFiles;
}
+ // see Justin Rogers comparison of testing for numeric strings http://weblogs.asp.net/justin_rogers/archive/2004/03/29/100982.aspx
+
+ private static bool IsNumber(string testee)
+ {
+ for (int i = 0; i < testee.Length; i++)
+ {
+ if (!char.IsNumber(testee[i]))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
///
/// Initiates a roll over if needed for crossing a date boundary since the last run.
///
@@ -743,7 +810,16 @@
if (!(last.ToString(m_datePattern,System.Globalization.DateTimeFormatInfo.InvariantInfo).Equals(m_now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo))))
{
- m_scheduledFilename = m_baseFileName + last.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
+ m_scheduledFilename = "";
+ if (PreserveLogFileNameExtension)
+ {
+ m_scheduledFilename = Path.GetDirectoryName(m_baseFileName) + "\\" + Path.GetFileNameWithoutExtension(m_baseFileName);
+ }
+ else
+ {
+ m_scheduledFilename = m_baseFileName;
+ }
+ m_scheduledFilename += last.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
LogLog.Debug("RollingFileAppender: Initial roll over to ["+m_scheduledFilename+"]");
RollOverTime(false);
LogLog.Debug("RollingFileAppender: curSizeRollBackups after rollOver at ["+m_curSizeRollBackups+"]");
@@ -808,7 +884,9 @@
///
private void InitializeFromOneFile(string baseFile, string curFileName)
{
- if (! curFileName.StartsWith(baseFile) )
+ int seqNoLength = 0; // length of the logfile sequence # in the filename (including delimiting period)
+ if (!(curFileName.StartsWith(baseFile)
+ || (PreserveLogFileNameExtension && curFileName.StartsWith(Path.GetFileNameWithoutExtension(baseFile))) ))
{
// This is not a log file, so ignore
return;
@@ -828,10 +906,23 @@
if (m_staticLogFileName)
{
- int endLength = curFileName.Length - index;
- if (baseFile.Length + endLength != curFileName.Length)
+ seqNoLength = curFileName.Length - index; // length of the logfile sequence # in the filename
+ // (sequence # normally last part of the filename)
+ if (PreserveLogFileNameExtension) // if we are preserving file extension, sequence #
+ // is the second last part of the filename
+ { // (between the second last "." and the last one)
+ int lastPeriodIndex = index;
+ int secondLastPeriodIndex = curFileName.Substring(0, index - 1).LastIndexOf(".");
+ string seqNo = curFileName.Substring(secondLastPeriodIndex, lastPeriodIndex - secondLastPeriodIndex);
+ seqNoLength = lastPeriodIndex - secondLastPeriodIndex;
+ index = curFileName.Substring(0, index - 1).LastIndexOf(".");
+ }
+ // if the file is in the current log set, it's length must be
+ // the length of the basefilename + the length of the sequence numbber
+ if ((baseFile.Length + seqNoLength != curFileName.Length) )
{
- // file is probably scheduledFilename + .x so I don't care
+ // filename must have more than the base filename and sequence number
+ // likely a date. In any event not part of the current log set
return;
}
}
@@ -850,7 +941,7 @@
{
// Bump the counter up to the highest count seen so far
int backup;
- if (SystemInfo.TryParse(curFileName.Substring(index + 1), out backup))
+ if (SystemInfo.TryParse(curFileName.Substring(index + 1, seqNoLength - 1), out backup))
{
if (backup > m_curSizeRollBackups)
{
@@ -1032,6 +1123,19 @@
#region Roll File
+ private string CombinePath(string path1, string path2)
+ {
+ string extension = Path.GetExtension(path1);
+ if (m_preserveLogFileNameExtension && extension.Length > 0)
+ {
+ return Path.GetDirectoryName(path1) + "\\" + Path.GetFileNameWithoutExtension(path1) + path2 + extension;
+ }
+ else
+ {
+ return path1 + path2;
+ }
+ }
+
///
/// Rollover the file(s) to date/time tagged file(s).
///
@@ -1045,47 +1149,64 @@
///
protected void RollOverTime(bool fileIsOpen)
{
- if (m_staticLogFileName)
- {
- // Compute filename, but only if datePattern is specified
- if (m_datePattern == null)
- {
- ErrorHandler.Error("Missing DatePattern option in rollOver().");
- return;
- }
-
- //is the new file name equivalent to the 'current' one
- //something has gone wrong if we hit this -- we should only
- //roll over if the new file will be different from the old
- string dateFormat = m_now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
- if (m_scheduledFilename.Equals(File + dateFormat))
- {
- ErrorHandler.Error("Compare " + m_scheduledFilename + " : " + File + dateFormat);
- return;
- }
-
- if (fileIsOpen)
- {
- // close current file, and rename it to datedFilename
- this.CloseFile();
- }
-
- //we may have to roll over a large number of backups here
- for (int i = 1; i <= m_curSizeRollBackups; i++)
- {
- string from = File + '.' + i;
- string to = m_scheduledFilename + '.' + i;
- RollFile(from, to);
- }
-
- RollFile(File, m_scheduledFilename);
- }
+ if (m_staticLogFileName)
+ {
+ // Compute filename, but only if datePattern is specified
+ if (m_datePattern == null)
+ {
+ ErrorHandler.Error("Missing DatePattern option in rollOver().");
+ return;
+ }
+
+ //is the new file name equivalent to the 'current' one
+ //something has gone wrong if we hit this -- we should only
+ //roll over if the new file will be different from the old
+ string dateFormat = m_now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
+ if (m_scheduledFilename.Equals(CombinePath(File, dateFormat)))
+ {
+ ErrorHandler.Error("Compare " + m_scheduledFilename + " : " + CombinePath(File, dateFormat));
+ return;
+ }
+
+ if (fileIsOpen)
+ {
+ // close current file, and rename it to datedFilename
+ this.CloseFile();
+ }
+
+ int maxSerial = 0; // keep trakc of the largest file used on the date being rolled
+
+ // roll over the archived files
+ //we may have to roll over a large number of backups here
+ for (int i = 1; i <= m_curSizeRollBackups; i++)
+ {
+ string from = CombinePath(File, "." + i);
+ string to = CombinePath(m_scheduledFilename + (PreserveLogFileNameExtension? Path.GetExtension(File): ""), "." + i);
+
+ if (FileExists(from))
+ {
+ RollFile(from, to);
+ maxSerial = i;
+ }
+ }
+ // roll the newest one
+ if (PreserveLogFileNameExtension)
+ {
+ // the Serial for the last file on a date/time is one more than
+ // the largest used in the ones we've already rolled
+ RollFile(File, CombinePath(m_scheduledFilename + Path.GetExtension(File), "." + (maxSerial + 1)));
+ }
+ else
+ {
+ RollFile(File, m_scheduledFilename);
+ }
+ }
//We've cleared out the old date and are ready for the new
m_curSizeRollBackups = 0;
//new scheduled name
- m_scheduledFilename = File + m_now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo);
+ m_scheduledFilename = CombinePath(File, m_now.ToString(m_datePattern, System.Globalization.DateTimeFormatInfo.InvariantInfo));
if (fileIsOpen)
{
@@ -1294,20 +1415,20 @@
// Delete the oldest file, to keep Windows happy.
if (m_curSizeRollBackups == m_maxSizeRollBackups)
{
- DeleteFile(baseFileName + '.' + m_maxSizeRollBackups);
+ DeleteFile(CombinePath(baseFileName , "." + m_maxSizeRollBackups));
m_curSizeRollBackups--;
}
// Map {(maxBackupIndex - 1), ..., 2, 1} to {maxBackupIndex, ..., 3, 2}
for (int i = m_curSizeRollBackups; i >= 1; i--)
{
- RollFile((baseFileName + "." + i), (baseFileName + '.' + (i + 1)));
+ RollFile((CombinePath(baseFileName, "." + i)), (CombinePath(baseFileName, "." + (i + 1))));
}
m_curSizeRollBackups++;
// Rename fileName to fileName.1
- RollFile(baseFileName, baseFileName + ".1");
+ RollFile(baseFileName, CombinePath(baseFileName, ".1"));
}
else
{
@@ -1343,7 +1464,7 @@
if (m_staticLogFileName)
{
m_curSizeRollBackups++;
- RollFile(baseFileName, baseFileName + '.' + m_curSizeRollBackups);
+ RollFile(baseFileName, CombinePath(baseFileName, "." + m_curSizeRollBackups));
}
}
}
@@ -1515,6 +1636,11 @@
private bool m_staticLogFileName = true;
///
+ /// Value indicating whether to preserve the file name extension when rolling.
+ ///
+ private bool m_preserveLogFileNameExtension = false;
+
+ ///
/// FileName provided in configuration. Used for rolling properly
///
private string m_baseFileName;