package it.cavallium.dbengine.database.collections; import io.netty.buffer.ByteBuf; import it.cavallium.dbengine.client.CompositeSnapshot; import it.cavallium.dbengine.database.LLDictionary; import it.cavallium.dbengine.database.collections.DatabaseEmpty.Nothing; import it.cavallium.dbengine.database.serialization.Serializer; import it.cavallium.dbengine.database.serialization.SerializerFixedBinaryLength; import java.util.Map; import java.util.function.Function; import org.jetbrains.annotations.Nullable; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @SuppressWarnings({"unused", "ClassCanBeRecord"}) public class SubStageGetterHashSet implements SubStageGetter, DatabaseSetDictionaryHashed> { private static final boolean assertsEnabled; static { boolean assertsEnabledTmp = false; //noinspection AssertWithSideEffects assert assertsEnabledTmp = true; //noinspection ConstantConditions assertsEnabled = assertsEnabledTmp; } private final Serializer keySerializer; private final Function keyHashFunction; private final SerializerFixedBinaryLength keyHashSerializer; private final boolean enableAssertionsWhenUsingAssertions; public SubStageGetterHashSet(Serializer keySerializer, Function keyHashFunction, SerializerFixedBinaryLength keyHashSerializer, boolean enableAssertionsWhenUsingAssertions) { this.keySerializer = keySerializer; this.keyHashFunction = keyHashFunction; this.keyHashSerializer = keyHashSerializer; this.enableAssertionsWhenUsingAssertions = enableAssertionsWhenUsingAssertions; } @Override public Mono> subStage(LLDictionary dictionary, @Nullable CompositeSnapshot snapshot, Mono prefixKeyMono, @Nullable Flux debuggingKeysFlux) { return Mono.usingWhen(prefixKeyMono, prefixKey -> Mono .fromSupplier(() -> DatabaseSetDictionaryHashed .tail(dictionary, prefixKey.retain(), keySerializer, keyHashFunction, keyHashSerializer ) ) .transform(mono -> { if (debuggingKeysFlux != null) { return debuggingKeysFlux.handle((key, sink) -> { try { if (key.readableBytes() != prefixKey.readableBytes() + getKeyHashBinaryLength()) { sink.error(new IndexOutOfBoundsException()); } else { sink.complete(); } } finally { key.release(); } }).then(mono); } else { return mono; } }), prefixKey -> Mono.fromRunnable(prefixKey::release) ); } @Override public boolean isMultiKey() { return true; } @Override public boolean needsDebuggingKeyFlux() { return assertsEnabled && enableAssertionsWhenUsingAssertions; } public int getKeyHashBinaryLength() { return keyHashSerializer.getSerializedBinaryLength(); } }