Make buckets unmodifiable
This commit is contained in:
parent
fe5f50be10
commit
2489c50022
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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());
|
||||
|
Loading…
x
Reference in New Issue
Block a user