Fix more possible leaks
This commit is contained in:
parent
18d5ddf6e1
commit
5c4519552d
@ -50,12 +50,12 @@ public class DatabaseMapDictionary<T, U> extends DatabaseMapDictionaryDeep<T, U,
|
||||
private final Serializer<U> valueSerializer;
|
||||
|
||||
protected DatabaseMapDictionary(LLDictionary dictionary,
|
||||
@Nullable Buffer prefixKey,
|
||||
@Nullable BufSupplier prefixKeySupplier,
|
||||
SerializerFixedBinaryLength<T> keySuffixSerializer,
|
||||
Serializer<U> valueSerializer,
|
||||
Runnable onClose) {
|
||||
// Do not retain or release or use the prefixKey here
|
||||
super(dictionary, prefixKey, keySuffixSerializer, new SubStageGetterSingle<>(valueSerializer), 0, onClose);
|
||||
super(dictionary, prefixKeySupplier, keySuffixSerializer, new SubStageGetterSingle<>(valueSerializer), 0, onClose);
|
||||
this.valueSerializer = valueSerializer;
|
||||
}
|
||||
|
||||
@ -67,11 +67,11 @@ public class DatabaseMapDictionary<T, U> extends DatabaseMapDictionaryDeep<T, U,
|
||||
}
|
||||
|
||||
public static <T, U> DatabaseMapDictionary<T, U> tail(LLDictionary dictionary,
|
||||
@Nullable Buffer prefixKey,
|
||||
@Nullable BufSupplier prefixKeySupplier,
|
||||
SerializerFixedBinaryLength<T> keySuffixSerializer,
|
||||
Serializer<U> valueSerializer,
|
||||
Runnable onClose) {
|
||||
return new DatabaseMapDictionary<>(dictionary, prefixKey, keySuffixSerializer, valueSerializer, onClose);
|
||||
return new DatabaseMapDictionary<>(dictionary, prefixKeySupplier, keySuffixSerializer, valueSerializer, onClose);
|
||||
}
|
||||
|
||||
public static <K, V> Flux<Entry<K, V>> getLeavesFrom(DatabaseMapDictionary<K, V> databaseMapDictionary,
|
||||
@ -134,17 +134,19 @@ public class DatabaseMapDictionary<T, U> extends DatabaseMapDictionaryDeep<T, U,
|
||||
if (exMessage != null && exMessage.contains("read 0 to 0, write 0 to ")) {
|
||||
var totalZeroBytesErrors = this.totalZeroBytesErrors.incrementAndGet();
|
||||
if (totalZeroBytesErrors < 512 || totalZeroBytesErrors % 10000 == 0) {
|
||||
try (var keySuffixBytes = serializeKeySuffixToKey(keySuffix)) {
|
||||
LOG.error(
|
||||
"Unexpected zero-bytes value at "
|
||||
+ dictionary.getDatabaseName() + ":" + dictionary.getColumnName()
|
||||
+ ":" + LLUtils.toStringSafe(this.keyPrefix) + ":" + keySuffix
|
||||
+ "(" + LLUtils.toStringSafe(keySuffixBytes) + ") total=" + totalZeroBytesErrors);
|
||||
} catch (SerializationException e) {
|
||||
LOG.error(
|
||||
"Unexpected zero-bytes value at " + dictionary.getDatabaseName() + ":" + dictionary.getColumnName()
|
||||
+ ":" + LLUtils.toStringSafe(this.keyPrefix) + ":" + keySuffix + "(?) total="
|
||||
+ totalZeroBytesErrors);
|
||||
try (var keyPrefix = keyPrefixSupplier.get()) {
|
||||
try (var keySuffixBytes = serializeKeySuffixToKey(keySuffix)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -169,8 +171,8 @@ public class DatabaseMapDictionary<T, U> extends DatabaseMapDictionaryDeep<T, U,
|
||||
|
||||
private Buffer serializeKeySuffixToKey(T keySuffix) throws SerializationException {
|
||||
Buffer keyBuf;
|
||||
if (keyPrefix != null) {
|
||||
keyBuf = keyPrefix.copy();
|
||||
if (keyPrefixSupplier != null) {
|
||||
keyBuf = keyPrefixSupplier.get();
|
||||
} else {
|
||||
keyBuf = this.dictionary.getAllocator().allocate(keyPrefixLength + keySuffixLength + keyExtLength);
|
||||
}
|
||||
@ -188,11 +190,8 @@ public class DatabaseMapDictionary<T, U> extends DatabaseMapDictionaryDeep<T, U,
|
||||
|
||||
private Buffer toKey(Buffer suffixKey) {
|
||||
assert suffixKeyLengthConsistency(suffixKey.readableBytes());
|
||||
if (keyPrefix != null && keyPrefix.readableBytes() > 0) {
|
||||
var result = LLUtils.compositeBuffer(dictionary.getAllocator(),
|
||||
LLUtils.copy(dictionary.getAllocator(), keyPrefix),
|
||||
suffixKey.send()
|
||||
);
|
||||
if (keyPrefixSupplier != null) {
|
||||
var result = LLUtils.compositeBuffer(dictionary.getAllocator(), keyPrefixSupplier.get().send(), suffixKey.send());
|
||||
try {
|
||||
assert result.readableBytes() == keyPrefixLength + keySuffixLength + keyExtLength;
|
||||
return result;
|
||||
@ -489,9 +488,8 @@ public class DatabaseMapDictionary<T, U> extends DatabaseMapDictionaryDeep<T, U,
|
||||
if (key == null) {
|
||||
return null;
|
||||
}
|
||||
var keyWithoutExtBuf = keyPrefix == null ? alloc.allocate(keySuffixLength + keyExtLength)
|
||||
// todo: use a read-only copy
|
||||
: keyPrefix.copy();
|
||||
var keyWithoutExtBuf =
|
||||
keyPrefixSupplier == null ? alloc.allocate(keySuffixLength + keyExtLength) : keyPrefixSupplier.get();
|
||||
try {
|
||||
keyWithoutExtBuf.ensureWritable(keySuffixLength + keyExtLength);
|
||||
serializeSuffix(key, keyWithoutExtBuf);
|
||||
|
@ -6,10 +6,10 @@ import io.netty5.buffer.api.DefaultBufferAllocators;
|
||||
import io.netty5.buffer.api.Drop;
|
||||
import io.netty5.buffer.api.Owned;
|
||||
import io.netty5.buffer.api.Resource;
|
||||
import io.netty5.buffer.api.Send;
|
||||
import io.netty5.buffer.api.internal.ResourceSupport;
|
||||
import it.cavallium.dbengine.client.BadBlock;
|
||||
import it.cavallium.dbengine.client.CompositeSnapshot;
|
||||
import it.cavallium.dbengine.database.BufSupplier;
|
||||
import it.cavallium.dbengine.database.LLDictionary;
|
||||
import it.cavallium.dbengine.database.LLDictionaryResultType;
|
||||
import it.cavallium.dbengine.database.LLRange;
|
||||
@ -24,7 +24,6 @@ import it.cavallium.dbengine.database.serialization.Serializer;
|
||||
import it.cavallium.dbengine.database.serialization.SerializerFixedBinaryLength;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@ -56,19 +55,12 @@ public class DatabaseMapDictionaryDeep<T, U, US extends DatabaseStage<U>> extend
|
||||
LOG.error("Failed to close range", ex);
|
||||
}
|
||||
try {
|
||||
if (obj.keyPrefix != null) {
|
||||
obj.keyPrefix.close();
|
||||
if (obj.keyPrefixSupplier != null) {
|
||||
obj.keyPrefixSupplier.close();
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
LOG.error("Failed to close keyPrefix", ex);
|
||||
}
|
||||
try {
|
||||
if (obj.keySuffixAndExtZeroBuffer != null) {
|
||||
obj.keySuffixAndExtZeroBuffer.close();
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
LOG.error("Failed to close keySuffixAndExtZeroBuffer", ex);
|
||||
}
|
||||
try {
|
||||
if (obj.onClose != null) {
|
||||
obj.onClose.run();
|
||||
@ -100,8 +92,7 @@ public class DatabaseMapDictionaryDeep<T, U, US extends DatabaseStage<U>> extend
|
||||
protected final Mono<LLRange> rangeMono;
|
||||
|
||||
protected RangeSupplier rangeSupplier;
|
||||
protected Buffer keyPrefix;
|
||||
protected Buffer keySuffixAndExtZeroBuffer;
|
||||
protected BufSupplier keyPrefixSupplier;
|
||||
protected Runnable onClose;
|
||||
|
||||
private static void incrementPrefix(Buffer prefix, int prefixLength) {
|
||||
@ -199,73 +190,70 @@ public class DatabaseMapDictionaryDeep<T, U, US extends DatabaseStage<U>> extend
|
||||
}
|
||||
|
||||
public static <T, U, US extends DatabaseStage<U>> DatabaseMapDictionaryDeep<T, U, US> deepIntermediate(
|
||||
LLDictionary dictionary, Buffer prefixKey, SerializerFixedBinaryLength<T> keySuffixSerializer,
|
||||
LLDictionary dictionary, BufSupplier prefixKey, SerializerFixedBinaryLength<T> keySuffixSerializer,
|
||||
SubStageGetter<U, US> subStageGetter, int keyExtLength, Runnable onClose) {
|
||||
return new DatabaseMapDictionaryDeep<>(dictionary, prefixKey, keySuffixSerializer, subStageGetter,
|
||||
keyExtLength, onClose);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
protected DatabaseMapDictionaryDeep(LLDictionary dictionary, @Nullable Buffer prefixKey,
|
||||
protected DatabaseMapDictionaryDeep(LLDictionary dictionary, @Nullable BufSupplier prefixKeySupplier,
|
||||
SerializerFixedBinaryLength<T> keySuffixSerializer, SubStageGetter<U, US> subStageGetter, int keyExtLength,
|
||||
Runnable onClose) {
|
||||
super((Drop<DatabaseMapDictionaryDeep<T, U, US>>) (Drop) DROP);
|
||||
try {
|
||||
try (var prefixKey = prefixKeySupplier != null ? prefixKeySupplier.get() : null) {
|
||||
this.dictionary = dictionary;
|
||||
this.alloc = dictionary.getAllocator();
|
||||
this.subStageGetter = subStageGetter;
|
||||
this.keySuffixSerializer = keySuffixSerializer;
|
||||
assert prefixKey == null || prefixKey.isAccessible();
|
||||
this.keyPrefixLength = prefixKey == null ? 0 : prefixKey.readableBytes();
|
||||
this.keyPrefixLength = prefixKey != null ? prefixKey.readableBytes() : 0;
|
||||
this.keySuffixLength = keySuffixSerializer.getSerializedBinaryLength();
|
||||
this.keyExtLength = keyExtLength;
|
||||
this.keySuffixAndExtZeroBuffer = alloc
|
||||
try (var keySuffixAndExtZeroBuffer = alloc
|
||||
.allocate(keySuffixLength + keyExtLength)
|
||||
.fill((byte) 0)
|
||||
.writerOffset(keySuffixLength + keyExtLength)
|
||||
.makeReadOnly();
|
||||
assert keySuffixAndExtZeroBuffer.readableBytes() == keySuffixLength + keyExtLength :
|
||||
"Key suffix and ext zero buffer readable length is not equal"
|
||||
+ " to the key suffix length + key ext length. keySuffixAndExtZeroBuffer="
|
||||
+ keySuffixAndExtZeroBuffer.readableBytes() + " keySuffixLength=" + keySuffixLength + " keyExtLength="
|
||||
+ keyExtLength;
|
||||
assert keySuffixAndExtZeroBuffer.readableBytes() > 0;
|
||||
var firstKey = prefixKey == null ? alloc.allocate(keyPrefixLength + keySuffixLength + keyExtLength)
|
||||
: prefixKey.copy();
|
||||
try {
|
||||
firstRangeKey(firstKey, keyPrefixLength, keySuffixAndExtZeroBuffer);
|
||||
var nextRangeKey = prefixKey == null ? alloc.allocate(keyPrefixLength + keySuffixLength + keyExtLength)
|
||||
: prefixKey.copy();
|
||||
.makeReadOnly()) {
|
||||
assert keySuffixAndExtZeroBuffer.readableBytes() == keySuffixLength + keyExtLength :
|
||||
"Key suffix and ext zero buffer readable length is not equal"
|
||||
+ " to the key suffix length + key ext length. keySuffixAndExtZeroBuffer="
|
||||
+ keySuffixAndExtZeroBuffer.readableBytes() + " keySuffixLength=" + keySuffixLength + " keyExtLength="
|
||||
+ keyExtLength;
|
||||
assert keySuffixAndExtZeroBuffer.readableBytes() > 0;
|
||||
var firstKey = prefixKey != null ? prefixKeySupplier.get()
|
||||
: alloc.allocate(keyPrefixLength + keySuffixLength + keyExtLength);
|
||||
try {
|
||||
nextRangeKey(nextRangeKey, keyPrefixLength, keySuffixAndExtZeroBuffer);
|
||||
assert prefixKey == null || prefixKey.isAccessible();
|
||||
assert keyPrefixLength == 0 || !LLUtils.equals(firstKey, nextRangeKey);
|
||||
if (keyPrefixLength == 0) {
|
||||
this.rangeSupplier = RangeSupplier.ofOwned(LLRange.all());
|
||||
firstKey.close();
|
||||
firstRangeKey(firstKey, keyPrefixLength, keySuffixAndExtZeroBuffer);
|
||||
var nextRangeKey = prefixKey != null ? prefixKeySupplier.get()
|
||||
: alloc.allocate(keyPrefixLength + keySuffixLength + keyExtLength);
|
||||
try {
|
||||
nextRangeKey(nextRangeKey, keyPrefixLength, keySuffixAndExtZeroBuffer);
|
||||
assert prefixKey == null || prefixKey.isAccessible();
|
||||
assert keyPrefixLength == 0 || !LLUtils.equals(firstKey, nextRangeKey);
|
||||
if (keyPrefixLength == 0) {
|
||||
this.rangeSupplier = RangeSupplier.ofOwned(LLRange.all());
|
||||
firstKey.close();
|
||||
nextRangeKey.close();
|
||||
} else {
|
||||
this.rangeSupplier = RangeSupplier.ofOwned(LLRange.ofUnsafe(firstKey, nextRangeKey));
|
||||
}
|
||||
this.rangeMono = Mono.fromSupplier(rangeSupplier);
|
||||
assert subStageKeysConsistency(keyPrefixLength + keySuffixLength + keyExtLength);
|
||||
} catch (Throwable t) {
|
||||
nextRangeKey.close();
|
||||
} else {
|
||||
this.rangeSupplier = RangeSupplier.ofOwned(LLRange.ofUnsafe(firstKey, nextRangeKey));
|
||||
throw t;
|
||||
}
|
||||
this.rangeMono = Mono.fromSupplier(rangeSupplier);
|
||||
assert subStageKeysConsistency(keyPrefixLength + keySuffixLength + keyExtLength);
|
||||
} catch (Throwable t) {
|
||||
nextRangeKey.close();
|
||||
firstKey.close();
|
||||
throw t;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
firstKey.close();
|
||||
throw t;
|
||||
}
|
||||
|
||||
this.keyPrefix = prefixKey;
|
||||
this.onClose = onClose;
|
||||
} catch (Throwable t) {
|
||||
if (this.keySuffixAndExtZeroBuffer != null && keySuffixAndExtZeroBuffer.isAccessible()) {
|
||||
keySuffixAndExtZeroBuffer.close();
|
||||
this.keyPrefixSupplier = prefixKeySupplier;
|
||||
this.onClose = onClose;
|
||||
}
|
||||
if (prefixKey != null && prefixKey.isAccessible()) {
|
||||
prefixKey.close();
|
||||
} catch (Throwable t) {
|
||||
if (prefixKeySupplier != null) {
|
||||
prefixKeySupplier.close();
|
||||
}
|
||||
throw t;
|
||||
}
|
||||
@ -281,8 +269,7 @@ public class DatabaseMapDictionaryDeep<T, U, US extends DatabaseStage<U>> extend
|
||||
int keyExtLength,
|
||||
Mono<LLRange> rangeMono,
|
||||
RangeSupplier rangeSupplier,
|
||||
Buffer keyPrefix,
|
||||
Buffer keySuffixAndExtZeroBuffer,
|
||||
BufSupplier keyPrefixSupplier,
|
||||
Runnable onClose) {
|
||||
super((Drop<DatabaseMapDictionaryDeep<T,U,US>>) (Drop) DROP);
|
||||
this.dictionary = dictionary;
|
||||
@ -295,8 +282,7 @@ public class DatabaseMapDictionaryDeep<T, U, US extends DatabaseStage<U>> extend
|
||||
this.rangeMono = rangeMono;
|
||||
|
||||
this.rangeSupplier = rangeSupplier;
|
||||
this.keyPrefix = keyPrefix;
|
||||
this.keySuffixAndExtZeroBuffer = keySuffixAndExtZeroBuffer;
|
||||
this.keyPrefixSupplier = keyPrefixSupplier;
|
||||
this.onClose = onClose;
|
||||
}
|
||||
|
||||
@ -349,15 +335,18 @@ public class DatabaseMapDictionaryDeep<T, U, US extends DatabaseStage<U>> extend
|
||||
@Override
|
||||
public Mono<US> at(@Nullable CompositeSnapshot snapshot, T keySuffix) {
|
||||
var suffixKeyWithoutExt = Mono.fromCallable(() -> {
|
||||
try (var keyWithoutExtBuf = keyPrefix == null
|
||||
? alloc.allocate(keySuffixLength + keyExtLength) : keyPrefix.copy()) {
|
||||
var keyWithoutExtBuf = keyPrefixSupplier == null
|
||||
? alloc.allocate(keySuffixLength + keyExtLength) : keyPrefixSupplier.get();
|
||||
try {
|
||||
keyWithoutExtBuf.ensureWritable(keySuffixLength + keyExtLength);
|
||||
serializeSuffix(keySuffix, keyWithoutExtBuf);
|
||||
return keyWithoutExtBuf.send();
|
||||
} catch (Throwable ex) {
|
||||
keyWithoutExtBuf.close();
|
||||
throw ex;
|
||||
}
|
||||
return keyWithoutExtBuf;
|
||||
});
|
||||
return this.subStageGetter
|
||||
.subStage(dictionary, snapshot, suffixKeyWithoutExt);
|
||||
return this.subStageGetter.subStage(dictionary, snapshot, suffixKeyWithoutExt);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -374,21 +363,17 @@ public class DatabaseMapDictionaryDeep<T, U, US extends DatabaseStage<U>> extend
|
||||
public Flux<SubStageEntry<T, US>> getAllStages(@Nullable CompositeSnapshot snapshot, boolean smallRange) {
|
||||
return dictionary
|
||||
.getRangeKeyPrefixes(resolveSnapshot(snapshot), rangeMono, keyPrefixLength + keySuffixLength, smallRange)
|
||||
.flatMapSequential(groupKeyWithoutExtSend_ -> Mono.using(
|
||||
() -> groupKeyWithoutExtSend_,
|
||||
groupKeyWithoutExtSend -> this.subStageGetter
|
||||
.subStage(dictionary, snapshot, Mono.fromCallable(() -> groupKeyWithoutExtSend.copy().send()))
|
||||
.handle((us, sink) -> {
|
||||
T deserializedSuffix;
|
||||
try (var splittedGroupSuffix = splitGroupSuffix(groupKeyWithoutExtSend)) {
|
||||
deserializedSuffix = this.deserializeSuffix(splittedGroupSuffix);
|
||||
sink.next(new SubStageEntry<>(deserializedSuffix, us));
|
||||
} catch (SerializationException ex) {
|
||||
sink.error(ex);
|
||||
}
|
||||
}),
|
||||
Resource::close
|
||||
));
|
||||
.flatMapSequential(groupKeyWithoutExt -> this.subStageGetter
|
||||
.subStage(dictionary, snapshot, Mono.fromCallable(groupKeyWithoutExt::copy))
|
||||
.map(us -> {
|
||||
T deserializedSuffix;
|
||||
try (var splittedGroupSuffix = splitGroupSuffix(groupKeyWithoutExt)) {
|
||||
deserializedSuffix = this.deserializeSuffix(splittedGroupSuffix);
|
||||
return new SubStageEntry<>(deserializedSuffix, us);
|
||||
}
|
||||
})
|
||||
.doFinally(s -> groupKeyWithoutExt.close())
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -447,7 +432,6 @@ public class DatabaseMapDictionaryDeep<T, U, US extends DatabaseStage<U>> extend
|
||||
protected T deserializeSuffix(@NotNull Buffer keySuffix) throws SerializationException {
|
||||
assert suffixKeyLengthConsistency(keySuffix.readableBytes());
|
||||
var result = keySuffixSerializer.deserialize(keySuffix);
|
||||
assert keyPrefix == null || keyPrefix.isAccessible();
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -457,7 +441,6 @@ public class DatabaseMapDictionaryDeep<T, U, US extends DatabaseStage<U>> extend
|
||||
keySuffixSerializer.serialize(keySuffix, output);
|
||||
var afterWriterOffset = output.writerOffset();
|
||||
assert suffixKeyLengthConsistency(afterWriterOffset - beforeWriterOffset);
|
||||
assert keyPrefix == null || keyPrefix.isAccessible();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -467,8 +450,7 @@ public class DatabaseMapDictionaryDeep<T, U, US extends DatabaseStage<U>> extend
|
||||
|
||||
@Override
|
||||
protected Owned<DatabaseMapDictionaryDeep<T, U, US>> prepareSend() {
|
||||
var keyPrefix = this.keyPrefix.send();
|
||||
var keySuffixAndExtZeroBuffer = this.keySuffixAndExtZeroBuffer.send();
|
||||
var keyPrefixSupplier = this.keyPrefixSupplier;
|
||||
var rangeSupplier = this.rangeSupplier;
|
||||
var onClose = this.onClose;
|
||||
return drop -> {
|
||||
@ -481,8 +463,7 @@ public class DatabaseMapDictionaryDeep<T, U, US extends DatabaseStage<U>> extend
|
||||
keyExtLength,
|
||||
rangeMono,
|
||||
rangeSupplier,
|
||||
keyPrefix.receive(),
|
||||
keySuffixAndExtZeroBuffer.receive(),
|
||||
keyPrefixSupplier,
|
||||
onClose
|
||||
);
|
||||
drop.attach(instance);
|
||||
@ -492,8 +473,7 @@ public class DatabaseMapDictionaryDeep<T, U, US extends DatabaseStage<U>> extend
|
||||
|
||||
@Override
|
||||
protected void makeInaccessible() {
|
||||
this.keyPrefix = null;
|
||||
this.keySuffixAndExtZeroBuffer = null;
|
||||
this.keyPrefixSupplier = null;
|
||||
this.rangeSupplier = null;
|
||||
this.onClose = null;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import io.netty5.buffer.api.Owned;
|
||||
import io.netty5.buffer.api.Send;
|
||||
import it.cavallium.dbengine.client.BadBlock;
|
||||
import it.cavallium.dbengine.client.CompositeSnapshot;
|
||||
import it.cavallium.dbengine.database.BufSupplier;
|
||||
import it.cavallium.dbengine.database.LLDictionary;
|
||||
import it.cavallium.dbengine.database.LLUtils;
|
||||
import io.netty5.buffer.api.internal.ResourceSupport;
|
||||
@ -67,7 +68,7 @@ public class DatabaseMapDictionaryHashed<T, U, TH> extends
|
||||
|
||||
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||
protected DatabaseMapDictionaryHashed(LLDictionary dictionary,
|
||||
@Nullable Buffer prefixKey,
|
||||
@Nullable BufSupplier prefixKeySupplier,
|
||||
Serializer<T> keySuffixSerializer,
|
||||
Serializer<U> valueSerializer,
|
||||
Function<T, TH> keySuffixHashFunction,
|
||||
@ -82,7 +83,7 @@ public class DatabaseMapDictionaryHashed<T, U, TH> extends
|
||||
= new ValueWithHashSerializer<>(keySuffixSerializer, valueSerializer);
|
||||
ValuesSetSerializer<Entry<T, U>> valuesSetSerializer
|
||||
= new ValuesSetSerializer<>(valueWithHashSerializer);
|
||||
this.subDictionary = DatabaseMapDictionary.tail(dictionary, prefixKey, keySuffixHashSerializer,
|
||||
this.subDictionary = DatabaseMapDictionary.tail(dictionary, prefixKeySupplier, keySuffixHashSerializer,
|
||||
valuesSetSerializer, onClose);
|
||||
this.keySuffixHashFunction = keySuffixHashFunction;
|
||||
}
|
||||
@ -117,14 +118,14 @@ public class DatabaseMapDictionaryHashed<T, U, TH> extends
|
||||
}
|
||||
|
||||
public static <T, U, UH> DatabaseMapDictionaryHashed<T, U, UH> tail(LLDictionary dictionary,
|
||||
@Nullable Buffer prefixKey,
|
||||
@Nullable BufSupplier prefixKeySupplier,
|
||||
Serializer<T> keySuffixSerializer,
|
||||
Serializer<U> valueSerializer,
|
||||
Function<T, UH> keySuffixHashFunction,
|
||||
SerializerFixedBinaryLength<UH> keySuffixHashSerializer,
|
||||
Runnable onClose) {
|
||||
return new DatabaseMapDictionaryHashed<>(dictionary,
|
||||
prefixKey,
|
||||
prefixKeySupplier,
|
||||
keySuffixSerializer,
|
||||
valueSerializer,
|
||||
keySuffixHashFunction,
|
||||
|
@ -80,13 +80,9 @@ public class DatabaseMapSingle<U> extends ResourceSupport<DatabaseStage<U>, Data
|
||||
}
|
||||
}
|
||||
|
||||
private void deserializeValue(Buffer value, SynchronousSink<U> sink) {
|
||||
private U deserializeValue(Buffer value) {
|
||||
try {
|
||||
U deserializedValue;
|
||||
try (value) {
|
||||
deserializedValue = serializer.deserialize(value);
|
||||
}
|
||||
sink.next(deserializedValue);
|
||||
return serializer.deserialize(value);
|
||||
} catch (IndexOutOfBoundsException ex) {
|
||||
var exMessage = ex.getMessage();
|
||||
if (exMessage != null && exMessage.contains("read 0 to 0, write 0 to ")) {
|
||||
@ -94,12 +90,12 @@ public class DatabaseMapSingle<U> extends ResourceSupport<DatabaseStage<U>, Data
|
||||
LOG.error("Unexpected zero-bytes value at "
|
||||
+ dictionary.getDatabaseName() + ":" + dictionary.getColumnName() + ":" + LLUtils.toStringSafe(key));
|
||||
}
|
||||
sink.complete();
|
||||
return null;
|
||||
} else {
|
||||
sink.error(ex);
|
||||
throw ex;
|
||||
}
|
||||
} catch (SerializationException ex) {
|
||||
sink.error(ex);
|
||||
throw ex;
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,22 +114,24 @@ public class DatabaseMapSingle<U> extends ResourceSupport<DatabaseStage<U>, Data
|
||||
|
||||
@Override
|
||||
public Mono<U> get(@Nullable CompositeSnapshot snapshot, boolean existsAlmostCertainly) {
|
||||
return dictionary
|
||||
.get(resolveSnapshot(snapshot), keyMono)
|
||||
.handle(this::deserializeValue);
|
||||
return Mono.usingWhen(dictionary.get(resolveSnapshot(snapshot), keyMono),
|
||||
buf -> Mono.fromSupplier(() -> deserializeValue(buf)),
|
||||
buf -> Mono.fromRunnable(buf::close)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<U> setAndGetPrevious(U value) {
|
||||
return dictionary
|
||||
.put(keyMono, Mono.fromCallable(() -> serializeValue(value)), LLDictionaryResultType.PREVIOUS_VALUE)
|
||||
.handle(this::deserializeValue);
|
||||
return Mono.usingWhen(dictionary
|
||||
.put(keyMono, Mono.fromCallable(() -> serializeValue(value)), LLDictionaryResultType.PREVIOUS_VALUE),
|
||||
buf -> Mono.fromSupplier(() -> deserializeValue(buf)),
|
||||
buf -> Mono.fromRunnable(buf::close));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<U> update(SerializationFunction<@Nullable U, @Nullable U> updater,
|
||||
UpdateReturnMode updateReturnMode) {
|
||||
return dictionary
|
||||
var resultMono = dictionary
|
||||
.update(keyMono, (oldValueSer) -> {
|
||||
U result;
|
||||
if (oldValueSer == null) {
|
||||
@ -147,8 +145,11 @@ public class DatabaseMapSingle<U> extends ResourceSupport<DatabaseStage<U>, Data
|
||||
} else {
|
||||
return serializeValue(result);
|
||||
}
|
||||
}, updateReturnMode)
|
||||
.handle(this::deserializeValue);
|
||||
}, updateReturnMode);
|
||||
return Mono.usingWhen(resultMono,
|
||||
result -> Mono.fromSupplier(() -> deserializeValue(result)),
|
||||
result -> Mono.fromRunnable(result::close)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -172,9 +173,10 @@ public class DatabaseMapSingle<U> extends ResourceSupport<DatabaseStage<U>, Data
|
||||
|
||||
@Override
|
||||
public Mono<U> clearAndGetPrevious() {
|
||||
return dictionary
|
||||
.remove(keyMono, LLDictionaryResultType.PREVIOUS_VALUE)
|
||||
.handle(this::deserializeValue);
|
||||
return Mono.usingWhen(dictionary.remove(keyMono, LLDictionaryResultType.PREVIOUS_VALUE),
|
||||
result -> Mono.fromSupplier(() -> deserializeValue(result)),
|
||||
result -> Mono.fromRunnable(result::close)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -4,6 +4,7 @@ import io.netty5.buffer.api.Buffer;
|
||||
import io.netty5.buffer.api.Drop;
|
||||
import io.netty5.buffer.api.Send;
|
||||
import it.cavallium.dbengine.client.CompositeSnapshot;
|
||||
import it.cavallium.dbengine.database.BufSupplier;
|
||||
import it.cavallium.dbengine.database.LLDictionary;
|
||||
import it.cavallium.dbengine.database.LLUtils;
|
||||
import it.cavallium.dbengine.database.collections.DatabaseEmpty.Nothing;
|
||||
@ -19,10 +20,15 @@ import reactor.core.publisher.Mono;
|
||||
public class DatabaseSetDictionary<T> extends DatabaseMapDictionary<T, Nothing> {
|
||||
|
||||
protected DatabaseSetDictionary(LLDictionary dictionary,
|
||||
Buffer prefixKey,
|
||||
BufSupplier prefixKeySupplier,
|
||||
SerializerFixedBinaryLength<T> keySuffixSerializer,
|
||||
Runnable onClose) {
|
||||
super(dictionary, prefixKey, keySuffixSerializer, DatabaseEmpty.nothingSerializer(dictionary.getAllocator()), onClose);
|
||||
super(dictionary,
|
||||
prefixKeySupplier,
|
||||
keySuffixSerializer,
|
||||
DatabaseEmpty.nothingSerializer(dictionary.getAllocator()),
|
||||
onClose
|
||||
);
|
||||
}
|
||||
|
||||
public static <T> DatabaseSetDictionary<T> simple(LLDictionary dictionary,
|
||||
@ -32,10 +38,10 @@ public class DatabaseSetDictionary<T> extends DatabaseMapDictionary<T, Nothing>
|
||||
}
|
||||
|
||||
public static <T> DatabaseSetDictionary<T> tail(LLDictionary dictionary,
|
||||
Buffer prefixKey,
|
||||
BufSupplier prefixKeySupplier,
|
||||
SerializerFixedBinaryLength<T> keySuffixSerializer,
|
||||
Runnable onClose) {
|
||||
return new DatabaseSetDictionary<>(dictionary, prefixKey, keySuffixSerializer, onClose);
|
||||
return new DatabaseSetDictionary<>(dictionary, prefixKeySupplier, keySuffixSerializer, onClose);
|
||||
}
|
||||
|
||||
public Mono<Set<T>> getKeySet(@Nullable CompositeSnapshot snapshot) {
|
||||
|
@ -4,6 +4,7 @@ import io.netty5.buffer.api.Buffer;
|
||||
import io.netty5.buffer.api.Drop;
|
||||
import io.netty5.buffer.api.Send;
|
||||
import it.cavallium.dbengine.client.CompositeSnapshot;
|
||||
import it.cavallium.dbengine.database.BufSupplier;
|
||||
import it.cavallium.dbengine.database.LLDictionary;
|
||||
import it.cavallium.dbengine.database.LLUtils;
|
||||
import it.cavallium.dbengine.database.collections.DatabaseEmpty.Nothing;
|
||||
@ -22,13 +23,13 @@ import reactor.core.publisher.Mono;
|
||||
public class DatabaseSetDictionaryHashed<T, TH> extends DatabaseMapDictionaryHashed<T, Nothing, TH> {
|
||||
|
||||
protected DatabaseSetDictionaryHashed(LLDictionary dictionary,
|
||||
@Nullable Buffer prefixKey,
|
||||
@Nullable BufSupplier prefixKeySupplier,
|
||||
Serializer<T> keySuffixSerializer,
|
||||
Function<T, TH> keySuffixHashFunction,
|
||||
SerializerFixedBinaryLength<TH> keySuffixHashSerializer,
|
||||
Runnable onClose) {
|
||||
super(dictionary,
|
||||
prefixKey,
|
||||
prefixKeySupplier,
|
||||
keySuffixSerializer,
|
||||
DatabaseEmpty.nothingSerializer(dictionary.getAllocator()),
|
||||
keySuffixHashFunction,
|
||||
@ -52,13 +53,13 @@ public class DatabaseSetDictionaryHashed<T, TH> extends DatabaseMapDictionaryHas
|
||||
}
|
||||
|
||||
public static <T, TH> DatabaseSetDictionaryHashed<T, TH> tail(LLDictionary dictionary,
|
||||
@Nullable Buffer prefixKey,
|
||||
@Nullable BufSupplier prefixKeySupplier,
|
||||
Serializer<T> keySuffixSerializer,
|
||||
Function<T, TH> keyHashFunction,
|
||||
SerializerFixedBinaryLength<TH> keyHashSerializer,
|
||||
Runnable onClose) {
|
||||
return new DatabaseSetDictionaryHashed<>(dictionary,
|
||||
prefixKey,
|
||||
prefixKeySupplier,
|
||||
keySuffixSerializer,
|
||||
keyHashFunction,
|
||||
keyHashSerializer,
|
||||
|
@ -11,6 +11,6 @@ public interface SubStageGetter<U, US extends DatabaseStage<U>> {
|
||||
|
||||
Mono<US> subStage(LLDictionary dictionary,
|
||||
@Nullable CompositeSnapshot snapshot,
|
||||
Mono<Send<Buffer>> prefixKey);
|
||||
Mono<Buffer> prefixKey);
|
||||
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import io.netty5.buffer.api.Buffer;
|
||||
import io.netty5.buffer.api.Resource;
|
||||
import io.netty5.buffer.api.Send;
|
||||
import it.cavallium.dbengine.client.CompositeSnapshot;
|
||||
import it.cavallium.dbengine.database.BufSupplier;
|
||||
import it.cavallium.dbengine.database.LLDictionary;
|
||||
import it.cavallium.dbengine.database.LLUtils;
|
||||
import it.cavallium.dbengine.database.serialization.Serializer;
|
||||
@ -36,18 +37,15 @@ public class SubStageGetterHashMap<T, U, TH> implements
|
||||
@Override
|
||||
public Mono<DatabaseMapDictionaryHashed<T, U, TH>> subStage(LLDictionary dictionary,
|
||||
@Nullable CompositeSnapshot snapshot,
|
||||
Mono<Send<Buffer>> prefixKeyMono) {
|
||||
return prefixKeyMono.map(prefixKeyToReceive -> {
|
||||
var prefixKey = prefixKeyToReceive.receive();
|
||||
return DatabaseMapDictionaryHashed.tail(dictionary,
|
||||
prefixKey,
|
||||
keySerializer,
|
||||
valueSerializer,
|
||||
keyHashFunction,
|
||||
keyHashSerializer,
|
||||
null
|
||||
);
|
||||
});
|
||||
Mono<Buffer> prefixKeyMono) {
|
||||
return prefixKeyMono.map(prefixKey -> DatabaseMapDictionaryHashed.tail(dictionary,
|
||||
BufSupplier.ofOwned(prefixKey),
|
||||
keySerializer,
|
||||
valueSerializer,
|
||||
keyHashFunction,
|
||||
keyHashSerializer,
|
||||
null
|
||||
));
|
||||
}
|
||||
|
||||
public int getKeyHashBinaryLength() {
|
||||
|
@ -4,6 +4,7 @@ import io.netty5.buffer.api.Buffer;
|
||||
import io.netty5.buffer.api.Resource;
|
||||
import io.netty5.buffer.api.Send;
|
||||
import it.cavallium.dbengine.client.CompositeSnapshot;
|
||||
import it.cavallium.dbengine.database.BufSupplier;
|
||||
import it.cavallium.dbengine.database.LLDictionary;
|
||||
import it.cavallium.dbengine.database.LLUtils;
|
||||
import it.cavallium.dbengine.database.collections.DatabaseEmpty.Nothing;
|
||||
@ -34,17 +35,14 @@ public class SubStageGetterHashSet<T, TH> implements
|
||||
@Override
|
||||
public Mono<DatabaseSetDictionaryHashed<T, TH>> subStage(LLDictionary dictionary,
|
||||
@Nullable CompositeSnapshot snapshot,
|
||||
Mono<Send<Buffer>> prefixKeyMono) {
|
||||
return prefixKeyMono.map(prefixKeyToReceive -> {
|
||||
var prefixKey = prefixKeyToReceive.receive();
|
||||
return DatabaseSetDictionaryHashed.tail(dictionary,
|
||||
prefixKey,
|
||||
keySerializer,
|
||||
keyHashFunction,
|
||||
keyHashSerializer,
|
||||
null
|
||||
);
|
||||
});
|
||||
Mono<Buffer> prefixKeyMono) {
|
||||
return prefixKeyMono.map(prefixKey -> DatabaseSetDictionaryHashed.tail(dictionary,
|
||||
BufSupplier.ofOwned(prefixKey),
|
||||
keySerializer,
|
||||
keyHashFunction,
|
||||
keyHashSerializer,
|
||||
null
|
||||
));
|
||||
}
|
||||
|
||||
public int getKeyHashBinaryLength() {
|
||||
|
@ -1,15 +1,12 @@
|
||||
package it.cavallium.dbengine.database.collections;
|
||||
|
||||
import io.netty5.buffer.api.Buffer;
|
||||
import io.netty5.buffer.api.Resource;
|
||||
import io.netty5.buffer.api.Send;
|
||||
import it.cavallium.dbengine.client.CompositeSnapshot;
|
||||
import it.cavallium.dbengine.database.BufSupplier;
|
||||
import it.cavallium.dbengine.database.LLDictionary;
|
||||
import it.cavallium.dbengine.database.LLUtils;
|
||||
import it.cavallium.dbengine.database.serialization.Serializer;
|
||||
import it.cavallium.dbengine.database.serialization.SerializerFixedBinaryLength;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMap;
|
||||
import java.util.Map;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@ -28,11 +25,13 @@ public class SubStageGetterMap<T, U> implements
|
||||
@Override
|
||||
public Mono<DatabaseMapDictionary<T, U>> subStage(LLDictionary dictionary,
|
||||
@Nullable CompositeSnapshot snapshot,
|
||||
Mono<Send<Buffer>> prefixKeyMono) {
|
||||
return prefixKeyMono.map(prefixKeyToReceive -> {
|
||||
var prefixKey = prefixKeyToReceive.receive();
|
||||
return DatabaseMapDictionary.tail(dictionary, prefixKey, keySerializer, valueSerializer, null);
|
||||
});
|
||||
Mono<Buffer> prefixKeyMono) {
|
||||
return prefixKeyMono.map(prefixKey -> DatabaseMapDictionary.tail(dictionary,
|
||||
BufSupplier.ofOwned(prefixKey),
|
||||
keySerializer,
|
||||
valueSerializer,
|
||||
null
|
||||
));
|
||||
}
|
||||
|
||||
public int getKeyBinaryLength() {
|
||||
|
@ -4,6 +4,7 @@ import io.netty5.buffer.api.Buffer;
|
||||
import io.netty5.buffer.api.Resource;
|
||||
import io.netty5.buffer.api.Send;
|
||||
import it.cavallium.dbengine.client.CompositeSnapshot;
|
||||
import it.cavallium.dbengine.database.BufSupplier;
|
||||
import it.cavallium.dbengine.database.LLDictionary;
|
||||
import it.cavallium.dbengine.database.LLUtils;
|
||||
import it.cavallium.dbengine.database.serialization.SerializerFixedBinaryLength;
|
||||
@ -42,17 +43,14 @@ public class SubStageGetterMapDeep<T, U, US extends DatabaseStage<U>> implements
|
||||
@Override
|
||||
public Mono<DatabaseMapDictionaryDeep<T, U, US>> subStage(LLDictionary dictionary,
|
||||
@Nullable CompositeSnapshot snapshot,
|
||||
Mono<Send<Buffer>> prefixKeyMono) {
|
||||
return prefixKeyMono.map(prefixKeyToReceive -> {
|
||||
var prefixKey = prefixKeyToReceive.receive();
|
||||
return DatabaseMapDictionaryDeep.deepIntermediate(dictionary,
|
||||
prefixKey,
|
||||
keySerializer,
|
||||
subStageGetter,
|
||||
keyExtLength,
|
||||
null
|
||||
);
|
||||
});
|
||||
Mono<Buffer> prefixKeyMono) {
|
||||
return prefixKeyMono.map(prefixKey -> DatabaseMapDictionaryDeep.deepIntermediate(dictionary,
|
||||
BufSupplier.ofOwned(prefixKey),
|
||||
keySerializer,
|
||||
subStageGetter,
|
||||
keyExtLength,
|
||||
null
|
||||
));
|
||||
}
|
||||
|
||||
public int getKeyBinaryLength() {
|
||||
|
@ -4,6 +4,7 @@ import io.netty5.buffer.api.Buffer;
|
||||
import io.netty5.buffer.api.Resource;
|
||||
import io.netty5.buffer.api.Send;
|
||||
import it.cavallium.dbengine.client.CompositeSnapshot;
|
||||
import it.cavallium.dbengine.database.BufSupplier;
|
||||
import it.cavallium.dbengine.database.LLDictionary;
|
||||
import it.cavallium.dbengine.database.collections.DatabaseEmpty.Nothing;
|
||||
import it.cavallium.dbengine.database.serialization.SerializerFixedBinaryLength;
|
||||
@ -24,11 +25,12 @@ public class SubStageGetterSet<T> implements
|
||||
@Override
|
||||
public Mono<DatabaseSetDictionary<T>> subStage(LLDictionary dictionary,
|
||||
@Nullable CompositeSnapshot snapshot,
|
||||
Mono<Send<Buffer>> prefixKeyMono) {
|
||||
return prefixKeyMono.map(prefixKeyToReceive -> {
|
||||
var prefixKey = prefixKeyToReceive.receive();
|
||||
return DatabaseSetDictionary.tail(dictionary, prefixKey, keySerializer, null);
|
||||
});
|
||||
Mono<Buffer> prefixKeyMono) {
|
||||
return prefixKeyMono.map(prefixKey -> DatabaseSetDictionary.tail(dictionary,
|
||||
BufSupplier.ofOwned(prefixKey),
|
||||
keySerializer,
|
||||
null
|
||||
));
|
||||
}
|
||||
|
||||
public int getKeyBinaryLength() {
|
||||
|
@ -20,8 +20,12 @@ public class SubStageGetterSingle<T> implements SubStageGetter<T, DatabaseStageE
|
||||
@Override
|
||||
public Mono<DatabaseStageEntry<T>> subStage(LLDictionary dictionary,
|
||||
@Nullable CompositeSnapshot snapshot,
|
||||
Mono<Send<Buffer>> keyPrefixMono) {
|
||||
return keyPrefixMono.map(keyPrefix -> new DatabaseMapSingle<>(dictionary, BufSupplier.of(keyPrefix), serializer, null));
|
||||
Mono<Buffer> keyPrefixMono) {
|
||||
return keyPrefixMono.map(keyPrefix -> new DatabaseMapSingle<>(dictionary,
|
||||
BufSupplier.ofOwned(keyPrefix),
|
||||
serializer,
|
||||
null
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -60,6 +60,7 @@ import org.rocksdb.Slice;
|
||||
import org.rocksdb.Snapshot;
|
||||
import org.rocksdb.WriteBatch;
|
||||
import org.rocksdb.WriteOptions;
|
||||
import reactor.core.Exceptions;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
import reactor.core.scheduler.Scheduler;
|
||||
@ -772,13 +773,7 @@ public class LLLocalDictionary implements LLDictionary {
|
||||
}
|
||||
|
||||
private Flux<LLEntry> getRangeSingle(LLSnapshot snapshot, Mono<Buffer> keyMono) {
|
||||
return Mono
|
||||
.zip(keyMono, this.get(snapshot, keyMono))
|
||||
.map(result -> LLEntry.of(
|
||||
result.getT1().touch("get-range-single key"),
|
||||
result.getT2().touch("get-range-single value")
|
||||
))
|
||||
.flux();
|
||||
return Mono.zip(keyMono, this.get(snapshot, keyMono), LLEntry::of).flux();
|
||||
}
|
||||
|
||||
private Flux<LLEntry> getRangeMulti(LLSnapshot snapshot,
|
||||
|
Loading…
Reference in New Issue
Block a user