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 &gt; 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
>    
>   
>   
>   
> 

Reply via email to