Doug, These updates should cover all the same points from you patch, but I did a few things differently so you may want to check to make sure that I haven't missed out anything.
It's probably easier to see the changes using the viewcvs diffs than reading the changelog diffs: http://cvs.apache.org/viewcvs.cgi/logging-log4net/src/Appender/ Cheers, Nicko > -----Original Message----- > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] > Sent: 18 September 2004 17:34 > To: [EMAIL PROTECTED] > Subject: cvs commit: logging-log4net/src/Appender > FileAppender.cs RollingFileAppender.cs TextWriterAppender.cs > > nicko 2004/09/18 09:34:16 > > Modified: src/Appender FileAppender.cs RollingFileAppender.cs > TextWriterAppender.cs > Log: > Added Doug de la Torre's updates to make the FileAppender > and RollingFileAppender more robust. > The TextWriterAppender.PrepareWriter method is called for > each message logged if the Writer has not been set. > FileAppender uses PrepareWriter to attempt to open the file > for each message rather than just once at configuration. Once > the file has been opened a write lock is held. > RollingFileAppender moves files before deleting them as > this reduces the number of situations where a file cannot be rolled. > > Revision Changes Path > 1.6 +85 -33 logging-log4net/src/Appender/FileAppender.cs > > Index: FileAppender.cs > =================================================================== > RCS file: /home/cvs/logging-log4net/src/Appender/FileAppender.cs,v > retrieving revision 1.5 > retrieving revision 1.6 > diff -u -r1.5 -r1.6 > --- FileAppender.cs 1 Jun 2004 18:34:40 -0000 1.5 > +++ FileAppender.cs 18 Sep 2004 16:34:16 -0000 1.6 > @@ -31,16 +31,35 @@ > /// </summary> > /// <remarks> > /// <para> > - /// Logging events are sent to the specified file. > + /// Logging events are sent to the file specified by > + /// the <see cref="File"/> property. > /// </para> > /// <para> > - /// The file can be opened in either append or > - /// overwrite mode. > + /// The file can be opened in either append or overwrite mode > + /// by specifying the <see cref="AppendToFile"/> property. > + /// If the file path is relative it is taken as relative from > + /// the application base directory. The file encoding can be > + /// specified by setting the <see cref="Encoding"/> property. > + /// </para> > + /// <para> > + /// The layout's <see cref="ILayout.Header"/> and <see > cref="ILayout.Footer"/> > + /// values will be written each time the file is opened > and closed > + /// respectively. If the <see cref="AppendToFile"/> > property is <see langword="true"/> > + /// then the file may contain multiple copies of the > header and footer. > + /// </para> > + /// <para> > + /// This appender will first try to open the file for > writing when <see cref="ActivateOptions"/> > + /// is called. This will typically be during configuration. > + /// If the file cannot be opened for writing the > appender will attempt > + /// to open the file again each time a message is > logged to the appender. > + /// If the file cannot be opened for writing when a > message is logged then > + /// the message will be discarded by this appender. > /// </para> > /// </remarks> > /// <author>Nicko Cadell</author> > /// <author>Gert Driesen</author> > /// <author>Rodrigo B. de Oliveira</author> > + /// <author>Douglas de la Torre</author> > public class FileAppender : TextWriterAppender > { > #region Public Instance Constructors > @@ -62,7 +81,7 @@ > public FileAppender(ILayout layout, string > filename, bool append) > { > Layout = layout; > - OpenFile(filename, append); > + SafeOpenFile(filename, append); > } > > /// <summary> > @@ -71,7 +90,7 @@ > /// </summary> > /// <param name="layout">the layout to use with > this appender</param> > /// <param name="filename">the full path to the > file to write to</param> > - [Obsolete("Instead use the default constructor > and set the Layout & File propertes")] > + [Obsolete("Instead use the default constructor > and set the Layout & File properties")] > public FileAppender(ILayout layout, string > filename) : this(layout, filename, true) > { > } > @@ -124,6 +143,12 @@ > /// <value> > /// The <see cref="Encoding"/> used to write to > the file. > /// </value> > + /// <remarks> > + /// <para> > + /// The default encoding set is <see > cref="System.Text.Encoding.Default"/> > + /// which is the encoding for the system's > current ANSI code page. > + /// </para> > + /// </remarks> > public Encoding Encoding > { > get { return m_encoding; } > @@ -158,21 +183,7 @@ > base.ActivateOptions(); > if (m_fileName != null) > { > - // We must cache the params > locally because OpenFile will call > - // Reset which will clear the > class fields. We need to remember the > - // values in case of an error. > - > - string fileName = m_fileName; > - bool appendToFile = m_appendToFile; > - > - try > - { > - OpenFile(fileName, > appendToFile); > - } > - catch(Exception e) > - { > - > ErrorHandler.Error("OpenFile("+fileName+","+appendToFile+") > call failed.", e, ErrorCode.FileOpenFailure); > - } > + SafeOpenFile(m_fileName, > m_appendToFile); > } > else > { > @@ -194,6 +205,20 @@ > m_fileName = null; > } > > + /// <summary> > + /// Called to initialize the file writer > + /// </summary> > + /// <remarks> > + /// <para> > + /// Will be called for each logged message > until the file is > + /// successfully opened. > + /// </para> > + /// </remarks> > + override protected void PrepareWriter() > + { > + SafeOpenFile(m_fileName, m_appendToFile); > + } > + > #endregion Override implementation of TextWriterAppender > > #region Public Instance Methods > @@ -211,17 +236,42 @@ > #region Protected Instance Methods > > /// <summary> > - /// Sets and <i>opens</i> the file where the > log output will > - /// go. The specified file must be writable. > + /// Sets and <i>opens</i> the file where the > log output will go. The specified file must be writable. > + /// </summary> > + /// <param name="fileName">The path to the log > file</param> > + /// <param name="append">If true will append to > fileName. Otherwise will truncate fileName</param> > + /// <remarks> > + /// <para> > + /// Calls <see cref="OpenFile"/> but guarantees > not to throw an exception. > + /// Errors are passed to the <see > cref="TextWriterAppender.ErrorHandler"/>. > + /// </para> > + /// </remarks> > + virtual protected void SafeOpenFile(string > fileName, bool append) > + { > + try > + { > + OpenFile(fileName, append); > + } > + catch(Exception e) > + { > + > ErrorHandler.Error("OpenFile("+fileName+","+append+") call > failed.", e, ErrorCode.FileOpenFailure); > + } > + } > + > + /// <summary> > + /// Sets and <i>opens</i> the file where the > log output will go. The specified file must be writable. > /// </summary> > /// <param name="fileName">The path to the log > file</param> > /// <param name="append">If true will append to > fileName. Otherwise will truncate fileName</param> > /// <remarks> > - /// <para>If there was already an opened file, > then the previous file > - /// is closed first.</para> > - /// > - /// <para>This method will ensure that the > directory structure > - /// for the <paramref name="fileName"/> > specified exists.</para> > + /// <para> > + /// If there was already an opened file, then > the previous file > + /// is closed first. > + /// </para> > + /// <para> > + /// This method will ensure that the directory structure > + /// for the <paramref name="fileName"/> > specified exists. > + /// </para> > /// </remarks> > virtual protected void OpenFile(string > fileName, bool append) > { > @@ -231,8 +281,12 @@ > > LogLog.Debug("FileAppender: > Opening file for writing ["+fileName+"] append ["+append+"]"); > > + // Save these for later, > allowing retries if file open fails > + m_fileName = fileName; > + m_appendToFile = append; > + > // Ensure that the directory > structure exists > - string directoryFullName = (new > FileInfo(fileName)).DirectoryName; > + string directoryFullName = > Path.GetDirectoryName(fileName); > > // Only create the directory if > it does not exist > // doing this check here > resolves some permissions failures > @@ -243,9 +297,6 @@ > > SetQWForFiles(new > StreamWriter(fileName, append, m_encoding)); > > - m_fileName = fileName; > - m_appendToFile = append; > - > WriteHeader(); > } > } > @@ -287,10 +338,11 @@ > throw new ArgumentNullException("path"); > } > > - if (SystemInfo.ApplicationBaseDirectory != null) > + string applicationBaseDirectory = > SystemInfo.ApplicationBaseDirectory; > + if (applicationBaseDirectory != null) > { > // Note that Path.Combine will > return the second path if it is rooted > - return > Path.GetFullPath(Path.Combine(SystemInfo.ApplicationBaseDirect > ory, path)); > + return > Path.GetFullPath(Path.Combine(applicationBaseDirectory, path)); > } > return Path.GetFullPath(path); > } > > > > 1.8 +165 -96 > logging-log4net/src/Appender/RollingFileAppender.cs > > Index: RollingFileAppender.cs > =================================================================== > RCS file: > /home/cvs/logging-log4net/src/Appender/RollingFileAppender.cs,v > retrieving revision 1.7 > retrieving revision 1.8 > diff -u -r1.7 -r1.8 > --- RollingFileAppender.cs 7 Jun 2004 01:09:38 -0000 1.7 > +++ RollingFileAppender.cs 18 Sep 2004 16:34:16 -0000 1.8 > @@ -33,31 +33,81 @@ > /// </summary> > /// <remarks> > /// <para> > - /// RollingFileAppender can function as either or and do both > - /// at the same time (making size based rolling files > until a data/time > - /// boundary is crossed at which time it rolls all of > those files > - /// based on the setting for <see cref="RollingStyle"/>. > + /// RollingFileAppender can roll log files based on > size or date or both > + /// depending on the setting of the <see > cref="RollingStyle"/> property. > + /// When set to <see cref="RollingMode.Size"/> the log > file will be rolled > + /// once its size exceeds the <see cref="MaximumFileSize"/>. > + /// When set to <see cref="RollingMode.Date"/> the log > file will be rolled > + /// once the date boundary specified in the <see > cref="DatePattern"/> property > + /// is crossed. > + /// When set to <see cref="RollingMode.Composite"/> the > log file will be > + /// rolled once the date boundary specified in the <see > cref="DatePattern"/> property > + /// is crossed, but within a date boundary the file > will also be rolled > + /// once its size exceeds the <see cref="MaximumFileSize"/>. > /// </para> > /// <para> > - /// A of few additional optional features have been added:<br/> > - /// -- Attach date pattern for current log file <see > cref="StaticLogFileName"/><br/> > - /// -- Backup number increments for newer files <see > cref="CountDirection"/><br/> > - /// -- Infinite number of backups by file size <see > cref="MaxSizeRollBackups"/> > + /// A of few additional optional features have been added: > + /// <list type="bullet"> > + /// <item>Attach date pattern for current log file <see > cref="StaticLogFileName"/></item> > + /// <item>Backup number increments for newer files <see > cref="CountDirection"/></item> > + /// <item>Infinite number of backups by file size <see > cref="MaxSizeRollBackups"/></item> > + /// </list> > /// </para> > + /// > + /// <note> > /// <para> > - /// A few notes and warnings: For large or infinite > number of backups > - /// countDirection > 0 is highly recommended, with > staticLogFileName = false if > - /// time based rolling is also used -- this will reduce > the number of file renamings > - /// to few or none. Changing staticLogFileName or > countDirection without clearing > - /// the directory could have nasty side effects. If > Date/Time based rolling > - /// is enabled, CompositeRollingAppender will attempt > to roll existing files > - /// in the directory without a date/time tag based on > the last modified date > - /// of the base log files last modification. > + /// For large or infinite numbers of backup files a > <see cref="CountDirection"/> > + /// greater than zero is highly recommended, otherwise > all the backup files need > + /// to be renamed each time a new backup is created. > /// </para> > /// <para> > - /// A maximum number of backups based on date/time > boundaries would be nice > - /// but is not yet implemented. > + /// When Date/Time based rolling is used setting <see > cref="StaticLogFileName"/> > + /// to <see langword="true"/> will reduce the number of > file renamings to few or none. > /// </para> > + /// </note> > + /// > + /// <note type="caution"> > + /// <para> > + /// Changing <see cref="StaticLogFileName"/> or <see > cref="CountDirection"/> without clearing > + /// the log file directory of backup files will cause > unexpected and unwanted side effects. > + /// </para> > + /// </note> > + /// > + /// <para> > + /// If Date/Time based rolling is enabled this appender > will attempt to roll existing files > + /// in the directory without a Date/Time tag based on > the last write date of the base log file. > + /// The appender only rolls the log file when a message > is logged. If Date/Time based rolling > + /// is enabled then the appender will not roll the log > file at the Date/Time boundary but > + /// at the point when the next message is logged after > the boundary has been crossed. > + /// </para> > + /// > + /// <para> > + /// The <see cref="RollingFileAppender"/> extends the > <see cref="FileAppender"/> and > + /// has the same behavior when opening the log file. > + /// The appender will first try to open the file for > writing when <see cref="ActivateOptions"/> > + /// is called. This will typically be during configuration. > + /// If the file cannot be opened for writing the > appender will attempt > + /// to open the file again each time a message is > logged to the appender. > + /// If the file cannot be opened for writing when a > message is logged then > + /// the message will be discarded by this appender. > + /// </para> > + /// <para> > + /// When rolling a backup file necessitates deleting an > older backup file the > + /// file to be deleted is moved to a temporary name > before being deleted. > + /// On the Windows platform if another process has a > write lock on the file > + /// that is to be deleted, but allows shared read > access to the file then the > + /// file can be moved, but cannot be deleted. If the > other process also allows > + /// shared delete access to the file then the file will > be deleted once that > + /// process closes the file. If it is necessary to open > the log file or any > + /// of the backup files outside of this appender for > either read or > + /// write access please ensure that read and delete > share modes are enabled. > + /// </para> > + /// > + /// <note type="caution"> > + /// <para> > + /// A maximum number of backup files when rolling on > date/time boundaries is not supported. > + /// </para> > + /// </note> > /// </remarks> > /// <author>Nicko Cadell</author> > /// <author>Gert Driesen</author> > @@ -212,7 +262,7 @@ > /// before being rolled over to backup files. > /// </summary> > /// <value> > - /// The maximum size that the output file is > allowed to reach before being > + /// The maximum size in bytes that the output > file is allowed to reach before being > /// rolled over to backup files. > /// </value> > /// <remarks> > @@ -223,7 +273,7 @@ > /// argument. > /// </para> > /// <para> > - /// The default maximum file size is 10MB. > + /// The default maximum file size is 10MB > (10*1024*1024). > /// </para> > /// </remarks> > public long MaxFileSize > @@ -247,11 +297,16 @@ > /// expressed respectively in kilobytes, > megabytes or gigabytes. > /// </para> > /// <para> > - /// For example, the value "10KB" will be > interpreted as 10240. > + /// For example, the value "10KB" will be > interpreted as 10240 bytes. > /// </para> > /// <para> > /// The default maximum file size is 10MB. > /// </para> > + /// <para> > + /// If you have the option to set the maximum > file size programmatically > + /// consider using the <see > cref="MaxFileSize"/> property instead as this > + /// allows you to set the size in bytes as a > <see cref="Int64"/>. > + /// </para> > /// </remarks> > public string MaximumFileSize > { > @@ -359,8 +414,7 @@ > /// </para> > /// <para> > /// This will make time based rollovers with a > large number of backups > - /// much faster -- it won't have to > - /// rename all the backups! > + /// much faster as the appender it won't have > to rename all the backups! > /// </para> > /// </remarks> > public bool StaticLogFileName > @@ -450,10 +504,9 @@ > long currentCount = 0; > if (append) > { > - FileInfo fileInfo = new > FileInfo(fileName); > - if (fileInfo.Exists) > + if > (System.IO.File.Exists(fileName)) > { > - currentCount = > fileInfo.Length; > + currentCount = > (new FileInfo(fileName)).Length; > } > } > > @@ -486,13 +539,11 @@ > sName = m_scheduledFilename; > } > > - FileInfo fileInfo = new FileInfo(sName); > - if (null != fileInfo) > - { > - ArrayList arrayFiles = > GetExistingFiles(fileInfo.FullName); > - InitializeRollBackups((new > FileInfo(m_baseFileName)).Name, arrayFiles); > + string fullPath = > System.IO.Path.GetFullPath(sName); > + string fileName = > System.IO.Path.GetFileName(fullPath); > > - } > + ArrayList arrayFiles = > GetExistingFiles(fullPath); > + InitializeRollBackups(fileName, arrayFiles); > > LogLog.Debug("RollingFileAppender: > curSizeRollBackups starts at ["+m_curSizeRollBackups+"]"); > } > @@ -518,21 +569,20 @@ > { > ArrayList alFiles = new ArrayList(); > > - FileInfo fileInfo = new FileInfo(baseFilePath); > - DirectoryInfo dirInfo = fileInfo.Directory; > - LogLog.Debug("RollingFileAppender: > Searching for existing files in ["+dirInfo+"]"); > + string directory = > Path.GetDirectoryName(baseFilePath); > + LogLog.Debug("RollingFileAppender: > Searching for existing files in ["+directory+"]"); > > - if (dirInfo.Exists) > + if (Directory.Exists(directory)) > { > - string baseFileName = fileInfo.Name; > + string baseFileName = > Path.GetFileName(baseFilePath); > > - FileInfo[] files = > dirInfo.GetFiles(GetWildcardPatternForFile(baseFileName)); > + string[] files = > Directory.GetFiles(directory, > GetWildcardPatternForFile(baseFileName)); > > if (files != null) > { > for (int i = 0; i < > files.Length; i++) > { > - string > curFileName = files[i].Name; > + string > curFileName = Path.GetFileName(files[i]); > if > (curFileName.StartsWith(baseFileName)) > { > > alFiles.Add(curFileName); > @@ -550,10 +600,9 @@ > { > if (m_staticLogFileName && m_rollDate) > { > - FileInfo old = new > FileInfo(m_baseFileName); > - if (old.Exists) > + if > (System.IO.File.Exists(m_baseFileName)) > { > - DateTime last = > old.LastWriteTime; > + DateTime last = > System.IO.File.GetLastWriteTime(m_baseFileName); > > LogLog.Debug("RollingFileAppender: > ["+last.ToString(m_datePattern,System.Globalization.DateTimeFo > rmatInfo.InvariantInfo)+"] vs. > ["+m_now.ToString(m_datePattern,System.Globalization.DateTimeF > ormatInfo.InvariantInfo)+"]"); > > if > (!(last.ToString(m_datePattern,System.Globalization.DateTimeFo > rmatInfo.InvariantInfo).Equals(m_now.ToString(m_datePattern, > System.Globalization.DateTimeFormatInfo.InvariantInfo)))) > @@ -568,11 +617,18 @@ > } > > /// <summary> > - /// <para>Initializes based on existing > conditions at time of <see cref="ActivateOptions"/>. > - /// The following is done:</para> > - /// A) determine curSizeRollBackups > (only within the current roll point) > - /// B) initiates a roll over if > needed for crossing a date boundary since the last run. > + /// Initializes based on existing conditions at > time of <see cref="ActivateOptions"/>. > /// </summary> > + /// <remarks> > + /// <para> > + /// Initializes based on existing conditions at > time of <see cref="ActivateOptions"/>. > + /// The following is done > + /// <list type="bullet"> > + /// <item>determine curSizeRollBackups > (only within the current roll point)</item> > + /// <item>initiates a roll over if needed > for crossing a date boundary since the last run.</item> > + /// </list> > + /// </para> > + /// </remarks> > protected void ExistingInit() > { > DetermineCurSizeRollBackups(); > @@ -663,7 +719,7 @@ > > LogLog.Debug("RollingFileAppender: File name > ["+curFileName+"] moves current count to ["+m_curSizeRollBackups+"]"); > } > } > - catch (FormatException /*e*/) > + catch(FormatException) > { > //this happens when file.log -> > file.log.yyyy-mm-dd which is normal > //when staticLogFileName == false > @@ -694,7 +750,7 @@ > /// <summary> > /// Calculates the RollPoint for the > datePattern supplied. > /// </summary> > - /// <param name="datePattern">the date pattern > to caluculate the check period for</param> > + /// <param name="datePattern">the date pattern > to calculate the check period for</param> > /// <returns>The RollPoint that is most > accurate for the date pattern supplied</returns> > /// <remarks> > /// Essentially the date pattern is examined to > determine what the > @@ -706,19 +762,18 @@ > /// </remarks> > private RollPoint ComputeCheckPeriod(string > datePattern) > { > - // set date to 1970-01-01 00:00:00 this > is UniversalSortableDateTimePattern > + // s_date1970 is 1970-01-01 00:00:00 > this is UniversalSortableDateTimePattern > // (based on ISO 8601) using universal > time. This date is used for reference > // purposes to calculate the resolution > of the date pattern. > - DateTime epoch = new DateTime(1970, 1, > 1, 0, 0, 0, 0); > > // Get string representation of base line date > - string r0 = epoch.ToString(datePattern, > System.Globalization.DateTimeFormatInfo.InvariantInfo); > + string r0 = > s_date1970.ToString(datePattern, > System.Globalization.DateTimeFormatInfo.InvariantInfo); > > // Check each type of rolling mode > starting with the smallest increment. > for(int i = (int)RollPoint.TopOfMinute; > i <= (int)RollPoint.TopOfMonth; i++) > { > // Get string representation of > next pattern > - string r1 = > NextCheckDate(epoch, (RollPoint)i).ToString(datePattern, > System.Globalization.DateTimeFormatInfo.InvariantInfo); > + string r1 = > NextCheckDate(s_date1970, (RollPoint)i).ToString(datePattern, > System.Globalization.DateTimeFormatInfo.InvariantInfo); > > > LogLog.Debug("RollingFileAppender: Type = ["+i+"], r0 = > ["+r0+"], r1 = ["+r1+"]"); > > @@ -799,7 +854,7 @@ > { > if (m_staticLogFileName) > { > - /* Compute filename, but only > if datePattern is specified */ > + // Compute filename, but only > if datePattern is specified > if (m_datePattern == null) > { > > ErrorHandler.Error("Missing DatePattern option in rollOver()."); > @@ -831,22 +886,14 @@ > RollFile(File, m_scheduledFilename); > } > > - try > - { > - //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); > + //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); > > - // This will also close the > file. This is OK since multiple > - // close operations are safe. > - this.OpenFile(m_baseFileName, false); > - } > - catch(Exception e) > - { > - ErrorHandler.Error("setFile(" + > File + ", false) call failed.", e, ErrorCode.FileOpenFailure); > - } > + // This will also close the file. This > is OK since multiple close operations are safe. > + SafeOpenFile(m_baseFileName, false); > } > > /// <summary> > @@ -857,25 +904,20 @@ > /// <param name="toFile">New name for file.</param> > protected void RollFile(string fromFile, string toFile) > { > - FileInfo target = new FileInfo(toFile); > - if (target.Exists) > - { > - > LogLog.Debug("RollingFileAppender: Deleting existing target > file ["+target+"]"); > - target.Delete(); > - } > - > - FileInfo file = new FileInfo(fromFile); > - if (file.Exists) > + if (System.IO.File.Exists(fromFile)) > { > + // Delete the toFile if it exists > + DeleteFile(toFile); > + > // We may not have permission > to move the file, or the file may be locked > try > { > - file.MoveTo(toFile); > - > LogLog.Debug("RollingFileAppender: Moved [" + fromFile + "] > -> [" + toFile + "]"); > + > LogLog.Debug("RollingFileAppender: Moving [" + fromFile + "] > -> [" + toFile + "]"); > + > System.IO.File.Move(fromFile, toFile); > } > - catch(Exception ex) > + catch(Exception moveEx) > { > - > ErrorHandler.Error("Exception while rolling file [" + > fromFile + "] -> [" + toFile + "]", ex, ErrorCode.GenericFailure); > + > ErrorHandler.Error("Exception while rolling file [" + > fromFile + "] -> [" + toFile + "]", moveEx, ErrorCode.GenericFailure); > } > } > else > @@ -890,18 +932,44 @@ > /// <param name="fileName">The file to delete.</param> > protected void DeleteFile(string fileName) > { > - FileInfo file = new FileInfo(fileName); > - if (file.Exists) > + if (System.IO.File.Exists(fileName)) > { > // We may not have permission > to delete the file, or the file may be locked > + > + string fileToDelete = fileName; > + > + // Try to move the file to temp name. > + // If the file is locked we > should still be able to move it > + string tempFileName = fileName > + "." + Environment.TickCount + ".DeletePending"; > + try > + { > + > System.IO.File.Move(fileName, tempFileName); > + fileToDelete = tempFileName; > + } > + catch(Exception moveEx) > + { > + > LogLog.Debug("RollingFileAppender: Exception while moving > file to be deleted [" + fileName + "] -> [" + tempFileName + > "]", moveEx); > + } > + > + // Try to delete the file > (either the original or the moved file) > try > { > - file.Delete(); > + > System.IO.File.Delete(fileToDelete); > > LogLog.Debug("RollingFileAppender: Deleted file [" + fileName + "]"); > } > - catch(Exception ex) > + catch(Exception deleteEx) > { > - > ErrorHandler.Error("Exception while deleting file [" + > fileName + "]", ex, ErrorCode.GenericFailure); > + if (fileToDelete == fileName) > + { > + // Unable to > move or delete the file > + > ErrorHandler.Error("Exception while deleting file [" + > fileToDelete + "]", deleteEx, ErrorCode.GenericFailure); > + } > + else > + { > + // Moved the > file, but the delete failed. File is probably locked. > + // The file > should automatically be deleted when the lock is released. > + > LogLog.Debug("RollingFileAppender: Exception while deleting > temp file [" + fileToDelete + "]", deleteEx); > + } > } > } > } > @@ -976,16 +1044,8 @@ > } > } > > - try > - { > - // This will also close the > file. This is OK since multiple > - // close operations are safe. > - this.OpenFile(m_baseFileName, false); > - } > - catch(Exception e) > - { > - ErrorHandler.Error("OpenFile > ["+m_baseFileName+"] call failed.", e); > - } > + // This will also close the file. This > is OK since multiple close operations are safe. > + SafeOpenFile(m_baseFileName, false); > } > > #endregion > @@ -1150,6 +1210,15 @@ > private string m_baseFileName; > > #endregion Private Instance Fields > + > + #region Static Members > + > + /// <summary> > + /// The 1st of January 1970 in UTC > + /// </summary> > + private static readonly DateTime s_date1970 = > new DateTime(1970, 1, 1); > + > + #endregion > > #region DateTime > > > > > 1.5 +37 -6 > logging-log4net/src/Appender/TextWriterAppender.cs > > Index: TextWriterAppender.cs > =================================================================== > RCS file: > /home/cvs/logging-log4net/src/Appender/TextWriterAppender.cs,v > retrieving revision 1.4 > retrieving revision 1.5 > diff -u -r1.4 -r1.5 > --- TextWriterAppender.cs 1 Jun 2004 18:34:40 -0000 1.4 > +++ TextWriterAppender.cs 18 Sep 2004 16:34:16 -0000 1.5 > @@ -29,10 +29,18 @@ > /// Sends logging events to a <see cref="TextWriter"/>. > /// </summary> > /// <remarks> > + /// <para> > /// An Appender that writes to a <see cref="TextWriter"/>. > + /// </para> > + /// <para> > + /// This appender may be used stand alone if > initialized with an appropriate > + /// writer, however it is typically used as a base > class for an appender that > + /// can open a <see cref="TextWriter"/> to write to. > + /// </para> > /// </remarks> > /// <author>Nicko Cadell</author> > /// <author>Gert Driesen</author> > + /// <author>Douglas de la Torre</author> > public class TextWriterAppender : AppenderSkeleton > { > #region Public Instance Constructors > @@ -128,8 +136,11 @@ > lock(this) > { > Reset(); > - m_qtw = new > QuietTextWriter(value, ErrorHandler); > - WriteHeader(); > + if (value != null) > + { > + m_qtw = new > QuietTextWriter(value, ErrorHandler); > + WriteHeader(); > + } > } > } > } > @@ -157,15 +168,21 @@ > > if (m_qtw == null) > { > - ErrorHandler.Error("No output > stream or file set for the appender named ["+ Name +"]."); > - return false; > + // Allow subclass to lazily > create the writer > + PrepareWriter(); > + > + if (m_qtw == null) > + { > + ErrorHandler.Error("No > output stream or file set for the appender named ["+ Name +"]."); > + return false; > + } > } > if (m_qtw.Closed) > { > ErrorHandler.Error("Output > stream for appender named ["+ Name +"] has been closed."); > return false; > } > - > + > return true; > } > > @@ -320,7 +337,21 @@ > m_qtw.Write(h); > } > } > - } > + } > + > + /// <summary> > + /// Called to allow a subclass to lazily > initialize the writer > + /// </summary> > + /// <remarks> > + /// <para> > + /// This method is called when an event is > logged and the <see cref="Writer"/> or > + /// <see cref="QuietWriter"/> have not been > set. This allows a subclass to > + /// attempt to initialize the writer multiple times. > + /// </para> > + /// </remarks> > + virtual protected void PrepareWriter() > + { > + } > > #endregion Protected Instance Methods > > > > >
