package it.cavallium.dbengine.database.collections; import io.netty.buffer.ByteBuf; import io.netty.util.ReferenceCounted; import it.cavallium.dbengine.client.CompositeSnapshot; import it.cavallium.dbengine.database.LLDictionary; import it.cavallium.dbengine.database.serialization.Serializer; import it.cavallium.dbengine.database.serialization.SerializerFixedBinaryLength; import java.util.List; import java.util.Map; import org.jetbrains.annotations.Nullable; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; public class SubStageGetterMap implements SubStageGetter, DatabaseMapDictionary> { private static final boolean assertsEnabled; static { boolean assertsEnabledTmp = false; //noinspection AssertWithSideEffects assert assertsEnabledTmp = true; //noinspection ConstantConditions assertsEnabled = assertsEnabledTmp; } private final SerializerFixedBinaryLength keySerializer; private final Serializer valueSerializer; public SubStageGetterMap(SerializerFixedBinaryLength keySerializer, Serializer valueSerializer) { this.keySerializer = keySerializer; this.valueSerializer = valueSerializer; } @Override public Mono> subStage(LLDictionary dictionary, @Nullable CompositeSnapshot snapshot, ByteBuf prefixKey, List debuggingKeys) { try { return Mono .defer(() -> { if (assertsEnabled) { return checkKeyFluxConsistency(prefixKey.retain(), debuggingKeys); } else { return Mono .fromCallable(() -> { for (ByteBuf key : debuggingKeys) { key.release(); } return null; }); } }) .then(Mono .fromSupplier(() -> DatabaseMapDictionary .tail(dictionary, prefixKey.retain(), keySerializer, valueSerializer ) ) ) .doFirst(prefixKey::retain) .doAfterTerminate(prefixKey::release); } finally { prefixKey.release(); } } @Override public boolean isMultiKey() { return true; } @Override public boolean needsDebuggingKeyFlux() { return assertsEnabled; } private Mono checkKeyFluxConsistency(ByteBuf prefixKey, List keys) { return Mono .fromCallable(() -> { try { for (ByteBuf key : keys) { assert key.readableBytes() == prefixKey.readableBytes() + getKeyBinaryLength(); } } finally { prefixKey.release(); for (ByteBuf key : keys) { key.release(); } } return null; }); } public int getKeyBinaryLength() { return keySerializer.getSerializedBinaryLength(); } }