ARTEMIS-2321 PageCursorProviderImpl can use primitive maps
This commit is contained in:
parent
30c82f43b0
commit
49836eca52
|
@ -21,26 +21,26 @@ import java.lang.ref.SoftReference;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import io.netty.util.collection.LongObjectHashMap;
|
||||
import io.netty.util.collection.LongObjectMap;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
public class SoftValueHashMap<K, V extends SoftValueHashMap.ValueCache> implements Map<K, V> {
|
||||
public class SoftValueLongObjectHashMap<V extends SoftValueLongObjectHashMap.ValueCache> implements LongObjectMap<V> {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(SoftValueHashMap.class);
|
||||
private static final Logger logger = Logger.getLogger(SoftValueLongObjectHashMap.class);
|
||||
|
||||
// The soft references that are already good.
|
||||
// too bad there's no way to override the queue method on ReferenceQueue, so I wouldn't need this
|
||||
private final ReferenceQueue<V> refQueue = new ReferenceQueue<>();
|
||||
|
||||
private final Map<K, AggregatedSoftReference> mapDelegate = new HashMap<>();
|
||||
private final LongObjectMap<AggregatedSoftReference<V>> mapDelegate = new LongObjectHashMap<>();
|
||||
|
||||
private final AtomicLong usedCounter = new AtomicLong(0);
|
||||
private long usedCounter = 0;
|
||||
|
||||
private int maxElements;
|
||||
|
||||
|
@ -57,7 +57,7 @@ public class SoftValueHashMap<K, V extends SoftValueHashMap.ValueCache> implemen
|
|||
|
||||
// Constructors --------------------------------------------------
|
||||
|
||||
public SoftValueHashMap(final int maxElements) {
|
||||
public SoftValueLongObjectHashMap(final int maxElements) {
|
||||
this.maxElements = maxElements;
|
||||
}
|
||||
|
||||
|
@ -96,8 +96,7 @@ public class SoftValueHashMap<K, V extends SoftValueHashMap.ValueCache> implemen
|
|||
*/
|
||||
@Override
|
||||
public boolean containsKey(final Object key) {
|
||||
processQueue();
|
||||
return mapDelegate.containsKey(key);
|
||||
return containsKey(objectToKey(key));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -107,7 +106,7 @@ public class SoftValueHashMap<K, V extends SoftValueHashMap.ValueCache> implemen
|
|||
@Override
|
||||
public boolean containsValue(final Object value) {
|
||||
processQueue();
|
||||
for (AggregatedSoftReference valueIter : mapDelegate.values()) {
|
||||
for (AggregatedSoftReference<V> valueIter : mapDelegate.values()) {
|
||||
V valueElement = valueIter.get();
|
||||
if (valueElement != null && value.equals(valueElement)) {
|
||||
return true;
|
||||
|
@ -117,16 +116,31 @@ public class SoftValueHashMap<K, V extends SoftValueHashMap.ValueCache> implemen
|
|||
return false;
|
||||
}
|
||||
|
||||
private static long objectToKey(Object key) {
|
||||
return ((Long) key).longValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key
|
||||
* @see java.util.Map#get(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public V get(final Object key) {
|
||||
return get(objectToKey(key));
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(Long key, V value) {
|
||||
return put(objectToKey(key), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(long key) {
|
||||
processQueue();
|
||||
AggregatedSoftReference value = mapDelegate.get(key);
|
||||
AggregatedSoftReference<V> value = mapDelegate.get(key);
|
||||
if (value != null) {
|
||||
value.used();
|
||||
usedCounter++;
|
||||
value.used(usedCounter);
|
||||
return value.get();
|
||||
} else {
|
||||
return null;
|
||||
|
@ -139,12 +153,13 @@ public class SoftValueHashMap<K, V extends SoftValueHashMap.ValueCache> implemen
|
|||
* @see java.util.Map#put(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public V put(final K key, final V value) {
|
||||
public V put(final long key, final V value) {
|
||||
processQueue();
|
||||
AggregatedSoftReference newRef = createReference(key, value);
|
||||
AggregatedSoftReference oldRef = mapDelegate.put(key, newRef);
|
||||
AggregatedSoftReference<V> newRef = createReference(key, value);
|
||||
AggregatedSoftReference<V> oldRef = mapDelegate.put(key, newRef);
|
||||
checkCacheSize();
|
||||
newRef.used();
|
||||
usedCounter++;
|
||||
newRef.used(usedCounter);
|
||||
if (oldRef != null) {
|
||||
return oldRef.get();
|
||||
} else {
|
||||
|
@ -152,11 +167,22 @@ public class SoftValueHashMap<K, V extends SoftValueHashMap.ValueCache> implemen
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(long key) {
|
||||
processQueue();
|
||||
AggregatedSoftReference<V> ref = mapDelegate.remove(key);
|
||||
if (ref != null) {
|
||||
return ref.get();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private void checkCacheSize() {
|
||||
if (maxElements > 0 && mapDelegate.size() > maxElements) {
|
||||
TreeSet<AggregatedSoftReference> usedReferences = new TreeSet<>(new ComparatorAgregated());
|
||||
|
||||
for (AggregatedSoftReference ref : mapDelegate.values()) {
|
||||
for (AggregatedSoftReference<V> ref : mapDelegate.values()) {
|
||||
V v = ref.get();
|
||||
|
||||
if (v != null && !v.isLive()) {
|
||||
|
@ -169,7 +195,7 @@ public class SoftValueHashMap<K, V extends SoftValueHashMap.ValueCache> implemen
|
|||
Object removed = mapDelegate.remove(ref.key);
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Removing " + removed + " with id = " + ref.key + " from SoftValueHashMap");
|
||||
logger.trace("Removing " + removed + " with id = " + ref.key + " from SoftValueLongObjectHashMap");
|
||||
}
|
||||
|
||||
if (mapDelegate.size() <= maxElements) {
|
||||
|
@ -210,13 +236,7 @@ public class SoftValueHashMap<K, V extends SoftValueHashMap.ValueCache> implemen
|
|||
*/
|
||||
@Override
|
||||
public V remove(final Object key) {
|
||||
processQueue();
|
||||
AggregatedSoftReference ref = mapDelegate.remove(key);
|
||||
if (ref != null) {
|
||||
return ref.get();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
return remove(objectToKey(key));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -224,10 +244,17 @@ public class SoftValueHashMap<K, V extends SoftValueHashMap.ValueCache> implemen
|
|||
* @see java.util.Map#putAll(java.util.Map)
|
||||
*/
|
||||
@Override
|
||||
public void putAll(final Map<? extends K, ? extends V> m) {
|
||||
public void putAll(final Map<? extends Long, ? extends V> m) {
|
||||
processQueue();
|
||||
for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
|
||||
put(e.getKey(), e.getValue());
|
||||
if (m instanceof LongObjectMap) {
|
||||
final LongObjectMap<? extends V> primitiveMap = (LongObjectMap<? extends V>) m;
|
||||
for (PrimitiveEntry<? extends V> entry : primitiveMap.entries()) {
|
||||
put(entry.key(), entry.value());
|
||||
}
|
||||
} else {
|
||||
for (Map.Entry<? extends Long, ? extends V> e : m.entrySet()) {
|
||||
put(e.getKey(), e.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -243,7 +270,7 @@ public class SoftValueHashMap<K, V extends SoftValueHashMap.ValueCache> implemen
|
|||
* @see java.util.Map#keySet()
|
||||
*/
|
||||
@Override
|
||||
public Set<K> keySet() {
|
||||
public Set<Long> keySet() {
|
||||
processQueue();
|
||||
return mapDelegate.keySet();
|
||||
}
|
||||
|
@ -256,7 +283,7 @@ public class SoftValueHashMap<K, V extends SoftValueHashMap.ValueCache> implemen
|
|||
processQueue();
|
||||
ArrayList<V> list = new ArrayList<>();
|
||||
|
||||
for (AggregatedSoftReference refs : mapDelegate.values()) {
|
||||
for (AggregatedSoftReference<V> refs : mapDelegate.values()) {
|
||||
V value = refs.get();
|
||||
if (value != null) {
|
||||
list.add(value);
|
||||
|
@ -266,20 +293,29 @@ public class SoftValueHashMap<K, V extends SoftValueHashMap.ValueCache> implemen
|
|||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.util.Map#entrySet()
|
||||
*/
|
||||
@Override
|
||||
public Set<java.util.Map.Entry<K, V>> entrySet() {
|
||||
public Set<Entry<Long, V>> entrySet() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<PrimitiveEntry<V>> entries() {
|
||||
processQueue();
|
||||
HashSet<Map.Entry<K, V>> set = new HashSet<>();
|
||||
for (Map.Entry<K, AggregatedSoftReference> pair : mapDelegate.entrySet()) {
|
||||
V value = pair.getValue().get();
|
||||
final int size = mapDelegate.size();
|
||||
final List<PrimitiveEntry<V>> entries = new ArrayList<>(size);
|
||||
for (PrimitiveEntry<AggregatedSoftReference<V>> pair : mapDelegate.entries()) {
|
||||
V value = pair.value().get();
|
||||
if (value != null) {
|
||||
set.add(new EntryElement<>(pair.getKey(), value));
|
||||
entries.add(new EntryElement<>(pair.key(), value));
|
||||
}
|
||||
}
|
||||
return set;
|
||||
return entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(long key) {
|
||||
processQueue();
|
||||
return mapDelegate.containsKey(key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -315,15 +351,15 @@ public class SoftValueHashMap<K, V extends SoftValueHashMap.ValueCache> implemen
|
|||
}
|
||||
}
|
||||
|
||||
private AggregatedSoftReference createReference(final K key, final V value) {
|
||||
return new AggregatedSoftReference(key, value);
|
||||
private AggregatedSoftReference createReference(final long key, final V value) {
|
||||
return new AggregatedSoftReference(key, value, refQueue);
|
||||
}
|
||||
|
||||
// Inner classes -------------------------------------------------
|
||||
|
||||
class AggregatedSoftReference extends SoftReference<V> {
|
||||
static final class AggregatedSoftReference<V> extends SoftReference<V> {
|
||||
|
||||
final K key;
|
||||
final long key;
|
||||
|
||||
long used = 0;
|
||||
|
||||
|
@ -331,11 +367,11 @@ public class SoftValueHashMap<K, V extends SoftValueHashMap.ValueCache> implemen
|
|||
return used;
|
||||
}
|
||||
|
||||
public void used() {
|
||||
used = usedCounter.incrementAndGet();
|
||||
public void used(long value) {
|
||||
this.used = value;
|
||||
}
|
||||
|
||||
AggregatedSoftReference(final K key, final V referent) {
|
||||
AggregatedSoftReference(final long key, final V referent, ReferenceQueue<V> refQueue) {
|
||||
super(referent, refQueue);
|
||||
this.key = key;
|
||||
}
|
||||
|
@ -346,40 +382,31 @@ public class SoftValueHashMap<K, V extends SoftValueHashMap.ValueCache> implemen
|
|||
}
|
||||
}
|
||||
|
||||
static final class EntryElement<K, V> implements Map.Entry<K, V> {
|
||||
static final class EntryElement<V> implements LongObjectMap.PrimitiveEntry<V> {
|
||||
|
||||
final K key;
|
||||
final long key;
|
||||
|
||||
volatile V value;
|
||||
final V value;
|
||||
|
||||
EntryElement(final K key, final V value) {
|
||||
EntryElement(final long key, final V value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.util.Map.Entry#getKey()
|
||||
*/
|
||||
@Override
|
||||
public K getKey() {
|
||||
public long key() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.util.Map.Entry#getValue()
|
||||
*/
|
||||
@Override
|
||||
public V getValue() {
|
||||
public V value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.util.Map.Entry#setValue(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public V setValue(final V value) {
|
||||
this.value = value;
|
||||
return value;
|
||||
@Deprecated
|
||||
public void setValue(V value) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
|
@ -17,9 +17,9 @@
|
|||
package org.apache.activemq.artemis.core.paging.cursor;
|
||||
|
||||
import org.apache.activemq.artemis.core.paging.PagedMessage;
|
||||
import org.apache.activemq.artemis.utils.SoftValueHashMap;
|
||||
import org.apache.activemq.artemis.utils.SoftValueLongObjectHashMap;
|
||||
|
||||
public interface PageCache extends SoftValueHashMap.ValueCache {
|
||||
public interface PageCache extends SoftValueLongObjectHashMap.ValueCache {
|
||||
|
||||
long getPageId();
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@ package org.apache.activemq.artemis.core.paging.cursor.impl;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
|
@ -39,8 +37,9 @@ import org.apache.activemq.artemis.core.persistence.StorageManager;
|
|||
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
|
||||
import org.apache.activemq.artemis.core.transaction.Transaction;
|
||||
import org.apache.activemq.artemis.core.transaction.impl.TransactionImpl;
|
||||
import org.apache.activemq.artemis.utils.SoftValueHashMap;
|
||||
import org.apache.activemq.artemis.utils.SoftValueLongObjectHashMap;
|
||||
import org.apache.activemq.artemis.utils.actors.ArtemisExecutor;
|
||||
import org.apache.activemq.artemis.utils.collections.ConcurrentLongHashMap;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
|
@ -70,9 +69,9 @@ public class PageCursorProviderImpl implements PageCursorProvider {
|
|||
// This is the same executor used at the PageStoreImpl. One Executor per pageStore
|
||||
private final ArtemisExecutor executor;
|
||||
|
||||
private final SoftValueHashMap<Long, PageCache> softCache;
|
||||
private final SoftValueLongObjectHashMap<PageCache> softCache;
|
||||
|
||||
private final ConcurrentMap<Long, PageSubscription> activeCursors = new ConcurrentHashMap<>();
|
||||
private final ConcurrentLongHashMap<PageSubscription> activeCursors = new ConcurrentLongHashMap<>();
|
||||
|
||||
// Static --------------------------------------------------------
|
||||
|
||||
|
@ -85,7 +84,7 @@ public class PageCursorProviderImpl implements PageCursorProvider {
|
|||
this.pagingStore = pagingStore;
|
||||
this.storageManager = storageManager;
|
||||
this.executor = executor;
|
||||
this.softCache = new SoftValueHashMap<>(maxCacheSize);
|
||||
this.softCache = new SoftValueLongObjectHashMap<>(maxCacheSize);
|
||||
}
|
||||
|
||||
// Public --------------------------------------------------------
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
package org.apache.activemq.artemis.tests.unit.util;
|
||||
|
||||
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
|
||||
import org.apache.activemq.artemis.utils.SoftValueHashMap;
|
||||
import org.apache.activemq.artemis.utils.SoftValueLongObjectHashMap;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SoftValueMapTest extends ActiveMQTestBase {
|
||||
|
@ -40,7 +40,7 @@ public class SoftValueMapTest extends ActiveMQTestBase {
|
|||
// each buffer will be 1/10th of the maxMemory
|
||||
int bufferSize = (int) (maxMemory / 100);
|
||||
|
||||
SoftValueHashMap<Long, Value> softCache = new SoftValueHashMap<>(100);
|
||||
SoftValueLongObjectHashMap<Value> softCache = new SoftValueLongObjectHashMap<>(100);
|
||||
|
||||
final int MAX_ELEMENTS = 1000;
|
||||
|
||||
|
@ -59,7 +59,7 @@ public class SoftValueMapTest extends ActiveMQTestBase {
|
|||
public void testEvictionsLeastUsed() {
|
||||
forceGC();
|
||||
|
||||
SoftValueHashMap<Long, Value> softCache = new SoftValueHashMap<>(200);
|
||||
SoftValueLongObjectHashMap<Value> softCache = new SoftValueLongObjectHashMap<>(200);
|
||||
|
||||
for (long i = 0; i < 100; i++) {
|
||||
Value v = new Value(new byte[1]);
|
||||
|
@ -99,7 +99,7 @@ public class SoftValueMapTest extends ActiveMQTestBase {
|
|||
Value two = new Value(new byte[100]);
|
||||
Value three = new Value(new byte[100]);
|
||||
|
||||
SoftValueHashMap<Integer, Value> softCache = new SoftValueHashMap<>(2);
|
||||
SoftValueLongObjectHashMap<Value> softCache = new SoftValueLongObjectHashMap<>(2);
|
||||
softCache.put(3, three);
|
||||
softCache.put(2, two);
|
||||
softCache.put(1, one);
|
||||
|
@ -110,7 +110,7 @@ public class SoftValueMapTest extends ActiveMQTestBase {
|
|||
|
||||
}
|
||||
|
||||
class Value implements SoftValueHashMap.ValueCache {
|
||||
class Value implements SoftValueLongObjectHashMap.ValueCache {
|
||||
|
||||
byte[] payload;
|
||||
|
||||
|
@ -121,7 +121,7 @@ public class SoftValueMapTest extends ActiveMQTestBase {
|
|||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.activemq.artemis.utils.SoftValueHashMap.ValueCache#isLive()
|
||||
* @see org.apache.activemq.artemis.utils.SoftValueLongObjectHashMap.ValueCache#isLive()
|
||||
*/
|
||||
@Override
|
||||
public boolean isLive() {
|
||||
|
|
Loading…
Reference in New Issue