2022-04-06 02:41:32 +02:00
|
|
|
package it.cavallium.dbengine.lucene;
|
|
|
|
|
|
|
|
import io.netty5.buffer.api.Buffer;
|
|
|
|
import it.cavallium.dbengine.database.LLUtils;
|
|
|
|
import it.cavallium.dbengine.database.SafeCloseable;
|
|
|
|
import it.cavallium.dbengine.database.disk.LLTempHugePqEnv;
|
|
|
|
import it.cavallium.dbengine.database.disk.HugePqEnv;
|
|
|
|
import it.cavallium.dbengine.database.disk.StandardRocksDBColumn;
|
|
|
|
import java.util.concurrent.atomic.AtomicBoolean;
|
|
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
import org.rocksdb.ReadOptions;
|
2022-04-06 14:25:53 +02:00
|
|
|
import org.rocksdb.RocksDB;
|
2022-04-06 02:41:32 +02:00
|
|
|
import org.rocksdb.RocksDBException;
|
|
|
|
import org.rocksdb.WriteOptions;
|
|
|
|
|
|
|
|
public class HugePqArray<V> implements IArray<V>, SafeCloseable {
|
|
|
|
|
2022-04-06 14:25:53 +02:00
|
|
|
static {
|
|
|
|
RocksDB.loadLibrary();
|
|
|
|
}
|
2022-04-06 02:41:32 +02:00
|
|
|
|
|
|
|
private final AtomicBoolean closed = new AtomicBoolean();
|
|
|
|
private final HugePqCodec<V> valueCodec;
|
|
|
|
private final LLTempHugePqEnv tempEnv;
|
|
|
|
private final HugePqEnv env;
|
|
|
|
private final int hugePqId;
|
|
|
|
private final StandardRocksDBColumn rocksDB;
|
|
|
|
private final V defaultValue;
|
|
|
|
|
|
|
|
private final long virtualSize;
|
|
|
|
|
|
|
|
public HugePqArray(LLTempHugePqEnv env, HugePqCodec<V> codec, long size, @Nullable V defaultValue) {
|
|
|
|
this.valueCodec = codec;
|
|
|
|
this.tempEnv = env;
|
|
|
|
this.env = env.getEnv();
|
|
|
|
this.hugePqId = env.allocateDb(null);
|
|
|
|
this.rocksDB = this.env.openDb(hugePqId);
|
|
|
|
this.defaultValue = defaultValue;
|
|
|
|
|
|
|
|
this.virtualSize = size;
|
|
|
|
}
|
|
|
|
|
2022-05-20 10:20:00 +02:00
|
|
|
private static ReadOptions newReadOptions() {
|
|
|
|
return new ReadOptions().setVerifyChecksums(false);
|
2022-05-12 19:14:27 +02:00
|
|
|
}
|
|
|
|
|
2022-05-20 10:20:00 +02:00
|
|
|
private static WriteOptions newWriteOptions() {
|
|
|
|
return new WriteOptions().setDisableWAL(true).setSync(false);
|
2022-05-12 19:14:27 +02:00
|
|
|
}
|
|
|
|
|
2022-04-06 02:41:32 +02:00
|
|
|
public HugePqCodec<V> getValueCodec() {
|
|
|
|
return valueCodec;
|
|
|
|
}
|
|
|
|
|
|
|
|
private Buffer allocate(int size) {
|
|
|
|
return rocksDB.getAllocator().allocate(size);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static void ensureThread() {
|
|
|
|
LLUtils.ensureBlocking();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void set(long index, @Nullable V value) {
|
|
|
|
ensureBounds(index);
|
|
|
|
ensureThread();
|
|
|
|
var keyBuf = allocate(Long.BYTES);
|
2022-05-12 19:14:27 +02:00
|
|
|
try (var writeOptions = newWriteOptions();
|
|
|
|
var valueBuf = valueCodec.serialize(this::allocate, value); keyBuf) {
|
2022-04-06 14:25:53 +02:00
|
|
|
keyBuf.writeLong(index);
|
2022-05-12 19:14:27 +02:00
|
|
|
rocksDB.put(writeOptions, keyBuf, valueBuf);
|
2022-04-06 02:41:32 +02:00
|
|
|
} catch (RocksDBException e) {
|
|
|
|
throw new IllegalStateException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void reset(long index) {
|
|
|
|
ensureBounds(index);
|
|
|
|
ensureThread();
|
2022-05-12 19:14:27 +02:00
|
|
|
try (var writeOptions = newWriteOptions();
|
|
|
|
var keyBuf = allocate(Long.BYTES)) {
|
2022-04-06 02:41:32 +02:00
|
|
|
keyBuf.writeLong(index);
|
2022-05-12 19:14:27 +02:00
|
|
|
rocksDB.delete(writeOptions, keyBuf);
|
2022-04-06 02:41:32 +02:00
|
|
|
} catch (RocksDBException e) {
|
|
|
|
throw new IllegalStateException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public @Nullable V get(long index) {
|
|
|
|
ensureBounds(index);
|
|
|
|
ensureThread();
|
|
|
|
|
|
|
|
var keyBuf = allocate(Long.BYTES);
|
|
|
|
try (keyBuf) {
|
2022-04-06 14:25:53 +02:00
|
|
|
keyBuf.writeLong(index);
|
2022-05-12 19:14:27 +02:00
|
|
|
try (var readOptions = newReadOptions();
|
|
|
|
var value = rocksDB.get(readOptions, keyBuf)) {
|
2022-04-06 14:25:53 +02:00
|
|
|
if (value == null) {
|
|
|
|
return null;
|
|
|
|
}
|
2022-04-06 02:41:32 +02:00
|
|
|
return valueCodec.deserialize(value);
|
|
|
|
}
|
|
|
|
} catch (RocksDBException e) {
|
|
|
|
throw new IllegalStateException(e);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private void ensureBounds(long index) {
|
|
|
|
if (index < 0 || index >= virtualSize) throw new IndexOutOfBoundsException();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public long size() {
|
|
|
|
ensureThread();
|
|
|
|
return virtualSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void close() {
|
|
|
|
if (closed.compareAndSet(false, true)) {
|
|
|
|
ensureThread();
|
|
|
|
this.tempEnv.freeDb(hugePqId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
|
|
|
return "huge_pq_array[" + virtualSize + "]";
|
|
|
|
}
|
2022-04-06 14:25:53 +02:00
|
|
|
|
|
|
|
public Object[] toArray() {
|
|
|
|
var result = new Object[Math.toIntExact(virtualSize)];
|
|
|
|
for (int i = 0; i < virtualSize; i++) {
|
|
|
|
result[i] = get(i);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
2022-04-06 02:41:32 +02:00
|
|
|
}
|