nicko       2004/09/26 16:21:53

  Modified:    src      ThreadContext.cs log4net.csproj
               src/Util GlobalContextProperties.cs ThreadContextLists.cs
                        ThreadContextProperties.cs ThreadContextStacks.cs
               src/Core LoggingEvent.cs
               src/Util/PatternStringConverters PropertyPatternConverter.cs
  Added:       src      LogicalThreadContext.cs
               src/Util ContextPropertiesBase.cs
                        LogicalThreadContextProperties.cs
  Log:
  Added LogicalThreadContext based on ideas by Ian Kundil.
  The LogicalThreadContext stores properties in the 
System.Runtime.Remoting.Messaging.CallContext which allows them to flow across 
thread boundaries as a call is marshalled. This does not support flowing across 
a Remoting boundary.
  
  Reduced the times when a PropertiesDictionary is created just to support 
reading.
  
  Revision  Changes    Path
  1.2       +8 -2      logging-log4net/src/ThreadContext.cs
  
  Index: ThreadContext.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/ThreadContext.cs,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ThreadContext.cs  9 Sep 2004 21:53:13 -0000       1.1
  +++ ThreadContext.cs  26 Sep 2004 23:21:52 -0000      1.2
  @@ -30,6 +30,8 @@
        /// <para>
        /// The <c>ThreadContext</c> provides a location for thread specific 
debugging 
        /// information to be stored.
  +     /// The <c>ThreadContext</c> properties override any <see 
cref="GlobalContext"/>
  +     /// properties with the same name.
        /// </para>
        /// <para>
        /// The thread context has a properties map and a stack.
  @@ -87,6 +89,10 @@
                /// <value>
                /// The thread properties map
                /// </value>
  +             /// <remarks>
  +             /// The <c>ThreadContext</c> properties override any <see 
cref="GlobalContext"/>
  +             /// properties with the same name.
  +             /// </remarks>
                public static ThreadContextProperties Properties
                {
                        get { return s_properties; }
  @@ -126,12 +132,12 @@
                /// <summary>
                /// The thread context stacks instance
                /// </summary>
  -             private readonly static ThreadContextStacks s_stacks = new 
ThreadContextStacks();
  +             private readonly static ThreadContextStacks s_stacks = new 
ThreadContextStacks(s_properties);
   
                /// <summary>
                /// The thread context lists instance
                /// </summary>
  -             private readonly static ThreadContextLists s_lists = new 
ThreadContextLists();
  +             private readonly static ThreadContextLists s_lists = new 
ThreadContextLists(s_properties);
   
                #endregion Private Static Fields
        }
  
  
  
  1.12      +15 -0     logging-log4net/src/log4net.csproj
  
  Index: log4net.csproj
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/log4net.csproj,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- log4net.csproj    26 Sep 2004 18:06:53 -0000      1.11
  +++ log4net.csproj    26 Sep 2004 23:21:52 -0000      1.12
  @@ -98,6 +98,11 @@
                       BuildAction = "Compile"
                   />
                   <File
  +                    RelPath = "LogicalThreadContext.cs"
  +                    SubType = "Code"
  +                    BuildAction = "Compile"
  +                />
  +                <File
                       RelPath = "LogManager.cs"
                       SubType = "Code"
                       BuildAction = "Compile"
  @@ -783,6 +788,11 @@
                       BuildAction = "Compile"
                   />
                   <File
  +                    RelPath = "Util\ContextPropertiesBase.cs"
  +                    SubType = "Code"
  +                    BuildAction = "Compile"
  +                />
  +                <File
                       RelPath = "Util\CountingQuietTextWriter.cs"
                       SubType = "Code"
                       BuildAction = "Compile"
  @@ -819,6 +829,11 @@
                   />
                   <File
                       RelPath = "Util\LevelMappingEntry.cs"
  +                    SubType = "Code"
  +                    BuildAction = "Compile"
  +                />
  +                <File
  +                    RelPath = "Util\LogicalThreadContextProperties.cs"
                       SubType = "Code"
                       BuildAction = "Compile"
                   />
  
  
  
  1.1                  logging-log4net/src/LogicalThreadContext.cs
  
  Index: LogicalThreadContext.cs
  ===================================================================
  #region Copyright & License
  //
  // Copyright 2001-2004 The Apache Software Foundation
  //
  // Licensed 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
  
  // .NET Compact Framework 1.0 has no support for 
System.Runtime.Remoting.Messaging.CallContext
  #if !NETCF
  
  using System;
  using System.Collections;
  
  using log4net.Util;
  
  namespace log4net
  {
        /// <summary>
        /// The log4net Logical Thread Context.
        /// </summary>
        /// <remarks>
        /// <para>
        /// The <c>LogicalThreadContext</c> provides a location for <see 
cref="System.Runtime.Remoting.Messaging.CallContext"/> specific debugging 
        /// information to be stored.
        /// The <c>LogicalThreadContext</c> properties override any <see 
cref="ThreadContext"/> or <see cref="GlobalContext"/>
        /// properties with the same name.
        /// </para>
        /// <para>
        /// The Logical Thread Context has a properties map and a stack.
        /// The properties and stack can 
        /// be included in the output of log messages. The <see 
cref="log4net.Layout.PatternLayout"/>
        /// supports selecting and outputting these properties.
        /// </para>
        /// <para>
        /// The Logical Thread Context provides a diagnostic context for the 
current call context. 
        /// This is an instrument for distinguishing interleaved log
        /// output from different sources. Log output is typically interleaved
        /// when a server handles multiple clients near-simultaneously.
        /// </para>
        /// <para>
        /// The Logical Thread Context is managed on a per <see 
cref="System.Runtime.Remoting.Messaging.CallContext"/> basis.
        /// </para>
        /// </remarks>
        /// <example>Example of using the thread context properties to store a 
username.
        /// <code>
        /// LogicalThreadContext.Properties["user"] = userName;
        ///     log.Info("This log message has a LogicalThreadContext Property 
called 'user'");
        /// </code>
        /// </example>
        /// <example>Example of how to push a message into the context stack
        /// <code>
        ///     using(LogicalThreadContext.Stack.Push("my context message"))
        ///     {
        ///             log.Info("This log message has a LogicalThreadContext 
Stack message that includes 'my context message'");
        ///     
        ///     } // at the end of the using block the message is automatically 
popped 
        /// </code>
        /// </example>
        /// <author>Nicko Cadell</author>
        public sealed class LogicalThreadContext
        {
                #region Private Instance Constructors
  
                /// <summary>
                /// Private Constructor. 
                /// </summary>
                /// <remarks>
                /// Uses a private access modifier to prevent instantiation of 
this class.
                /// </remarks>
                private LogicalThreadContext()
                {
                }
  
                #endregion Private Instance Constructors
  
                #region Public Static Properties
  
                /// <summary>
                /// The thread properties map
                /// </summary>
                /// <value>
                /// The thread properties map
                /// </value>
                /// <remarks>
                /// The <c>LogicalThreadContext</c> properties override any 
<see cref="ThreadContext"/> or <see cref="GlobalContext"/>
                /// properties with the same name.
                /// </remarks>
                public static LogicalThreadContextProperties Properties
                {
                        get { return s_properties; }
                }
  
                /// <summary>
                /// The thread stacks
                /// </summary>
                /// <value>
                /// stack map
                /// </value>
                public static ThreadContextStacks Stacks
                {
                        get { return s_stacks; }
                }
  
                /// <summary>
                /// The thread lists
                /// </summary>
                /// <value>
                /// list map
                /// </value>
                public static ThreadContextLists Lists
                {
                        get { return s_lists; }
                }
  
                #endregion Public Static Properties
  
                #region Private Static Fields
  
                /// <summary>
                /// The thread context properties instance
                /// </summary>
                private readonly static LogicalThreadContextProperties 
s_properties = new LogicalThreadContextProperties();
  
                /// <summary>
                /// The thread context stacks instance
                /// </summary>
                private readonly static ThreadContextStacks s_stacks = new 
ThreadContextStacks(s_properties);
  
                /// <summary>
                /// The thread context lists instance
                /// </summary>
                private readonly static ThreadContextLists s_lists = new 
ThreadContextLists(s_properties);
  
                #endregion Private Static Fields
        }
  }
  
  #endif
  
  
  1.4       +2 -2      logging-log4net/src/Util/GlobalContextProperties.cs
  
  Index: GlobalContextProperties.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Util/GlobalContextProperties.cs,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- GlobalContextProperties.cs        9 Sep 2004 18:58:32 -0000       1.3
  +++ GlobalContextProperties.cs        26 Sep 2004 23:21:52 -0000      1.4
  @@ -35,7 +35,7 @@
        /// </para>
        /// </remarks>
        /// <author>Nicko Cadell</author>
  -     public sealed class GlobalContextProperties
  +     public sealed class GlobalContextProperties : ContextPropertiesBase
        {
                #region Private Instance Fields
   
  @@ -87,7 +87,7 @@
                /// the properties is created.
                /// </para>
                /// </remarks>
  -             public object this[string key]
  +             override public object this[string key]
                {
                        get 
                        { 
  
  
  
  1.2       +6 -3      logging-log4net/src/Util/ThreadContextLists.cs
  
  Index: ThreadContextLists.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Util/ThreadContextLists.cs,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ThreadContextLists.cs     9 Sep 2004 21:53:14 -0000       1.1
  +++ ThreadContextLists.cs     26 Sep 2004 23:21:52 -0000      1.2
  @@ -31,13 +31,16 @@
        /// <author>Nicko Cadell</author>
        public sealed class ThreadContextLists
        {
  +             private readonly ContextPropertiesBase m_properties;
  +
                #region Public Instance Constructors
   
                /// <summary>
                /// Initializes a new instance of the <see 
cref="ThreadContextLists" /> class.
                /// </summary>
  -             internal ThreadContextLists()
  +             internal ThreadContextLists(ContextPropertiesBase properties)
                {
  +                     m_properties = properties;
                }
   
                #endregion Public Instance Constructors
  @@ -56,12 +59,12 @@
                        {
                                ThreadContextList list = null;
   
  -                             object propertyValue = 
ThreadContext.Properties[key];
  +                             object propertyValue = m_properties[key];
                                if (propertyValue == null)
                                {
                                        // List does not exist, create
                                        list = new ThreadContextList();
  -                                     ThreadContext.Properties[key] = list;
  +                                     m_properties[key] = list;
                                }
                                else
                                {
  
  
  
  1.2       +29 -8     logging-log4net/src/Util/ThreadContextProperties.cs
  
  Index: ThreadContextProperties.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Util/ThreadContextProperties.cs,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ThreadContextProperties.cs        9 Sep 2004 21:53:14 -0000       1.1
  +++ ThreadContextProperties.cs        26 Sep 2004 23:21:52 -0000      1.2
  @@ -31,7 +31,7 @@
        /// </para>
        /// </remarks>
        /// <author>Nicko Cadell</author>
  -     public sealed class ThreadContextProperties
  +     public sealed class ThreadContextProperties : ContextPropertiesBase
        {
                #region Private Instance Fields
   
  @@ -61,10 +61,21 @@
                /// <value>
                /// The value for the property with the specified key
                /// </value>
  -             public object this[string key]
  +             override public object this[string key]
                {
  -                     get { return GetProperties()[key]; }
  -                     set { GetProperties()[key] = value; }
  +                     get 
  +                     { 
  +                             PropertiesDictionary dictionary = 
GetProperties(false);
  +                             if (dictionary != null)
  +                             {
  +                                     return dictionary[key]; 
  +                             }
  +                             return null;
  +                     }
  +                     set 
  +                     { 
  +                             GetProperties(true)[key] = value; 
  +                     }
                }
   
                #endregion Public Instance Properties
  @@ -77,7 +88,11 @@
                /// <param name="key">the key for the entry to remove</param>
                public void Remove(string key)
                {
  -                     GetProperties().Remove(key);
  +                     PropertiesDictionary dictionary = GetProperties(false);
  +                     if (dictionary != null)
  +                     {
  +                             dictionary.Remove(key);
  +                     }
                }
   
                /// <summary>
  @@ -85,7 +100,11 @@
                /// </summary>
                public void Clear()
                {
  -                     GetProperties().Clear();
  +                     PropertiesDictionary dictionary = GetProperties(false);
  +                     if (dictionary != null)
  +                     {
  +                             dictionary.Clear();
  +                     }
                }
   
                #endregion Public Instance Methods
  @@ -95,6 +114,7 @@
                /// <summary>
                /// Get the PropertiesDictionary stored in the 
LocalDataStoreSlot for this thread.
                /// </summary>
  +             /// <param name="create">create the dictionary if it does not 
exist, otherwise return null if is does not exist</param>
                /// <returns>the properties for this thread</returns>
                /// <remarks>
                /// <para>
  @@ -103,10 +123,10 @@
                /// caller must clone the collection before doings so.
                /// </para>
                /// </remarks>
  -             internal PropertiesDictionary GetProperties()
  +             internal PropertiesDictionary GetProperties(bool create)
                {
                        PropertiesDictionary properties = 
(PropertiesDictionary)System.Threading.Thread.GetData(s_threadLocalSlot);
  -                     if (properties == null)
  +                     if (properties == null && create)
                        {
                                properties  = new PropertiesDictionary();
                                
System.Threading.Thread.SetData(s_threadLocalSlot, properties);
  @@ -117,4 +137,5 @@
                #endregion Internal Instance Methods
        }
   }
  +
   
  
  
  
  1.2       +6 -3      logging-log4net/src/Util/ThreadContextStacks.cs
  
  Index: ThreadContextStacks.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Util/ThreadContextStacks.cs,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ThreadContextStacks.cs    9 Sep 2004 21:53:14 -0000       1.1
  +++ ThreadContextStacks.cs    26 Sep 2004 23:21:52 -0000      1.2
  @@ -31,13 +31,16 @@
        /// <author>Nicko Cadell</author>
        public sealed class ThreadContextStacks
        {
  +             private readonly ContextPropertiesBase m_properties;
  +
                #region Public Instance Constructors
   
                /// <summary>
                /// Initializes a new instance of the <see 
cref="ThreadContextStacks" /> class.
                /// </summary>
  -             internal ThreadContextStacks()
  +             internal ThreadContextStacks(ContextPropertiesBase properties)
                {
  +                     m_properties = properties;
                }
   
                #endregion Public Instance Constructors
  @@ -56,12 +59,12 @@
                        {
                                ThreadContextStack stack = null;
   
  -                             object propertyValue = 
ThreadContext.Properties[key];
  +                             object propertyValue = m_properties[key];
                                if (propertyValue == null)
                                {
                                        // Stack does not exist, create
                                        stack = new ThreadContextStack();
  -                                     ThreadContext.Properties[key] = stack;
  +                                     m_properties[key] = stack;
                                }
                                else
                                {
  
  
  
  1.1                  logging-log4net/src/Util/ContextPropertiesBase.cs
  
  Index: ContextPropertiesBase.cs
  ===================================================================
  #region Copyright & License
  //
  // Copyright 2001-2004 The Apache Software Foundation
  //
  // Licensed 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;
  
  namespace log4net.Util
  {
        /// <summary>
        /// Base class for Context Properties implementations
        /// </summary>
        /// <remarks>
        /// <para>
        /// This class defines a basic property get set accessor
        /// </para>
        /// </remarks>
        /// <author>Nicko Cadell</author>
        public abstract class ContextPropertiesBase
        {
                /// <summary>
                /// Gets or sets the value of a property
                /// </summary>
                /// <value>
                /// The value for the property with the specified key
                /// </value>
                public abstract object this[string key] { get; set; }
        }
  }
  
  
  
  
  1.1                  
logging-log4net/src/Util/LogicalThreadContextProperties.cs
  
  Index: LogicalThreadContextProperties.cs
  ===================================================================
  #region Copyright & License
  //
  // Copyright 2001-2004 The Apache Software Foundation
  //
  // Licensed 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
  
  // .NET Compact Framework 1.0 has no support for 
System.Runtime.Remoting.Messaging.CallContext
  #if !NETCF
  
  using System;
  using System.Collections;
  
  using System.Runtime.Remoting.Messaging;
  
  namespace log4net.Util
  {
        /// <summary>
        /// Implementation of Properties collection for the <see 
cref="log4net.LogicalThreadContext"/>
        /// </summary>
        /// <remarks>
        /// <para>
        /// Class implements a collection of properties that is specific to 
each thread.
        /// The class is not synchronized as each thread has its own <see 
cref="PropertiesDictionary"/>.
        /// </para>
        /// </remarks>
        /// <author>Nicko Cadell</author>
        public sealed class LogicalThreadContextProperties : 
ContextPropertiesBase
        {
                #region Public Instance Constructors
  
                /// <summary>
                /// Initializes a new instance of the <see 
cref="LogicalThreadContextProperties" /> class.
                /// </summary>
                internal LogicalThreadContextProperties()
                {
                }
  
                #endregion Public Instance Constructors
  
                #region Public Instance Properties
  
                /// <summary>
                /// Gets or sets the value of a property
                /// </summary>
                /// <value>
                /// The value for the property with the specified key
                /// </value>
                override public object this[string key]
                {
                        get 
                        { 
                                PropertiesDictionary dictionary = 
GetProperties(false);
                                if (dictionary != null)
                                {
                                        return dictionary[key]; 
                                }
                                return null;
                        }
                        set 
                        { 
                                GetProperties(true)[key] = value; 
                        }
                }
  
                #endregion Public Instance Properties
  
                #region Public Instance Methods
  
                /// <summary>
                /// Remove a property
                /// </summary>
                /// <param name="key">the key for the entry to remove</param>
                public void Remove(string key)
                {
                        PropertiesDictionary dictionary = GetProperties(false);
                        if (dictionary != null)
                        {
                                dictionary.Remove(key);
                        }
                }
  
                /// <summary>
                /// Clear the global context properties
                /// </summary>
                public void Clear()
                {
                        PropertiesDictionary dictionary = GetProperties(false);
                        if (dictionary != null)
                        {
                                dictionary.Clear();
                        }
                }
  
                #endregion Public Instance Methods
  
                #region Internal Instance Methods
  
                /// <summary>
                /// Get the PropertiesDictionary stored in the 
LocalDataStoreSlot for this thread.
                /// </summary>
                /// <param name="create">create the dictionary if it does not 
exist, otherwise return null if is does not exist</param>
                /// <returns>the properties for this thread</returns>
                /// <remarks>
                /// <para>
                /// The collection returned is only to be used on the calling 
thread. If the
                /// caller needs to share the collection between different 
threads then the 
                /// caller must clone the collection before doings so.
                /// </para>
                /// </remarks>
                internal PropertiesDictionary GetProperties(bool create)
                {
                        PropertiesDictionary properties = 
(PropertiesDictionary)CallContext.GetData("log4net.Util.LogicalThreadContextProperties");
                        if (properties == null && create)
                        {
                                properties  = new PropertiesDictionary();
                                
CallContext.SetData("log4net.Util.LogicalThreadContextProperties", properties);
                        }
                        return properties;
                }
  
                #endregion Internal Instance Methods
        }
  }
  
  #endif
  
  
  
  1.12      +12 -1     logging-log4net/src/Core/LoggingEvent.cs
  
  Index: LoggingEvent.cs
  ===================================================================
  RCS file: /home/cvs/logging-log4net/src/Core/LoggingEvent.cs,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- LoggingEvent.cs   19 Sep 2004 17:52:54 -0000      1.11
  +++ LoggingEvent.cs   26 Sep 2004 23:21:52 -0000      1.12
  @@ -1156,7 +1156,18 @@
                        {
                                m_compositeProperties.Add(m_eventProperties);
                        }
  -                     
m_compositeProperties.Add(ThreadContext.Properties.GetProperties());
  +#if !NETCF
  +                     PropertiesDictionary logicalThreadProperties = 
LogicalThreadContext.Properties.GetProperties(false);
  +                     if (logicalThreadProperties != null)
  +                     {
  +                             
m_compositeProperties.Add(logicalThreadProperties);
  +                     }
  +#endif
  +                     PropertiesDictionary threadProperties = 
ThreadContext.Properties.GetProperties(false);
  +                     if (threadProperties != null)
  +                     {
  +                             m_compositeProperties.Add(threadProperties);
  +                     }
   
                        // TODO: Add Repository Properties
   
  
  
  
  1.2       +13 -1     
logging-log4net/src/Util/PatternStringConverters/PropertyPatternConverter.cs
  
  Index: PropertyPatternConverter.cs
  ===================================================================
  RCS file: 
/home/cvs/logging-log4net/src/Util/PatternStringConverters/PropertyPatternConverter.cs,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- PropertyPatternConverter.cs       9 Sep 2004 21:53:14 -0000       1.1
  +++ PropertyPatternConverter.cs       26 Sep 2004 23:21:52 -0000      1.2
  @@ -57,7 +57,19 @@
                {
                        CompositeProperties compositeProperties = new 
CompositeProperties();
   
  -                     
compositeProperties.Add(ThreadContext.Properties.GetProperties());
  +#if !NETCF
  +                     PropertiesDictionary logicalThreadProperties = 
LogicalThreadContext.Properties.GetProperties(false);
  +                     if (logicalThreadProperties != null)
  +                     {
  +                             
compositeProperties.Add(logicalThreadProperties);
  +                     }
  +#endif
  +                     PropertiesDictionary threadProperties = 
ThreadContext.Properties.GetProperties(false);
  +                     if (threadProperties != null)
  +                     {
  +                             compositeProperties.Add(threadProperties);
  +                     }
  +
                        // TODO: Add Repository Properties
                        
compositeProperties.Add(GlobalContext.Properties.GetReadOnlyProperties());
   
  
  
  

Reply via email to