CavalliumDBEngine/src/main/java/it/cavallium/dbengine/database/disk/StandardRocksDBColumn.java

142 lines
4.4 KiB
Java
Raw Normal View History

2021-10-20 01:51:34 +02:00
package it.cavallium.dbengine.database.disk;
import static it.cavallium.dbengine.database.LLUtils.MARKER_ROCKSDB;
import io.micrometer.core.instrument.MeterRegistry;
2022-03-16 13:47:56 +01:00
import io.netty5.buffer.api.Buffer;
import io.netty5.buffer.api.BufferAllocator;
2021-10-20 01:51:34 +02:00
import it.cavallium.dbengine.database.LLDelta;
import it.cavallium.dbengine.database.LLUtils;
import java.io.IOException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.StampedLock;
2021-10-20 01:51:34 +02:00
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.rocksdb.ColumnFamilyHandle;
import org.rocksdb.ReadOptions;
import org.rocksdb.RocksDB;
import org.rocksdb.Transaction;
2022-05-12 19:14:27 +02:00
import org.rocksdb.TransactionOptions;
2021-10-20 01:51:34 +02:00
import org.rocksdb.WriteOptions;
public final class StandardRocksDBColumn extends AbstractRocksDBColumn<RocksDB> {
public StandardRocksDBColumn(RocksDB db,
boolean nettyDirect,
2021-10-20 01:51:34 +02:00
BufferAllocator alloc,
String dbName,
ColumnFamilyHandle cfh,
2022-05-12 19:14:27 +02:00
MeterRegistry meterRegistry,
StampedLock closeLock) {
super(db, nettyDirect, alloc, dbName, cfh, meterRegistry, closeLock);
2021-10-20 01:51:34 +02:00
}
@Override
protected boolean commitOptimistically(Transaction tx) {
2021-10-20 01:51:34 +02:00
throw new UnsupportedOperationException("Transactions not supported");
}
@Override
protected Transaction beginTransaction(@NotNull WriteOptions writeOptions,
TransactionOptions txOpts) {
2021-10-20 01:51:34 +02:00
throw new UnsupportedOperationException("Transactions not supported");
}
@Override
public @NotNull UpdateAtomicResult updateAtomicImpl(@NotNull ReadOptions readOptions,
@NotNull WriteOptions writeOptions,
Buffer key,
BinarySerializationFunction updater,
UpdateAtomicResultMode returnMode) throws IOException {
long initNanoTime = System.nanoTime();
try {
@Nullable Buffer prevData = this.get(readOptions, key);
try (prevData) {
if (logger.isTraceEnabled()) {
logger.trace(MARKER_ROCKSDB,
"Reading {}: {} (before update)",
LLUtils.toStringSafe(key),
LLUtils.toStringSafe(prevData)
);
}
Buffer prevDataToSendToUpdater;
if (prevData != null) {
prevDataToSendToUpdater = prevData.copy().makeReadOnly();
} else {
prevDataToSendToUpdater = null;
}
2022-05-20 18:31:05 +02:00
@Nullable Buffer newData;
try {
newData = updater.apply(prevDataToSendToUpdater);
} finally {
if (prevDataToSendToUpdater != null && prevDataToSendToUpdater.isAccessible()) {
prevDataToSendToUpdater.close();
}
}
try (newData) {
boolean changed;
assert newData == null || newData.isAccessible();
2022-03-02 18:33:58 +01:00
if (logger.isTraceEnabled()) {
logger.trace(MARKER_ROCKSDB,
"Updating {}. previous data: {}, updated data: {}",
2022-03-02 18:33:58 +01:00
LLUtils.toStringSafe(key),
LLUtils.toStringSafe(prevData),
LLUtils.toStringSafe(newData)
2022-03-02 18:33:58 +01:00
);
2021-10-20 01:51:34 +02:00
}
if (prevData != null && newData == null) {
if (logger.isTraceEnabled()) {
logger.trace(MARKER_ROCKSDB, "Deleting {} (after update)", LLUtils.toStringSafe(key));
2021-10-20 01:51:34 +02:00
}
this.delete(writeOptions, key);
changed = true;
} else if (newData != null && (prevData == null || !LLUtils.equals(prevData, newData))) {
2021-10-20 01:51:34 +02:00
if (logger.isTraceEnabled()) {
2021-12-29 00:31:35 +01:00
logger.trace(MARKER_ROCKSDB,
"Writing {}: {} (after update)",
2022-03-02 18:33:58 +01:00
LLUtils.toStringSafe(key),
LLUtils.toStringSafe(newData)
);
2021-10-20 01:51:34 +02:00
}
Buffer dataToPut;
if (returnMode == UpdateAtomicResultMode.CURRENT) {
dataToPut = newData.copy();
} else {
dataToPut = newData;
}
try {
this.put(writeOptions, key, dataToPut);
2021-10-20 01:51:34 +02:00
changed = true;
} finally {
if (dataToPut != newData) {
dataToPut.close();
2021-10-20 01:51:34 +02:00
}
}
} else {
changed = false;
}
recordAtomicUpdateTime(changed, prevData != null, newData != null, initNanoTime);
return switch (returnMode) {
2022-05-20 18:31:05 +02:00
case NOTHING -> RESULT_NOTHING;
case CURRENT -> new UpdateAtomicResultCurrent(newData != null ? newData.copy() : null);
case PREVIOUS -> new UpdateAtomicResultPrevious(prevData != null ? prevData.copy() : null);
case BINARY_CHANGED -> new UpdateAtomicResultBinaryChanged(changed);
2022-05-20 18:31:05 +02:00
case DELTA -> new UpdateAtomicResultDelta(LLDelta.of(
prevData != null ? prevData.copy() : null,
newData != null ? newData.copy() : null));
};
2021-10-20 01:51:34 +02:00
}
}
} catch (Throwable ex) {
throw new IOException("Failed to update key " + LLUtils.toStringSafe(key), ex);
2021-10-20 01:51:34 +02:00
}
}
@Override
public boolean supportsTransactions() {
return false;
}
}