Major bugfix
This commit is contained in:
parent
93fc28101a
commit
df946146a1
|
@ -2,4 +2,4 @@ package it.cavallium.dbengine.client;
|
||||||
|
|
||||||
public record MemoryStats(long estimateTableReadersMem, long sizeAllMemTables,
|
public record MemoryStats(long estimateTableReadersMem, long sizeAllMemTables,
|
||||||
long curSizeAllMemTables, long estimateNumKeys, long blockCacheUsage,
|
long curSizeAllMemTables, long estimateNumKeys, long blockCacheUsage,
|
||||||
long blockCachePinnedUsage) {}
|
long blockCachePinnedUsage, long liveVersions) {}
|
||||||
|
|
|
@ -6,13 +6,14 @@ import io.micrometer.core.instrument.MeterRegistry;
|
||||||
import it.cavallium.dbengine.client.IBackuppable;
|
import it.cavallium.dbengine.client.IBackuppable;
|
||||||
import it.cavallium.dbengine.database.collections.DatabaseInt;
|
import it.cavallium.dbengine.database.collections.DatabaseInt;
|
||||||
import it.cavallium.dbengine.database.collections.DatabaseLong;
|
import it.cavallium.dbengine.database.collections.DatabaseLong;
|
||||||
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.rocksdb.RocksDBException;
|
import org.rocksdb.RocksDBException;
|
||||||
|
|
||||||
public interface LLKeyValueDatabase extends LLSnapshottable, LLKeyValueDatabaseStructure, DatabaseProperties,
|
public interface LLKeyValueDatabase extends LLSnapshottable, LLKeyValueDatabaseStructure, DatabaseProperties,
|
||||||
IBackuppable, DatabaseOperations {
|
IBackuppable, DatabaseOperations, Closeable {
|
||||||
|
|
||||||
LLSingleton getSingleton(byte[] singletonListColumnName, byte[] name, byte @Nullable [] defaultValue);
|
LLSingleton getSingleton(byte[] singletonListColumnName, byte[] name, byte @Nullable [] defaultValue);
|
||||||
|
|
||||||
|
|
|
@ -678,6 +678,10 @@ public class LLUtils {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Buf wrapNullable(byte[] array) {
|
||||||
|
return array != null ? Buf.wrap(array) : null;
|
||||||
|
}
|
||||||
|
|
||||||
private static class FakeBytesRefBuilder extends BytesRefBuilder {
|
private static class FakeBytesRefBuilder extends BytesRefBuilder {
|
||||||
|
|
||||||
private final LLTerm term;
|
private final LLTerm term;
|
||||||
|
|
|
@ -235,9 +235,7 @@ public sealed abstract class AbstractRocksDBColumn<T extends RocksDB> implements
|
||||||
* This method should not modify or move the writerIndex/readerIndex of the key
|
* This method should not modify or move the writerIndex/readerIndex of the key
|
||||||
*/
|
*/
|
||||||
static void setIterateBound(LLReadOptions readOpts, IterateBound boundType, Buf key) {
|
static void setIterateBound(LLReadOptions readOpts, IterateBound boundType, Buf key) {
|
||||||
requireNonNull(key);
|
byte[] slice = key != null ? requireNonNull(LLUtils.asArray(key)) : null;
|
||||||
LLSlice slice;
|
|
||||||
slice = LLSlice.of(requireNonNull(LLUtils.asArray(key)));
|
|
||||||
if (boundType == IterateBound.LOWER) {
|
if (boundType == IterateBound.LOWER) {
|
||||||
readOpts.setIterateLowerBound(slice);
|
readOpts.setIterateLowerBound(slice);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import static it.cavallium.dbengine.database.LLUtils.MARKER_ROCKSDB;
|
||||||
import static it.cavallium.dbengine.database.LLUtils.isBoundedRange;
|
import static it.cavallium.dbengine.database.LLUtils.isBoundedRange;
|
||||||
import static it.cavallium.dbengine.database.LLUtils.mapList;
|
import static it.cavallium.dbengine.database.LLUtils.mapList;
|
||||||
import static it.cavallium.dbengine.database.LLUtils.toStringSafe;
|
import static it.cavallium.dbengine.database.LLUtils.toStringSafe;
|
||||||
|
import static it.cavallium.dbengine.database.LLUtils.wrapNullable;
|
||||||
import static it.cavallium.dbengine.database.disk.UpdateAtomicResultMode.DELTA;
|
import static it.cavallium.dbengine.database.disk.UpdateAtomicResultMode.DELTA;
|
||||||
import static it.cavallium.dbengine.utils.StreamUtils.ROCKSDB_POOL;
|
import static it.cavallium.dbengine.utils.StreamUtils.ROCKSDB_POOL;
|
||||||
import static it.cavallium.dbengine.utils.StreamUtils.collectOn;
|
import static it.cavallium.dbengine.utils.StreamUtils.collectOn;
|
||||||
|
@ -1092,26 +1093,11 @@ public class LLLocalDictionary implements LLDictionary {
|
||||||
)).map(range -> {
|
)).map(range -> {
|
||||||
long partialCount = 0;
|
long partialCount = 0;
|
||||||
try (var rangeReadOpts = readOpts.copy()) {
|
try (var rangeReadOpts = readOpts.copy()) {
|
||||||
LLSlice sliceBegin;
|
|
||||||
if (range.getKey() != null) {
|
|
||||||
sliceBegin = LLSlice.of(range.getKey());
|
|
||||||
} else {
|
|
||||||
sliceBegin = null;
|
|
||||||
}
|
|
||||||
LLSlice sliceEnd;
|
|
||||||
if (range.getValue() != null) {
|
|
||||||
sliceEnd = LLSlice.of(range.getValue());
|
|
||||||
} else {
|
|
||||||
sliceEnd = null;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
if (sliceBegin != null) {
|
try (var rocksIterator = db.newIterator(rangeReadOpts,
|
||||||
rangeReadOpts.setIterateLowerBound(sliceBegin);
|
wrapNullable(range.getKey()),
|
||||||
}
|
wrapNullable(range.getValue())
|
||||||
if (sliceEnd != null) {
|
)) {
|
||||||
rangeReadOpts.setIterateUpperBound(sliceEnd);
|
|
||||||
}
|
|
||||||
try (var rocksIterator = db.newIterator(rangeReadOpts, null, null)) {
|
|
||||||
rocksIterator.seekToFirst();
|
rocksIterator.seekToFirst();
|
||||||
while (rocksIterator.isValid()) {
|
while (rocksIterator.isValid()) {
|
||||||
partialCount++;
|
partialCount++;
|
||||||
|
@ -1121,13 +1107,6 @@ public class LLLocalDictionary implements LLDictionary {
|
||||||
}
|
}
|
||||||
} catch (RocksDBException ex) {
|
} catch (RocksDBException ex) {
|
||||||
throw new CompletionException(new IOException("Failed to get size", ex));
|
throw new CompletionException(new IOException("Failed to get size", ex));
|
||||||
} finally {
|
|
||||||
if (sliceBegin != null) {
|
|
||||||
sliceBegin.close();
|
|
||||||
}
|
|
||||||
if (sliceEnd != null) {
|
|
||||||
sliceEnd.close();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}), fastSummingLong());
|
}), fastSummingLong());
|
||||||
|
|
|
@ -56,6 +56,7 @@ import java.util.stream.Stream;
|
||||||
import org.apache.commons.lang3.time.StopWatch;
|
import org.apache.commons.lang3.time.StopWatch;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.rocksdb.AbstractImmutableNativeReference;
|
import org.rocksdb.AbstractImmutableNativeReference;
|
||||||
import org.rocksdb.BlockBasedTableConfig;
|
import org.rocksdb.BlockBasedTableConfig;
|
||||||
|
@ -135,7 +136,7 @@ public class LLLocalKeyValueDatabase extends Backuppable implements LLKeyValueDa
|
||||||
private volatile boolean closed = false;
|
private volatile boolean closed = false;
|
||||||
|
|
||||||
@SuppressWarnings("SwitchStatementWithTooFewBranches")
|
@SuppressWarnings("SwitchStatementWithTooFewBranches")
|
||||||
public LLLocalKeyValueDatabase(MeterRegistry meterRegistry,
|
public LLLocalKeyValueDatabase(@NotNull MeterRegistry meterRegistry,
|
||||||
String name,
|
String name,
|
||||||
boolean inMemory,
|
boolean inMemory,
|
||||||
@Nullable Path path,
|
@Nullable Path path,
|
||||||
|
@ -1263,7 +1264,8 @@ public class LLLocalKeyValueDatabase extends Backuppable implements LLKeyValueDa
|
||||||
db.getAggregatedLongProperty("rocksdb.cur-size-all-mem-tables"),
|
db.getAggregatedLongProperty("rocksdb.cur-size-all-mem-tables"),
|
||||||
db.getAggregatedLongProperty("rocksdb.estimate-num-keys"),
|
db.getAggregatedLongProperty("rocksdb.estimate-num-keys"),
|
||||||
db.getAggregatedLongProperty("rocksdb.block-cache-usage") / this.handles.size(),
|
db.getAggregatedLongProperty("rocksdb.block-cache-usage") / this.handles.size(),
|
||||||
db.getAggregatedLongProperty("rocksdb.block-cache-pinned-usage") / this.handles.size()
|
db.getAggregatedLongProperty("rocksdb.block-cache-pinned-usage") / this.handles.size(),
|
||||||
|
db.getAggregatedLongProperty("rocksdb.num-live-versions") / this.handles.size()
|
||||||
);
|
);
|
||||||
} catch (RocksDBException e) {
|
} catch (RocksDBException e) {
|
||||||
throw new DBException("Failed to read memory stats", e);
|
throw new DBException("Failed to read memory stats", e);
|
||||||
|
|
|
@ -11,9 +11,34 @@ public final class LLReadOptions extends SimpleResource {
|
||||||
|
|
||||||
private final ReadOptions val;
|
private final ReadOptions val;
|
||||||
private LLSlice itLowerBoundRef;
|
private LLSlice itLowerBoundRef;
|
||||||
|
private boolean itLowerBoundRefOwned;
|
||||||
private LLSlice itUpperBoundRef;
|
private LLSlice itUpperBoundRef;
|
||||||
|
private boolean itUpperBoundRefOwned;
|
||||||
private Snapshot snapshot;
|
private Snapshot snapshot;
|
||||||
|
|
||||||
|
public LLReadOptions copy() {
|
||||||
|
|
||||||
|
if (this.val.timestamp() != null) {
|
||||||
|
throw new IllegalStateException("Unsupported copy of timestamped read options");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.val.iterStartTs() != null) {
|
||||||
|
throw new IllegalStateException("Unsupported copy of read options with non-null iterStartTs property");
|
||||||
|
}
|
||||||
|
|
||||||
|
ReadOptions newVal = new ReadOptions(this.val);
|
||||||
|
|
||||||
|
var ro = new LLReadOptions(newVal);
|
||||||
|
if (this.val.iterateLowerBound() != null) {
|
||||||
|
ro.setIterateLowerBound(this.val.iterateLowerBound().data());
|
||||||
|
}
|
||||||
|
if (this.val.iterateUpperBound() != null) {
|
||||||
|
ro.setIterateUpperBound(this.val.iterateUpperBound().data());
|
||||||
|
}
|
||||||
|
ro.snapshot = this.snapshot;
|
||||||
|
return ro;
|
||||||
|
}
|
||||||
|
|
||||||
public LLReadOptions(ReadOptions val) {
|
public LLReadOptions(ReadOptions val) {
|
||||||
super(val::close);
|
super(val::close);
|
||||||
this.val = val;
|
this.val = val;
|
||||||
|
@ -23,30 +48,59 @@ public final class LLReadOptions extends SimpleResource {
|
||||||
this(new ReadOptions());
|
this(new ReadOptions());
|
||||||
}
|
}
|
||||||
|
|
||||||
public LLReadOptions copy() {
|
|
||||||
var ro = new LLReadOptions(new ReadOptions(this.val));
|
|
||||||
ro.itUpperBoundRef = this.itUpperBoundRef;
|
|
||||||
ro.itLowerBoundRef = this.itLowerBoundRef;
|
|
||||||
ro.snapshot = this.snapshot;
|
|
||||||
return ro;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onClose() {
|
protected void onClose() {
|
||||||
val.close();
|
val.close();
|
||||||
itLowerBoundRef = null;
|
|
||||||
itUpperBoundRef = null;
|
if (this.itUpperBoundRefOwned && this.itUpperBoundRef != null) {
|
||||||
|
this.itUpperBoundRef.close();
|
||||||
|
}
|
||||||
|
this.itUpperBoundRef = null;
|
||||||
|
|
||||||
|
if (this.itLowerBoundRefOwned && this.itLowerBoundRef != null) {
|
||||||
|
this.itLowerBoundRef.close();
|
||||||
|
}
|
||||||
|
this.itLowerBoundRef = null;
|
||||||
|
|
||||||
snapshot = null;
|
snapshot = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIterateLowerBound(LLSlice slice) {
|
|
||||||
val.setIterateLowerBound(slice.getSliceUnsafe());
|
public void setIterateLowerBound(byte[] slice) {
|
||||||
itLowerBoundRef = slice;
|
setIterateLowerBound(slice != null ? LLSlice.copyOf(slice) : null, true);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @param move if true, the read options will close the slice when they are closed
|
||||||
|
*/
|
||||||
|
public void setIterateLowerBound(LLSlice slice, boolean move) {
|
||||||
|
val.setIterateLowerBound(slice != null ? slice.getSliceUnsafe() : null);
|
||||||
|
|
||||||
|
// Close the previous owned value, if present
|
||||||
|
if (this.itLowerBoundRefOwned && this.itLowerBoundRef != null) {
|
||||||
|
this.itLowerBoundRef.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.itLowerBoundRef = slice;
|
||||||
|
this.itLowerBoundRefOwned = move;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIterateUpperBound(LLSlice slice) {
|
public void setIterateUpperBound(byte[] slice) {
|
||||||
val.setIterateUpperBound(slice.getSliceUnsafe());
|
setIterateUpperBound(slice != null ? LLSlice.copyOf(slice) : null, true);
|
||||||
itUpperBoundRef = slice;
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param move if true, the read options will close the slice when they are closed
|
||||||
|
*/
|
||||||
|
public void setIterateUpperBound(LLSlice slice, boolean move) {
|
||||||
|
val.setIterateUpperBound(slice != null ? slice.getSliceUnsafe() : null);
|
||||||
|
|
||||||
|
// Close the previous owned value, if present
|
||||||
|
if (this.itUpperBoundRefOwned && this.itUpperBoundRef != null) {
|
||||||
|
this.itUpperBoundRef.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.itUpperBoundRef = slice;
|
||||||
|
this.itUpperBoundRefOwned = move;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long readaheadSize() {
|
public long readaheadSize() {
|
||||||
|
|
|
@ -13,7 +13,7 @@ public final class LLSlice extends SimpleResource {
|
||||||
this.val = val;
|
this.val = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static LLSlice of(byte[] data) {
|
public static LLSlice copyOf(byte[] data) {
|
||||||
return new LLSlice(new Slice(data));
|
return new LLSlice(new Slice(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ public class LLMemoryKeyValueDatabase implements LLKeyValueDatabase {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MemoryStats getMemoryStats() {
|
public MemoryStats getMemoryStats() {
|
||||||
return new MemoryStats(0, 0, 0, 0, 0, 0);
|
return new MemoryStats(0, 0, 0, 0, 0, 0, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue
Block a user