Modified: logging/log4net/trunk/src/Appender/RollingFileAppender.cs
URL: 
http://svn.apache.org/viewvc/logging/log4net/trunk/src/Appender/RollingFileAppender.cs?rev=1714248&r1=1714247&r2=1714248&view=diff
==============================================================================
--- logging/log4net/trunk/src/Appender/RollingFileAppender.cs (original)
+++ logging/log4net/trunk/src/Appender/RollingFileAppender.cs Fri Nov 13 
18:35:34 2015
@@ -1,239 +1,239 @@
-#region Apache License
-//
-// Licensed to the Apache Software Foundation (ASF) under one or more 
-// contributor license agreements. See the NOTICE file distributed with
-// this work for additional information regarding copyright ownership. 
-// The ASF licenses this file to you under the Apache License, Version 2.0
-// (the "License"); you may not use this file except in compliance with 
-// the License. You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-#endregion
-
-using System;
-using System.Collections;
-using System.Globalization;
-using System.IO;
-
-using log4net.Util;
+#region Apache License
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more 
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership. 
+// The ASF licenses this file to you under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with 
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+#endregion
+
+using System;
+using System.Collections;
+using System.Globalization;
+using System.IO;
+
+using log4net.Util;
 using log4net.Core;
-using System.Threading;
-
-namespace log4net.Appender
-{
-#if CONFIRM_WIN32_FILE_SHAREMODES
-       // The following sounds good, and I though it was the case, but after
-       // further testing on Windows I have not been able to confirm it.
-
-       /// 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.
-#endif
-
-       /// <summary>
-       /// Appender that rolls log files based on size or date or both.
-       /// </summary>
-       /// <remarks>
-       /// <para>
-       /// 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"/>.
-       /// When set to <see cref="RollingMode.Once"/> the log file will be 
rolled when
-       /// the appender is configured. This effectively means that the log 
file can be
-       /// rolled once per program execution.
-       /// </para>
-       /// <para>
-       /// 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>
-       /// 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>
-       /// 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.
-       /// </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>
-       /// <author>Aspi Havewala</author>
-       /// <author>Douglas de la Torre</author>
-       /// <author>Edward Smit</author>
-       public class RollingFileAppender : FileAppender
-    {
-        #region Public Enums
-
-        /// <summary>
-               /// Style of rolling to use
-               /// </summary>
-               /// <remarks>
-               /// <para>
-               /// Style of rolling to use
-               /// </para>
-               /// </remarks>
-               public enum RollingMode
-               {
-                       /// <summary>
-                       /// Roll files once per program execution
-                       /// </summary>
-                       /// <remarks>
-                       /// <para>
-                       /// Roll files once per program execution.
-                       /// Well really once each time this appender is
-                       /// configured.
-                       /// </para>
-                       /// <para>
-                       /// Setting this option also sets <c>AppendToFile</c> to
-                       /// <c>false</c> on the <c>RollingFileAppender</c>, 
otherwise
-                       /// this appender would just be a normal file appender.
-                       /// </para>
-                       /// </remarks>
-                       Once            = 0,
-
-                       /// <summary>
-                       /// Roll files based only on the size of the file
-                       /// </summary>
-                       Size            = 1,
-
-                       /// <summary>
-                       /// Roll files based only on the date
-                       /// </summary>
-                       Date            = 2,
-
-                       /// <summary>
-                       /// Roll files based on both the size and date of the 
file
-                       /// </summary>
-                       Composite       = 3
-               }
-
-               #endregion
-
-               #region Protected Enums
-
-               /// <summary>
-               /// The code assumes that the following 'time' constants are in 
a increasing sequence.
-               /// </summary>
-               /// <remarks>
-               /// <para>
-               /// The code assumes that the following 'time' constants are in 
a increasing sequence.
-               /// </para>
-               /// </remarks>
-               protected enum RollPoint
-               {
-                       /// <summary>
-                       /// Roll the log not based on the date
-                       /// </summary>
-                       InvalidRollPoint        =-1,
-
-                       /// <summary>
-                       /// Roll the log for each minute
-                       /// </summary>
-                       TopOfMinute                     = 0,
-
-                       /// <summary>
-                       /// Roll the log for each hour
-                       /// </summary>
-                       TopOfHour                       = 1,
-
-                       /// <summary>
-                       /// Roll the log twice a day (midday and midnight)
-                       /// </summary>
-                       HalfDay                         = 2,
-
-                       /// <summary>
-                       /// Roll the log each day (midnight)
-                       /// </summary>
-                       TopOfDay                        = 3,
-
-                       /// <summary>
-                       /// Roll the log each week
-                       /// </summary>
-                       TopOfWeek                       = 4,
-
-                       /// <summary>
-                       /// Roll the log each month
-                       /// </summary>
-                       TopOfMonth                      = 5
-               }
-
-               #endregion Protected Enums
-
-               #region Public Instance Constructors
-
-               /// <summary>
-               /// Initializes a new instance of the <see 
cref="RollingFileAppender" /> class.
-               /// </summary>
-               /// <remarks>
-               /// <para>
-               /// Default constructor.
-               /// </para>
-               /// </remarks>
-               public RollingFileAppender() 
-               {
+using System.Threading;
+
+namespace log4net.Appender
+{
+#if CONFIRM_WIN32_FILE_SHAREMODES
+       // The following sounds good, and I though it was the case, but after
+       // further testing on Windows I have not been able to confirm it.
+
+       /// 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.
+#endif
+
+       /// <summary>
+       /// Appender that rolls log files based on size or date or both.
+       /// </summary>
+       /// <remarks>
+       /// <para>
+       /// 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"/>.
+       /// When set to <see cref="RollingMode.Once"/> the log file will be 
rolled when
+       /// the appender is configured. This effectively means that the log 
file can be
+       /// rolled once per program execution.
+       /// </para>
+       /// <para>
+       /// 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>
+       /// 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>
+       /// 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.
+       /// </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>
+       /// <author>Aspi Havewala</author>
+       /// <author>Douglas de la Torre</author>
+       /// <author>Edward Smit</author>
+       public class RollingFileAppender : FileAppender
+    {
+        #region Public Enums
+
+        /// <summary>
+               /// Style of rolling to use
+               /// </summary>
+               /// <remarks>
+               /// <para>
+               /// Style of rolling to use
+               /// </para>
+               /// </remarks>
+               public enum RollingMode
+               {
+                       /// <summary>
+                       /// Roll files once per program execution
+                       /// </summary>
+                       /// <remarks>
+                       /// <para>
+                       /// Roll files once per program execution.
+                       /// Well really once each time this appender is
+                       /// configured.
+                       /// </para>
+                       /// <para>
+                       /// Setting this option also sets <c>AppendToFile</c> to
+                       /// <c>false</c> on the <c>RollingFileAppender</c>, 
otherwise
+                       /// this appender would just be a normal file appender.
+                       /// </para>
+                       /// </remarks>
+                       Once            = 0,
+
+                       /// <summary>
+                       /// Roll files based only on the size of the file
+                       /// </summary>
+                       Size            = 1,
+
+                       /// <summary>
+                       /// Roll files based only on the date
+                       /// </summary>
+                       Date            = 2,
+
+                       /// <summary>
+                       /// Roll files based on both the size and date of the 
file
+                       /// </summary>
+                       Composite       = 3
+               }
+
+               #endregion
+
+               #region Protected Enums
+
+               /// <summary>
+               /// The code assumes that the following 'time' constants are in 
a increasing sequence.
+               /// </summary>
+               /// <remarks>
+               /// <para>
+               /// The code assumes that the following 'time' constants are in 
a increasing sequence.
+               /// </para>
+               /// </remarks>
+               protected enum RollPoint
+               {
+                       /// <summary>
+                       /// Roll the log not based on the date
+                       /// </summary>
+                       InvalidRollPoint        =-1,
+
+                       /// <summary>
+                       /// Roll the log for each minute
+                       /// </summary>
+                       TopOfMinute                     = 0,
+
+                       /// <summary>
+                       /// Roll the log for each hour
+                       /// </summary>
+                       TopOfHour                       = 1,
+
+                       /// <summary>
+                       /// Roll the log twice a day (midday and midnight)
+                       /// </summary>
+                       HalfDay                         = 2,
+
+                       /// <summary>
+                       /// Roll the log each day (midnight)
+                       /// </summary>
+                       TopOfDay                        = 3,
+
+                       /// <summary>
+                       /// Roll the log each week
+                       /// </summary>
+                       TopOfWeek                       = 4,
+
+                       /// <summary>
+                       /// Roll the log each month
+                       /// </summary>
+                       TopOfMonth                      = 5
+               }
+
+               #endregion Protected Enums
+
+               #region Public Instance Constructors
+
+               /// <summary>
+               /// Initializes a new instance of the <see 
cref="RollingFileAppender" /> class.
+               /// </summary>
+               /// <remarks>
+               /// <para>
+               /// Default constructor.
+               /// </para>
+               /// </remarks>
+               public RollingFileAppender() 
+               {
                }
 
                /// <summary>
@@ -246,365 +246,365 @@ namespace log4net.Appender
                                m_mutexForRolling.Close();
                                m_mutexForRolling = null;
                        }
-               }
-
-               #endregion Public Instance Constructors
-
-               #region Public Instance Properties
-
-#if !NET_1_0 && !CLI_1_0 && !NETCF
-        /// <summary>
-               /// Gets or sets the strategy for determining the current date 
and time. The default
-               /// implementation is to use LocalDateTime which internally 
calls through to DateTime.Now. 
-               /// DateTime.UtcNow may be used on frameworks newer than .NET 
1.0 by specifying
-               /// <see cref="RollingFileAppender.UniversalDateTime"/>.
-               /// </summary>
-               /// <value>
-               /// An implementation of the <see 
cref="RollingFileAppender.IDateTime"/> interface which returns the current date 
and time.
-               /// </value>
-               /// <remarks>
-               /// <para>
-               /// Gets or sets the <see 
cref="RollingFileAppender.IDateTime"/> used to return the current date and time.
-               /// </para>
-        /// <para>
-        /// There are two built strategies for determining the current date 
and time, 
-               /// <see cref="RollingFileAppender.LocalDateTime"/>
-        /// and <see cref="RollingFileAppender.UniversalDateTime"/>.
-        /// </para>
-        /// <para>
-               /// The default strategy is <see 
cref="RollingFileAppender.LocalDateTime"/>.
-               /// </para>
-               /// </remarks>
-#else
-        /// <summary>
-               /// Gets or sets the strategy for determining the current date 
and time. The default
-               /// implementation is to use LocalDateTime which internally 
calls through to DateTime.Now. 
-               /// </summary>
-               /// <value>
-               /// An implementation of the <see 
cref="RollingFileAppender.IDateTime"/> interface which returns the current date 
and time.
-               /// </value>
-               /// <remarks>
-               /// <para>
-               /// Gets or sets the <see 
cref="RollingFileAppender.IDateTime"/> used to return the current date and time.
-               /// </para>
-        /// <para>
-               /// The default strategy is <see 
cref="RollingFileAppender.LocalDateTime"/>.
-               /// </para>
-               /// </remarks>
-#endif
-        public IDateTime DateTimeStrategy
-               {
-                       get { return m_dateTime; }
-                       set { m_dateTime = value; }
-               }
-
-               /// <summary>
-               /// Gets or sets the date pattern to be used for generating 
file names
-               /// when rolling over on date.
-               /// </summary>
-               /// <value>
-               /// The date pattern to be used for generating file names when 
rolling 
-               /// over on date.
-               /// </value>
-               /// <remarks>
-               /// <para>
-               /// Takes a string in the same format as expected by 
-               /// <see cref="log4net.DateFormatter.SimpleDateFormatter" />.
-               /// </para>
-               /// <para>
-               /// This property determines the rollover schedule when rolling 
over
-               /// on date.
-               /// </para>
-               /// </remarks>
-               public string DatePattern
-               {
-                       get { return m_datePattern; }
-                       set { m_datePattern = value; }
-               }
-  
-               /// <summary>
-               /// Gets or sets the maximum number of backup files that are 
kept before
-               /// the oldest is erased.
-               /// </summary>
-               /// <value>
-               /// The maximum number of backup files that are kept before the 
oldest is
-               /// erased.
-               /// </value>
-               /// <remarks>
-               /// <para>
-               /// If set to zero, then there will be no backup files and the 
log file 
-               /// will be truncated when it reaches <see 
cref="MaxFileSize"/>.  
-               /// </para>
-               /// <para>
-               /// If a negative number is supplied then no deletions will be 
made.  Note 
-               /// that this could result in very slow performance as a large 
number of 
-               /// files are rolled over unless <see cref="CountDirection"/> 
is used.
-               /// </para>
-               /// <para>
-               /// The maximum applies to <b>each</b> time based group of 
files and 
-               /// <b>not</b> the total.
-               /// </para>
-               /// </remarks>
-               public int MaxSizeRollBackups
-               {
-                       get { return m_maxSizeRollBackups; }
-                       set { m_maxSizeRollBackups = value; }
-               }
-  
-               /// <summary>
-               /// Gets or sets the maximum size that the output file is 
allowed to reach
-               /// before being rolled over to backup files.
-               /// </summary>
-               /// <value>
-               /// The maximum size in bytes that the output file is allowed 
to reach before being 
-               /// rolled over to backup files.
-               /// </value>
-               /// <remarks>
-               /// <para>
-               /// This property is equivalent to <see 
cref="MaximumFileSize"/> except
-               /// that it is required for differentiating the setter taking a
-               /// <see cref="long"/> argument from the setter taking a <see 
cref="string"/> 
-               /// argument.
-               /// </para>
-               /// <para>
-               /// The default maximum file size is 10MB (10*1024*1024).
-               /// </para>
-               /// </remarks>
-               public long MaxFileSize
-               {
-                       get { return m_maxFileSize; }
-                       set { m_maxFileSize = value; }
-               }
-  
-               /// <summary>
-               /// Gets or sets the maximum size that the output file is 
allowed to reach
-               /// before being rolled over to backup files.
-               /// </summary>
-               /// <value>
-               /// The maximum size that the output file is allowed to reach 
before being 
-               /// rolled over to backup files.
-               /// </value>
-               /// <remarks>
-               /// <para>
-               /// This property allows you to specify the maximum size with 
the
-               /// suffixes "KB", "MB" or "GB" so that the size is interpreted 
being 
-               /// expressed respectively in kilobytes, megabytes or 
gigabytes. 
-               /// </para>
-               /// <para>
-               /// 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
-               {
-                       get { return 
m_maxFileSize.ToString(NumberFormatInfo.InvariantInfo); }
-                       set { m_maxFileSize = OptionConverter.ToFileSize(value, 
m_maxFileSize + 1); }
-               }
-
-               /// <summary>
-               /// Gets or sets the rolling file count direction. 
-               /// </summary>
-               /// <value>
-               /// The rolling file count direction.
-               /// </value>
-               /// <remarks>
-               /// <para>
-               /// Indicates if the current file is the lowest numbered file 
or the
-               /// highest numbered file.
-               /// </para>
-               /// <para>
-               /// By default newer files have lower numbers (<see 
cref="CountDirection" /> &lt; 0),
-               /// i.e. log.1 is most recent, log.5 is the 5th backup, etc...
-               /// </para>
-               /// <para>
-               /// <see cref="CountDirection" /> &gt;= 0 does the opposite i.e.
-               /// log.1 is the first backup made, log.5 is the 5th backup 
made, etc.
-               /// For infinite backups use <see cref="CountDirection" /> 
&gt;= 0 to reduce 
-               /// rollover costs.
-               /// </para>
-               /// <para>The default file count direction is -1.</para>
-               /// </remarks>
-               public int CountDirection
-               {
-                       get { return m_countDirection; }
-                       set { m_countDirection = value; }
-               }
-  
-               /// <summary>
-               /// Gets or sets the rolling style.
-               /// </summary>
-               /// <value>The rolling style.</value>
-               /// <remarks>
-               /// <para>
-               /// The default rolling style is <see 
cref="RollingMode.Composite" />.
-               /// </para>
-               /// <para>
-               /// When set to <see cref="RollingMode.Once"/> this appender's
-               /// <see cref="FileAppender.AppendToFile"/> property is set to 
<c>false</c>, otherwise
-               /// the appender would append to a single file rather than 
rolling
-               /// the file each time it is opened.
-               /// </para>
-               /// </remarks>
-               public RollingMode RollingStyle
-               {
-                       get { return m_rollingStyle; }
-                       set
-                       {
-                               m_rollingStyle = value;
-                               switch (m_rollingStyle) 
-                               {
-                                       case RollingMode.Once:
-                                               m_rollDate = false;
-                                               m_rollSize = false;
-
-                                               this.AppendToFile = false;
-                                               break;
-
-                                       case RollingMode.Size:
-                                               m_rollDate = false;
-                                               m_rollSize = true;
-                                               break;
-
-                                       case RollingMode.Date:
-                                               m_rollDate = true;
-                                               m_rollSize = false;
-                                               break;
-
-                                       case RollingMode.Composite:
-                                               m_rollDate = true;
-                                               m_rollSize = true;
-                                               break;    
-                               }
-                       }
-               }
-
-        /// <summary>
-        /// Gets or sets a value indicating whether to preserve the file name 
extension when rolling.
-        /// </summary>
-        /// <value>
-        /// <c>true</c> if the file name extension should be preserved.
-        /// </value>
-        /// <remarks>
-        /// <para>
-        /// By default file.log is rolled to file.log.yyyy-MM-dd or 
file.log.curSizeRollBackup.
-        /// However, under Windows the new file name will loose any program 
associations as the
-        /// extension is changed. Optionally file.log can be renamed to 
file.yyyy-MM-dd.log or
-        /// file.curSizeRollBackup.log to maintain any program associations.
-        /// </para>
-        /// </remarks>
-        public bool PreserveLogFileNameExtension
-        {
-            get { return m_preserveLogFileNameExtension; }
-            set { m_preserveLogFileNameExtension = value; }
-        }
-
-               /// <summary>
-               /// Gets or sets a value indicating whether to always log to
-               /// the same file.
-               /// </summary>
-               /// <value>
-               /// <c>true</c> if always should be logged to the same file, 
otherwise <c>false</c>.
-               /// </value>
-               /// <remarks>
-               /// <para>
-               /// By default file.log is always the current file.  Optionally
-               /// file.log.yyyy-mm-dd for current formatted datePattern can 
by the currently
-               /// logging file (or file.log.curSizeRollBackup or even
-               /// file.log.yyyy-mm-dd.curSizeRollBackup).
-               /// </para>
-               /// <para>
-               /// This will make time based rollovers with a large number of 
backups 
-               /// much faster as the appender it won't have to rename all the 
backups!
-               /// </para>
-               /// </remarks>
-               public bool StaticLogFileName
-               {
-                       get { return m_staticLogFileName; }
-                       set { m_staticLogFileName = value; }
-               }
-
-               #endregion Public Instance Properties
-
-           #region Private Static Fields
-
-           /// <summary>
-           /// The fully qualified type of the RollingFileAppender class.
-           /// </summary>
-           /// <remarks>
-           /// Used by the internal logger to record the Type of the
-           /// log message.
-           /// </remarks>
-           private readonly static Type declaringType = 
typeof(RollingFileAppender);
-
-           #endregion Private Static Fields
-
-               #region Override implementation of FileAppender 
-  
-               /// <summary>
-               /// Sets the quiet writer being used.
-               /// </summary>
-               /// <remarks>
-               /// This method can be overridden by sub classes.
-               /// </remarks>
-               /// <param name="writer">the writer to set</param>
-               override protected void SetQWForFiles(TextWriter writer) 
-               {
-                       QuietWriter = new CountingQuietTextWriter(writer, 
ErrorHandler);
-               }
-
-               /// <summary>
-               /// Write out a logging event.
-               /// </summary>
-               /// <param name="loggingEvent">the event to write to 
file.</param>
-               /// <remarks>
-               /// <para>
-               /// Handles append time behavior for RollingFileAppender.  This 
checks
-               /// if a roll over either by date (checked first) or time 
(checked second)
-               /// is need and then appends to the file last.
-               /// </para>
-               /// </remarks>
-               override protected void Append(LoggingEvent loggingEvent) 
-               {
-                       AdjustFileBeforeAppend();
-                       base.Append(loggingEvent);
-               }
-  
-               /// <summary>
-               /// Write out an array of logging events.
-               /// </summary>
-               /// <param name="loggingEvents">the events to write to 
file.</param>
-               /// <remarks>
-               /// <para>
-               /// Handles append time behavior for RollingFileAppender.  This 
checks
-               /// if a roll over either by date (checked first) or time 
(checked second)
-               /// is need and then appends to the file last.
-               /// </para>
-               /// </remarks>
-               override protected void Append(LoggingEvent[] loggingEvents) 
-               {
-                       AdjustFileBeforeAppend();
-                       base.Append(loggingEvents);
-               }
-
-               /// <summary>
-               /// Performs any required rolling before outputting the next 
event
-               /// </summary>
-               /// <remarks>
-               /// <para>
-               /// Handles append time behavior for RollingFileAppender.  This 
checks
-               /// if a roll over either by date (checked first) or time 
(checked second)
-               /// is need and then appends to the file last.
-               /// </para>
-               /// </remarks>
-               virtual protected void AdjustFileBeforeAppend()
-               {
+               }
+
+               #endregion Public Instance Constructors
+
+               #region Public Instance Properties
+
+#if !NET_1_0 && !CLI_1_0 && !NETCF
+        /// <summary>
+               /// Gets or sets the strategy for determining the current date 
and time. The default
+               /// implementation is to use LocalDateTime which internally 
calls through to DateTime.Now. 
+               /// DateTime.UtcNow may be used on frameworks newer than .NET 
1.0 by specifying
+               /// <see cref="RollingFileAppender.UniversalDateTime"/>.
+               /// </summary>
+               /// <value>
+               /// An implementation of the <see 
cref="RollingFileAppender.IDateTime"/> interface which returns the current date 
and time.
+               /// </value>
+               /// <remarks>
+               /// <para>
+               /// Gets or sets the <see 
cref="RollingFileAppender.IDateTime"/> used to return the current date and time.
+               /// </para>
+        /// <para>
+        /// There are two built strategies for determining the current date 
and time, 
+               /// <see cref="RollingFileAppender.LocalDateTime"/>
+        /// and <see cref="RollingFileAppender.UniversalDateTime"/>.
+        /// </para>
+        /// <para>
+               /// The default strategy is <see 
cref="RollingFileAppender.LocalDateTime"/>.
+               /// </para>
+               /// </remarks>
+#else
+        /// <summary>
+               /// Gets or sets the strategy for determining the current date 
and time. The default
+               /// implementation is to use LocalDateTime which internally 
calls through to DateTime.Now. 
+               /// </summary>
+               /// <value>
+               /// An implementation of the <see 
cref="RollingFileAppender.IDateTime"/> interface which returns the current date 
and time.
+               /// </value>
+               /// <remarks>
+               /// <para>
+               /// Gets or sets the <see 
cref="RollingFileAppender.IDateTime"/> used to return the current date and time.
+               /// </para>
+        /// <para>
+               /// The default strategy is <see 
cref="RollingFileAppender.LocalDateTime"/>.
+               /// </para>
+               /// </remarks>
+#endif
+        public IDateTime DateTimeStrategy
+               {
+                       get { return m_dateTime; }
+                       set { m_dateTime = value; }
+               }
+
+               /// <summary>
+               /// Gets or sets the date pattern to be used for generating 
file names
+               /// when rolling over on date.
+               /// </summary>
+               /// <value>
+               /// The date pattern to be used for generating file names when 
rolling 
+               /// over on date.
+               /// </value>
+               /// <remarks>
+               /// <para>
+               /// Takes a string in the same format as expected by 
+               /// <see cref="log4net.DateFormatter.SimpleDateFormatter" />.
+               /// </para>
+               /// <para>
+               /// This property determines the rollover schedule when rolling 
over
+               /// on date.
+               /// </para>
+               /// </remarks>
+               public string DatePattern
+               {
+                       get { return m_datePattern; }
+                       set { m_datePattern = value; }
+               }
+  
+               /// <summary>
+               /// Gets or sets the maximum number of backup files that are 
kept before
+               /// the oldest is erased.
+               /// </summary>
+               /// <value>
+               /// The maximum number of backup files that are kept before the 
oldest is
+               /// erased.
+               /// </value>
+               /// <remarks>
+               /// <para>
+               /// If set to zero, then there will be no backup files and the 
log file 
+               /// will be truncated when it reaches <see 
cref="MaxFileSize"/>.  
+               /// </para>
+               /// <para>
+               /// If a negative number is supplied then no deletions will be 
made.  Note 
+               /// that this could result in very slow performance as a large 
number of 
+               /// files are rolled over unless <see cref="CountDirection"/> 
is used.
+               /// </para>
+               /// <para>
+               /// The maximum applies to <b>each</b> time based group of 
files and 
+               /// <b>not</b> the total.
+               /// </para>
+               /// </remarks>
+               public int MaxSizeRollBackups
+               {
+                       get { return m_maxSizeRollBackups; }
+                       set { m_maxSizeRollBackups = value; }
+               }
+  
+               /// <summary>
+               /// Gets or sets the maximum size that the output file is 
allowed to reach
+               /// before being rolled over to backup files.
+               /// </summary>
+               /// <value>
+               /// The maximum size in bytes that the output file is allowed 
to reach before being 
+               /// rolled over to backup files.
+               /// </value>
+               /// <remarks>
+               /// <para>
+               /// This property is equivalent to <see 
cref="MaximumFileSize"/> except
+               /// that it is required for differentiating the setter taking a
+               /// <see cref="long"/> argument from the setter taking a <see 
cref="string"/> 
+               /// argument.
+               /// </para>
+               /// <para>
+               /// The default maximum file size is 10MB (10*1024*1024).
+               /// </para>
+               /// </remarks>
+               public long MaxFileSize
+               {
+                       get { return m_maxFileSize; }
+                       set { m_maxFileSize = value; }
+               }
+  
+               /// <summary>
+               /// Gets or sets the maximum size that the output file is 
allowed to reach
+               /// before being rolled over to backup files.
+               /// </summary>
+               /// <value>
+               /// The maximum size that the output file is allowed to reach 
before being 
+               /// rolled over to backup files.
+               /// </value>
+               /// <remarks>
+               /// <para>
+               /// This property allows you to specify the maximum size with 
the
+               /// suffixes "KB", "MB" or "GB" so that the size is interpreted 
being 
+               /// expressed respectively in kilobytes, megabytes or 
gigabytes. 
+               /// </para>
+               /// <para>
+               /// 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
+               {
+                       get { return 
m_maxFileSize.ToString(NumberFormatInfo.InvariantInfo); }
+                       set { m_maxFileSize = OptionConverter.ToFileSize(value, 
m_maxFileSize + 1); }
+               }
+
+               /// <summary>
+               /// Gets or sets the rolling file count direction. 
+               /// </summary>
+               /// <value>
+               /// The rolling file count direction.
+               /// </value>
+               /// <remarks>
+               /// <para>
+               /// Indicates if the current file is the lowest numbered file 
or the
+               /// highest numbered file.
+               /// </para>
+               /// <para>
+               /// By default newer files have lower numbers (<see 
cref="CountDirection" /> &lt; 0),
+               /// i.e. log.1 is most recent, log.5 is the 5th backup, etc...
+               /// </para>
+               /// <para>
+               /// <see cref="CountDirection" /> &gt;= 0 does the opposite i.e.
+               /// log.1 is the first backup made, log.5 is the 5th backup 
made, etc.
+               /// For infinite backups use <see cref="CountDirection" /> 
&gt;= 0 to reduce 
+               /// rollover costs.
+               /// </para>
+               /// <para>The default file count direction is -1.</para>
+               /// </remarks>
+               public int CountDirection
+               {
+                       get { return m_countDirection; }
+                       set { m_countDirection = value; }
+               }
+  
+               /// <summary>
+               /// Gets or sets the rolling style.
+               /// </summary>
+               /// <value>The rolling style.</value>
+               /// <remarks>
+               /// <para>
+               /// The default rolling style is <see 
cref="RollingMode.Composite" />.
+               /// </para>
+               /// <para>
+               /// When set to <see cref="RollingMode.Once"/> this appender's
+               /// <see cref="FileAppender.AppendToFile"/> property is set to 
<c>false</c>, otherwise
+               /// the appender would append to a single file rather than 
rolling
+               /// the file each time it is opened.
+               /// </para>
+               /// </remarks>
+               public RollingMode RollingStyle
+               {
+                       get { return m_rollingStyle; }
+                       set
+                       {
+                               m_rollingStyle = value;
+                               switch (m_rollingStyle) 
+                               {
+                                       case RollingMode.Once:
+                                               m_rollDate = false;
+                                               m_rollSize = false;
+
+                                               this.AppendToFile = false;
+                                               break;
+
+                                       case RollingMode.Size:
+                                               m_rollDate = false;
+                                               m_rollSize = true;
+                                               break;
+
+                                       case RollingMode.Date:
+                                               m_rollDate = true;
+                                               m_rollSize = false;
+                                               break;
+
+                                       case RollingMode.Composite:
+                                               m_rollDate = true;
+                                               m_rollSize = true;
+                                               break;    
+                               }
+                       }
+               }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether to preserve the file name 
extension when rolling.
+        /// </summary>
+        /// <value>
+        /// <c>true</c> if the file name extension should be preserved.
+        /// </value>
+        /// <remarks>
+        /// <para>
+        /// By default file.log is rolled to file.log.yyyy-MM-dd or 
file.log.curSizeRollBackup.
+        /// However, under Windows the new file name will loose any program 
associations as the
+        /// extension is changed. Optionally file.log can be renamed to 
file.yyyy-MM-dd.log or
+        /// file.curSizeRollBackup.log to maintain any program associations.
+        /// </para>
+        /// </remarks>
+        public bool PreserveLogFileNameExtension
+        {
+            get { return m_preserveLogFileNameExtension; }
+            set { m_preserveLogFileNameExtension = value; }
+        }
+
+               /// <summary>
+               /// Gets or sets a value indicating whether to always log to
+               /// the same file.
+               /// </summary>
+               /// <value>
+               /// <c>true</c> if always should be logged to the same file, 
otherwise <c>false</c>.
+               /// </value>
+               /// <remarks>
+               /// <para>
+               /// By default file.log is always the current file.  Optionally
+               /// file.log.yyyy-mm-dd for current formatted datePattern can 
by the currently
+               /// logging file (or file.log.curSizeRollBackup or even
+               /// file.log.yyyy-mm-dd.curSizeRollBackup).
+               /// </para>
+               /// <para>
+               /// This will make time based rollovers with a large number of 
backups 
+               /// much faster as the appender it won't have to rename all the 
backups!
+               /// </para>
+               /// </remarks>
+               public bool StaticLogFileName
+               {
+                       get { return m_staticLogFileName; }
+                       set { m_staticLogFileName = value; }
+               }
+
+               #endregion Public Instance Properties
+
+           #region Private Static Fields
+
+           /// <summary>
+           /// The fully qualified type of the RollingFileAppender class.
+           /// </summary>
+           /// <remarks>
+           /// Used by the internal logger to record the Type of the
+           /// log message.
+           /// </remarks>
+           private readonly static Type declaringType = 
typeof(RollingFileAppender);
+
+           #endregion Private Static Fields
+
+               #region Override implementation of FileAppender 
+  
+               /// <summary>
+               /// Sets the quiet writer being used.
+               /// </summary>
+               /// <remarks>
+               /// This method can be overridden by sub classes.
+               /// </remarks>
+               /// <param name="writer">the writer to set</param>
+               override protected void SetQWForFiles(TextWriter writer) 
+               {
+                       QuietWriter = new CountingQuietTextWriter(writer, 
ErrorHandler);
+               }
+
+               /// <summary>
+               /// Write out a logging event.
+               /// </summary>
+               /// <param name="loggingEvent">the event to write to 
file.</param>
+               /// <remarks>
+               /// <para>
+               /// Handles append time behavior for RollingFileAppender.  This 
checks
+               /// if a roll over either by date (checked first) or time 
(checked second)
+               /// is need and then appends to the file last.
+               /// </para>
+               /// </remarks>
+               override protected void Append(LoggingEvent loggingEvent) 
+               {
+                       AdjustFileBeforeAppend();
+                       base.Append(loggingEvent);
+               }
+  
+               /// <summary>
+               /// Write out an array of logging events.
+               /// </summary>
+               /// <param name="loggingEvents">the events to write to 
file.</param>
+               /// <remarks>
+               /// <para>
+               /// Handles append time behavior for RollingFileAppender.  This 
checks
+               /// if a roll over either by date (checked first) or time 
(checked second)
+               /// is need and then appends to the file last.
+               /// </para>
+               /// </remarks>
+               override protected void Append(LoggingEvent[] loggingEvents) 
+               {
+                       AdjustFileBeforeAppend();
+                       base.Append(loggingEvents);
+               }
+
+               /// <summary>
+               /// Performs any required rolling before outputting the next 
event
+               /// </summary>
+               /// <remarks>
+               /// <para>
+               /// Handles append time behavior for RollingFileAppender.  This 
checks
+               /// if a roll over either by date (checked first) or time 
(checked second)
+               /// is need and then appends to the file last.
+               /// </para>
+               /// </remarks>
+               virtual protected void AdjustFileBeforeAppend()
+               {
                        // reuse the file appenders locking model to lock the 
rolling
                        try
                        {
@@ -640,1125 +640,1125 @@ namespace log4net.Appender
                                {
                                        m_mutexForRolling.ReleaseMutex();
                                }
-                       }
-               }
-
-               /// <summary>
-               /// Creates and opens the file for logging.  If <see 
cref="StaticLogFileName"/>
-               /// is false then the fully qualified name is determined and 
used.
-               /// </summary>
-               /// <param name="fileName">the name of the file to open</param>
-               /// <param name="append">true to append to existing file</param>
-               /// <remarks>
-               /// <para>This method will ensure that the directory structure
-               /// for the <paramref name="fileName"/> specified exists.</para>
-               /// </remarks>
-               override protected void OpenFile(string fileName, bool append)
-               {
-                       lock(this)
-                       {
-                               fileName = GetNextOutputFileName(fileName);
-
-                               // Calculate the current size of the file
-                               long currentCount = 0;
-                               if (append) 
-                               {
-                                       using(SecurityContext.Impersonate(this))
-                                       {
-                                               if 
(System.IO.File.Exists(fileName))
-                                               {
-                                                       currentCount = (new 
FileInfo(fileName)).Length;
-                                               }
-                                       }
-                               }
-                               else
-                               {
-                                       if (LogLog.IsErrorEnabled)
-                                       {
-                                               // Internal check that the file 
is not being overwritten
-                                               // If not Appending to an 
existing file we should have rolled the file out of the
-                                               // way. Therefore we should not 
be over-writing an existing file.
-                                               // The only exception is if we 
are not allowed to roll the existing file away.
-                                               if (m_maxSizeRollBackups != 0 
&& FileExists(fileName))
-                                               {
-                                                       
LogLog.Error(declaringType, "RollingFileAppender: INTERNAL ERROR. Append is 
False but OutputFile ["+fileName+"] already exists.");
-                                               }
-                                       }
-                               }
-
-                               if (!m_staticLogFileName) 
-                               {
-                                       m_scheduledFilename = fileName;
-                               }
-
-                               // Open the file (call the base class to do it)
-                               base.OpenFile(fileName, append);
-
-                               // Set the file size onto the counting writer
-                               ((CountingQuietTextWriter)QuietWriter).Count = 
currentCount;
-                       }
-               }
-
-               /// <summary>
-               /// Get the current output file name
-               /// </summary>
-               /// <param name="fileName">the base file name</param>
-               /// <returns>the output file name</returns>
-               /// <remarks>
-               /// The output file name is based on the base fileName 
specified.
-               /// If <see cref="StaticLogFileName"/> is set then the output 
-               /// file name is the same as the base file passed in. Otherwise
-               /// the output file depends on the date pattern, on the count
-               /// direction or both.
-               /// </remarks>
-               protected string GetNextOutputFileName(string fileName)
-               {
-                       if (!m_staticLogFileName) 
-                       {
-                               fileName = fileName.Trim();
-
-                               if (m_rollDate)
-                               {
-                    fileName = CombinePath(fileName, 
m_now.ToString(m_datePattern, 
System.Globalization.DateTimeFormatInfo.InvariantInfo));
-                               }
-
-                               if (m_countDirection >= 0) 
-                               {
-                    fileName = CombinePath(fileName, "." + 
m_curSizeRollBackups);
-                               }
-                       }
-
-                       return fileName;
-               }
-
-               #endregion
-
-               #region Initialize Options
-
-               /// <summary>
-               ///     Determines curSizeRollBackups (only within the current 
roll point)
-               /// </summary>
-               private void DetermineCurSizeRollBackups()
-               {
-                       m_curSizeRollBackups = 0;
-       
-                       string fullPath = null;
-                       string fileName = null;
-
-                       using(SecurityContext.Impersonate(this))
-                       {
-                               fullPath = 
System.IO.Path.GetFullPath(m_baseFileName);
-                               fileName = System.IO.Path.GetFileName(fullPath);
-                       }
-
-                       ArrayList arrayFiles = GetExistingFiles(fullPath);
-                       InitializeRollBackups(fileName, arrayFiles);
-
-                       LogLog.Debug(declaringType, "curSizeRollBackups starts 
at ["+m_curSizeRollBackups+"]");
-               }
-
-               /// <summary>
-               /// Generates a wildcard pattern that can be used to find all 
files
-               /// that are similar to the base file name.
-               /// </summary>
-               /// <param name="baseFileName"></param>
-               /// <returns></returns>
-               private string GetWildcardPatternForFile(string baseFileName)
-               {
-            if (m_preserveLogFileNameExtension)
-            {
-                return Path.GetFileNameWithoutExtension(baseFileName) + "*" + 
Path.GetExtension(baseFileName);
-            }
-            else
-            {
-                return baseFileName + '*';
-            }
-               }
-
-               /// <summary>
-               /// Builds a list of filenames for all files matching the base 
filename plus a file
-               /// pattern.
-               /// </summary>
-               /// <param name="baseFilePath"></param>
-               /// <returns></returns>
-               private ArrayList GetExistingFiles(string baseFilePath)
-               {
-                       ArrayList alFiles = new ArrayList();
-
-                       string directory = null;
-
-                       using(SecurityContext.Impersonate(this))
-                       {
-                               string fullPath = 
Path.GetFullPath(baseFilePath);
-
-                               directory = Path.GetDirectoryName(fullPath);
-                               if (Directory.Exists(directory))
-                               {
-                                       string baseFileName = 
Path.GetFileName(fullPath);
-
-                                       string[] files = 
Directory.GetFiles(directory, GetWildcardPatternForFile(baseFileName));
-       
-                                       if (files != null)
-                                       {
-                                               for (int i = 0; i < 
files.Length; i++) 
-                                               {
-                                                       string curFileName = 
Path.GetFileName(files[i]);
-                                                       if 
(curFileName.StartsWith(Path.GetFileNameWithoutExtension(baseFileName)))
-                                                       {
-                                                               
alFiles.Add(curFileName);
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-                       LogLog.Debug(declaringType, "Searched for existing 
files in ["+directory+"]");
-                       return alFiles;
-               }
-
-               /// <summary>
-               /// Initiates a roll over if needed for crossing a date 
boundary since the last run.
-               /// </summary>
-               private void RollOverIfDateBoundaryCrossing()
-               {
-                       if (m_staticLogFileName && m_rollDate) 
-                       {
-                               if (FileExists(m_baseFileName)) 
-                               {
-                                       DateTime last;
-                                       
using(SecurityContext.Impersonate(this)) {
-#if !NET_1_0 && !CLI_1_0 && !NETCF
-                        if (DateTimeStrategy is UniversalDateTime)
-                                               {
-                                                       last = 
System.IO.File.GetLastWriteTimeUtc(m_baseFileName);
-                                               }
-                                               else
-                                               {
-#endif
-                                                       last = 
System.IO.File.GetLastWriteTime(m_baseFileName);
-#if !NET_1_0 && !CLI_1_0 && !NETCF
-                        }
-#endif
-                    }
-                                       LogLog.Debug(declaringType, 
"["+last.ToString(m_datePattern,System.Globalization.DateTimeFormatInfo.InvariantInfo)+"]
 vs. 
["+m_now.ToString(m_datePattern,System.Globalization.DateTimeFormatInfo.InvariantInfo)+"]");
-
-                                       if 
(!(last.ToString(m_datePattern,System.Globalization.DateTimeFormatInfo.InvariantInfo).Equals(m_now.ToString(m_datePattern,
 System.Globalization.DateTimeFormatInfo.InvariantInfo)))) 
-                                       {
-                                               m_scheduledFilename = 
CombinePath(m_baseFileName, last.ToString(m_datePattern, 
System.Globalization.DateTimeFormatInfo.InvariantInfo));
-                                               LogLog.Debug(declaringType, 
"Initial roll over to ["+m_scheduledFilename+"]");
-                                               RollOverTime(false);
-                                               LogLog.Debug(declaringType, 
"curSizeRollBackups after rollOver at ["+m_curSizeRollBackups+"]");
-                                       }
-                               }
-                       }
-               }
-
-               /// <summary>
-               /// 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();
-                       RollOverIfDateBoundaryCrossing();
-
-                       // If file exists and we are not appending then roll it 
out of the way
-                       if (AppendToFile == false)
-                       {
-                               bool fileExists = false;
-                               string fileName = 
GetNextOutputFileName(m_baseFileName);
-
-                               using(SecurityContext.Impersonate(this))
-                               {
-                                       fileExists = 
System.IO.File.Exists(fileName);
-                               }
-
-                               if (fileExists)
-                               {
-                                       if (m_maxSizeRollBackups == 0)
-                                       {
-                                               LogLog.Debug(declaringType, 
"Output file ["+fileName+"] already exists. MaxSizeRollBackups is 0; cannot 
roll. Overwriting existing file.");
-                                       }
-                                       else
-                                       {
-                                               LogLog.Debug(declaringType, 
"Output file ["+fileName+"] already exists. Not appending to file. Rolling 
existing file out of the way.");
-
-                                               RollOverRenameFiles(fileName);
-                                       }
-                               }
-                       }
-               }
-
-               /// <summary>
-               /// Does the work of bumping the 'current' file counter higher
-               /// to the highest count when an incremental file name is seen.
-               /// The highest count is either the first file (when count 
direction
-               /// is greater than 0) or the last file (when count direction 
less than 0).
-               /// In either case, we want to know the highest count that is 
present.
-               /// </summary>
-               /// <param name="baseFile"></param>
-               /// <param name="curFileName"></param>
-               private void InitializeFromOneFile(string baseFile, string 
curFileName)
-               {
-            if 
(curFileName.StartsWith(Path.GetFileNameWithoutExtension(baseFile)) == false)
-                       {
-                               // This is not a log file, so ignore
-                               return;
-                       }
-                       if (curFileName.Equals(baseFile)) 
-                       {
-                               // Base log file is not an incremented logfile 
(.1 or .2, etc)
-                               return;
-                       }
-       
-            /*
-                       if (m_staticLogFileName) 
-                       {
-                               int endLength = curFileName.Length - index;
-                               if (baseFile.Length + endLength != 
curFileName.Length) 
-                               {
-                                       // file is probably scheduledFilename + 
.x so I don't care
-                                       return;
-                               }
-                       }
-            */
-       
-                       // Only look for files in the current roll point
-                       if (m_rollDate && !m_staticLogFileName)
-                       {
-                               string date = 
m_dateTime.Now.ToString(m_datePattern, 
System.Globalization.DateTimeFormatInfo.InvariantInfo);
-                               string prefix = m_preserveLogFileNameExtension 
? Path.GetFileNameWithoutExtension(baseFile) + date : baseFile + date;
-                               string suffix = m_preserveLogFileNameExtension 
? Path.GetExtension(baseFile) : "";
-                               if (!curFileName.StartsWith(prefix) || 
!curFileName.EndsWith(suffix))
-                               {
-                                       LogLog.Debug(declaringType, "Ignoring 
file ["+curFileName+"] because it is from a different date period");
-                                       return;
-                               }
-                       }
-            
-                       try 
-                       {
-                               // Bump the counter up to the highest count 
seen so far
-                int backup = GetBackUpIndex(curFileName);
-                
-                // caution: we might get a false positive when certain
-                // date patterns such as yyyyMMdd are used...those are
-                // valid number but aren't the kind of back up index
-                // we're looking for
-                if (backup > m_curSizeRollBackups)
-                {
-                    if (0 == m_maxSizeRollBackups)
-                    {
-                        // Stay at zero when zero backups are desired
-                    }
-                    else if (-1 == m_maxSizeRollBackups)
-                    {
-                        // Infinite backups, so go as high as the highest value
-                        m_curSizeRollBackups = backup;
-                    }
-                    else
-                    {
-                        // Backups limited to a finite number
-                        if (m_countDirection >= 0)
-                        {
-                            // Go with the highest file when counting up
-                            m_curSizeRollBackups = backup;
-                        }
-                        else
-                        {
-                            // Clip to the limit when counting down
-                            if (backup <= m_maxSizeRollBackups)
-                            {
-                                m_curSizeRollBackups = backup;
-                            }
-                        }
-                    }
-                    LogLog.Debug(declaringType, "File name [" + curFileName + 
"] moves current count to [" + m_curSizeRollBackups + "]");
-                }
-                       } 
-                       catch(FormatException) 
-                       {
-                               //this happens when file.log -> 
file.log.yyyy-MM-dd which is normal
-                               //when staticLogFileName == false
-                               LogLog.Debug(declaringType, "Encountered a 
backup file not ending in .x ["+curFileName+"]");
-                       }
-               }
-
-        /// <summary>
-        /// Attempts to extract a number from the end of the file name that 
indicates
-        /// the number of the times the file has been rolled over.
-        /// </summary>
-        /// <remarks>
-        /// Certain date pattern extensions like yyyyMMdd will be parsed as 
valid backup indexes.
-        /// </remarks>
-        /// <param name="curFileName"></param>
-        /// <returns></returns>
-           private int GetBackUpIndex(string curFileName)
-           {
-            int backUpIndex = -1;
-            string fileName = curFileName;
-
-            if (m_preserveLogFileNameExtension)
-            {
-                fileName = Path.GetFileNameWithoutExtension(fileName);
-            }
-            
-            int index = fileName.LastIndexOf(".");
-            if (index > 0)
-            {
-                // if the "yyyy-MM-dd" component of file.log.yyyy-MM-dd is 
passed to TryParse
-                // it will gracefully fail and return backUpIndex will be 0
-                SystemInfo.TryParse(fileName.Substring(index + 1), out 
backUpIndex);
-            }
-
-            return backUpIndex;
-           }
-
-           /// <summary>
-               /// Takes a list of files and a base file name, and looks for 
-               /// 'incremented' versions of the base file.  Bumps the max
-               /// count up to the highest count seen.
-               /// </summary>
-               /// <param name="baseFile"></param>
-               /// <param name="arrayFiles"></param>
-               private void InitializeRollBackups(string baseFile, ArrayList 
arrayFiles)
-               {
-                       if (null != arrayFiles)
-                       {
-                               string baseFileLower = 
baseFile.ToLower(System.Globalization.CultureInfo.InvariantCulture);
-
-                               foreach(string curFileName in arrayFiles)
-                               {
-                                       InitializeFromOneFile(baseFileLower, 
curFileName.ToLower(System.Globalization.CultureInfo.InvariantCulture));
-                               }
-                       }
-               }
-
-               /// <summary>
-               /// Calculates the RollPoint for the datePattern supplied.
-               /// </summary>
-               /// <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
-               /// most suitable roll point is. The roll point chosen is the 
roll point
-               /// with the smallest period that can be detected using the 
date pattern
-               /// supplied. i.e. if the date pattern only outputs the year, 
month, day 
-               /// and hour then the smallest roll point that can be detected 
would be
-               /// and hourly roll point as minutes could not be detected.
-               /// </remarks>
-               private RollPoint ComputeCheckPeriod(string datePattern) 
-               {
-                       // 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.
-
-                       // Get string representation of base line date
-                       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(s_date1970, 
(RollPoint)i).ToString(datePattern, 
System.Globalization.DateTimeFormatInfo.InvariantInfo);
-
-                               LogLog.Debug(declaringType, "Type = ["+i+"], r0 
= ["+r0+"], r1 = ["+r1+"]");
-
-                               // Check if the string representations are 
different
-                               if (r0 != null && r1 != null && !r0.Equals(r1)) 
-                               {
-                                       // Found highest precision roll point
-                                       return (RollPoint)i;
-                               }
-                       }
-
-                       return RollPoint.InvalidRollPoint; // Deliberately head 
for trouble...
-               }
-
-               /// <summary>
-               /// Initialize the appender based on the options set
-               /// </summary>
-               /// <remarks>
-               /// <para>
-               /// This is part of the <see cref="IOptionHandler"/> delayed 
object
-               /// activation scheme. The <see cref="ActivateOptions"/> method 
must 
-               /// be called on this object after the configuration properties 
have
-               /// been set. Until <see cref="ActivateOptions"/> is called this
-               /// object is in an undefined state and must not be used. 
-               /// </para>
-               /// <para>
-               /// If any of the configuration properties are modified then 
-               /// <see cref="ActivateOptions"/> must be called again.
-               /// </para>
-               /// <para>
-               /// Sets initial conditions including date/time roll over 
information, first check,
-               /// scheduledFilename, and calls <see cref="ExistingInit"/> to 
initialize
-               /// the current number of backups.
-               /// </para>
-               /// </remarks>
-               override public void ActivateOptions() 
-               {
-                       if (m_dateTime == null)
-                       {
-                               m_dateTime = new LocalDateTime();
-                       }
-
-                       if (m_rollDate && m_datePattern != null) 
-                       {
-                               m_now = m_dateTime.Now;
-                               m_rollPoint = ComputeCheckPeriod(m_datePattern);
-
-                               if (m_rollPoint == RollPoint.InvalidRollPoint)
-                               {
-                                       throw new ArgumentException("Invalid 
RollPoint, unable to parse ["+m_datePattern+"]");
-                               }
-
-                               // next line added as this removes the name 
check in rollOver
-                               m_nextCheck = NextCheckDate(m_now, m_rollPoint);
-                       } 
-                       else 
-                       {
-                               if (m_rollDate)
-                               {
-                                       ErrorHandler.Error("Either DatePattern 
or rollingStyle options are not set for ["+Name+"].");
-                               }
-                       }
-
-                       if (SecurityContext == null)
-                       {
-                               SecurityContext = 
SecurityContextProvider.DefaultProvider.CreateSecurityContext(this);
-                       }
-
-                       using(SecurityContext.Impersonate(this))
-                       {
-                               // Must convert the FileAppender's m_filePath 
to an absolute path before we
-                               // call ExistingInit(). This will be done by 
the base.ActivateOptions() but
-                               // we need to duplicate that functionality here 
first.
-                               base.File = ConvertToFullPath(base.File.Trim());
-
-                               // Store fully qualified base file name
+                       }
+               }
+
+               /// <summary>
+               /// Creates and opens the file for logging.  If <see 
cref="StaticLogFileName"/>
+               /// is false then the fully qualified name is determined and 
used.
+               /// </summary>
+               /// <param name="fileName">the name of the file to open</param>
+               /// <param name="append">true to append to existing file</param>
+               /// <remarks>
+               /// <para>This method will ensure that the directory structure
+               /// for the <paramref name="fileName"/> specified exists.</para>
+               /// </remarks>
+               override protected void OpenFile(string fileName, bool append)
+               {
+                       lock(this)
+                       {
+                               fileName = GetNextOutputFileName(fileName);
+
+                               // Calculate the current size of the file
+                               long currentCount = 0;
+                               if (append) 
+                               {
+                                       using(SecurityContext.Impersonate(this))
+                                       {
+                                               if 
(System.IO.File.Exists(fileName))
+                                               {
+                                                       currentCount = (new 
FileInfo(fileName)).Length;
+                                               }
+                                       }
+                               }
+                               else
+                               {
+                                       if (LogLog.IsErrorEnabled)
+                                       {
+                                               // Internal check that the file 
is not being overwritten
+                                               // If not Appending to an 
existing file we should have rolled the file out of the
+                                               // way. Therefore we should not 
be over-writing an existing file.
+                                               // The only exception is if we 
are not allowed to roll the existing file away.
+                                               if (m_maxSizeRollBackups != 0 
&& FileExists(fileName))
+                                               {
+                                                       
LogLog.Error(declaringType, "RollingFileAppender: INTERNAL ERROR. Append is 
False but OutputFile ["+fileName+"] already exists.");
+                                               }
+                                       }
+                               }
+
+                               if (!m_staticLogFileName) 
+                               {
+                                       m_scheduledFilename = fileName;
+                               }
+
+                               // Open the file (call the base class to do it)
+                               base.OpenFile(fileName, append);
+
+                               // Set the file size onto the counting writer
+                               ((CountingQuietTextWriter)QuietWriter).Count = 
currentCount;
+                       }
+               }
+
+               /// <summary>
+               /// Get the current output file name
+               /// </summary>
+               /// <param name="fileName">the base file name</param>
+               /// <returns>the output file name</returns>
+               /// <remarks>
+               /// The output file name is based on the base fileName 
specified.
+               /// If <see cref="StaticLogFileName"/> is set then the output 
+               /// file name is the same as the base file passed in. Otherwise
+               /// the output file depends on the date pattern, on the count
+               /// direction or both.
+               /// </remarks>
+               protected string GetNextOutputFileName(string fileName)
+               {
+                       if (!m_staticLogFileName) 
+                       {
+                               fileName = fileName.Trim();
+
+                               if (m_rollDate)
+                               {
+                    fileName = CombinePath(fileName, 
m_now.ToString(m_datePattern, 
System.Globalization.DateTimeFormatInfo.InvariantInfo));
+                               }
+
+                               if (m_countDirection >= 0) 
+                               {
+                    fileName = CombinePath(fileName, "." + 
m_curSizeRollBackups);
+                               }
+                       }
+
+                       return fileName;
+               }
+
+               #endregion
+
+               #region Initialize Options
+
+               /// <summary>
+               ///     Determines curSizeRollBackups (only within the current 
roll point)
+               /// </summary>
+               private void DetermineCurSizeRollBackups()
+               {
+                       m_curSizeRollBackups = 0;
+       
+                       string fullPath = null;
+                       string fileName = null;
+
+                       using(SecurityContext.Impersonate(this))
+                       {
+                               fullPath = 
System.IO.Path.GetFullPath(m_baseFileName);
+                               fileName = System.IO.Path.GetFileName(fullPath);
+                       }
+
+                       ArrayList arrayFiles = GetExistingFiles(fullPath);
+                       InitializeRollBackups(fileName, arrayFiles);
+
+                       LogLog.Debug(declaringType, "curSizeRollBackups starts 
at ["+m_curSizeRollBackups+"]");
+               }
+
+               /// <summary>
+               /// Generates a wildcard pattern that can be used to find all 
files
+               /// that are similar to the base file name.
+               /// </summary>
+               /// <param name="baseFileName"></param>
+               /// <returns></returns>
+               private string GetWildcardPatternForFile(string baseFileName)
+               {
+            if (m_preserveLogFileNameExtension)
+            {
+                return Path.GetFileNameWithoutExtension(baseFileName) + "*" + 
Path.GetExtension(baseFileName);
+            }
+            else
+            {
+                return baseFileName + '*';
+            }
+               }
+
+               /// <summary>
+               /// Builds a list of filenames for all files matching the base 
filename plus a file
+               /// pattern.
+               /// </summary>
+               /// <param name="baseFilePath"></param>
+               /// <returns></returns>
+               private ArrayList GetExistingFiles(string baseFilePath)
+               {
+                       ArrayList alFiles = new ArrayList();
+
+                       string directory = null;
+
+                       using(SecurityContext.Impersonate(this))
+                       {
+                               string fullPath = 
Path.GetFullPath(baseFilePath);
+
+                               directory = Path.GetDirectoryName(fullPath);
+                               if (Directory.Exists(directory))
+                               {
+                                       string baseFileName = 
Path.GetFileName(fullPath);
+
+                                       string[] files = 
Directory.GetFiles(directory, GetWildcardPatternForFile(baseFileName));
+       
+                                       if (files != null)
+                                       {
+                                               for (int i = 0; i < 
files.Length; i++) 
+                                               {
+                                                       string curFileName = 
Path.GetFileName(files[i]);
+                                                       if 
(curFileName.StartsWith(Path.GetFileNameWithoutExtension(baseFileName)))
+                                                       {
+                                                               
alFiles.Add(curFileName);
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       LogLog.Debug(declaringType, "Searched for existing 
files in ["+directory+"]");
+                       return alFiles;
+               }
+
+               /// <summary>
+               /// Initiates a roll over if needed for crossing a date 
boundary since the last run.
+               /// </summary>
+               private void RollOverIfDateBoundaryCrossing()
+               {
+                       if (m_staticLogFileName && m_rollDate) 
+                       {
+                               if (FileExists(m_baseFileName)) 
+                               {
+                                       DateTime last;
+                                       
using(SecurityContext.Impersonate(this)) {
+#if !NET_1_0 && !CLI_1_0 && !NETCF
+                        if (DateTimeStrategy is UniversalDateTime)
+                                               {
+                                                       last = 
System.IO.File.GetLastWriteTimeUtc(m_baseFileName);
+                                               }
+                                               else
+                                               {
+#endif
+                                                       last = 
System.IO.File.GetLastWriteTime(m_baseFileName);
+#if !NET_1_0 && !CLI_1_0 && !NETCF
+                        }
+#endif
+                    }
+                                       LogLog.Debug(declaringType, 
"["+last.ToString(m_datePattern,System.Globalization.DateTimeFormatInfo.InvariantInfo)+"]
 vs. 
["+m_now.ToString(m_datePattern,System.Globalization.DateTimeFormatInfo.InvariantInfo)+"]");
+
+                                       if 
(!(last.ToString(m_datePattern,System.Globalization.DateTimeFormatInfo.InvariantInfo).Equals(m_now.ToString(m_datePattern,
 System.Globalization.DateTimeFormatInfo.InvariantInfo)))) 
+                                       {
+                                               m_scheduledFilename = 
CombinePath(m_baseFileName, last.ToString(m_datePattern, 
System.Globalization.DateTimeFormatInfo.InvariantInfo));
+                                               LogLog.Debug(declaringType, 
"Initial roll over to ["+m_scheduledFilename+"]");
+                                               RollOverTime(false);
+                                               LogLog.Debug(declaringType, 
"curSizeRollBackups after rollOver at ["+m_curSizeRollBackups+"]");
+                                       }
+                               }
+                       }
+               }
+
+               /// <summary>
+               /// 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();
+                       RollOverIfDateBoundaryCrossing();
+
+                       // If file exists and we are not appending then roll it 
out of the way
+                       if (AppendToFile == false)
+                       {
+                               bool fileExists = false;
+                               string fileName = 
GetNextOutputFileName(m_baseFileName);
+
+                               using(SecurityContext.Impersonate(this))
+                               {
+                                       fileExists = 
System.IO.File.Exists(fileName);
+                               }
+
+                               if (fileExists)
+                               {
+                                       if (m_maxSizeRollBackups == 0)
+                                       {
+                                               LogLog.Debug(declaringType, 
"Output file ["+fileName+"] already exists. MaxSizeRollBackups is 0; cannot 
roll. Overwriting existing file.");
+                                       }
+                                       else
+                                       {
+                                               LogLog.Debug(declaringType, 
"Output file ["+fileName+"] already exists. Not appending to file. Rolling 
existing file out of the way.");
+
+                                               RollOverRenameFiles(fileName);
+                                       }
+                               }
+                       }
+               }
+
+               /// <summary>
+               /// Does the work of bumping the 'current' file counter higher
+               /// to the highest count when an incremental file name is seen.
+               /// The highest count is either the first file (when count 
direction
+               /// is greater than 0) or the last file (when count direction 
less than 0).
+               /// In either case, we want to know the highest count that is 
present.
+               /// </summary>
+               /// <param name="baseFile"></param>
+               /// <param name="curFileName"></param>
+               private void InitializeFromOneFile(string baseFile, string 
curFileName)
+               {
+            if 
(curFileName.StartsWith(Path.GetFileNameWithoutExtension(baseFile)) == false)
+                       {
+                               // This is not a log file, so ignore
+                               return;
+                       }
+                       if (curFileName.Equals(baseFile)) 
+                       {
+                               // Base log file is not an incremented logfile 
(.1 or .2, etc)
+                               return;
+                       }
+       
+            /*
+                       if (m_staticLogFileName) 
+                       {
+                               int endLength = curFileName.Length - index;
+                               if (baseFile.Length + endLength != 
curFileName.Length) 
+                               {
+                                       // file is probably scheduledFilename + 
.x so I don't care
+                                       return;
+                               }
+                       }
+            */
+       
+                       // Only look for files in the current roll point
+                       if (m_rollDate && !m_staticLogFileName)
+                       {
+                               string date = 
m_dateTime.Now.ToString(m_datePattern, 
System.Globalization.DateTimeFormatInfo.InvariantInfo);
+                               string prefix = m_preserveLogFileNameExtension 
? Path.GetFileNameWithoutExtension(baseFile) + date : baseFile + date;
+                               string suffix = m_preserveLogFileNameExtension 
? Path.GetExtension(baseFile) : "";
+                               if (!curFileName.StartsWith(prefix) || 
!curFileName.EndsWith(suffix))
+                               {
+                                       LogLog.Debug(declaringType, "Ignoring 
file ["+curFileName+"] because it is from a different date period");
+                                       return;
+                               }
+                       }
+            
+                       try 
+                       {
+                               // Bump the counter up to the highest count 
seen so far
+                int backup = GetBackUpIndex(curFileName);
+                
+                // caution: we might get a false positive when certain
+                // date patterns such as yyyyMMdd are used...those are
+                // valid number but aren't the kind of back up index
+                // we're looking for
+                if (backup > m_curSizeRollBackups)
+                {
+                    if (0 == m_maxSizeRollBackups)
+                    {
+                        // Stay at zero when zero backups are desired
+                    }
+                    else if (-1 == m_maxSizeRollBackups)
+                    {
+                        // Infinite backups, so go as high as the highest value
+                        m_curSizeRollBackups = backup;
+                    }
+                    else
+                    {
+                        // Backups limited to a finite number
+                        if (m_countDirection >= 0)
+                        {
+                            // Go with the highest file when counting up
+                            m_curSizeRollBackups = backup;
+                        }
+                        else
+                        {
+                            // Clip to the limit when counting down
+                            if (backup <= m_maxSizeRollBackups)
+                            {
+                                m_curSizeRollBackups = backup;
+                            }
+                        }
+                    }
+                    LogLog.Debug(declaringType, "File name [" + curFileName + 
"] moves current count to [" + m_curSizeRollBackups + "]");
+                }
+                       } 
+                       catch(FormatException) 
+                       {
+                               //this happens when file.log -> 
file.log.yyyy-MM-dd which is normal
+                               //when staticLogFileName == false
+                               LogLog.Debug(declaringType, "Encountered a 
backup file not ending in .x ["+curFileName+"]");
+                       }
+               }
+
+        /// <summary>
+        /// Attempts to extract a number from the end of the file name that 
indicates
+        /// the number of the times the file has been rolled over.
+        /// </summary>
+        /// <remarks>
+        /// Certain date pattern extensions like yyyyMMdd will be parsed as 
valid backup indexes.
+        /// </remarks>
+        /// <param name="curFileName"></param>
+        /// <returns></returns>
+           private int GetBackUpIndex(string curFileName)
+           {
+            int backUpIndex = -1;
+            string fileName = curFileName;
+
+            if (m_preserveLogFileNameExtension)
+            {
+                fileName = Path.GetFileNameWithoutExtension(fileName);
+            }
+            
+            int index = fileName.LastIndexOf(".");
+            if (index > 0)
+            {
+                // if the "yyyy-MM-dd" component of file.log.yyyy-MM-dd is 
passed to TryParse
+                // it will gracefully fail and return backUpIndex will be 0
+                SystemInfo.TryParse(fileName.Substring(index + 1), out 
backUpIndex);
+            }
+
+            return backUpIndex;
+           }
+
+           /// <summary>
+               /// Takes a list of files and a base file name, and looks for 
+               /// 'incremented' versions of the base file.  Bumps the max
+               /// count up to the highest count seen.
+               /// </summary>
+               /// <param name="baseFile"></param>
+               /// <param name="arrayFiles"></param>
+               private void InitializeRollBackups(string baseFile, ArrayList 
arrayFiles)
+               {
+                       if (null != arrayFiles)
+                       {
+                               string baseFileLower = 
baseFile.ToLower(System.Globalization.CultureInfo.InvariantCulture);
+
+                               foreach(string curFileName in arrayFiles)
+                               {
+                                       InitializeFromOneFile(baseFileLower, 
curFileName.ToLower(System.Globalization.CultureInfo.InvariantCulture));
+                               }
+                       }
+               }
+
+               /// <summary>
+               /// Calculates the RollPoint for the datePattern supplied.
+               /// </summary>
+               /// <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
+               /// most suitable roll point is. The roll point chosen is the 
roll point
+               /// with the smallest period that can be detected using the 
date pattern
+               /// supplied. i.e. if the date pattern only outputs the year, 
month, day 
+               /// and hour then the smallest roll point that can be detected 
would be
+               /// and hourly roll point as minutes could not be detected.
+               /// </remarks>
+               private RollPoint ComputeCheckPeriod(string datePattern) 
+               {
+                       // 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.
+
+                       // Get string representation of base line date
+                       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(s_date1970, 
(RollPoint)i).ToString(datePattern, 
System.Globalization.DateTimeFormatInfo.InvariantInfo);
+
+                               LogLog.Debug(declaringType, "Type = ["+i+"], r0 
= ["+r0+"], r1 = ["+r1+"]");
+
+                               // Check if the string representations are 
different
+                               if (r0 != null && r1 != null && !r0.Equals(r1)) 
+                               {
+                                       // Found highest precision roll point
+                                       return (RollPoint)i;
+                               }
+                       }
+
+                       return RollPoint.InvalidRollPoint; // Deliberately head 
for trouble...
+               }
+
+               /// <summary>
+               /// Initialize the appender based on the options set
+               /// </summary>
+               /// <remarks>
+               /// <para>
+               /// This is part of the <see cref="IOptionHandler"/> delayed 
object
+               /// activation scheme. The <see cref="ActivateOptions"/> method 
must 
+               /// be called on this object after the configuration properties 
have
+               /// been set. Until <see cref="ActivateOptions"/> is called this
+               /// object is in an undefined state and must not be used. 
+               /// </para>
+               /// <para>
+               /// If any of the configuration properties are modified then 
+               /// <see cref="ActivateOptions"/> must be called again.
+               /// </para>
+               /// <para>
+               /// Sets initial conditions including date/time roll over 
information, first check,
+               /// scheduledFilename, and calls <see cref="ExistingInit"/> to 
initialize
+               /// the current number of backups.
+               /// </para>
+               /// </remarks>
+               override public void ActivateOptions() 
+               {
+                       if (m_dateTime == null)
+                       {
+                               m_dateTime = new LocalDateTime();
+                       }
+
+                       if (m_rollDate && m_datePattern != null) 
+                       {
+                               m_now = m_dateTime.Now;
+                               m_rollPoint = ComputeCheckPeriod(m_datePattern);
+
+                               if (m_rollPoint == RollPoint.InvalidRollPoint)
+                               {
+                                       throw new ArgumentException("Invalid 
RollPoint, unable to parse ["+m_datePattern+"]");
+                               }
+
+                               // next line added as this removes the name 
check in rollOver
+                               m_nextCheck = NextCheckDate(m_now, m_rollPoint);
+                       } 
+                       else 
+                       {
+                               if (m_rollDate)
+                               {
+                                       ErrorHandler.Error("Either DatePattern 
or rollingStyle options are not set for ["+Name+"].");
+                               }
+                       }
+
+                       if (SecurityContext == null)
+                       {
+                               SecurityContext = 
SecurityContextProvider.DefaultProvider.CreateSecurityContext(this);
+                       }
+
+                       using(SecurityContext.Impersonate(this))
+                       {
+                               // Must convert the FileAppender's m_filePath 
to an absolute path before we
+                               // call ExistingInit(). This will be done by 
the base.ActivateOptions() but
+                               // we need to duplicate that functionality here 
first.
+                               base.File = ConvertToFullPath(base.File.Trim());
+
+                               // Store fully qualified base file name
                                m_baseFileName = base.File;
                        }
 
                        // initialize the mutex that is used to lock rolling
-                       m_mutexForRolling = new Mutex(false, 
m_baseFileName.Replace("\\", "_").Replace(":", "_").Replace("/", "_"));
-
-                       if (m_rollDate && File != null && m_scheduledFilename 
== null)
-                       {
-                m_scheduledFilename = CombinePath(File, 
m_now.ToString(m_datePattern, 
System.Globalization.DateTimeFormatInfo.InvariantInfo));
-                       }
-
-                       ExistingInit();
-       
-                       base.ActivateOptions();
-               }
-
-               #endregion
-  
-               #region Roll File
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="path1"></param>
-        /// <param name="path2">.1, .2, .3, etc.</param>
-        /// <returns></returns>
-        private string CombinePath(string path1, string path2)
-        {
-            string extension = Path.GetExtension(path1);
-            if (m_preserveLogFileNameExtension && extension.Length > 0)
-            {
-                return Path.Combine(Path.GetDirectoryName(path1), 
Path.GetFileNameWithoutExtension(path1) + path2 + extension);
-            }
-            else
-            {
-                return path1 + path2;
-            }
-        }
-
-               /// <summary>
-               /// Rollover the file(s) to date/time tagged file(s).
-               /// </summary>
-               /// <param name="fileIsOpen">set to true if the file to be 
rolled is currently open</param>
-               /// <remarks>
-               /// <para>
-               /// Rollover the file(s) to date/time tagged file(s).
-               /// Resets curSizeRollBackups. 
-               /// If fileIsOpen is set then the new file is opened (through 
SafeOpenFile).
-               /// </para>
-               /// </remarks>
-               protected void RollOverTime(bool fileIsOpen) 
-               {
-                       if (m_staticLogFileName) 
-                       {
-                               // Compute filename, but only if datePattern is 
specified
-                               if (m_datePattern == null) 
-                               {
-                                       ErrorHandler.Error("Missing DatePattern 
option in rollOver().");
-                                       return;
-                               }
-         
-                               //is the new file name equivalent to the 
'current' one
-                               //something has gone wrong if we hit this -- we 
should only
-                               //roll over if the new file will be different 
from the old
-                               string dateFormat = 
m_now.ToString(m_datePattern, 
System.Globalization.DateTimeFormatInfo.InvariantInfo);
-                if (m_scheduledFilename.Equals(CombinePath(File, dateFormat))) 
-                               {
-                    ErrorHandler.Error("Compare " + m_scheduledFilename + " : 
" + CombinePath(File, dateFormat));
-                                       return;
-                               }
-         
-                               if (fileIsOpen)
-                               {
-                                       // close current file, and rename it to 
datedFilename
-                                       this.CloseFile();
-                               }
-         
-                               //we may have to roll over a large number of 
backups here
-                               for (int i = 1; i <= m_curSizeRollBackups; i++) 
-                               {
-                    string from = CombinePath(File, "." + i);
-                    string to = CombinePath(m_scheduledFilename, "." + i);
-                                       RollFile(from, to);
-                               }
-         
-                               RollFile(File, m_scheduledFilename);
-                       }
-       
-                       //We've cleared out the old date and are ready for the 
new
-                       m_curSizeRollBackups = 0; 
-       
-                       //new scheduled name
-            m_scheduledFilename = CombinePath(File, 
m_now.ToString(m_datePattern, 
System.Globalization.DateTimeFormatInfo.InvariantInfo));
-
-                       if (fileIsOpen)
-                       {
-                               // This will also close the file. This is OK 
since multiple close operations are safe.
-                               SafeOpenFile(m_baseFileName, false);
-                       }
-               }
-  
-               /// <summary>
-               /// Renames file <paramref name="fromFile"/> to file <paramref 
name="toFile"/>.
-               /// </summary>
-               /// <param name="fromFile">Name of existing file to 
roll.</param>
-               /// <param name="toFile">New name for file.</param>
-               /// <remarks>
-               /// <para>
-               /// Renames file <paramref name="fromFile"/> to file <paramref 
name="toFile"/>. It
-               /// also checks for existence of target file and deletes if it 
does.
-               /// </para>
-               /// </remarks>
-               protected void RollFile(string fromFile, string toFile) 
-               {
-                       if (FileExists(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(declaringType, "Moving [" 
+ fromFile + "] -> [" + toFile + "]");
-                                       using(SecurityContext.Impersonate(this))
-                                       {
-                                               System.IO.File.Move(fromFile, 
toFile);
-                                       }
-                               }
-                               catch(Exception moveEx)
-                               {
-                                       ErrorHandler.Error("Exception while 
rolling file [" + fromFile + "] -> [" + toFile + "]", moveEx, 
ErrorCode.GenericFailure);
-                               }
-                       }
-                       else
-                       {
-                               LogLog.Warn(declaringType, "Cannot RollFile [" 
+ fromFile + "] -> [" + toFile + "]. Source does not exist");
-                       }
-               }
-
-               /// <summary>
-               /// Test if a file exists at a specified path
-               /// </summary>
-               /// <param name="path">the path to the file</param>
-               /// <returns>true if the file exists</returns>
-               /// <remarks>
-               /// <para>
-               /// Test if a file exists at a specified path
-               /// </para>
-               /// </remarks>
-               protected bool FileExists(string path)
-               {
-                       using(SecurityContext.Impersonate(this))
-                       {
-                               return System.IO.File.Exists(path);
-                       }
-               }
-  
-               /// <summary>
-               /// Deletes the specified file if it exists.
-               /// </summary>
-               /// <param name="fileName">The file to delete.</param>
-               /// <remarks>
-               /// <para>
-               /// Delete a file if is exists.
-               /// The file is first moved to a new filename then deleted.
-               /// This allows the file to be removed even when it cannot
-               /// be deleted, but it still can be moved.
-               /// </para>
-               /// </remarks>
-               protected void DeleteFile(string fileName) 
-               {
-                       if (FileExists(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 may still be able 
to move it
-                               string tempFileName = fileName + "." + 
Environment.TickCount + ".DeletePending";
-                               try
-                               {
-                                       using(SecurityContext.Impersonate(this))
-                                       {
-                                               System.IO.File.Move(fileName, 
tempFileName);
-                                       }
-                                       fileToDelete = tempFileName;
-                               }
-                               catch(Exception moveEx)
-                               {
-                                       LogLog.Debug(declaringType, "Exception 
while moving file to be deleted [" + fileName + "] -> [" + tempFileName + "]", 
moveEx);
-                               }
-
-                               // Try to delete the file (either the original 
or the moved file)
-                               try
-                               {
-                                       using(SecurityContext.Impersonate(this))
-                                       {
-                                               
System.IO.File.Delete(fileToDelete);
-                                       }
-                                       LogLog.Debug(declaringType, "Deleted 
file [" + fileName + "]");
-                               }
-                               catch(Exception deleteEx)
-                               {
-                                       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(declaringType, 
"Exception while deleting temp file [" + fileToDelete + "]", deleteEx);
-                                       }
-                               }
-                       }
-               }
-  
-               /// <summary>
-               /// Implements file roll base on file size.
-               /// </summary>
-               /// <remarks>
-               /// <para>
-               /// If the maximum number of size based backups is reached
-               /// (<c>curSizeRollBackups == maxSizeRollBackups</c>) then the 
oldest
-               /// file is deleted -- its index determined by the sign of 
countDirection.
-               /// If <c>countDirection</c> &lt; 0, then files
-               /// {<c>File.1</c>, ..., <c>File.curSizeRollBackups -1</c>}
-               /// are renamed to {<c>File.2</c>, ...,
-               /// <c>File.curSizeRollBackups</c>}. Moreover, <c>File</c> is
-               /// renamed <c>File.1</c> and closed.
-               /// </para>
-               /// <para>
-               /// A new file is created to receive further log output.
-               /// </para>
-               /// <para>
-               /// If <c>maxSizeRollBackups</c> is equal to zero, then the
-               /// <c>File</c> is truncated with no backup files created.
-               /// </para>
-               /// <para>
-               /// If <c>maxSizeRollBackups</c> &lt; 0, then <c>File</c> is
-               /// renamed if needed and no files are deleted.
-               /// </para>
-               /// </remarks>
-               protected void RollOverSize() 
-               {
-                       this.CloseFile(); // keep windows happy.
-       
-                       LogLog.Debug(declaringType, "rolling over count 
["+((CountingQuietTextWriter)QuietWriter).Count+"]");
-                       LogLog.Debug(declaringType, "maxSizeRollBackups 
["+m_maxSizeRollBackups+"]");
-                       LogLog.Debug(declaringType, "curSizeRollBackups 
["+m_curSizeRollBackups+"]");
-                       LogLog.Debug(declaringType, "countDirection 
["+m_countDirection+"]");
-
-                       RollOverRenameFiles(File);
-       
-                       if (!m_staticLogFileName && m_countDirection >= 0) 
-                       {
-                               m_curSizeRollBackups++;
-                       }
-
-                       // This will also close the file. This is OK since 
multiple close operations are safe.
-                       SafeOpenFile(m_baseFileName, false);
-               }
-
-               /// <summary>
-               /// Implements file roll.
-               /// </summary>
-               /// <param name="baseFileName">the base name to rename</param>
-               /// <remarks>
-               /// <para>
-               /// If the maximum number of size based backups is reached
-               /// (<c>curSizeRollBackups == maxSizeRollBackups</c>) then the 
oldest
-               /// file is deleted -- its index determined by the sign of 
countDirection.
-               /// If <c>countDirection</c> &lt; 0, then files
-               /// {<c>File.1</c>, ..., <c>File.curSizeRollBackups -1</c>}
-               /// are renamed to {<c>File.2</c>, ...,
-               /// <c>File.curSizeRollBackups</c>}. 
-               /// </para>
-               /// <para>
-               /// If <c>maxSizeRollBackups</c> is equal to zero, then the
-               /// <c>File</c> is truncated with no backup files created.
-               /// </para>
-               /// <para>
-               /// If <c>maxSizeRollBackups</c> &lt; 0, then <c>File</c> is
-               /// renamed if needed and no files are deleted.
-               /// </para>
-               /// <para>
-               /// This is called by <see cref="RollOverSize"/> to rename the 
files.
-               /// </para>
-               /// </remarks>
-               protected void RollOverRenameFiles(string baseFileName) 
-               {
-                       // If maxBackups <= 0, then there is no file renaming 
to be done.
-                       if (m_maxSizeRollBackups != 0) 
-                       {
-                               if (m_countDirection < 0) 
-                               {
-                                       // Delete the oldest file, to keep 
Windows happy.
-                                       if (m_curSizeRollBackups == 
m_maxSizeRollBackups) 
-                                       {
-                        DeleteFile(CombinePath(baseFileName, "." + 
m_maxSizeRollBackups));
-                                               m_curSizeRollBackups--;
-                                       }
-       
-                                       // Map {(maxBackupIndex - 1), ..., 2, 
1} to {maxBackupIndex, ..., 3, 2}
-                                       for (int i = m_curSizeRollBackups; i >= 
1; i--) 
-                                       {
-                        RollFile((CombinePath(baseFileName, "." + i)), 
(CombinePath(baseFileName, "." + (i + 1))));
-                                       }
-       
-                                       m_curSizeRollBackups++;
-
-                                       // Rename fileName to fileName.1
-                    RollFile(baseFileName, CombinePath(baseFileName, ".1"));
-                               } 
-                               else 
-                               {
-                                       //countDirection >= 0
-                                       if (m_curSizeRollBackups >= 
m_maxSizeRollBackups && m_maxSizeRollBackups > 0) 
-                                       {
-                                               //delete the first and keep 
counting up.
-                                               int oldestFileIndex = 
m_curSizeRollBackups - m_maxSizeRollBackups;
-
-                                               // If static then there is 1 
file without a number, therefore 1 less archive
-                                               if (m_staticLogFileName)
-                                               {
-                                                       oldestFileIndex++;
-                                               }
-
-                                               // If using a static log file 
then the base for the numbered sequence is the baseFileName passed in
-                                               // If not using a static log 
file then the baseFileName will already have a numbered postfix which
-                                               // we must remove, however it 
may have a date postfix which we must keep!
-                                               string archiveFileBaseName = 
baseFileName;
-                                               if (!m_staticLogFileName)
-                                               {
-                                                       int lastDotIndex = 
archiveFileBaseName.LastIndexOf(".");
-                                                       if (lastDotIndex >= 0) 
-                                                       {
-                                                               
archiveFileBaseName = archiveFileBaseName.Substring(0, lastDotIndex);
-                                                       }
-                                               }
-
-                                               // Delete the archive file
-                        DeleteFile(CombinePath(archiveFileBaseName, "." + 
oldestFileIndex));
-                                       }
-       
-                                       if (m_staticLogFileName) 

[... 878 lines stripped ...]


Reply via email to