You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4net-dev@logging.apache.org by Nicko Cadell <ni...@neoworks.com> on 2004/11/01 02:25:02 UTC

RE: cvs commit: logging-log4net/src/Appender FileAppender.cs RollingFileAppender.cs TextWriterAppender.cs

Mike,

The changelog context diff accurately represents the changes required to
update the old source to the new source. You have to look for the lines
starting with + and - to see what the diff represents.

> Incidentally, the exception taken in the call 
> System.IO.File.Move says that the toFile is in use by another 
> process even though DeleteFile should have removed it first! 
> Here's the text from the exception: "The process cannot 
> access the file "C:\ProphIT_CTI_Log.log.3" because it is 
> being used by another process.

If the file is in use then DeleteFile will not be able to delete the
file, so Move will fail as the file has not been deleted.

Cheers,
Nicko

Oh, the best place for this discussion is the log4net-dev list.
 

> -----Original Message-----
> From: Mike Blake-Knox [mailto:mikebk@knology.net] On Behalf 
> Of Mike Blake-Knox
> Sent: 31 October 2004 19:17
> To: logging-log4net-cvs@apache.org
> Cc: mikebk@knology.net
> Subject: RE: cvs commit: logging-log4net/src/Appender 
> FileAppender.cs RollingFileAppender.cs TextWriterAppender.cs
> 
> Hi there!
> 
> I had checked out Thursday morning's version of log4net from 
> cvs. It doesn't have (all) the changes in the following 
> email. In it, RollFile is defined
> as:
> 
> 		protected void RollFile(string fromFile, string toFile) 
> 		{
> 			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
> 				{
> 					
> LogLog.Debug("RollingFileAppender:
> Moving [" + fromFile + "] -> [" + toFile + "]");
> 					System.IO.File.Move(fromFile,
> toFile);
> 				}
> 				catch(Exception moveEx)
> 				{
> 					
> ErrorHandler.Error("Exception while rolling file [" + 
> fromFile + "] -> [" + toFile + "]", moveEx, ErrorCode.GenericFailure);
> 				}
> 			}
> 			else
> 			{
> 				
> LogLog.Warn("RollingFileAppender: Cannot RollFile [" + 
> fromFile + "] -> [" + toFile + "]. Source does not exist");
> 			}
> 		}
> 
> The version in the change notice is MUCH longer.
> 
> Have I missed something?
> 
> Incidentally, the exception taken in the call 
> System.IO.File.Move says that the toFile is in use by another 
> process even though DeleteFile should have removed it first! 
> Here's the text from the exception: "The process cannot 
> access the file "C:\ProphIT_CTI_Log.log.3" because it is 
> being used by another process.
> 
> Thanks
> 
> Mike Blake-Knox
> email: MBlake-Knox@tsystsol.com
> TSYS Office: (706) 644-3643
> cellphone: (706) 570-4641
>  
> 
> > -----Original Message-----
> > From: nicko@apache.org [mailto:nicko@apache.org]
> > Sent: Saturday, September 18, 2004 12:34 PM
> > To: logging-log4net-cvs@apache.org
> > 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
> > 
> >    
> > 
> >   
> >   
> >   
> > 
> > 
> 
>