You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ta...@apache.org on 2011/07/22 23:17:45 UTC

svn commit: r1149741 - in /activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src: main/csharp/Util/LRUCache.cs test/csharp/Util/LRUCacheTest.cs

Author: tabish
Date: Fri Jul 22 21:17:43 2011
New Revision: 1149741

URL: http://svn.apache.org/viewvc?rev=1149741&view=rev
Log:
https://issues.apache.org/jira/browse/AMQNET-329

Adds a basic LRU Cache for use in Message Auditing to prevent dups.

Added:
    activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Util/LRUCache.cs   (with props)
    activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/Util/LRUCacheTest.cs   (with props)

Added: activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Util/LRUCache.cs
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Util/LRUCache.cs?rev=1149741&view=auto
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Util/LRUCache.cs (added)
+++ activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Util/LRUCache.cs Fri Jul 22 21:17:43 2011
@@ -0,0 +1,130 @@
+/**
+ * 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.
+ */
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace Apache.NMS.ActiveMQ.Util
+{
+    /// <summary>
+    /// Implements the basic IDictionary interface and adds functionality for controlling
+    /// the maximum number of entries that can be contained in the Map.  When the maximum
+    /// value is reached the oldest entry is removed so that the max size is never exceeded.
+    /// </summary>
+	public class LRUCache<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
+	{
+        public const int DEFAULT_MAX_CACHE_SIZE = 10000;
+
+        private readonly Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>();
+        private readonly LinkedList<KeyValuePair<TKey, TValue>> entries =
+            new LinkedList<KeyValuePair<TKey, TValue>>();
+		private int maxCacheSize = DEFAULT_MAX_CACHE_SIZE;
+
+        public LRUCache() : base()
+        {
+        }
+
+        public LRUCache(int maxCacheSize) : base()
+        {
+            this.maxCacheSize = maxCacheSize;
+        }
+
+		public void Clear()
+		{
+			dictionary.Clear();
+		}
+
+        public int Count
+        {
+            get { return this.dictionary.Count; }
+        }
+		
+		public int MaxCacheSize
+		{
+			get { return maxCacheSize; }
+			set { this.maxCacheSize = value; }
+		}
+
+		public TValue this[TKey key]
+		{
+			get { return dictionary[key]; }
+			set { this.Add(key, value); }
+		}
+
+		public bool TryGetValue(TKey key, out TValue val)
+		{
+			return dictionary.TryGetValue(key, out val);
+		}
+
+		public ICollection<TKey> Keys
+		{
+			get { return dictionary.Keys; }
+		}
+
+		public ICollection<TValue> Values
+		{
+			get { return dictionary.Values; }
+		}
+
+		public void Add(TKey key, TValue val)
+        {
+    		dictionary.Add(key, val);
+            entries.AddLast(new KeyValuePair<TKey, TValue>(key, val));
+
+            KeyValuePair<TKey, TValue> eldest = entries.First.Value;
+
+		    if(this.RemoveEldestEntry(eldest))
+            {
+                this.dictionary.Remove(eldest.Key);
+                this.entries.RemoveFirst();
+            }
+		}
+
+		public bool Remove(TKey v)
+		{
+			return dictionary.Remove(v);
+		}
+
+        public bool ContainsKey(TKey key)
+        {
+            return this.dictionary.ContainsKey(key);
+        }
+
+        public bool ContainsValue(TValue theValue)
+        {
+            return this.dictionary.ContainsValue(theValue);
+        }
+
+        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
+        {
+            return dictionary.GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return dictionary.GetEnumerator();
+        }
+
+		protected virtual bool RemoveEldestEntry(KeyValuePair<TKey, TValue> eldest)
+		{
+			return this.dictionary.Count > this.maxCacheSize;
+		}
+	}
+
+}
+

Propchange: activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/main/csharp/Util/LRUCache.cs
------------------------------------------------------------------------------
    svn:eol-style = native

Added: activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/Util/LRUCacheTest.cs
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/Util/LRUCacheTest.cs?rev=1149741&view=auto
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/Util/LRUCacheTest.cs (added)
+++ activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/Util/LRUCacheTest.cs Fri Jul 22 21:17:43 2011
@@ -0,0 +1,161 @@
+/**
+ * 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.
+ */
+
+using System;
+using Apache.NMS;
+using Apache.NMS.ActiveMQ;
+using Apache.NMS.ActiveMQ.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.ActiveMQ.Test
+{
+    [TestFixture]
+    public class LRUCacheTest
+    {
+        [Test]
+        public void TestConstructor1()
+        {
+            LRUCache<Int64, Int64> underTest = new LRUCache<Int64, Int64>();
+            Assert.AreEqual(LRUCache<Int64, Int64>.DEFAULT_MAX_CACHE_SIZE, underTest.MaxCacheSize);
+        }
+
+        [Test]
+        public void TestConstructor2()
+        {
+            LRUCache<Int64, Int64> underTest = new LRUCache<Int64, Int64>(666);
+            Assert.AreEqual(666, underTest.MaxCacheSize);
+        }
+
+        [Test]
+        public void TestMaxCacheSize()
+        {
+            LRUCache<Int64, Int64> underTest = new LRUCache<Int64, Int64>(666);
+            Assert.AreEqual(666, underTest.MaxCacheSize);
+            underTest.MaxCacheSize = 512;
+            Assert.AreEqual(512, underTest.MaxCacheSize);
+        }
+
+        [Test]
+        public void TestAdd()
+        {
+            LRUCache<String, String> underTest = new LRUCache<String, String>(666);
+
+            underTest.Add("key", "value");
+            Assert.That(underTest.Count == 1);
+        }
+
+        [Test]
+        public void TestRemove()
+        {
+            LRUCache<String, String> underTest = new LRUCache<String, String>(666);
+
+            underTest.Add("key", "value");
+            Assert.That(underTest.Count == 1);
+            underTest.Remove("key");
+            Assert.That(underTest.Count == 0);
+        }
+
+        [Test]
+        public void TestContainsKey()
+        {
+            LRUCache<String, String> underTest = new LRUCache<String, String>(666);
+
+            underTest.Add("key1", "value");
+            underTest.Add("key2", "value");
+            underTest.Add("key3", "value");
+            Assert.That(underTest.Count == 3);
+            Assert.That(underTest.ContainsKey("key2"));
+            Assert.That(underTest.ContainsKey("key1"));
+            Assert.That(underTest.ContainsKey("key3"));
+            Assert.IsFalse(underTest.ContainsKey("Key4"));
+        }
+
+        [Test]
+        public void TestContainsValue()
+        {
+            LRUCache<String, String> underTest = new LRUCache<String, String>(666);
+
+            underTest.Add("key1", "value1");
+            underTest.Add("key2", "value2");
+            underTest.Add("key3", "value3");
+            Assert.That(underTest.Count == 3);
+            Assert.That(underTest.ContainsValue("value1"));
+            Assert.That(underTest.ContainsValue("value2"));
+            Assert.That(underTest.ContainsValue("value3"));
+            Assert.IsFalse(underTest.ContainsValue("value4"));
+        }
+
+        [Test]
+        public void TestCount()
+        {
+            LRUCache<String, String> underTest = new LRUCache<String, String>(666);
+
+            Assert.That(underTest.Count == 0);
+            underTest.Add("key1", "value");
+            Assert.That(underTest.Count == 1);
+            underTest.Add("key2", "value");
+            Assert.That(underTest.Count == 2);
+            underTest.Add("key3", "value");
+            Assert.That(underTest.Count == 3);
+            underTest.Clear();
+            Assert.That(underTest.Count == 0);
+        }
+
+        [Test]
+        public void TestClear()
+        {
+            LRUCache<String, String> underTest = new LRUCache<String, String>(666);
+
+            underTest.Add("key1", "value");
+            underTest.Add("key2", "value");
+            underTest.Add("key3", "value");
+            Assert.That(underTest.Count == 3);
+            underTest.Clear();
+            Assert.That(underTest.Count == 0);
+        }
+
+        [Test]
+        public void TestResize()
+        {
+            LRUCache<Int64, Int64> underTest = new LRUCache<Int64, Int64>(1000);
+
+            Int64 count = new Int64();
+            long max = 0;
+            for (; count < 27276827; count++)
+            {
+                long start = DateTime.Now.Ticks;
+                if (!underTest.ContainsKey(count))
+                {
+                    underTest.Add(count, count);
+                }
+                long duration = DateTime.Now.Ticks - start;
+                if (duration > max)
+                {
+                    Tracer.Debug("count: " + count + ", new max=" + duration);
+                    max = duration;
+                }
+                if (count % 100000000 == 0)
+                {
+                    Tracer.Debug("count: " + count + ", max=" + max);
+                }
+            }
+
+            Assert.AreEqual(1000, underTest.Count, "size is still in order");
+        }
+    }
+}
+

Propchange: activemq/activemq-dotnet/Apache.NMS.ActiveMQ/trunk/src/test/csharp/Util/LRUCacheTest.cs
------------------------------------------------------------------------------
    svn:eol-style = native