You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by dp...@apache.org on 2015/11/13 19:35:34 UTC
svn commit: r1714248 [2/2] -
/logging/log4net/trunk/src/Appender/RollingFileAppender.cs
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" /> < 0),
- /// i.e. log.1 is most recent, log.5 is the 5th backup, etc...
- /// </para>
- /// <para>
- /// <see cref="CountDirection" /> >= 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" /> >= 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" /> < 0),
+ /// i.e. log.1 is most recent, log.5 is the 5th backup, etc...
+ /// </para>
+ /// <para>
+ /// <see cref="CountDirection" /> >= 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" /> >= 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> < 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> < 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> < 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> < 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 ...]