CavalliumDBEngine/src/main/java/it/cavallium/dbengine/database/collections/DatabaseMapDictionary.java

558 lines
20 KiB
Java
Raw Normal View History

package it.cavallium.dbengine.database.collections;
import static it.cavallium.dbengine.utils.StreamUtils.resourceStream;
2023-03-06 12:19:08 +01:00
import it.cavallium.buffer.Buf;
import it.cavallium.buffer.BufDataInput;
import it.cavallium.buffer.BufDataOutput;
import it.cavallium.dbengine.client.CompositeSnapshot;
2021-05-08 03:09:00 +02:00
import it.cavallium.dbengine.database.Delta;
import it.cavallium.dbengine.database.LLDictionary;
2021-01-31 21:23:43 +01:00
import it.cavallium.dbengine.database.LLDictionaryResultType;
2021-08-28 22:42:51 +02:00
import it.cavallium.dbengine.database.LLEntry;
2022-01-22 23:21:40 +01:00
import it.cavallium.dbengine.database.LLRange;
2021-01-31 21:23:43 +01:00
import it.cavallium.dbengine.database.LLUtils;
import it.cavallium.dbengine.database.SerializedKey;
2022-05-20 23:59:56 +02:00
import it.cavallium.dbengine.database.SubStageEntry;
2021-05-02 19:18:15 +02:00
import it.cavallium.dbengine.database.UpdateMode;
2021-05-08 03:09:00 +02:00
import it.cavallium.dbengine.database.UpdateReturnMode;
2023-03-27 22:00:32 +02:00
import it.cavallium.dbengine.database.disk.CachedSerializationFunction;
2021-11-08 10:49:59 +01:00
import it.cavallium.dbengine.database.serialization.KVSerializationFunction;
2021-08-22 21:23:22 +02:00
import it.cavallium.dbengine.database.serialization.SerializationException;
import it.cavallium.dbengine.database.serialization.SerializationFunction;
2021-02-02 19:40:37 +01:00
import it.cavallium.dbengine.database.serialization.Serializer;
import it.cavallium.dbengine.database.serialization.SerializerFixedBinaryLength;
import it.cavallium.dbengine.utils.StreamUtils;
2021-12-18 18:16:56 +01:00
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMaps;
import java.util.Map;
import java.util.Map.Entry;
2021-05-02 19:18:15 +02:00
import java.util.Objects;
2021-07-23 15:20:33 +02:00
import java.util.Optional;
2022-03-11 17:59:46 +01:00
import java.util.concurrent.atomic.AtomicLong;
2023-02-28 23:10:31 +01:00
import java.util.function.BiFunction;
import java.util.stream.Collectors;
import java.util.stream.Stream;
2022-03-11 17:59:46 +01:00
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
2021-01-31 21:23:43 +01:00
/**
* Optimized implementation of "DatabaseMapDictionary with SubStageGetterSingle"
*/
public class DatabaseMapDictionary<T, U> extends DatabaseMapDictionaryDeep<T, U, DatabaseStageEntry<U>> {
2022-03-11 17:59:46 +01:00
private static final Logger LOG = LogManager.getLogger(DatabaseMapDictionary.class);
private final AtomicLong totalZeroBytesErrors = new AtomicLong();
2021-09-02 17:15:40 +02:00
private final Serializer<U> valueSerializer;
protected DatabaseMapDictionary(LLDictionary dictionary,
@Nullable Buf prefixKey,
2021-09-02 17:15:40 +02:00
SerializerFixedBinaryLength<T> keySuffixSerializer,
2022-07-19 23:45:39 +02:00
Serializer<U> valueSerializer) {
// Do not retain or release or use the prefixKey here
super(dictionary, prefixKey, keySuffixSerializer, new SubStageGetterSingle<>(valueSerializer), 0);
2021-01-31 21:23:43 +01:00
this.valueSerializer = valueSerializer;
}
2021-01-31 21:23:43 +01:00
public static <T, U> DatabaseMapDictionary<T, U> simple(LLDictionary dictionary,
2021-09-02 17:15:40 +02:00
SerializerFixedBinaryLength<T> keySerializer,
2022-07-19 23:45:39 +02:00
Serializer<U> valueSerializer) {
return new DatabaseMapDictionary<>(dictionary, null, keySerializer, valueSerializer);
}
2021-01-31 21:23:43 +01:00
public static <T, U> DatabaseMapDictionary<T, U> tail(LLDictionary dictionary,
@Nullable Buf prefixKey,
2021-09-02 17:15:40 +02:00
SerializerFixedBinaryLength<T> keySuffixSerializer,
2022-07-19 23:45:39 +02:00
Serializer<U> valueSerializer) {
return new DatabaseMapDictionary<>(dictionary, prefixKey, keySuffixSerializer, valueSerializer);
}
public static <K, V> Stream<Entry<K, V>> getLeavesFrom(DatabaseMapDictionary<K, V> databaseMapDictionary,
2022-03-20 14:33:27 +01:00
CompositeSnapshot snapshot,
@Nullable K keyMin,
@Nullable K keyMax,
boolean reverse,
boolean smallRange) {
if (keyMin != null || keyMax != null) {
2023-02-28 23:10:31 +01:00
return databaseMapDictionary.getAllEntries(snapshot,
keyMin,
keyMax,
reverse,
2023-02-28 23:10:31 +01:00
smallRange,
Map::entry
);
} else {
2023-02-28 23:10:31 +01:00
return databaseMapDictionary.getAllEntries(snapshot, smallRange, Map::entry);
}
2022-03-20 14:33:27 +01:00
}
public static <K> Stream<K> getKeyLeavesFrom(DatabaseMapDictionary<K, ?> databaseMapDictionary,
2022-03-24 21:14:17 +01:00
CompositeSnapshot snapshot,
@Nullable K keyMin,
@Nullable K keyMax,
boolean reverse,
boolean smallRange) {
Stream<? extends Entry<K, ? extends DatabaseStageEntry<?>>> stagesFlux;
if (keyMin != null || keyMax != null) {
stagesFlux = databaseMapDictionary.getAllStages(snapshot, keyMin, keyMax, reverse, smallRange);
} else {
stagesFlux = databaseMapDictionary.getAllStages(snapshot, smallRange);
}
return stagesFlux.map(Entry::getKey);
2022-03-24 21:14:17 +01:00
}
2023-03-27 22:00:32 +02:00
private U deserializeValue(Buf value) {
return valueSerializer.deserialize(BufDataInput.create(value));
}
private @Nullable U deserializeValue(T keySuffix, BufDataInput value) {
2022-05-20 18:31:05 +02:00
try {
2022-05-20 23:59:56 +02:00
return valueSerializer.deserialize(value);
2022-05-20 18:31:05 +02:00
} catch (IndexOutOfBoundsException ex) {
var exMessage = ex.getMessage();
if (exMessage != null && exMessage.contains("read 0 to 0, write 0 to ")) {
var totalZeroBytesErrors = this.totalZeroBytesErrors.incrementAndGet();
if (totalZeroBytesErrors < 512 || totalZeroBytesErrors % 10000 == 0) {
var keySuffixBytes = serializeKeySuffixToKey(keySuffix);
try {
LOG.error(
"Unexpected zero-bytes value at " + dictionary.getDatabaseName() + ":" + dictionary.getColumnName()
+ ":" + LLUtils.toStringSafe(keyPrefix) + ":" + keySuffix + "(" + LLUtils.toStringSafe(
keySuffixBytes) + ") total=" + totalZeroBytesErrors);
} catch (SerializationException e) {
LOG.error(
"Unexpected zero-bytes value at " + dictionary.getDatabaseName() + ":" + dictionary.getColumnName()
+ ":" + LLUtils.toStringSafe(keyPrefix) + ":" + keySuffix + "(?) total=" + totalZeroBytesErrors);
}
2022-03-11 17:59:46 +01:00
}
2022-05-20 23:59:56 +02:00
return null;
2022-05-20 18:31:05 +02:00
} else {
2022-05-20 23:59:56 +02:00
throw ex;
2022-03-11 17:59:46 +01:00
}
2021-10-19 00:22:05 +02:00
}
}
private Buf serializeValue(U value) throws SerializationException {
2021-10-19 00:22:05 +02:00
var valSizeHint = valueSerializer.getSerializedSizeHint();
if (valSizeHint == -1) valSizeHint = 128;
var valBuf = BufDataOutput.create(valSizeHint);
2023-03-02 23:13:54 +01:00
try {
valueSerializer.serialize(value, valBuf);
} catch (SerializationException ex) {
throw ex;
} catch (Exception ex) {
throw new SerializationException("Failed to serialize value");
}
return valBuf.asList();
2021-10-19 00:22:05 +02:00
}
private Buf serializeKeySuffixToKey(T keySuffix) throws SerializationException {
BufDataOutput keyBuf = BufDataOutput.createLimited(keyPrefixLength + keySuffixLength + keyExtLength);
if (keyPrefix != null) {
keyBuf.writeBytes(keyPrefix);
2021-11-08 16:33:41 +01:00
}
assert keyBuf.size() == keyPrefixLength;
serializeSuffixTo(keySuffix, keyBuf);
assert keyBuf.size() == keyPrefixLength + keySuffixLength + keyExtLength;
return keyBuf.asList();
}
private Buf toKey(Buf suffixKey) {
assert suffixKeyLengthConsistency(suffixKey.size());
if (keyPrefix != null) {
var result = keyPrefix.copy();
result.addAll(suffixKey);
assert result.size() == keyPrefixLength + keySuffixLength + keyExtLength;
return result;
2021-11-08 16:33:41 +01:00
} else {
assert suffixKey.size() == keyPrefixLength + keySuffixLength + keyExtLength;
2021-11-08 16:33:41 +01:00
return suffixKey;
}
}
2021-01-31 21:23:43 +01:00
@Override
public Object2ObjectSortedMap<T, U> get(@Nullable CompositeSnapshot snapshot) {
Stream<Entry<T, U>> stream = dictionary
.getRange(resolveSnapshot(snapshot), range, false, true)
2022-05-21 15:28:52 +02:00
.map(entry -> {
2021-10-19 00:22:05 +02:00
Entry<T, U> deserializedEntry;
T key;
// serializedKey
var buf1 = BufDataInput.create(entry.getKey());
var serializedValue = BufDataInput.create(entry.getValue());
// after this, it becomes serializedSuffixAndExt
buf1.skipNBytes(keyPrefixLength);
suffixAndExtKeyConsistency(buf1.available());
2023-02-22 22:31:36 +01:00
key = deserializeSuffix(buf1);
U value = valueSerializer.deserialize(serializedValue);
deserializedEntry = Map.entry(key, value);
2022-05-21 15:28:52 +02:00
return deserializedEntry;
});
// serializedKey
// after this, it becomes serializedSuffixAndExt
var map = StreamUtils.collect(stream,
Collectors.toMap(Entry::getKey, Entry::getValue, (a, b) -> a, Object2ObjectLinkedOpenHashMap::new)
);
2023-02-28 23:10:31 +01:00
return map == null || map.isEmpty() ? null : map;
2021-01-31 19:52:47 +01:00
}
2021-01-31 21:23:43 +01:00
@Override
public Object2ObjectSortedMap<T, U> setAndGetPrevious(Object2ObjectSortedMap<T, U> value) {
Object2ObjectSortedMap<T, U> prev = this.get(null);
if (value == null || value.isEmpty()) {
dictionary.clear();
} else {
dictionary.setRange(range, value.entrySet().stream().map(this::serializeEntry), true);
}
2023-02-24 00:18:02 +01:00
return prev != null && prev.isEmpty() ? null : prev;
2021-01-31 19:52:47 +01:00
}
2021-01-31 21:23:43 +01:00
@Override
public Object2ObjectSortedMap<T, U> clearAndGetPrevious() {
return this.setAndGetPrevious(Object2ObjectSortedMaps.emptyMap());
}
2021-01-31 21:23:43 +01:00
@Override
public long leavesCount(@Nullable CompositeSnapshot snapshot, boolean fast) {
return dictionary.sizeRange(resolveSnapshot(snapshot), range, fast);
}
2021-03-14 03:13:19 +01:00
@Override
public boolean isEmpty(@Nullable CompositeSnapshot snapshot) {
return dictionary.isRangeEmpty(resolveSnapshot(snapshot), range, false);
2021-03-14 03:13:19 +01:00
}
2021-01-31 21:23:43 +01:00
@Override
public @NotNull DatabaseStageEntry<U> at(@Nullable CompositeSnapshot snapshot, T keySuffix) {
return new DatabaseMapSingle<>(dictionary, serializeKeySuffixToKey(keySuffix), valueSerializer);
}
2022-01-22 23:21:40 +01:00
@Override
public boolean containsKey(@Nullable CompositeSnapshot snapshot, T keySuffix) {
return !dictionary.isRangeEmpty(resolveSnapshot(snapshot),
LLRange.single(serializeKeySuffixToKey(keySuffix)), true);
2022-01-22 23:21:40 +01:00
}
2021-01-31 21:23:43 +01:00
@Override
public U getValue(@Nullable CompositeSnapshot snapshot, T keySuffix) {
var keySuffixBuf = serializeKeySuffixToKey(keySuffix);
Buf value = dictionary.get(resolveSnapshot(snapshot), keySuffixBuf);
2023-02-24 00:18:02 +01:00
return value != null ? deserializeValue(keySuffix, BufDataInput.create(value)) : null;
}
2021-01-31 21:23:43 +01:00
@Override
public void putValue(T keySuffix, U value) {
var keyMono = serializeKeySuffixToKey(keySuffix);
var valueMono = serializeValue(value);
dictionary.put(keyMono, valueMono, LLDictionaryResultType.VOID);
}
2021-05-02 19:18:15 +02:00
@Override
2022-09-12 20:14:56 +02:00
public UpdateMode getUpdateMode() {
2021-05-02 19:18:15 +02:00
return dictionary.getUpdateMode();
}
2021-02-06 19:21:31 +01:00
@Override
public U updateValue(T keySuffix,
UpdateReturnMode updateReturnMode,
2021-08-22 21:23:22 +02:00
SerializationFunction<@Nullable U, @Nullable U> updater) {
var keyMono = serializeKeySuffixToKey(keySuffix);
2023-03-27 22:00:32 +02:00
var serializedUpdater = getSerializedUpdater(updater);
dictionary.update(keyMono, serializedUpdater, UpdateReturnMode.NOTHING);
return serializedUpdater.getResult(updateReturnMode);
2021-05-08 03:09:00 +02:00
}
@Override
public Delta<U> updateValueAndGetDelta(T keySuffix, SerializationFunction<@Nullable U, @Nullable U> updater) {
var keyMono = serializeKeySuffixToKey(keySuffix);
2023-03-27 22:00:32 +02:00
var serializedUpdater = getSerializedUpdater(updater);
dictionary.update(keyMono, serializedUpdater, UpdateReturnMode.NOTHING);
return serializedUpdater.getDelta();
2021-02-06 19:21:31 +01:00
}
2023-03-27 22:00:32 +02:00
public CachedSerializationFunction<U, Buf, Buf> getSerializedUpdater(SerializationFunction<@Nullable U, @Nullable U> updater) {
return new CachedSerializationFunction<>(updater, this::serializeValue, this::deserializeValue);
2021-07-17 11:52:08 +02:00
}
public KVSerializationFunction<@NotNull T, @Nullable Buf, @Nullable Buf> getSerializedUpdater(
2021-11-08 10:49:59 +01:00
KVSerializationFunction<@NotNull T, @Nullable U, @Nullable U> updater) {
return (key, oldSerialized) -> {
U result;
if (oldSerialized == null) {
result = updater.apply(key, null);
} else {
result = updater.apply(key, valueSerializer.deserialize(BufDataInput.create(oldSerialized)));
}
if (result == null) {
return null;
} else {
return serializeValue(result);
2021-07-17 11:52:08 +02:00
}
};
}
2021-01-31 21:23:43 +01:00
@Override
public U putValueAndGetPrevious(T keySuffix, U value) {
var keyMono = serializeKeySuffixToKey(keySuffix);
var valueMono = serializeValue(value);
var valueBuf = dictionary.put(keyMono, valueMono, LLDictionaryResultType.PREVIOUS_VALUE);
2023-02-22 22:31:36 +01:00
if (valueBuf == null) {
return null;
}
return deserializeValue(keySuffix, BufDataInput.create(valueBuf));
}
2021-01-31 21:23:43 +01:00
@Override
public boolean putValueAndGetChanged(T keySuffix, U value) {
var keyMono = serializeKeySuffixToKey(keySuffix);
var valueMono = serializeValue(value);
var oldValueBuf = dictionary.put(keyMono, valueMono, LLDictionaryResultType.PREVIOUS_VALUE);
2023-02-24 00:18:02 +01:00
var oldValue = oldValueBuf != null ? deserializeValue(keySuffix, BufDataInput.create(oldValueBuf)) : null;
if (oldValue == null) {
return value != null;
} else {
return !Objects.equals(oldValue, value);
}
}
2021-01-31 21:23:43 +01:00
@Override
public void remove(T keySuffix) {
var keyMono = serializeKeySuffixToKey(keySuffix);
dictionary.remove(keyMono, LLDictionaryResultType.VOID);
}
2021-01-31 21:23:43 +01:00
@Override
public U removeAndGetPrevious(T keySuffix) {
var keyMono = serializeKeySuffixToKey(keySuffix);
var valueBuf = dictionary.remove(keyMono, LLDictionaryResultType.PREVIOUS_VALUE);
2023-02-24 00:18:02 +01:00
return valueBuf != null ? deserializeValue(keySuffix, BufDataInput.create(valueBuf)) : null;
}
2021-01-31 21:23:43 +01:00
@Override
public boolean removeAndGetStatus(T keySuffix) {
var keyMono = serializeKeySuffixToKey(keySuffix);
return LLUtils.responseToBoolean(dictionary.remove(keyMono, LLDictionaryResultType.PREVIOUS_VALUE_EXISTENCE));
}
@Override
public Stream<Optional<U>> getMulti(@Nullable CompositeSnapshot snapshot, Stream<T> keys) {
var mappedKeys = keys.map(keySuffix -> serializeKeySuffixToKey(keySuffix));
2021-08-31 09:14:46 +02:00
return dictionary
2022-03-24 21:14:17 +01:00
.getMulti(resolveSnapshot(snapshot), mappedKeys)
2022-05-21 15:28:52 +02:00
.map(valueBufOpt -> {
if (valueBufOpt.isPresent()) {
return Optional.of(valueSerializer.deserialize(BufDataInput.create(valueBufOpt.get())));
} else {
return Optional.empty();
2021-08-31 09:14:46 +02:00
}
2022-01-26 14:22:54 +01:00
});
2021-05-02 19:18:15 +02:00
}
2021-11-08 16:33:41 +01:00
private LLEntry serializeEntry(T keySuffix, U value) throws SerializationException {
var key = serializeKeySuffixToKey(keySuffix);
var serializedValue = serializeValue(value);
return LLEntry.of(key, serializedValue);
}
2022-05-21 15:28:52 +02:00
private LLEntry serializeEntry(Entry<T, U> entry) throws SerializationException {
return serializeEntry(entry.getKey(), entry.getValue());
2021-10-19 00:22:05 +02:00
}
@Override
public void putMulti(Stream<Entry<T, U>> entries) {
try (var serializedEntries = entries.map(entry -> serializeEntry(entry))) {
dictionary.putMulti(serializedEntries);
}
}
2021-07-17 11:52:08 +02:00
@Override
public Stream<Boolean> updateMulti(Stream<T> keys,
2021-11-08 10:49:59 +01:00
KVSerializationFunction<T, @Nullable U, @Nullable U> updater) {
var serializedKeys = keys.map(keySuffix -> new SerializedKey<>(keySuffix, serializeKeySuffixToKey(keySuffix)));
2021-07-17 11:52:08 +02:00
var serializedUpdater = getSerializedUpdater(updater);
return dictionary.updateMulti(serializedKeys, serializedUpdater);
2021-07-17 11:52:08 +02:00
}
@Override
public Stream<SubStageEntry<T, DatabaseStageEntry<U>>> getAllStages(@Nullable CompositeSnapshot snapshot, boolean smallRange) {
return getAllStages(snapshot, range, false, smallRange);
2022-03-24 21:14:17 +01:00
}
private LLRange getPatchedRange(@NotNull LLRange range, @Nullable T keyMin, @Nullable T keyMax)
throws SerializationException {
Buf keyMinBuf = serializeSuffixForRange(keyMin);
if (keyMinBuf == null) {
keyMinBuf = range.getMin();
}
Buf keyMaxBuf = serializeSuffixForRange(keyMax);
if (keyMaxBuf == null) {
keyMaxBuf = range.getMax();
}
return LLRange.of(keyMinBuf, keyMaxBuf);
}
private Buf serializeSuffixForRange(@Nullable T key) throws SerializationException {
if (key == null) {
return null;
}
var keyWithoutExtBuf = BufDataOutput.createLimited(keyPrefixLength + keySuffixLength);
if (keyPrefix != null) {
keyWithoutExtBuf.writeBytes(keyPrefix);
}
serializeSuffixTo(key, keyWithoutExtBuf);
return keyWithoutExtBuf.asList();
}
2022-03-24 21:14:17 +01:00
/**
* Get all stages
* @param reverse if true, the results will go backwards from the specified key (inclusive)
*/
public Stream<SubStageEntry<T, DatabaseStageEntry<U>>> getAllStages(@Nullable CompositeSnapshot snapshot,
@Nullable T keyMin,
@Nullable T keyMax,
2022-03-24 23:56:23 +01:00
boolean reverse,
boolean smallRange) {
if (keyMin == null && keyMax == null) {
2022-03-24 23:56:23 +01:00
return getAllStages(snapshot, smallRange);
2022-03-24 21:14:17 +01:00
} else {
LLRange boundedRange = getPatchedRange(range, keyMin, keyMax);
return getAllStages(snapshot, boundedRange, reverse, smallRange);
2022-03-24 21:14:17 +01:00
}
}
private Stream<SubStageEntry<T, DatabaseStageEntry<U>>> getAllStages(@Nullable CompositeSnapshot snapshot,
LLRange sliceRange, boolean reverse, boolean smallRange) {
return dictionary
.getRangeKeys(resolveSnapshot(snapshot), sliceRange, reverse, smallRange)
2022-05-21 23:49:06 +02:00
.map(keyBuf -> {
assert keyBuf.size() == keyPrefixLength + keySuffixLength + keyExtLength;
// Remove prefix. Keep only the suffix and the ext
var suffixAndExtIn = BufDataInput.create(keyBuf);
suffixAndExtIn.skipBytes(keyPrefixLength);
suffixKeyLengthConsistency(suffixAndExtIn.available());
T keySuffix = deserializeSuffix(suffixAndExtIn);
var subStage = new DatabaseMapSingle<>(dictionary, keyBuf, valueSerializer);
return new SubStageEntry<>(keySuffix, subStage);
2022-05-21 23:49:06 +02:00
});
}
2023-02-28 23:10:31 +01:00
private Stream<T> getAllKeys(@Nullable CompositeSnapshot snapshot,
LLRange sliceRange, boolean reverse, boolean smallRange) {
return dictionary
.getRangeKeys(resolveSnapshot(snapshot), sliceRange, reverse, smallRange)
.map(keyBuf -> {
assert keyBuf.size() == keyPrefixLength + keySuffixLength + keyExtLength;
// Remove prefix. Keep only the suffix and the ext
var suffixAndExtIn = BufDataInput.create(keyBuf);
suffixAndExtIn.skipBytes(keyPrefixLength);
suffixKeyLengthConsistency(suffixAndExtIn.available());
return deserializeSuffix(suffixAndExtIn);
});
}
@Override
public Stream<Entry<T, U>> getAllEntries(@Nullable CompositeSnapshot snapshot, boolean smallRange) {
return getAllEntries(snapshot, smallRange, Map::entry);
}
@Override
public Stream<U> getAllValues(@Nullable CompositeSnapshot snapshot, boolean smallRange) {
return getAllEntries(snapshot, range, false, smallRange, (k, v) -> v);
}
2021-03-22 20:02:19 +01:00
@Override
2023-02-28 23:10:31 +01:00
public Stream<T> getAllKeys(@Nullable CompositeSnapshot snapshot, boolean smallRange) {
return getAllKeys(snapshot, range, false, smallRange);
2022-03-20 14:33:27 +01:00
}
2022-03-24 21:14:17 +01:00
/**
* Get all values
* @param reverse if true, the results will go backwards from the specified key (inclusive)
*/
2023-02-28 23:10:31 +01:00
public Stream<Entry<T, U>> getAllEntries(@Nullable CompositeSnapshot snapshot,
@Nullable T keyMin,
@Nullable T keyMax,
2022-03-24 23:56:23 +01:00
boolean reverse,
boolean smallRange) {
2023-02-28 23:10:31 +01:00
return getAllEntries(snapshot, keyMin, keyMax, reverse, smallRange, Map::entry);
}
/**
* Get all values
* @param reverse if true, the results will go backwards from the specified key (inclusive)
*/
public <X> Stream<X> getAllEntries(@Nullable CompositeSnapshot snapshot,
@Nullable T keyMin,
@Nullable T keyMax,
boolean reverse,
boolean smallRange,
BiFunction<T, U, X> mapper) {
if (keyMin == null && keyMax == null) {
2023-02-28 23:10:31 +01:00
return getAllEntries(snapshot, smallRange, mapper);
2022-03-20 14:33:27 +01:00
} else {
LLRange boundedRange = getPatchedRange(range, keyMin, keyMax);
2023-02-28 23:10:31 +01:00
return getAllEntries(snapshot, boundedRange, reverse, smallRange, mapper);
2022-03-20 14:33:27 +01:00
}
}
2023-02-28 23:10:31 +01:00
private <X> Stream<X> getAllEntries(@Nullable CompositeSnapshot snapshot, boolean smallRange, BiFunction<T, U, X> mapper) {
return getAllEntries(snapshot, range, false, smallRange, mapper);
}
private <X> Stream<X> getAllEntries(@Nullable CompositeSnapshot snapshot,
LLRange sliceRangeMono,
2023-02-28 23:10:31 +01:00
boolean reverse,
boolean smallRange,
BiFunction<T, U, X> mapper) {
return dictionary
2022-03-24 23:56:23 +01:00
.getRange(resolveSnapshot(snapshot), sliceRangeMono, reverse, smallRange)
2022-05-21 15:28:52 +02:00
.map((serializedEntry) -> {
2023-02-28 23:10:31 +01:00
X entry;
var keyBuf = serializedEntry.getKey();
assert keyBuf != null;
assert keyBuf.size() == keyPrefixLength + keySuffixLength + keyExtLength;
// Remove prefix. Keep only the suffix and the ext
var suffixAndExtIn = BufDataInput.create(keyBuf);
suffixAndExtIn.skipBytes(keyPrefixLength);
assert suffixKeyLengthConsistency(suffixAndExtIn.available());
T keySuffix = deserializeSuffix(suffixAndExtIn);
assert serializedEntry.getValue() != null;
U value = valueSerializer.deserialize(BufDataInput.create(serializedEntry.getValue()));
2023-02-28 23:10:31 +01:00
entry = mapper.apply(keySuffix, value);
2022-05-21 15:28:52 +02:00
return entry;
});
2021-03-22 20:02:19 +01:00
}
2021-01-31 15:47:48 +01:00
@Override
2023-02-28 23:10:31 +01:00
public Stream<Entry<T, U>> setAllEntriesAndGetPrevious(Stream<Entry<T, U>> entries) {
return resourceStream(
() -> getAllEntries(null, false),
() -> dictionary.setRange(range, entries.map(entry -> serializeEntry(entry)), false)
);
2021-01-31 15:47:48 +01:00
}
2021-03-14 03:13:19 +01:00
@Override
public void clear() {
if (range.isAll()) {
dictionary.clear();
} else if (range.isSingle()) {
dictionary.remove(range.getSingleUnsafe(), LLDictionaryResultType.VOID);
} else {
dictionary.setRange(range, Stream.empty(), false);
}
}
}