You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by da...@apache.org on 2022/08/21 14:12:04 UTC

[logging-log4net] branch master updated: New locking model for single log file in native applications with managed parts

This is an automated email from the ASF dual-hosted git repository.

davydm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4net.git


The following commit(s) were added to refs/heads/master by this push:
     new 4b027beb New locking model for single log file in native applications with managed parts
     new 77b9f853 Merge pull request #92 from komsa-ag/Feature/NoLock
4b027beb is described below

commit 4b027beb384b6c933e18670972c2a5d365f394a2
Author: Jan Friedrich <Ja...@komsa.de>
AuthorDate: Mon Aug 8 15:46:10 2022 +0200

    New locking model for single log file in native applications with managed parts
---
 src/log4net/Appender/FileAppender.cs | 117 ++++++++++++++++++++++++++++++++++-
 1 file changed, 115 insertions(+), 2 deletions(-)

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 @@ namespace log4net.Appender
 				}
 
 #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 @@ namespace log4net.Appender
 			/// <returns></returns>
 			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 @@ namespace log4net.Appender
 		}
 #endif
 
+		/// <summary>
+		/// Hold no lock on the output file
+		/// </summary>
+		/// <remarks>
+		/// <para>
+		/// Open the file once and hold it open until <see cref="CloseFile"/> is called. 
+		/// Maintains no lock on the file during this time.
+		/// </para>
+		/// </remarks>
+		public class NoLock : LockingModelBase
+		{
+			private Stream m_stream = null;
+
+			/// <summary>
+			/// Open the file specified and prepare for logging.
+			/// </summary>
+			/// <param name="filename">The filename to use</param>
+			/// <param name="append">Whether to append to the file, or overwrite</param>
+			/// <param name="encoding">The encoding to use</param>
+			/// <remarks>
+			/// <para>
+			/// Open the file specified and prepare for logging. 
+			/// No writes will be made until <see cref="AcquireLock"/> is called.
+			/// Must be called before any calls to <see cref="AcquireLock"/>,
+			/// <see cref="ReleaseLock"/> and <see cref="CloseFile"/>.
+			/// </para>
+			/// </remarks>
+			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);
+				}
+			}
+
+			/// <summary>
+			/// Close the file
+			/// </summary>
+			/// <remarks>
+			/// <para>
+			/// Close the file. No further writes will be made.
+			/// </para>
+			/// </remarks>
+			public override void CloseFile()
+			{
+				CloseStream(m_stream);
+				m_stream = null;
+			}
+
+			/// <summary>
+			/// Acquire the lock on the file
+			/// </summary>
+			/// <returns>A stream that is ready to be written to.</returns>
+			/// <remarks>
+			/// <para>
+			/// Does nothing. The lock is already taken
+			/// </para>
+			/// </remarks>
+			public override Stream AcquireLock()
+			{
+				return m_stream;
+			}
+
+			/// <summary>
+			/// Release the lock on the file
+			/// </summary>
+			/// <remarks>
+			/// <para>
+			/// Does nothing. The lock will be released when the file is closed.
+			/// </para>
+			/// </remarks>
+			public override void ReleaseLock()
+			{
+				// NOP
+			}
+
+			/// <summary>
+			/// Initializes all resources used by this locking model.
+			/// </summary>
+			public override void ActivateOptions()
+			{
+				// NOP
+			}
+
+			/// <summary>
+			/// Disposes all resources that were initialized by this locking model.
+			/// </summary>
+			public override void OnClose()
+			{
+				// NOP
+			}
+		}
+
+		/// <summary>
+		/// Default locking model (when no locking model was configured)
+		/// </summary>
+		private static Type defaultLockingModelType = typeof(ExclusiveLock);
+
+		/// <summary>
+		/// Specify default locking model
+		/// </summary>
+		/// <typeparam name="TLockingModel">Type of LockingModel</typeparam>
+		public static void SetDefaultLockingModelType<TLockingModel>() where TLockingModel : LockingModelBase
+		{
+			defaultLockingModelType = typeof(TLockingModel);
+		}
+
 		#endregion Locking Models
 
 		#region Public Instance Constructors
@@ -1112,7 +1225,7 @@ namespace log4net.Appender
 
 			if (m_lockingModel == null)
 			{
-				m_lockingModel = new FileAppender.ExclusiveLock();
+				m_lockingModel = (LockingModelBase)Activator.CreateInstance(defaultLockingModelType);
 			}
 
 			m_lockingModel.CurrentAppender = this;