Make buckets unmodifiable

This commit is contained in:
Andrea Cavalli 2021-07-13 22:58:08 +02:00
parent fe5f50be10
commit 2489c50022
3 changed files with 42 additions and 34 deletions

View File

@ -12,6 +12,7 @@ import it.cavallium.dbengine.database.collections.JoinerBlocking.ValueGetterBloc
import it.cavallium.dbengine.database.serialization.Serializer;
import it.cavallium.dbengine.database.serialization.SerializerFixedBinaryLength;
import it.unimi.dsi.fastutil.objects.ObjectArraySet;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import it.unimi.dsi.fastutil.objects.ObjectSets;
import java.util.Collections;
import java.util.HashMap;
@ -30,7 +31,7 @@ import reactor.core.publisher.Mono;
public class DatabaseMapDictionaryHashed<T, U, TH> implements DatabaseStageMap<T, U, DatabaseStageEntry<U>> {
private final ByteBufAllocator alloc;
private final DatabaseMapDictionary<TH, Set<Entry<T, U>>> subDictionary;
private final DatabaseMapDictionary<TH, ObjectArraySet<Entry<T, U>>> subDictionary;
private final Function<T, TH> keySuffixHashFunction;
protected DatabaseMapDictionaryHashed(LLDictionary dictionary,
@ -89,11 +90,11 @@ public class DatabaseMapDictionaryHashed<T, U, TH> implements DatabaseStageMap<T
);
}
private Map<TH, Set<Entry<T, U>>> serializeMap(Map<T, U> map) {
var newMap = new HashMap<TH, Set<Entry<T, U>>>(map.size());
private Map<TH, ObjectArraySet<Entry<T, U>>> serializeMap(Map<T, U> map) {
var newMap = new HashMap<TH, ObjectArraySet<Entry<T, U>>>(map.size());
map.forEach((key, value) -> newMap.compute(keySuffixHashFunction.apply(key), (hash, prev) -> {
if (prev == null) {
prev = new HashSet<>();
prev = new ObjectArraySet<>();
}
prev.add(Map.entry(key, value));
return prev;
@ -101,7 +102,7 @@ public class DatabaseMapDictionaryHashed<T, U, TH> implements DatabaseStageMap<T
return newMap;
}
private Map<T, U> deserializeMap(Map<TH, Set<Entry<T, U>>> map) {
private Map<T, U> deserializeMap(Map<TH, ObjectArraySet<Entry<T, U>>> map) {
var newMap = new HashMap<T, U>(map.size());
map.forEach((hash, set) -> set.forEach(entry -> newMap.put(entry.getKey(), entry.getValue())));
return newMap;
@ -246,24 +247,24 @@ public class DatabaseMapDictionaryHashed<T, U, TH> implements DatabaseStageMap<T
@Override
public ValueGetterBlocking<T, U> getDbValueGetter(@Nullable CompositeSnapshot snapshot) {
ValueGetterBlocking<TH, Set<Entry<T, U>>> getter = subDictionary.getDbValueGetter(snapshot);
ValueGetterBlocking<TH, ObjectArraySet<Entry<T, U>>> getter = subDictionary.getDbValueGetter(snapshot);
return key -> extractValue(getter.get(keySuffixHashFunction.apply(key)), key);
}
@Override
public ValueGetter<T, U> getAsyncDbValueGetter(@Nullable CompositeSnapshot snapshot) {
ValueGetter<TH, Set<Entry<T, U>>> getter = subDictionary.getAsyncDbValueGetter(snapshot);
ValueGetter<TH, ObjectArraySet<Entry<T, U>>> getter = subDictionary.getAsyncDbValueGetter(snapshot);
return key -> getter
.get(keySuffixHashFunction.apply(key))
.flatMap(set -> this.extractValueTransformation(set, key));
}
private Mono<U> extractValueTransformation(Set<Entry<T, U>> entries, T key) {
private Mono<U> extractValueTransformation(ObjectArraySet<Entry<T, U>> entries, T key) {
return Mono.fromCallable(() -> extractValue(entries, key));
}
@Nullable
private U extractValue(Set<Entry<T, U>> entries, T key) {
private U extractValue(ObjectArraySet<Entry<T, U>> entries, T key) {
if (entries == null) return null;
for (Entry<T, U> entry : entries) {
if (Objects.equals(entry.getKey(), key)) {
@ -274,21 +275,23 @@ public class DatabaseMapDictionaryHashed<T, U, TH> implements DatabaseStageMap<T
}
@NotNull
private Set<Entry<T, U>> insertValueOrCreate(@Nullable Set<Entry<T, U>> entries, T key, U value) {
private ObjectArraySet<Entry<T, U>> insertValueOrCreate(@Nullable ObjectArraySet<Entry<T, U>> entries, T key, U value) {
if (entries != null) {
entries.add(Map.entry(key, value));
return entries;
var clonedEntries = entries.clone();
clonedEntries.add(Map.entry(key, value));
return clonedEntries;
} else {
var oas = new HashSet<Entry<T, U>>(1);
var oas = new ObjectArraySet<Entry<T, U>>(1);
oas.add(Map.entry(key, value));
return oas;
}
}
@Nullable
private Set<Entry<T, U>> removeValueOrDelete(@Nullable Set<Entry<T, U>> entries, T key) {
private Set<Entry<T, U>> removeValueOrDelete(@Nullable ObjectArraySet<Entry<T, U>> entries, T key) {
if (entries != null) {
var it = entries.iterator();
var clonedEntries = entries.clone();
var it = clonedEntries.iterator();
while (it.hasNext()) {
var entry = it.next();
if (Objects.equals(entry.getKey(), key)) {
@ -296,10 +299,10 @@ public class DatabaseMapDictionaryHashed<T, U, TH> implements DatabaseStageMap<T
break;
}
}
if (entries.size() == 0) {
if (clonedEntries.size() == 0) {
return null;
} else {
return entries;
return clonedEntries;
}
} else {
return null;

View File

@ -24,10 +24,10 @@ import reactor.core.publisher.Mono;
@SuppressWarnings("unused")
public class DatabaseSingleBucket<K, V, TH> implements DatabaseStageEntry<V> {
private final DatabaseStageEntry<Set<Entry<K, V>>> bucketStage;
private final DatabaseStageEntry<ObjectArraySet<Entry<K, V>>> bucketStage;
private final K key;
public DatabaseSingleBucket(DatabaseStageEntry<Set<Entry<K, V>>> bucketStage, K key) {
public DatabaseSingleBucket(DatabaseStageEntry<ObjectArraySet<Entry<K, V>>> bucketStage, K key) {
this.bucketStage = bucketStage;
this.key = key;
}
@ -151,9 +151,10 @@ public class DatabaseSingleBucket<K, V, TH> implements DatabaseStageEntry<V> {
}
@NotNull
private Set<Entry<K, V>> insertValueOrCreate(@Nullable Set<Entry<K, V>> entries, V value) {
private ObjectArraySet<Entry<K, V>> insertValueOrCreate(@Nullable ObjectArraySet<Entry<K, V>> entries, V value) {
if (entries != null) {
var it = entries.iterator();
var clonedEntries = entries.clone();
var it = clonedEntries.iterator();
while (it.hasNext()) {
var entry = it.next();
if (Objects.equals(entry.getKey(), key)) {
@ -161,19 +162,20 @@ public class DatabaseSingleBucket<K, V, TH> implements DatabaseStageEntry<V> {
break;
}
}
entries.add(Map.entry(key, value));
return entries;
clonedEntries.add(Map.entry(key, value));
return clonedEntries;
} else {
var oas = new HashSet<Entry<K, V>>(1);
var oas = new ObjectArraySet<Entry<K, V>>(1);
oas.add(Map.entry(key, value));
return oas;
}
}
@Nullable
private Set<Entry<K, V>> removeValueOrDelete(@Nullable Set<Entry<K, V>> entries) {
private ObjectArraySet<Entry<K, V>> removeValueOrDelete(@Nullable ObjectArraySet<Entry<K, V>> entries) {
if (entries != null) {
var it = entries.iterator();
var clonedEntries = entries.clone();
var it = clonedEntries.iterator();
while (it.hasNext()) {
var entry = it.next();
if (Objects.equals(entry.getKey(), key)) {
@ -181,10 +183,10 @@ public class DatabaseSingleBucket<K, V, TH> implements DatabaseStageEntry<V> {
break;
}
}
if (entries.size() == 0) {
if (clonedEntries.size() == 0) {
return null;
} else {
return entries;
return clonedEntries;
}
} else {
return null;

View File

@ -4,12 +4,15 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import it.cavallium.dbengine.database.serialization.Serializer;
import it.unimi.dsi.fastutil.objects.ObjectArraySet;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import it.unimi.dsi.fastutil.objects.ObjectSets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.jetbrains.annotations.NotNull;
class ValuesSetSerializer<X> implements Serializer<Set<X>, ByteBuf> {
class ValuesSetSerializer<X> implements Serializer<ObjectArraySet<X>, ByteBuf> {
private final ByteBufAllocator allocator;
private final Serializer<X, ByteBuf> entrySerializer;
@ -20,22 +23,22 @@ class ValuesSetSerializer<X> implements Serializer<Set<X>, ByteBuf> {
}
@Override
public @NotNull Set<X> deserialize(@NotNull ByteBuf serialized) {
public @NotNull ObjectArraySet<X> deserialize(@NotNull ByteBuf serialized) {
try {
int entriesLength = serialized.readInt();
var set = new HashSet<X>();
ArrayList<X> deserializedElements = new ArrayList<>(entriesLength);
for (int i = 0; i < entriesLength; i++) {
X entry = entrySerializer.deserialize(serialized.retain());
set.add(entry);
deserializedElements.add(entry);
}
return set;
return new ObjectArraySet<>(deserializedElements);
} finally {
serialized.release();
}
}
@Override
public @NotNull ByteBuf serialize(@NotNull Set<X> deserialized) {
public @NotNull ByteBuf serialize(@NotNull ObjectArraySet<X> deserialized) {
ByteBuf output = allocator.buffer();
try {
output.writeInt(deserialized.size());