diff --git a/src/log4net/Appender/FileAppender.cs b/src/log4net/Appender/FileAppender.cs index dbade37f..8853a8cc 100644 --- a/src/log4net/Appender/FileAppender.cs +++ b/src/log4net/Appender/FileAppender.cs @@ -160,7 +160,7 @@ public LockStateException(string message, Exception innerException) : base(messa } #if !NETCR && !NETSTANDARD1_3 - private LockStateException(SerializationInfo info, StreamingContext context) : base(info, context) + private LockStateException(SerializationInfo info, StreamingContext context) : base(info, context) { } #endif @@ -494,6 +494,7 @@ public FileAppender CurrentAppender /// protected Stream CreateStream(string filename, bool append, FileShare fileShare) { + filename = Environment.ExpandEnvironmentVariables(filename); using (CurrentAppender.SecurityContext.Impersonate(this)) { // Ensure that the directory structure exists @@ -896,6 +897,118 @@ public override void OnClose() } #endif + /// + /// Hold no lock on the output file + /// + /// + /// + /// Open the file once and hold it open until is called. + /// Maintains no lock on the file during this time. + /// + /// + public class NoLock : LockingModelBase + { + private Stream m_stream = null; + + /// + /// Open the file specified and prepare for logging. + /// + /// The filename to use + /// Whether to append to the file, or overwrite + /// The encoding to use + /// + /// + /// Open the file specified and prepare for logging. + /// No writes will be made until is called. + /// Must be called before any calls to , + /// and . + /// + /// + public override void OpenFile(string filename, bool append, Encoding encoding) + { + try + { + // no lock + m_stream = CreateStream(filename, append, FileShare.ReadWrite); + } + catch (Exception e1) + { + CurrentAppender.ErrorHandler.Error("Unable to acquire lock on file " + filename + ". " + e1.Message); + } + } + + /// + /// Close the file + /// + /// + /// + /// Close the file. No further writes will be made. + /// + /// + public override void CloseFile() + { + CloseStream(m_stream); + m_stream = null; + } + + /// + /// Acquire the lock on the file + /// + /// A stream that is ready to be written to. + /// + /// + /// Does nothing. The lock is already taken + /// + /// + public override Stream AcquireLock() + { + return m_stream; + } + + /// + /// Release the lock on the file + /// + /// + /// + /// Does nothing. The lock will be released when the file is closed. + /// + /// + public override void ReleaseLock() + { + // NOP + } + + /// + /// Initializes all resources used by this locking model. + /// + public override void ActivateOptions() + { + // NOP + } + + /// + /// Disposes all resources that were initialized by this locking model. + /// + public override void OnClose() + { + // NOP + } + } + + /// + /// Default locking model (when no locking model was configured) + /// + private static Type defaultLockingModelType = typeof(ExclusiveLock); + + /// + /// Specify default locking model + /// + /// Type of LockingModel + public static void SetDefaultLockingModelType() where TLockingModel : LockingModelBase + { + defaultLockingModelType = typeof(TLockingModel); + } + #endregion Locking Models #region Public Instance Constructors @@ -1112,7 +1225,7 @@ public override void ActivateOptions() if (m_lockingModel == null) { - m_lockingModel = new FileAppender.ExclusiveLock(); + m_lockingModel = (LockingModelBase)Activator.CreateInstance(defaultLockingModelType); } m_lockingModel.CurrentAppender = this;