What's the best way of implementing a chronicle map where the value side is a map or a set?
I need data structures similar to the following where I can store multiple versions of some data with a specific id:
chronicle-map: String -> Map<String,V>
$id -> {v0-> value-v0, v1-> value-v1, v2 -> value-v2}
or possibly two maps:
chronicle-map-1: String -> Set<String>
key-$id -> Set{v0,v1,v2}
chronicle-map-2: String -> V
version-$id-v0 -> value-v0
version-$id-v1 -> value-v1
version-$id-v2 -> value-v2
(Atomicity and serialisation performance are my main concerns). acquireUsingLocked/getUsingLocked
methods don't seem to work with standard map/set implementations.
Multimap
sometimes.[The following regards Chronicle Map 3.x]
To ensure atomicity (thread-safety), you could either:
use Java 8's new Map methods: compute()
, computeIfAbsent()
, computeIfPresent()
or merge()
methods, like:
static <K, V> void multiMapAdd(ChronicleMap<K, Set<V>> map, K key, V value) {
map.compute(key, (k, v) -> {
if (v == null)
v = new HashSet<>();
v.add(value);
return v;
});
}
acquire a context, and operate with value bytes, for optimizing some serialization/deserialization costs, probably. E. g.
interface LimitedSet {
public static final int MAX_VALUES_SIZE = 20;
byte getSize();
void setSize(byte);
MyValue getValue(int index);
void setValue(@MaxSize(MAX_VALUES_SIZE) int index, MyValue value);
}
...
try (ExternalMapQueryContext<K, LimitedSet, ?> cxt = map.queryContext(key) {
cxt.writeLock().lock();
MapEntry<K, LimitedSet> entry = cxt.entry();
if (entry == null) {
MapAbsentEntry<K, LimitedSet> absentEntry = cxt.absentEntry();
cxt.insert(absentEntry, absentEntry.defaultValue());
entry = cxt.entry();
assert entry != null;
}
LimitedSet values = entry.value().get();
int size = values.getSize();
for (int i = 0; i < size; i++) {
if (same(values.getValue(i), value))
return false;
}
if (size == MAX_VALUES_SIZE)
throw new IllegalStateException("values set overflow");
values.set(size, value);
values.setSize((byte) (size + 1));
}
You could also find a couple of such advanced "MultiMap" usages of Chronicle Map, which reveals additional abilities as CRDT replication and multi-entry locking, in Chronicle Map README: