package it.cavallium.dbengine.database.collections; import io.netty5.buffer.api.Drop; import io.netty5.buffer.api.Owned; import io.netty5.util.Send; import io.netty5.buffer.api.internal.ResourceSupport; import it.cavallium.dbengine.client.BadBlock; import it.cavallium.dbengine.client.CompositeSnapshot; import it.cavallium.dbengine.client.Mapper; import it.cavallium.dbengine.database.Delta; import it.cavallium.dbengine.database.LLUtils; import it.cavallium.dbengine.database.UpdateReturnMode; import it.cavallium.dbengine.database.serialization.SerializationException; import it.cavallium.dbengine.database.serialization.SerializationFunction; import it.cavallium.dbengine.utils.SimpleResource; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.core.publisher.SynchronousSink; @SuppressWarnings("unused") public class DatabaseSingleMapped extends SimpleResource implements DatabaseStageEntry { private static final Logger logger = LogManager.getLogger(DatabaseSingleMapped.class); private final Mapper mapper; private final DatabaseStageEntry serializedSingle; @SuppressWarnings({"unchecked", "rawtypes"}) public DatabaseSingleMapped(DatabaseStageEntry serializedSingle, Mapper mapper, Drop> drop) { this.serializedSingle = serializedSingle; this.mapper = mapper; } @SuppressWarnings({"unchecked", "rawtypes"}) private DatabaseSingleMapped(DatabaseStage serializedSingle, Mapper mapper, Drop> drop) { this.mapper = mapper; this.serializedSingle = (DatabaseStageEntry) serializedSingle; } private void deserializeSink(B value, SynchronousSink sink) { try { sink.next(this.unMap(value)); } catch (SerializationException ex) { sink.error(ex); } } @Override public Mono get(@Nullable CompositeSnapshot snapshot) { return serializedSingle.get(snapshot).handle((value, sink) -> deserializeSink(value, sink)); } @Override public Mono getOrDefault(@Nullable CompositeSnapshot snapshot, Mono defaultValue) { return serializedSingle.get(snapshot).handle((B value, SynchronousSink sink) -> deserializeSink(value, sink)).switchIfEmpty(defaultValue); } @Override public Mono set(A value) { return Mono .fromCallable(() -> map(value)) .flatMap(value1 -> serializedSingle.set(value1)); } @Override public Mono setAndGetPrevious(A value) { return Mono .fromCallable(() -> map(value)) .flatMap(value2 -> serializedSingle.setAndGetPrevious(value2)) .handle((value1, sink) -> deserializeSink(value1, sink)); } @Override public Mono setAndGetChanged(A value) { return Mono .fromCallable(() -> map(value)) .flatMap(value1 -> serializedSingle.setAndGetChanged(value1)) .single(); } @Override public Mono update(SerializationFunction<@Nullable A, @Nullable A> updater, UpdateReturnMode updateReturnMode) { return serializedSingle.update(oldValue -> { var result = updater.apply(oldValue == null ? null : this.unMap(oldValue)); if (result == null) { return null; } else { return this.map(result); } }, updateReturnMode).handle((value, sink) -> deserializeSink(value, sink)); } @Override public Mono> updateAndGetDelta(SerializationFunction<@Nullable A, @Nullable A> updater) { return serializedSingle.updateAndGetDelta(oldValue -> { var result = updater.apply(oldValue == null ? null : this.unMap(oldValue)); if (result == null) { return null; } else { return this.map(result); } }).transform(mono -> LLUtils.mapDelta(mono, bytes -> unMap(bytes))); } @Override public Mono clear() { return serializedSingle.clear(); } @Override public Mono clearAndGetPrevious() { return serializedSingle.clearAndGetPrevious().handle((value, sink) -> deserializeSink(value, sink)); } @Override public Mono clearAndGetStatus() { return serializedSingle.clearAndGetStatus(); } @Override public Mono leavesCount(@Nullable CompositeSnapshot snapshot, boolean fast) { return serializedSingle.leavesCount(snapshot, fast); } @Override public Mono isEmpty(@Nullable CompositeSnapshot snapshot) { return serializedSingle.isEmpty(snapshot); } @Override public DatabaseStageEntry entry() { return this; } @Override public Flux badBlocks() { return this.serializedSingle.badBlocks(); } private A unMap(B bytes) throws SerializationException { return mapper.unmap(bytes); } private B map(A bytes) throws SerializationException { return mapper.map(bytes); } @Override protected void onClose() { serializedSingle.close(); } }