From c801808b672ddf80122b1b5ebb011187d7024ab4 Mon Sep 17 00:00:00 2001 From: uujava Date: Mon, 12 Dec 2016 21:24:15 +0300 Subject: [PATCH 1/5] Primary key collection idea --- .../pk/PrimaryKeyIndexedCollection.java | 36 ++++ .../pk/PrimaryKeyOnHeapObjectStore.java | 160 ++++++++++++++++++ .../pk/PrimaryKeyOnHeapPersistence.java | 35 ++++ 3 files changed, 231 insertions(+) create mode 100644 code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyIndexedCollection.java create mode 100644 code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapObjectStore.java create mode 100644 code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapPersistence.java diff --git a/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyIndexedCollection.java b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyIndexedCollection.java new file mode 100644 index 000000000..d64074fde --- /dev/null +++ b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyIndexedCollection.java @@ -0,0 +1,36 @@ +package com.googlecode.cqengine.pk; + +import com.googlecode.cqengine.ConcurrentIndexedCollection; +import com.googlecode.cqengine.attribute.SimpleAttribute; +import com.googlecode.cqengine.index.unique.UniqueIndex; + +import java.util.concurrent.ConcurrentMap; + +/** + * Indexed collection backed by primary key to object map + */ +public class PrimaryKeyIndexedCollection> extends ConcurrentIndexedCollection { + + private ConcurrentMap pkMap; + + public PrimaryKeyIndexedCollection(SimpleAttribute attribute) { + this(new PrimaryKeyOnHeapPersistence<>(attribute)); + } + + public PrimaryKeyIndexedCollection(PrimaryKeyOnHeapPersistence persistence) { + super(persistence); + pkMap = ((PrimaryKeyOnHeapObjectStore) objectStore).getPkMap(); + UniqueIndex pkIndex = UniqueIndex.onAttribute(persistence.getPrimaryKeyAttribute()); + addIndex(pkIndex); + + } + + /** + * Fast access to entry by Key + * @param key + * @return + */ + public O get(A key){ + return pkMap.get(key); + } +} diff --git a/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapObjectStore.java b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapObjectStore.java new file mode 100644 index 000000000..81486d806 --- /dev/null +++ b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapObjectStore.java @@ -0,0 +1,160 @@ +package com.googlecode.cqengine.pk; + +import com.googlecode.cqengine.attribute.SimpleAttribute; +import com.googlecode.cqengine.persistence.support.CollectionWrappingObjectStore; + +import java.io.IOException; +import java.io.Serializable; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.stream.Stream; + +/** + * ObjectStore backed by index + */ +public class PrimaryKeyOnHeapObjectStore> extends CollectionWrappingObjectStore { + private final ConcurrentMap pkMap; + + public PrimaryKeyOnHeapObjectStore(SimpleAttribute pkAttr) { + super(new SetFromMap(new ConcurrentHashMap(), pkAttr)); + pkMap = ((SetFromMap) getBackingCollection()).getMap(); + } + + public PrimaryKeyOnHeapObjectStore(int initialCapacity, float loadFactor, int concurrencyLevel, SimpleAttribute pkAttr) { + super(new SetFromMap(new ConcurrentHashMap(initialCapacity, loadFactor, concurrencyLevel), pkAttr)); + pkMap = ((SetFromMap) getBackingCollection()).getMap(); + } + + public ConcurrentMap getPkMap() { + return pkMap; + } + + private static class SetFromMap> extends AbstractSet + implements Set, Serializable { + // The backing map + private final ConcurrentMap map; + // Its values view + private transient Collection values; + // Attribute to read a key + private final SimpleAttribute attr; + + SetFromMap(ConcurrentMap map, SimpleAttribute attr) { + if (!map.isEmpty()) + throw new IllegalArgumentException("Map must be empty"); + this.map = map; + // ValuesView in ConcurrentHashMap is unique and final! + // store the reference for faster access + values = map.values(); + this.attr = attr; + } + + public void clear() { + map.clear(); + } + + public int size() { + return map.size(); + } + + public boolean isEmpty() { + return map.isEmpty(); + } + + public boolean contains(Object o) { + return map.containsKey(attr.getValue((O)o, null)); + } + + public boolean remove(Object o) { + return map.remove(attr.getValue((O)o, null)) != null; + } + + public boolean add(O o) { + return map.put(attr.getValue((O)o, null), o) == null; + } + + public Iterator iterator() { + return values.iterator(); + } + + public Object[] toArray() { + return values.toArray(); + } + + public T[] toArray(T[] a) { + return values.toArray(a); + } + + public String toString() { + return values.toString(); + } + + public int hashCode() { + return map.keySet().hashCode(); + } + + public boolean equals(Object o) { + return o == this; + } + + public boolean containsAll(Collection c) { + for (Object o : c) { + A value = attr.getValue((O) o, null); + if(map.get(value) == null) return false; + } + return true; + } + + public boolean removeAll(Collection c) { + boolean changed = false; + for (Object o : c) { + A value = attr.getValue((O) o, null); + if(map.remove(value) != null) changed = true; + } + return changed; + } + + // retainAll and addAll is are inherited implementation + + // Override default methods in Collection + @Override + public void forEach(Consumer action) { + values.forEach(action); + } + + @Override + public boolean removeIf(Predicate filter) { + return values.removeIf(filter); + } + + @Override + public Spliterator spliterator() { + return values.spliterator(); + } + + @Override + public Stream stream() { + return values.stream(); + } + + @Override + public Stream parallelStream() { + return values.parallelStream(); + } + + ConcurrentMap getMap(){ + return map; + } + + private static final long serialVersionUID = 2454657854757543879L; + + private void readObject(java.io.ObjectInputStream stream) + throws IOException, ClassNotFoundException { + stream.defaultReadObject(); + values = map.values(); + } + + } +} diff --git a/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapPersistence.java b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapPersistence.java new file mode 100644 index 000000000..78fc8ada7 --- /dev/null +++ b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapPersistence.java @@ -0,0 +1,35 @@ +package com.googlecode.cqengine.pk; + +import com.googlecode.cqengine.attribute.SimpleAttribute; +import com.googlecode.cqengine.persistence.onheap.OnHeapPersistence; +import com.googlecode.cqengine.persistence.support.ObjectStore; + +/** + * ObjectStore with direct access to pk map + */ +public class PrimaryKeyOnHeapPersistence> extends OnHeapPersistence { + private final SimpleAttribute primaryKeyAttribute; + private final int initialCapacity; + private final float loadFactor; + private final int concurrencyLevel; + + public PrimaryKeyOnHeapPersistence() { + this(null, 16, 0.75F, 16); + } + + public PrimaryKeyOnHeapPersistence(SimpleAttribute primaryKeyAttribute) { + this(primaryKeyAttribute, 16, 0.75F, 16); + } + + public PrimaryKeyOnHeapPersistence(SimpleAttribute primaryKeyAttribute, int initialCapacity, float loadFactor, int concurrencyLevel) { + this.primaryKeyAttribute = primaryKeyAttribute; + this.initialCapacity = initialCapacity; + this.loadFactor = loadFactor; + this.concurrencyLevel = concurrencyLevel; + } + + @Override + public ObjectStore createObjectStore() { + return new PrimaryKeyOnHeapObjectStore<>(initialCapacity, loadFactor, concurrencyLevel, primaryKeyAttribute); + } +} From 4080b3194130765a29cc675f0ed649adfae405fb Mon Sep 17 00:00:00 2001 From: uujava Date: Mon, 12 Dec 2016 21:55:50 +0300 Subject: [PATCH 2/5] fix primary key attribute access --- .../googlecode/cqengine/pk/PrimaryKeyOnHeapPersistence.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapPersistence.java b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapPersistence.java index 78fc8ada7..811915396 100644 --- a/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapPersistence.java +++ b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapPersistence.java @@ -8,7 +8,7 @@ * ObjectStore with direct access to pk map */ public class PrimaryKeyOnHeapPersistence> extends OnHeapPersistence { - private final SimpleAttribute primaryKeyAttribute; + private final int initialCapacity; private final float loadFactor; private final int concurrencyLevel; @@ -22,7 +22,7 @@ public PrimaryKeyOnHeapPersistence(SimpleAttribute primaryKeyAttribute) { } public PrimaryKeyOnHeapPersistence(SimpleAttribute primaryKeyAttribute, int initialCapacity, float loadFactor, int concurrencyLevel) { - this.primaryKeyAttribute = primaryKeyAttribute; + super(primaryKeyAttribute, initialCapacity, loadFactor, concurrencyLevel); this.initialCapacity = initialCapacity; this.loadFactor = loadFactor; this.concurrencyLevel = concurrencyLevel; @@ -30,6 +30,6 @@ public PrimaryKeyOnHeapPersistence(SimpleAttribute primaryKeyAttribute, in @Override public ObjectStore createObjectStore() { - return new PrimaryKeyOnHeapObjectStore<>(initialCapacity, loadFactor, concurrencyLevel, primaryKeyAttribute); + return new PrimaryKeyOnHeapObjectStore<>(initialCapacity, loadFactor, concurrencyLevel, getPrimaryKeyAttribute()); } } From ecb39b3085676c2f723f84b6abf8e0af4d3843f4 Mon Sep 17 00:00:00 2001 From: vkozyr Date: Tue, 20 Dec 2016 19:15:33 +0300 Subject: [PATCH 3/5] primary key index reuses collection object store --- .../cqengine/pk/PrimaryKeyIndex.java | 21 +++++++++++++++++++ .../pk/PrimaryKeyIndexedCollection.java | 9 +++++--- 2 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyIndex.java diff --git a/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyIndex.java b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyIndex.java new file mode 100644 index 000000000..1ab521e3a --- /dev/null +++ b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyIndex.java @@ -0,0 +1,21 @@ +package com.googlecode.cqengine.pk; + +import com.googlecode.cqengine.attribute.Attribute; +import com.googlecode.cqengine.index.support.Factory; +import com.googlecode.cqengine.index.unique.UniqueIndex; + +import java.util.concurrent.ConcurrentMap; + +/** + * An index that reuses map supplied in constructor + */ +public class PrimaryKeyIndex extends UniqueIndex { + public PrimaryKeyIndex(final ConcurrentMap indexMap, Attribute attribute) { + super(new Factory>() { + @Override + public ConcurrentMap create() { + return indexMap; + } + }, attribute); + } +} diff --git a/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyIndexedCollection.java b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyIndexedCollection.java index d64074fde..30d0de0ea 100644 --- a/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyIndexedCollection.java +++ b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyIndexedCollection.java @@ -12,6 +12,7 @@ public class PrimaryKeyIndexedCollection> extends ConcurrentIndexedCollection { private ConcurrentMap pkMap; + private SimpleAttribute primaryKeyAttribute; public PrimaryKeyIndexedCollection(SimpleAttribute attribute) { this(new PrimaryKeyOnHeapPersistence<>(attribute)); @@ -20,17 +21,19 @@ public PrimaryKeyIndexedCollection(SimpleAttribute attribute) { public PrimaryKeyIndexedCollection(PrimaryKeyOnHeapPersistence persistence) { super(persistence); pkMap = ((PrimaryKeyOnHeapObjectStore) objectStore).getPkMap(); - UniqueIndex pkIndex = UniqueIndex.onAttribute(persistence.getPrimaryKeyAttribute()); + primaryKeyAttribute = persistence.getPrimaryKeyAttribute(); + UniqueIndex pkIndex = new PrimaryKeyIndex<>(pkMap, primaryKeyAttribute); addIndex(pkIndex); - } /** * Fast access to entry by Key + * * @param key * @return */ - public O get(A key){ + public O get(A key) { return pkMap.get(key); } + } From d55aedd13012be2027c69a5cb4dfba8f199ef5ef Mon Sep 17 00:00:00 2001 From: vkozyr Date: Tue, 20 Dec 2016 19:18:24 +0300 Subject: [PATCH 4/5] fixed 1.6 compatibility --- .../googlecode/cqengine/pk/PrimaryKeyIndexedCollection.java | 4 ++-- .../googlecode/cqengine/pk/PrimaryKeyOnHeapPersistence.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyIndexedCollection.java b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyIndexedCollection.java index 30d0de0ea..c94837e8f 100644 --- a/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyIndexedCollection.java +++ b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyIndexedCollection.java @@ -15,14 +15,14 @@ public class PrimaryKeyIndexedCollection> extends Con private SimpleAttribute primaryKeyAttribute; public PrimaryKeyIndexedCollection(SimpleAttribute attribute) { - this(new PrimaryKeyOnHeapPersistence<>(attribute)); + this(new PrimaryKeyOnHeapPersistence(attribute)); } public PrimaryKeyIndexedCollection(PrimaryKeyOnHeapPersistence persistence) { super(persistence); pkMap = ((PrimaryKeyOnHeapObjectStore) objectStore).getPkMap(); primaryKeyAttribute = persistence.getPrimaryKeyAttribute(); - UniqueIndex pkIndex = new PrimaryKeyIndex<>(pkMap, primaryKeyAttribute); + UniqueIndex pkIndex = new PrimaryKeyIndex(pkMap, primaryKeyAttribute); addIndex(pkIndex); } diff --git a/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapPersistence.java b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapPersistence.java index 811915396..d6fe928d9 100644 --- a/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapPersistence.java +++ b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapPersistence.java @@ -30,6 +30,6 @@ public PrimaryKeyOnHeapPersistence(SimpleAttribute primaryKeyAttribute, in @Override public ObjectStore createObjectStore() { - return new PrimaryKeyOnHeapObjectStore<>(initialCapacity, loadFactor, concurrencyLevel, getPrimaryKeyAttribute()); + return new PrimaryKeyOnHeapObjectStore(initialCapacity, loadFactor, concurrencyLevel, getPrimaryKeyAttribute()); } } From 3982bbe615c3529497777758eb9ab483588cd416 Mon Sep 17 00:00:00 2001 From: vkozyr Date: Tue, 20 Dec 2016 19:22:52 +0300 Subject: [PATCH 5/5] fixed 1.6 compatibility --- .../pk/PrimaryKeyOnHeapObjectStore.java | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapObjectStore.java b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapObjectStore.java index 81486d806..c5b46cbdc 100644 --- a/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapObjectStore.java +++ b/code/src/main/java/com/googlecode/cqengine/pk/PrimaryKeyOnHeapObjectStore.java @@ -8,9 +8,6 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -import java.util.function.Consumer; -import java.util.function.Predicate; -import java.util.stream.Stream; /** * ObjectStore backed by index @@ -118,32 +115,6 @@ public boolean removeAll(Collection c) { // retainAll and addAll is are inherited implementation - // Override default methods in Collection - @Override - public void forEach(Consumer action) { - values.forEach(action); - } - - @Override - public boolean removeIf(Predicate filter) { - return values.removeIf(filter); - } - - @Override - public Spliterator spliterator() { - return values.spliterator(); - } - - @Override - public Stream stream() { - return values.stream(); - } - - @Override - public Stream parallelStream() { - return values.parallelStream(); - } - ConcurrentMap getMap(){ return map; }