Author: bodewig
Date: Sun Mar 29 17:17:47 2015
New Revision: 1669935
URL: http://svn.apache.org/r1669935
Log:
LOG4NET-447 provide a PopAllEvents method for thread-safe access to
MemoryAppender
Patch by Gregory Babski
Added:
logging/log4net/trunk/src/log4net.Tests/Appender/MemoryAppenderTest.cs
(with props)
Modified:
logging/log4net/trunk/src/log4net/Appender/MemoryAppender.cs
Added: logging/log4net/trunk/src/log4net.Tests/Appender/MemoryAppenderTest.cs
URL:
http://svn.apache.org/viewvc/logging/log4net/trunk/src/log4net.Tests/Appender/MemoryAppenderTest.cs?rev=1669935&view=auto
==============================================================================
--- logging/log4net/trunk/src/log4net.Tests/Appender/MemoryAppenderTest.cs
(added)
+++ logging/log4net/trunk/src/log4net.Tests/Appender/MemoryAppenderTest.cs Sun
Mar 29 17:17:47 2015
@@ -0,0 +1,91 @@
+/*
+ *
+ * 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.
+ *
+*/
+
+#if FRAMEWORK_3_5_OR_ABOVE
+
+using System.Linq;
+using System.Threading;
+using NUnit.Framework;
+using log4net;
+using log4net.Appender;
+using log4net.Core;
+using log4net.Layout;
+using log4net.Repository.Hierarchy;
+
+using Hier = log4net.Repository.Hierarchy.Hierarchy;
+
+namespace log4net.Tests.Appender
+{
+ [TestFixture]
+ public class MemoryAppenderTest
+ {
+ private static int cThreadsRunning;
+ private const int cThreadsMax = 10;
+ private const int cLogEntriesPerThread = 100;
+ private const long cEventsExpected = cLogEntriesPerThread *
cThreadsMax;
+
+ [Test]
+ public void TestThreadSafety()
+ {
+ var hierarchy = (Hier)LogManager.GetRepository();
+ var memoryAppender = new MemoryAppender();
+ var patternLayout = new PatternLayout();
+ memoryAppender.Layout = patternLayout;
+ memoryAppender.ActivateOptions();
+ hierarchy.Root.AddAppender(memoryAppender);
+ hierarchy.Root.Level = Level.All;
+ hierarchy.Configured = true;
+
+ cThreadsRunning = cThreadsMax;
+ var threads = Enumerable.Range(0, cThreadsMax)
+ .Select(i => new Thread(LogMessages))
+ .ToList();
+
+ foreach (var thread in threads)
+ {
+ thread.Start();
+ }
+
+ long cEventsRead = 0;
+ while (cThreadsRunning > 0)
+ {
+ var events = memoryAppender.PopAllEvents();
+ cEventsRead += events.Length;
+ }
+ foreach (var thread in threads)
+ {
+ thread.Join();
+ }
+ Assert.AreEqual(cEventsExpected, cEventsRead, "Log events were
lost.");
+ }
+
+ private static void LogMessages()
+ {
+ var logger = LogManager.GetLogger("LoggerThread");
+ for (var i = 0; i < cLogEntriesPerThread; i++)
+ {
+ logger.InfoFormat("Logging message {0}", i);
+ }
+ Interlocked.Decrement(ref cThreadsRunning);
+ }
+ }
+}
+#endif
\ No newline at end of file
Propchange:
logging/log4net/trunk/src/log4net.Tests/Appender/MemoryAppenderTest.cs
------------------------------------------------------------------------------
svn:eol-style = native
Modified: logging/log4net/trunk/src/log4net/Appender/MemoryAppender.cs
URL:
http://svn.apache.org/viewvc/logging/log4net/trunk/src/log4net/Appender/MemoryAppender.cs?rev=1669935&r1=1669934&r2=1669935&view=diff
==============================================================================
--- logging/log4net/trunk/src/log4net/Appender/MemoryAppender.cs (original)
+++ logging/log4net/trunk/src/log4net/Appender/MemoryAppender.cs Sun Mar 29
17:17:47 2015
@@ -33,12 +33,22 @@ namespace log4net.Appender
/// that are appended in an in-memory array.
/// </para>
/// <para>
- /// Use the <see cref="GetEvents"/> method to get
- /// the current list of events that have been appended.
+ /// Use the <see cref="M:PopAllEvents()"/> method to get
+ /// and clear the current list of events that have been appended.
+ /// </para>
+ /// <para>
+ /// Use the <see cref="M:GetEvents()"/> method to get the current
+ /// list of events that have been appended. Note there is a
+ /// race-condition when calling <see cref="M:GetEvents()"/> and
+ /// <see cref="M:Clear()"/> in pairs, you better use <see
+ /// mref="M:PopAllEvents()"/> in that case.
/// </para>
/// <para>
/// Use the <see cref="M:Clear()"/> method to clear the
- /// current list of events.
+ /// current list of events. Note there is a
+ /// race-condition when calling <see cref="M:GetEvents()"/> and
+ /// <see cref="M:Clear()"/> in pairs, you better use <see
+ /// mref="M:PopAllEvents()"/> in that case.
/// </para>
/// </remarks>
/// <author>Julian Biddle</author>
@@ -174,6 +184,25 @@ namespace log4net.Appender
}
}
+ /// <summary>
+ /// Gets the events that have been logged and clears the list of
events.
+ /// </summary>
+ /// <returns>The events that have been logged</returns>
+ /// <remarks>
+ /// <para>
+ /// Gets the events that have been logged and clears the list of
events.
+ /// </para>
+ /// </remarks>
+ virtual public LoggingEvent[] PopAllEvents()
+ {
+ lock (m_eventsList.SyncRoot)
+ {
+ var tmp = (LoggingEvent[]) m_eventsList.ToArray(typeof
(LoggingEvent));
+ m_eventsList.Clear();
+ return tmp;
+ }
+ }
+
#endregion Public Instance Methods
#region Protected Instance Fields