2021-01-30 20:16:14 +01:00
|
|
|
package it.cavallium.dbengine.database.collections;
|
|
|
|
|
2021-08-29 23:18:03 +02:00
|
|
|
import io.netty.buffer.api.Buffer;
|
|
|
|
import io.netty.buffer.api.Send;
|
2021-05-02 19:18:15 +02:00
|
|
|
import io.netty.util.ReferenceCounted;
|
2021-01-30 20:16:14 +01:00
|
|
|
import it.cavallium.dbengine.client.CompositeSnapshot;
|
2021-05-08 03:09:00 +02:00
|
|
|
import it.cavallium.dbengine.database.Delta;
|
2021-07-17 11:52:08 +02:00
|
|
|
import it.cavallium.dbengine.database.ExtraKeyOperationResult;
|
2021-01-30 20:16:14 +01:00
|
|
|
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;
|
2021-01-31 21:23:43 +01:00
|
|
|
import it.cavallium.dbengine.database.LLUtils;
|
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;
|
2021-08-22 21:23:22 +02:00
|
|
|
import it.cavallium.dbengine.database.serialization.BiSerializationFunction;
|
|
|
|
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;
|
2021-08-28 22:42:51 +02:00
|
|
|
import java.nio.ByteBuffer;
|
2021-06-06 02:23:51 +02:00
|
|
|
import java.util.Collections;
|
2021-01-31 21:23:43 +01:00
|
|
|
import java.util.HashMap;
|
2021-01-30 20:16:14 +01:00
|
|
|
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;
|
2021-07-17 11:52:08 +02:00
|
|
|
import java.util.function.BiFunction;
|
2021-02-06 19:21:31 +01:00
|
|
|
import java.util.function.Function;
|
2021-01-30 20:16:14 +01:00
|
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
import reactor.core.publisher.Flux;
|
|
|
|
import reactor.core.publisher.Mono;
|
2021-08-22 21:23:22 +02:00
|
|
|
import reactor.core.publisher.SynchronousSink;
|
2021-07-17 11:52:08 +02:00
|
|
|
import reactor.util.function.Tuple2;
|
2021-08-28 22:42:51 +02:00
|
|
|
import reactor.util.function.Tuple3;
|
2021-07-17 11:52:08 +02:00
|
|
|
import reactor.util.function.Tuples;
|
2021-01-30 20:16:14 +01:00
|
|
|
|
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>> {
|
2021-01-30 20:16:14 +01:00
|
|
|
|
2021-08-29 23:18:03 +02:00
|
|
|
private final Serializer<U, Send<Buffer>> valueSerializer;
|
2021-01-30 20:16:14 +01:00
|
|
|
|
2021-02-01 11:00:27 +01:00
|
|
|
protected DatabaseMapDictionary(LLDictionary dictionary,
|
2021-08-29 23:18:03 +02:00
|
|
|
Send<Buffer> prefixKey,
|
|
|
|
SerializerFixedBinaryLength<T, Send<Buffer>> keySuffixSerializer,
|
|
|
|
Serializer<U, Send<Buffer>> valueSerializer) {
|
2021-04-30 19:15:04 +02:00
|
|
|
// Do not retain or release or use the prefixKey here
|
2021-02-02 19:40:37 +01:00
|
|
|
super(dictionary, prefixKey, keySuffixSerializer, new SubStageGetterSingle<>(valueSerializer), 0);
|
2021-01-31 21:23:43 +01:00
|
|
|
this.valueSerializer = valueSerializer;
|
2021-01-30 20:16:14 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 21:23:43 +01:00
|
|
|
public static <T, U> DatabaseMapDictionary<T, U> simple(LLDictionary dictionary,
|
2021-08-29 23:18:03 +02:00
|
|
|
SerializerFixedBinaryLength<T, Send<Buffer>> keySerializer,
|
|
|
|
Serializer<U, Send<Buffer>> valueSerializer) {
|
|
|
|
return new DatabaseMapDictionary<>(dictionary, dictionary.getAllocator().allocate(0).send(), keySerializer, valueSerializer);
|
2021-01-30 20:16:14 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 21:23:43 +01:00
|
|
|
public static <T, U> DatabaseMapDictionary<T, U> tail(LLDictionary dictionary,
|
2021-08-29 23:18:03 +02:00
|
|
|
Send<Buffer> prefixKey,
|
|
|
|
SerializerFixedBinaryLength<T, Send<Buffer>> keySuffixSerializer,
|
|
|
|
Serializer<U, Send<Buffer>> valueSerializer) {
|
2021-01-31 21:23:43 +01:00
|
|
|
return new DatabaseMapDictionary<>(dictionary, prefixKey, keySuffixSerializer, valueSerializer);
|
2021-01-30 20:16:14 +01:00
|
|
|
}
|
|
|
|
|
2021-08-29 23:18:03 +02:00
|
|
|
private Send<Buffer> toKey(Send<Buffer> suffixKeyToSend) {
|
|
|
|
try (var suffixKey = suffixKeyToSend.receive()) {
|
2021-05-02 19:18:15 +02:00
|
|
|
assert suffixKeyConsistency(suffixKey.readableBytes());
|
2021-08-29 23:18:03 +02:00
|
|
|
return LLUtils.compositeBuffer(dictionary.getAllocator(), keyPrefix.copy().send(), suffixKey.send());
|
2021-04-30 19:15:04 +02:00
|
|
|
}
|
2021-01-30 20:16:14 +01:00
|
|
|
}
|
|
|
|
|
2021-08-29 23:18:03 +02:00
|
|
|
private void deserializeValue(Send<Buffer> value, SynchronousSink<U> sink) {
|
2021-08-22 21:23:22 +02:00
|
|
|
try {
|
|
|
|
sink.next(valueSerializer.deserialize(value));
|
|
|
|
} catch (SerializationException ex) {
|
|
|
|
sink.error(ex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-31 21:23:43 +01:00
|
|
|
@Override
|
2021-03-18 16:19:41 +01:00
|
|
|
public Mono<Map<T, U>> get(@Nullable CompositeSnapshot snapshot, boolean existsAlmostCertainly) {
|
2021-08-22 18:20:05 +02:00
|
|
|
return dictionary
|
|
|
|
.getRange(resolveSnapshot(snapshot), rangeMono, existsAlmostCertainly)
|
2021-08-22 21:23:22 +02:00
|
|
|
.<Entry<T, U>>handle((entry, sink) -> {
|
|
|
|
try {
|
|
|
|
var key = deserializeSuffix(stripPrefix(entry.getKey(), false));
|
|
|
|
var value = valueSerializer.deserialize(entry.getValue());
|
|
|
|
sink.next(Map.entry(key, value));
|
|
|
|
} catch (SerializationException ex) {
|
|
|
|
sink.error(ex);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.collectMap(Entry::getKey, Entry::getValue, HashMap::new)
|
2021-08-22 18:20:05 +02:00
|
|
|
.filter(map -> !map.isEmpty());
|
2021-01-31 19:52:47 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 21:23:43 +01:00
|
|
|
@Override
|
|
|
|
public Mono<Map<T, U>> setAndGetPrevious(Map<T, U> value) {
|
2021-08-22 21:23:22 +02:00
|
|
|
return this
|
|
|
|
.get(null, false)
|
|
|
|
.concatWith(dictionary.setRange(rangeMono, Flux
|
2021-08-22 19:54:23 +02:00
|
|
|
.fromIterable(Collections.unmodifiableMap(value).entrySet())
|
2021-08-22 21:23:22 +02:00
|
|
|
.handle((entry, sink) -> {
|
|
|
|
try {
|
2021-08-28 22:42:51 +02:00
|
|
|
sink.next(new LLEntry(this.toKey(serializeSuffix(entry.getKey())),
|
2021-08-22 21:23:22 +02:00
|
|
|
valueSerializer.serialize(entry.getValue())));
|
|
|
|
} catch (SerializationException e) {
|
|
|
|
sink.error(e);
|
|
|
|
}
|
|
|
|
})
|
|
|
|
).then(Mono.empty()))
|
|
|
|
.singleOrEmpty()
|
|
|
|
.transform(LLUtils::handleDiscard);
|
2021-01-31 19:52:47 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 21:23:43 +01:00
|
|
|
@Override
|
|
|
|
public Mono<Map<T, U>> clearAndGetPrevious() {
|
2021-05-02 19:18:15 +02:00
|
|
|
return this
|
|
|
|
.setAndGetPrevious(Map.of());
|
2021-01-30 20:16:14 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 21:23:43 +01:00
|
|
|
@Override
|
2021-02-24 16:43:07 +01:00
|
|
|
public Mono<Long> leavesCount(@Nullable CompositeSnapshot snapshot, boolean fast) {
|
2021-08-22 18:20:05 +02:00
|
|
|
return dictionary.sizeRange(resolveSnapshot(snapshot), rangeMono, fast);
|
2021-01-30 20:16:14 +01:00
|
|
|
}
|
|
|
|
|
2021-03-14 03:13:19 +01:00
|
|
|
@Override
|
|
|
|
public Mono<Boolean> isEmpty(@Nullable CompositeSnapshot snapshot) {
|
2021-08-22 18:20:05 +02:00
|
|
|
return dictionary.isRangeEmpty(resolveSnapshot(snapshot), rangeMono);
|
2021-03-14 03:13:19 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 21:23:43 +01:00
|
|
|
@Override
|
|
|
|
public Mono<DatabaseStageEntry<U>> at(@Nullable CompositeSnapshot snapshot, T keySuffix) {
|
2021-02-01 11:00:27 +01:00
|
|
|
return Mono
|
2021-08-22 21:23:22 +02:00
|
|
|
.fromCallable(() -> new DatabaseSingleMapped<>(
|
2021-05-12 21:41:47 +02:00
|
|
|
new DatabaseSingle<>(dictionary, toKey(serializeSuffix(keySuffix)), Serializer.noop())
|
|
|
|
, valueSerializer)
|
2021-05-12 19:02:51 +02:00
|
|
|
);
|
2021-01-30 20:16:14 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 21:23:43 +01:00
|
|
|
@Override
|
2021-03-18 16:19:41 +01:00
|
|
|
public Mono<U> getValue(@Nullable CompositeSnapshot snapshot, T keySuffix, boolean existsAlmostCertainly) {
|
2021-05-02 19:18:15 +02:00
|
|
|
return Mono
|
|
|
|
.using(
|
|
|
|
() -> toKey(serializeSuffix(keySuffix)),
|
|
|
|
keyBuf -> dictionary
|
2021-08-22 18:20:05 +02:00
|
|
|
.get(resolveSnapshot(snapshot), LLUtils.lazyRetain(keyBuf), existsAlmostCertainly)
|
2021-08-22 21:23:22 +02:00
|
|
|
.handle(this::deserializeValue),
|
2021-05-02 19:18:15 +02:00
|
|
|
ReferenceCounted::release
|
|
|
|
);
|
2021-01-30 20:16:14 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 21:23:43 +01:00
|
|
|
@Override
|
|
|
|
public Mono<Void> putValue(T keySuffix, U value) {
|
2021-08-28 22:42:51 +02:00
|
|
|
return Mono.using(() -> serializeSuffix(keySuffix),
|
|
|
|
keySuffixBuf -> Mono.using(() -> toKey(keySuffixBuf.retain()),
|
|
|
|
keyBuf -> Mono.using(() -> valueSerializer.serialize(value),
|
|
|
|
valueBuf -> dictionary
|
|
|
|
.put(LLUtils.lazyRetain(keyBuf), LLUtils.lazyRetain(valueBuf), LLDictionaryResultType.VOID)
|
|
|
|
.doOnNext(ReferenceCounted::release),
|
|
|
|
ReferenceCounted::release
|
|
|
|
),
|
2021-05-12 19:02:51 +02:00
|
|
|
ReferenceCounted::release
|
2021-08-28 22:42:51 +02:00
|
|
|
),
|
|
|
|
ReferenceCounted::release
|
|
|
|
).then();
|
2021-01-30 20:16:14 +01:00
|
|
|
}
|
|
|
|
|
2021-05-02 19:18:15 +02:00
|
|
|
@Override
|
|
|
|
public Mono<UpdateMode> getUpdateMode() {
|
|
|
|
return dictionary.getUpdateMode();
|
|
|
|
}
|
|
|
|
|
2021-02-06 19:21:31 +01:00
|
|
|
@Override
|
2021-05-08 03:09:00 +02:00
|
|
|
public Mono<U> updateValue(T keySuffix,
|
|
|
|
UpdateReturnMode updateReturnMode,
|
2021-03-18 16:19:41 +01:00
|
|
|
boolean existsAlmostCertainly,
|
2021-08-22 21:23:22 +02:00
|
|
|
SerializationFunction<@Nullable U, @Nullable U> updater) {
|
2021-05-02 19:18:15 +02:00
|
|
|
return Mono
|
|
|
|
.using(
|
|
|
|
() -> toKey(serializeSuffix(keySuffix)),
|
2021-05-08 03:09:00 +02:00
|
|
|
keyBuf -> dictionary
|
2021-08-22 18:20:05 +02:00
|
|
|
.update(LLUtils.lazyRetain(keyBuf), getSerializedUpdater(updater), updateReturnMode, existsAlmostCertainly)
|
2021-08-22 21:23:22 +02:00
|
|
|
.handle(this::deserializeValue),
|
2021-05-08 03:09:00 +02:00
|
|
|
ReferenceCounted::release
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public Mono<Delta<U>> updateValueAndGetDelta(T keySuffix,
|
|
|
|
boolean existsAlmostCertainly,
|
2021-08-22 21:23:22 +02:00
|
|
|
SerializationFunction<@Nullable U, @Nullable U> updater) {
|
2021-05-08 03:09:00 +02:00
|
|
|
return Mono
|
|
|
|
.using(
|
|
|
|
() -> toKey(serializeSuffix(keySuffix)),
|
|
|
|
keyBuf -> dictionary
|
2021-08-22 18:20:05 +02:00
|
|
|
.updateAndGetDelta(LLUtils.lazyRetain(keyBuf), getSerializedUpdater(updater), existsAlmostCertainly)
|
|
|
|
.transform(mono -> LLUtils.mapDelta(mono, valueSerializer::deserialize)),
|
2021-05-02 19:18:15 +02:00
|
|
|
ReferenceCounted::release
|
|
|
|
);
|
2021-02-06 19:21:31 +01:00
|
|
|
}
|
|
|
|
|
2021-08-29 23:18:03 +02:00
|
|
|
public SerializationFunction<@Nullable Buffer, @Nullable Buffer> getSerializedUpdater(SerializationFunction<@Nullable U, @Nullable U> updater) {
|
2021-07-17 11:52:08 +02:00
|
|
|
return oldSerialized -> {
|
|
|
|
try {
|
2021-08-22 21:23:22 +02:00
|
|
|
U result;
|
|
|
|
if (oldSerialized == null) {
|
|
|
|
result = updater.apply(null);
|
|
|
|
} else {
|
|
|
|
result = updater.apply(valueSerializer.deserialize(oldSerialized.retain()));
|
|
|
|
}
|
2021-07-17 11:52:08 +02:00
|
|
|
if (result == null) {
|
|
|
|
return null;
|
|
|
|
} else {
|
2021-08-22 18:20:05 +02:00
|
|
|
return valueSerializer.serialize(result);
|
2021-07-17 11:52:08 +02:00
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
if (oldSerialized != null) {
|
|
|
|
oldSerialized.release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-08-29 23:18:03 +02:00
|
|
|
public <X> BiSerializationFunction<@Nullable Buffer, X, @Nullable Buffer> getSerializedUpdater(
|
2021-08-22 21:23:22 +02:00
|
|
|
BiSerializationFunction<@Nullable U, X, @Nullable U> updater) {
|
2021-07-17 11:52:08 +02:00
|
|
|
return (oldSerialized, extra) -> {
|
|
|
|
try {
|
2021-08-22 21:23:22 +02:00
|
|
|
U result;
|
|
|
|
if (oldSerialized == null) {
|
|
|
|
result = updater.apply(null, extra);
|
|
|
|
} else {
|
|
|
|
result = updater.apply(valueSerializer.deserialize(oldSerialized.retain()), extra);
|
|
|
|
}
|
2021-07-17 11:52:08 +02:00
|
|
|
if (result == null) {
|
|
|
|
return null;
|
|
|
|
} else {
|
2021-08-22 18:20:05 +02:00
|
|
|
return valueSerializer.serialize(result);
|
2021-07-17 11:52:08 +02:00
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
if (oldSerialized != null) {
|
|
|
|
oldSerialized.release();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2021-01-31 21:23:43 +01:00
|
|
|
@Override
|
|
|
|
public Mono<U> putValueAndGetPrevious(T keySuffix, U value) {
|
2021-05-12 19:02:51 +02:00
|
|
|
return Mono
|
|
|
|
.using(
|
|
|
|
() -> serializeSuffix(keySuffix),
|
|
|
|
keySuffixBuf -> Mono
|
|
|
|
.using(
|
|
|
|
() -> toKey(keySuffixBuf.retain()),
|
|
|
|
keyBuf -> Mono
|
2021-08-22 18:20:05 +02:00
|
|
|
.using(() -> valueSerializer.serialize(value),
|
2021-05-12 19:02:51 +02:00
|
|
|
valueBuf -> dictionary
|
2021-08-22 18:20:05 +02:00
|
|
|
.put(LLUtils.lazyRetain(keyBuf),
|
|
|
|
LLUtils.lazyRetain(valueBuf),
|
|
|
|
LLDictionaryResultType.PREVIOUS_VALUE)
|
2021-08-22 21:23:22 +02:00
|
|
|
.handle(this::deserializeValue),
|
2021-05-12 19:02:51 +02:00
|
|
|
ReferenceCounted::release
|
|
|
|
),
|
|
|
|
ReferenceCounted::release
|
|
|
|
),
|
|
|
|
ReferenceCounted::release
|
|
|
|
);
|
2021-01-31 00:36:21 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 21:23:43 +01:00
|
|
|
@Override
|
2021-05-02 19:18:15 +02:00
|
|
|
public Mono<Boolean> putValueAndGetChanged(T keySuffix, U value) {
|
2021-05-12 19:02:51 +02:00
|
|
|
return Mono
|
|
|
|
.using(
|
|
|
|
() -> serializeSuffix(keySuffix),
|
|
|
|
keySuffixBuf -> Mono
|
|
|
|
.using(
|
|
|
|
() -> toKey(keySuffixBuf.retain()),
|
|
|
|
keyBuf -> Mono
|
2021-08-22 18:20:05 +02:00
|
|
|
.using(() -> valueSerializer.serialize(value),
|
2021-05-12 19:02:51 +02:00
|
|
|
valueBuf -> dictionary
|
2021-08-22 18:20:05 +02:00
|
|
|
.put(LLUtils.lazyRetain(keyBuf),
|
|
|
|
LLUtils.lazyRetain(valueBuf),
|
|
|
|
LLDictionaryResultType.PREVIOUS_VALUE
|
|
|
|
)
|
2021-08-22 21:23:22 +02:00
|
|
|
.handle(this::deserializeValue)
|
2021-05-12 19:02:51 +02:00
|
|
|
.map(oldValue -> !Objects.equals(oldValue, value))
|
|
|
|
.defaultIfEmpty(value != null),
|
|
|
|
ReferenceCounted::release
|
|
|
|
),
|
|
|
|
ReferenceCounted::release
|
|
|
|
),
|
|
|
|
ReferenceCounted::release
|
|
|
|
);
|
2021-01-31 00:36:21 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 21:23:43 +01:00
|
|
|
@Override
|
|
|
|
public Mono<Void> remove(T keySuffix) {
|
2021-05-02 19:18:15 +02:00
|
|
|
return Mono
|
|
|
|
.using(
|
|
|
|
() -> toKey(serializeSuffix(keySuffix)),
|
2021-05-03 12:29:15 +02:00
|
|
|
keyBuf -> dictionary
|
2021-08-22 18:20:05 +02:00
|
|
|
.remove(LLUtils.lazyRetain(keyBuf), LLDictionaryResultType.VOID)
|
2021-05-03 12:29:15 +02:00
|
|
|
.doOnNext(ReferenceCounted::release)
|
|
|
|
.then(),
|
2021-05-02 19:18:15 +02:00
|
|
|
ReferenceCounted::release
|
|
|
|
);
|
2021-01-30 20:16:14 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 21:23:43 +01:00
|
|
|
@Override
|
|
|
|
public Mono<U> removeAndGetPrevious(T keySuffix) {
|
2021-05-12 21:41:47 +02:00
|
|
|
return Mono
|
|
|
|
.using(
|
|
|
|
() -> toKey(serializeSuffix(keySuffix)),
|
|
|
|
keyBuf -> dictionary
|
2021-08-22 18:20:05 +02:00
|
|
|
.remove(LLUtils.lazyRetain(keyBuf), LLDictionaryResultType.PREVIOUS_VALUE)
|
2021-08-22 21:23:22 +02:00
|
|
|
.handle(this::deserializeValue),
|
2021-05-12 21:41:47 +02:00
|
|
|
ReferenceCounted::release
|
|
|
|
);
|
2021-01-30 20:16:14 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 21:23:43 +01:00
|
|
|
@Override
|
|
|
|
public Mono<Boolean> removeAndGetStatus(T keySuffix) {
|
2021-05-12 21:41:47 +02:00
|
|
|
return Mono
|
|
|
|
.using(
|
|
|
|
() -> toKey(serializeSuffix(keySuffix)),
|
|
|
|
keyBuf -> dictionary
|
2021-08-22 18:20:05 +02:00
|
|
|
.remove(LLUtils.lazyRetain(keyBuf), LLDictionaryResultType.PREVIOUS_VALUE_EXISTENCE)
|
2021-05-12 21:41:47 +02:00
|
|
|
.map(LLUtils::responseToBoolean),
|
|
|
|
ReferenceCounted::release
|
|
|
|
);
|
2021-01-30 20:16:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2021-07-23 15:20:33 +02:00
|
|
|
public Flux<Entry<T, Optional<U>>> getMulti(@Nullable CompositeSnapshot snapshot, Flux<T> keys, boolean existsAlmostCertainly) {
|
2021-08-28 22:42:51 +02:00
|
|
|
return dictionary.getMulti(resolveSnapshot(snapshot), keys.flatMap(keySuffix -> Mono.fromCallable(() -> {
|
2021-08-29 23:18:03 +02:00
|
|
|
Buffer keySuffixBuf = serializeSuffix(keySuffix);
|
2021-08-28 22:42:51 +02:00
|
|
|
try {
|
|
|
|
var key = toKey(keySuffixBuf.retain());
|
2021-08-22 18:20:05 +02:00
|
|
|
try {
|
2021-08-28 22:42:51 +02:00
|
|
|
return Tuples.of(keySuffix, key.retain());
|
2021-08-22 18:20:05 +02:00
|
|
|
} finally {
|
2021-08-28 22:42:51 +02:00
|
|
|
key.release();
|
2021-08-22 18:20:05 +02:00
|
|
|
}
|
2021-08-28 22:42:51 +02:00
|
|
|
} finally {
|
|
|
|
keySuffixBuf.release();
|
|
|
|
}
|
|
|
|
})), existsAlmostCertainly).flatMapSequential(entry -> {
|
|
|
|
entry.getT2().release();
|
|
|
|
return Mono.fromCallable(() -> {
|
|
|
|
Optional<U> valueOpt;
|
|
|
|
if (entry.getT3().isPresent()) {
|
|
|
|
var buf = entry.getT3().get();
|
|
|
|
try {
|
|
|
|
valueOpt = Optional.of(valueSerializer.deserialize(buf.retain()));
|
|
|
|
} finally {
|
|
|
|
buf.release();
|
2021-08-22 21:23:22 +02:00
|
|
|
}
|
2021-08-28 22:42:51 +02:00
|
|
|
} else {
|
|
|
|
valueOpt = Optional.empty();
|
|
|
|
}
|
|
|
|
return Map.entry(entry.getT1(), valueOpt);
|
2021-08-22 18:20:05 +02:00
|
|
|
});
|
2021-08-28 22:42:51 +02:00
|
|
|
}).transform(LLUtils::handleDiscard);
|
2021-05-02 19:18:15 +02:00
|
|
|
}
|
|
|
|
|
2021-08-28 22:42:51 +02:00
|
|
|
private LLEntry serializeEntry(T key, U value) throws SerializationException {
|
2021-08-29 23:18:03 +02:00
|
|
|
Buffer serializedKey = toKey(serializeSuffix(key));
|
2021-05-02 19:18:15 +02:00
|
|
|
try {
|
2021-08-29 23:18:03 +02:00
|
|
|
Buffer serializedValue = valueSerializer.serialize(value);
|
2021-05-02 19:18:15 +02:00
|
|
|
try {
|
2021-08-28 22:42:51 +02:00
|
|
|
return new LLEntry(serializedKey.retain(), serializedValue.retain());
|
2021-05-02 19:18:15 +02:00
|
|
|
} finally {
|
|
|
|
serializedValue.release();
|
|
|
|
}
|
|
|
|
} finally {
|
|
|
|
serializedKey.release();
|
|
|
|
}
|
2021-01-30 20:16:14 +01:00
|
|
|
}
|
|
|
|
|
2021-02-01 02:21:53 +01:00
|
|
|
@Override
|
|
|
|
public Mono<Void> putMulti(Flux<Entry<T, U>> entries) {
|
2021-05-02 19:18:15 +02:00
|
|
|
var serializedEntries = entries
|
2021-08-28 22:42:51 +02:00
|
|
|
.<LLEntry>handle((entry, sink) -> {
|
|
|
|
try {
|
|
|
|
sink.next(serializeEntry(entry.getKey(), entry.getValue()));
|
|
|
|
} catch (SerializationException e) {
|
|
|
|
sink.error(e);
|
|
|
|
}
|
|
|
|
});
|
2021-02-01 02:21:53 +01:00
|
|
|
return dictionary
|
2021-05-02 19:18:15 +02:00
|
|
|
.putMulti(serializedEntries, false)
|
2021-08-28 22:42:51 +02:00
|
|
|
.then()
|
|
|
|
.doOnDiscard(LLEntry.class, entry -> {
|
|
|
|
if (!entry.isReleased()) {
|
|
|
|
entry.release();
|
|
|
|
}
|
|
|
|
});
|
2021-02-01 02:21:53 +01:00
|
|
|
}
|
|
|
|
|
2021-07-17 11:52:08 +02:00
|
|
|
@Override
|
|
|
|
public <X> Flux<ExtraKeyOperationResult<T, X>> updateMulti(Flux<Tuple2<T, X>> entries,
|
2021-08-22 21:23:22 +02:00
|
|
|
BiSerializationFunction<@Nullable U, X, @Nullable U> updater) {
|
2021-08-29 23:18:03 +02:00
|
|
|
Flux<Tuple2<Buffer, X>> serializedEntries = entries
|
2021-07-17 11:52:08 +02:00
|
|
|
.flatMap(entry -> Mono
|
|
|
|
.fromCallable(() -> Tuples.of(serializeSuffix(entry.getT1()), entry.getT2()))
|
2021-07-23 22:18:08 +02:00
|
|
|
)
|
|
|
|
.doOnDiscard(Tuple2.class, uncastedEntry -> {
|
2021-08-29 23:18:03 +02:00
|
|
|
if (uncastedEntry.getT1() instanceof Buffer byteBuf) {
|
2021-07-23 22:18:08 +02:00
|
|
|
byteBuf.release();
|
|
|
|
}
|
2021-08-29 23:18:03 +02:00
|
|
|
if (uncastedEntry.getT2() instanceof Buffer byteBuf) {
|
2021-07-23 22:18:08 +02:00
|
|
|
byteBuf.release();
|
|
|
|
}
|
|
|
|
});
|
2021-07-17 11:52:08 +02:00
|
|
|
var serializedUpdater = getSerializedUpdater(updater);
|
|
|
|
return dictionary.updateMulti(serializedEntries, serializedUpdater)
|
2021-08-22 21:23:22 +02:00
|
|
|
.handle((result, sink) -> {
|
|
|
|
try {
|
|
|
|
sink.next(new ExtraKeyOperationResult<>(deserializeSuffix(result.key()),
|
|
|
|
result.extra(),
|
|
|
|
result.changed()
|
|
|
|
));
|
|
|
|
} catch (SerializationException ex) {
|
|
|
|
sink.error(ex);
|
|
|
|
}
|
|
|
|
});
|
2021-07-17 11:52:08 +02:00
|
|
|
}
|
|
|
|
|
2021-01-30 20:16:14 +01:00
|
|
|
@Override
|
2021-01-31 21:23:43 +01:00
|
|
|
public Flux<Entry<T, DatabaseStageEntry<U>>> getAllStages(@Nullable CompositeSnapshot snapshot) {
|
2021-08-22 18:20:05 +02:00
|
|
|
return dictionary
|
|
|
|
.getRangeKeys(resolveSnapshot(snapshot), rangeMono)
|
2021-08-22 21:23:22 +02:00
|
|
|
.handle((key, sink) -> {
|
2021-05-02 19:18:15 +02:00
|
|
|
try {
|
2021-08-29 23:18:03 +02:00
|
|
|
Buffer keySuffixWithExt = stripPrefix(key.retain(), false);
|
2021-05-12 21:41:47 +02:00
|
|
|
try {
|
2021-08-22 21:23:22 +02:00
|
|
|
sink.next(Map.entry(deserializeSuffix(keySuffixWithExt.retainedSlice()),
|
2021-05-12 21:41:47 +02:00
|
|
|
new DatabaseSingleMapped<>(new DatabaseSingle<>(dictionary,
|
|
|
|
toKey(keySuffixWithExt.retainedSlice()),
|
|
|
|
Serializer.noop()
|
|
|
|
), valueSerializer)
|
2021-08-22 21:23:22 +02:00
|
|
|
));
|
|
|
|
} catch (SerializationException ex) {
|
|
|
|
sink.error(ex);
|
2021-05-12 21:41:47 +02:00
|
|
|
} finally {
|
|
|
|
keySuffixWithExt.release();
|
|
|
|
}
|
2021-05-02 19:18:15 +02:00
|
|
|
} finally {
|
2021-05-12 21:41:47 +02:00
|
|
|
key.release();
|
2021-05-02 19:18:15 +02:00
|
|
|
}
|
2021-08-22 18:20:05 +02:00
|
|
|
});
|
2021-01-30 20:16:14 +01:00
|
|
|
}
|
2021-01-31 12:02:02 +01:00
|
|
|
|
2021-03-22 20:02:19 +01:00
|
|
|
@Override
|
|
|
|
public Flux<Entry<T, U>> getAllValues(@Nullable CompositeSnapshot snapshot) {
|
2021-08-22 18:20:05 +02:00
|
|
|
return dictionary
|
|
|
|
.getRange(resolveSnapshot(snapshot), rangeMono)
|
2021-08-22 21:23:22 +02:00
|
|
|
.<Entry<T, U>>handle((serializedEntry, sink) -> {
|
2021-08-29 23:18:03 +02:00
|
|
|
Buffer key = serializedEntry.getKey();
|
|
|
|
Buffer value = serializedEntry.getValue();
|
2021-08-22 21:23:22 +02:00
|
|
|
try {
|
2021-08-29 23:18:03 +02:00
|
|
|
Buffer keySuffix = stripPrefix(key.retain(), false);
|
2021-08-28 22:42:51 +02:00
|
|
|
try {
|
|
|
|
sink.next(Map.entry(deserializeSuffix(keySuffix.retain()),
|
|
|
|
valueSerializer.deserialize(value.retain())));
|
|
|
|
} finally {
|
|
|
|
keySuffix.release();
|
|
|
|
}
|
2021-08-22 21:23:22 +02:00
|
|
|
} catch (SerializationException e) {
|
|
|
|
sink.error(e);
|
2021-08-28 22:42:51 +02:00
|
|
|
} finally {
|
|
|
|
key.release();
|
|
|
|
value.release();
|
2021-08-22 21:23:22 +02:00
|
|
|
}
|
|
|
|
})
|
2021-07-23 22:18:08 +02:00
|
|
|
.doOnDiscard(Entry.class, uncastedEntry -> {
|
2021-08-29 23:18:03 +02:00
|
|
|
if (uncastedEntry.getKey() instanceof Buffer byteBuf) {
|
2021-08-28 22:42:51 +02:00
|
|
|
if (byteBuf.refCnt() > 0) {
|
|
|
|
byteBuf.release();
|
|
|
|
}
|
2021-07-23 22:18:08 +02:00
|
|
|
}
|
2021-08-29 23:18:03 +02:00
|
|
|
if (uncastedEntry.getValue() instanceof Buffer byteBuf) {
|
2021-08-28 22:42:51 +02:00
|
|
|
if (byteBuf.refCnt() > 0) {
|
|
|
|
byteBuf.release();
|
|
|
|
}
|
2021-07-23 22:18:08 +02:00
|
|
|
}
|
2021-08-22 18:20:05 +02:00
|
|
|
});
|
2021-03-22 20:02:19 +01:00
|
|
|
}
|
|
|
|
|
2021-01-31 15:47:48 +01:00
|
|
|
@Override
|
|
|
|
public Flux<Entry<T, U>> setAllValuesAndGetPrevious(Flux<Entry<T, U>> entries) {
|
2021-08-29 01:15:51 +02:00
|
|
|
return Flux.concat(
|
|
|
|
this.getAllValues(null),
|
|
|
|
dictionary.setRange(rangeMono, entries.handle((entry, sink) -> {
|
2021-08-22 21:23:22 +02:00
|
|
|
try {
|
2021-08-29 23:18:03 +02:00
|
|
|
Buffer serializedKey = toKey(serializeSuffix(entry.getKey()));
|
2021-08-28 22:42:51 +02:00
|
|
|
try {
|
2021-08-29 23:18:03 +02:00
|
|
|
Buffer serializedValue = valueSerializer.serialize(entry.getValue());
|
2021-08-28 22:42:51 +02:00
|
|
|
try {
|
2021-08-28 22:51:05 +02:00
|
|
|
sink.next(new LLEntry(serializedKey.retain(), serializedValue.retain()));
|
2021-08-28 22:42:51 +02:00
|
|
|
} finally {
|
2021-08-28 22:51:05 +02:00
|
|
|
serializedValue.release();
|
2021-08-28 22:42:51 +02:00
|
|
|
}
|
|
|
|
} finally {
|
2021-08-28 22:51:05 +02:00
|
|
|
serializedKey.release();
|
2021-08-28 22:42:51 +02:00
|
|
|
}
|
2021-08-22 21:23:22 +02:00
|
|
|
} catch (SerializationException e) {
|
|
|
|
sink.error(e);
|
|
|
|
}
|
2021-08-29 01:15:51 +02:00
|
|
|
})).then(Mono.empty())
|
2021-08-22 21:23:22 +02:00
|
|
|
);
|
2021-01-31 15:47:48 +01:00
|
|
|
}
|
|
|
|
|
2021-03-14 03:13:19 +01:00
|
|
|
@Override
|
|
|
|
public Mono<Void> clear() {
|
2021-08-22 18:20:05 +02:00
|
|
|
return Mono.defer(() -> {
|
|
|
|
if (range.isAll()) {
|
|
|
|
return dictionary.clear();
|
|
|
|
} else if (range.isSingle()) {
|
|
|
|
return dictionary
|
|
|
|
.remove(LLUtils.lazyRetain(range.getSingle()), LLDictionaryResultType.VOID)
|
|
|
|
.doOnNext(ReferenceCounted::release)
|
|
|
|
.then();
|
|
|
|
} else {
|
|
|
|
return dictionary.setRange(rangeMono, Flux.empty());
|
|
|
|
}
|
|
|
|
});
|
2021-01-31 12:02:02 +01:00
|
|
|
}
|
|
|
|
|
2021-01-30 20:16:14 +01:00
|
|
|
}
|