Repository: qpid-jms
Updated Branches:
  refs/heads/master e3d21a7e6 -> 8b0993c9b


Add simple LRUCache implementation that can be used to cache anonymous
producer instances for the AMQP provider.

Project: http://git-wip-us.apache.org/repos/asf/qpid-jms/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-jms/commit/8b0993c9
Tree: http://git-wip-us.apache.org/repos/asf/qpid-jms/tree/8b0993c9
Diff: http://git-wip-us.apache.org/repos/asf/qpid-jms/diff/8b0993c9

Branch: refs/heads/master
Commit: 8b0993c9b4ac079cff76411fd735a95f49cffe39
Parents: e3d21a7
Author: Timothy Bish <tabish...@gmail.com>
Authored: Fri Oct 3 12:30:46 2014 -0400
Committer: Timothy Bish <tabish...@gmail.com>
Committed: Fri Oct 3 12:31:18 2014 -0400

----------------------------------------------------------------------
 .../java/org/apache/qpid/jms/util/LRUCache.java | 99 ++++++++++++++++++++
 .../org/apache/qpid/jms/util/LRUCacheTest.java  | 98 +++++++++++++++++++
 2 files changed, 197 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/8b0993c9/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/LRUCache.java
----------------------------------------------------------------------
diff --git 
a/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/LRUCache.java 
b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/LRUCache.java
new file mode 100644
index 0000000..76b130e
--- /dev/null
+++ b/qpid-jms-client/src/main/java/org/apache/qpid/jms/util/LRUCache.java
@@ -0,0 +1,99 @@
+/**
+ * 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.
+ */
+package org.apache.qpid.jms.util;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * A Simple LRU Cache based on a LinkedHashMap.
+ *
+ * @param <K>
+ * @param <V>
+ */
+public class LRUCache<K, V> extends LinkedHashMap<K, V> {
+
+    private static final long serialVersionUID = -342098639681884413L;
+    protected int maxCacheSize = 10000;
+
+    /**
+     * Default constructor for an LRU Cache The default capacity is 10000
+     */
+    public LRUCache() {
+        this(0,10000, 0.75f, true);
+    }
+
+    /**
+     * Constructs a LRUCache with a maximum capacity
+     *
+     * @param maximumCacheSize
+     */
+    public LRUCache(int maximumCacheSize) {
+        this(0, maximumCacheSize, 0.75f, true);
+    }
+
+    /**
+     * Constructs an empty <tt>LRUCache</tt> instance with the specified
+     * initial capacity, maximumCacheSize,load factor and ordering mode.
+     *
+     * @param initialCapacity the initial capacity.
+     * @param maximumCacheSize
+     * @param loadFactor the load factor.
+     * @param accessOrder the ordering mode - <tt>true</tt> for access-order,
+     *                <tt>false</tt> for insertion-order.
+     *
+     * @throws IllegalArgumentException if the initial capacity is negative or
+     *                 the load factor is non-positive.
+     */
+    public LRUCache(int initialCapacity, int maximumCacheSize, float 
loadFactor, boolean accessOrder) {
+        super(initialCapacity, loadFactor, accessOrder);
+        this.maxCacheSize = maximumCacheSize;
+    }
+
+    /**
+     * @return Returns the maxCacheSize.
+     */
+    public int getMaxCacheSize() {
+        return maxCacheSize;
+    }
+
+    /**
+     * @param maxCacheSize The maxCacheSize to set.
+     */
+    public void setMaxCacheSize(int maxCacheSize) {
+        this.maxCacheSize = maxCacheSize;
+    }
+
+    @Override
+    protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
+        if( size() > maxCacheSize ) {
+            onCacheEviction(eldest);
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Event point used by subclasses to perform some cleanup action when an
+     * element is evicted from the cache.
+     *
+     * @param eldest
+     *        the item being evicted from the LRUCache.
+     */
+    protected void onCacheEviction(Map.Entry<K,V> eldest) {
+    }
+}

http://git-wip-us.apache.org/repos/asf/qpid-jms/blob/8b0993c9/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/LRUCacheTest.java
----------------------------------------------------------------------
diff --git 
a/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/LRUCacheTest.java 
b/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/LRUCacheTest.java
new file mode 100644
index 0000000..ce3b08e
--- /dev/null
+++ b/qpid-jms-client/src/test/java/org/apache/qpid/jms/util/LRUCacheTest.java
@@ -0,0 +1,98 @@
+/**
+ * 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.
+ */
+package org.apache.qpid.jms.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LRUCacheTest {
+
+    protected static final Logger LOG = 
LoggerFactory.getLogger(LRUCacheTest.class);
+
+    @Test
+    public void testResize() throws Exception {
+        LRUCache<Long, Long> underTest = new LRUCache<Long, Long>(1000);
+
+        Long count = new Long(0);
+        long max = 0;
+        for (; count < 27276827; count++) {
+            long start = System.currentTimeMillis();
+            if (!underTest.containsKey(count)) {
+                underTest.put(count, count);
+            }
+            long duration = System.currentTimeMillis() - start;
+            if (duration > max) {
+                LOG.info("count: " + count + ", new max=" + duration);
+                max = duration;
+            }
+            if (count % 100000000 == 0) {
+                LOG.info("count: " + count + ", max=" + max);
+            }
+        }
+        assertEquals("size is still in order", 1000, underTest.size());
+    }
+
+    @SuppressWarnings("serial")
+    @Test
+    public void testOnCacheEviction() {
+
+        final int ENTRY_COUNT = 20;
+
+        List<CacheEntry> entries = new ArrayList<CacheEntry>();
+        LRUCache<String, CacheEntry> cache = new LRUCache<String, 
CacheEntry>(ENTRY_COUNT / 2) {
+
+            @Override
+            protected void 
onCacheEviction(java.util.Map.Entry<String,CacheEntry> eldest) {
+                eldest.getValue().close();
+            };
+        };
+
+        for (int i = 0; i < ENTRY_COUNT; ++i) {
+            CacheEntry entry = new CacheEntry();
+            entries.add(entry);
+            cache.put("Entry:" + i, entry);
+        }
+
+        for (int i = 0; i < ENTRY_COUNT; ++i) {
+            if (i < ENTRY_COUNT / 2) {
+                assertFalse(entries.get(i).isOpen());
+            } else {
+                assertTrue(entries.get(i).isOpen());
+            }
+        }
+    }
+
+    private static class CacheEntry {
+        private boolean open = true;
+
+        public void close() {
+            this.open = false;
+        }
+
+        public boolean isOpen() {
+            return open;
+        }
+    }
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org
For additional commands, e-mail: commits-h...@qpid.apache.org

Reply via email to