Author: bodewig
Date: Mon Mar  5 19:38:11 2012
New Revision: 1297194

URL: http://svn.apache.org/viewvc?rev=1297194&view=rev
Log:
cache in AbsoluteTimeDateFormatter must be sensitive to subclass.  LOG4NET-323

Added:
    logging/log4net/trunk/tests/src/DateFormatter/
    
logging/log4net/trunk/tests/src/DateFormatter/AbsoluteTimeDateFormatterTest.cs  
 (with props)
Modified:
    logging/log4net/trunk/src/DateFormatter/AbsoluteTimeDateFormatter.cs

Modified: logging/log4net/trunk/src/DateFormatter/AbsoluteTimeDateFormatter.cs
URL: 
http://svn.apache.org/viewvc/logging/log4net/trunk/src/DateFormatter/AbsoluteTimeDateFormatter.cs?rev=1297194&r1=1297193&r2=1297194&view=diff
==============================================================================
--- logging/log4net/trunk/src/DateFormatter/AbsoluteTimeDateFormatter.cs 
(original)
+++ logging/log4net/trunk/src/DateFormatter/AbsoluteTimeDateFormatter.cs Mon 
Mar  5 19:38:11 2012
@@ -18,6 +18,7 @@
 #endregion
 
 using System;
+using System.Collections;
 using System.IO;
 using System.Text;
 
@@ -103,19 +104,31 @@ namespace log4net.DateFormatter
                        // Calculate the current time precise only to the second
                        long currentTimeToTheSecond = (dateToFormat.Ticks - 
(dateToFormat.Ticks % TimeSpan.TicksPerSecond));
 
+                        string timeString = null;
                        // Compare this time with the stored last time
                        // If we are in the same second then append
                        // the previously calculated time string
-                       if (s_lastTimeToTheSecond != currentTimeToTheSecond)
-                       {
+                        if (s_lastTimeToTheSecond != currentTimeToTheSecond)
+                        {
+                            s_lastTimeStrings.Clear();
+                        }
+                        else
+                        {
+                            timeString = (string) s_lastTimeStrings[GetType()];
+                        }
+
+                        if (timeString == null)
+                        {
                                // lock so that only one thread can use the 
buffer and
-                               // update the s_lastTimeToTheSecond and 
s_lastTimeString
+                               // update the s_lastTimeToTheSecond and 
s_lastTimeStrings
 
                                // PERF: Try removing this lock and using a new 
StringBuilder each time
                                lock(s_lastTimeBuf)
                                {
-                                       if (s_lastTimeToTheSecond != 
currentTimeToTheSecond)
-                                       {
+                                        timeString = (string) 
s_lastTimeStrings[GetType()];
+
+                                        if (timeString == null)
+                                        {
                                                // We are in a new second.
                                                s_lastTimeBuf.Length = 0;
 
@@ -123,7 +136,7 @@ namespace log4net.DateFormatter
                                                
FormatDateWithoutMillis(dateToFormat, s_lastTimeBuf);
 
                                                // Render the string buffer to 
a string
-                                               string currentDateWithoutMillis 
= s_lastTimeBuf.ToString();
+                                                timeString = 
s_lastTimeBuf.ToString();
 
 #if NET_1_1
                                                // Ensure that the above string 
is written into the variable NOW on all threads.
@@ -131,12 +144,12 @@ namespace log4net.DateFormatter
                                                
System.Threading.Thread.MemoryBarrier();
 #endif
                                                // Store the time as a string 
(we only have to do this once per second)
-                                               s_lastTimeString = 
currentDateWithoutMillis;
+                                                s_lastTimeStrings[GetType()] = 
timeString;
                                                s_lastTimeToTheSecond = 
currentTimeToTheSecond;
                                        }
                                }
                        }
-                       writer.Write(s_lastTimeString);
+                       writer.Write(timeString);
        
                        // Append the current millisecond info
                        writer.Write(',');
@@ -190,7 +203,7 @@ namespace log4net.DateFormatter
                /// Last stored time with precision up to the second, formatted
                /// as a string.
                /// </summary>
-               private static string s_lastTimeString;
+               private static Hashtable s_lastTimeStrings = new Hashtable();
 
                #endregion Private Static Fields
        }

Added: 
logging/log4net/trunk/tests/src/DateFormatter/AbsoluteTimeDateFormatterTest.cs
URL: 
http://svn.apache.org/viewvc/logging/log4net/trunk/tests/src/DateFormatter/AbsoluteTimeDateFormatterTest.cs?rev=1297194&view=auto
==============================================================================
--- 
logging/log4net/trunk/tests/src/DateFormatter/AbsoluteTimeDateFormatterTest.cs 
(added)
+++ 
logging/log4net/trunk/tests/src/DateFormatter/AbsoluteTimeDateFormatterTest.cs 
Mon Mar  5 19:38:11 2012
@@ -0,0 +1,105 @@
+#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.IO;
+using System.Text;
+using log4net.DateFormatter;
+using NUnit.Framework;
+
+namespace log4net.Tests.DateFormatter
+{
+
+    [TestFixture]
+    public class AbsoluteTimeDateFormatterTest
+    {
+
+        [TearDown]
+        public void resetCounts()
+        {
+            FormatterOne.invocations = 0;
+        }
+
+        [Test]
+        public void CacheWorksForSameTicks()
+        {
+            StringWriter sw = new StringWriter();
+            FormatterOne f1 = new FormatterOne();
+            FormatterOne f2 = new FormatterOne();
+            DateTime dt = DateTime.Now;
+            f1.FormatDate(dt, sw);
+            f2.FormatDate(dt, sw);
+            Assert.AreEqual(1, FormatterOne.invocations);
+        }
+
+        [Test]
+        public void CacheWorksForSameSecond()
+        {
+            StringWriter sw = new StringWriter();
+            FormatterOne f1 = new FormatterOne();
+            FormatterOne f2 = new FormatterOne();
+            DateTime dt1 = DateTime.Today;
+            DateTime dt2 = dt1.AddMilliseconds(600);
+            f1.FormatDate(dt1, sw);
+            f2.FormatDate(dt2, sw);
+            Assert.AreEqual(1, FormatterOne.invocations);
+        }
+
+        [Test]
+        public void CacheExpiresWhenCrossingSecond()
+        {
+            StringWriter sw = new StringWriter();
+            FormatterOne f1 = new FormatterOne();
+            FormatterOne f2 = new FormatterOne();
+            DateTime dt1 = DateTime.Today.AddMinutes(1);
+            DateTime dt2 = dt1.AddMilliseconds(1100);
+            f1.FormatDate(dt1, sw);
+            f2.FormatDate(dt2, sw);
+            Assert.AreEqual(2, FormatterOne.invocations);
+        }
+
+        [Test]
+        public void CacheIsLocalToSubclass()
+        {
+            StringWriter sw = new StringWriter();
+            FormatterOne f1 = new FormatterOne();
+            FormatterTwo f2 = new FormatterTwo();
+            DateTime dt1 = DateTime.Today.AddMinutes(10);
+            f1.FormatDate(dt1, sw);
+            f2.FormatDate(dt1, sw);
+            Assert.AreEqual(2, FormatterOne.invocations);
+        }
+    }
+
+    internal class FormatterOne : AbsoluteTimeDateFormatter
+    {
+        internal static int invocations = 0;
+
+        override protected void FormatDateWithoutMillis(DateTime dateToFormat,
+                                                        StringBuilder buffer)
+        {
+            invocations++;
+        }
+        
+    }
+
+    internal class FormatterTwo : FormatterOne
+    {
+    }
+}

Propchange: 
logging/log4net/trunk/tests/src/DateFormatter/AbsoluteTimeDateFormatterTest.cs
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to