2021-05-08 03:09:00 +02:00
|
|
|
package it.cavallium.dbengine.database.collections;
|
|
|
|
|
|
|
|
import it.cavallium.dbengine.client.CompositeSnapshot;
|
2023-10-10 00:39:41 +02:00
|
|
|
import it.cavallium.dbengine.client.DbProgress;
|
|
|
|
import it.cavallium.dbengine.client.SSTVerificationProgress;
|
2021-05-08 03:09:00 +02:00
|
|
|
import it.cavallium.dbengine.database.Delta;
|
|
|
|
import it.cavallium.dbengine.database.LLUtils;
|
|
|
|
import it.cavallium.dbengine.database.UpdateReturnMode;
|
2021-08-22 21:23:22 +02:00
|
|
|
import it.cavallium.dbengine.database.serialization.SerializationFunction;
|
2021-05-08 03:09:00 +02:00
|
|
|
import it.unimi.dsi.fastutil.objects.ObjectArraySet;
|
|
|
|
import java.util.Map;
|
|
|
|
import java.util.Map.Entry;
|
|
|
|
import java.util.Objects;
|
|
|
|
import java.util.Set;
|
2023-02-09 23:34:25 +01:00
|
|
|
import java.util.stream.Stream;
|
2021-12-17 01:48:49 +01:00
|
|
|
import org.apache.logging.log4j.LogManager;
|
|
|
|
import org.apache.logging.log4j.Logger;
|
2021-05-08 03:09:00 +02:00
|
|
|
import org.jetbrains.annotations.NotNull;
|
|
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
|
|
|
|
@SuppressWarnings("unused")
|
2023-02-09 23:34:25 +01:00
|
|
|
public class DatabaseSingleBucket<K, V, TH> implements DatabaseStageEntry<V> {
|
2021-05-08 03:09:00 +02:00
|
|
|
|
2021-12-17 01:48:49 +01:00
|
|
|
private static final Logger logger = LogManager.getLogger(DatabaseSingleBucket.class);
|
2021-10-01 19:17:33 +02:00
|
|
|
|
2021-05-08 03:09:00 +02:00
|
|
|
private final K key;
|
|
|
|
|
2022-07-19 23:45:39 +02:00
|
|
|
private final DatabaseStageEntry<ObjectArraySet<Entry<K, V>>> bucketStage;
|
2021-10-01 19:17:33 +02:00
|
|
|
|
2022-07-19 23:45:39 +02:00
|
|
|
public DatabaseSingleBucket(DatabaseStageEntry<ObjectArraySet<Entry<K, V>>> bucketStage, K key) {
|
2021-09-23 20:57:28 +02:00
|
|
|
this.key = key;
|
2021-05-08 03:09:00 +02:00
|
|
|
this.bucketStage = bucketStage;
|
2021-09-23 20:57:28 +02:00
|
|
|
}
|
|
|
|
|
2022-07-19 23:45:39 +02:00
|
|
|
private DatabaseSingleBucket(DatabaseStage<ObjectArraySet<Entry<K, V>>> bucketStage, K key) {
|
2021-05-08 03:09:00 +02:00
|
|
|
this.key = key;
|
2022-07-19 23:45:39 +02:00
|
|
|
this.bucketStage = (DatabaseStageEntry<ObjectArraySet<Entry<K, V>>>) bucketStage;
|
2021-05-08 03:09:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2023-02-09 23:34:25 +01:00
|
|
|
public V get(@Nullable CompositeSnapshot snapshot) {
|
|
|
|
var entries = bucketStage.get(snapshot);
|
|
|
|
return entries != null ? extractValue(entries) : null;
|
2021-05-08 03:09:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2023-02-09 23:34:25 +01:00
|
|
|
public V getOrDefault(@Nullable CompositeSnapshot snapshot, V defaultValue) {
|
|
|
|
var entries = bucketStage.get(snapshot);
|
|
|
|
return entries != null ? extractValue(entries) : defaultValue;
|
2021-05-08 03:09:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2023-02-09 23:34:25 +01:00
|
|
|
public void set(V value) {
|
|
|
|
this.update(prev -> value, UpdateReturnMode.NOTHING);
|
2021-05-08 03:09:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2023-02-09 23:34:25 +01:00
|
|
|
public V setAndGetPrevious(V value) {
|
2021-05-08 03:09:00 +02:00
|
|
|
return this.update(prev -> value, UpdateReturnMode.GET_OLD_VALUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2023-02-09 23:34:25 +01:00
|
|
|
public boolean setAndGetChanged(V value) {
|
|
|
|
return LLUtils.isDeltaChanged(this.updateAndGetDelta(prev -> value));
|
2021-05-08 03:09:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2023-02-09 23:34:25 +01:00
|
|
|
public V update(SerializationFunction<@Nullable V, @Nullable V> updater, UpdateReturnMode updateReturnMode) {
|
|
|
|
var result = bucketStage
|
2021-05-08 03:09:00 +02:00
|
|
|
.update(oldBucket -> {
|
|
|
|
V oldValue = extractValue(oldBucket);
|
2021-06-19 12:14:14 +02:00
|
|
|
V newValue = updater.apply(oldValue);
|
2021-05-08 03:09:00 +02:00
|
|
|
|
|
|
|
if (newValue == null) {
|
|
|
|
return this.removeValueOrDelete(oldBucket);
|
|
|
|
} else {
|
|
|
|
return this.insertValueOrCreate(oldBucket, newValue);
|
|
|
|
}
|
2023-02-09 23:34:25 +01:00
|
|
|
}, updateReturnMode);
|
|
|
|
return result != null ? extractValue(result) : null;
|
2021-05-08 03:09:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2023-02-09 23:34:25 +01:00
|
|
|
public Delta<V> updateAndGetDelta(SerializationFunction<@Nullable V, @Nullable V> updater) {
|
|
|
|
var delta = bucketStage.updateAndGetDelta(oldBucket -> {
|
2022-05-20 23:59:56 +02:00
|
|
|
V oldValue = extractValue(oldBucket);
|
|
|
|
var result = updater.apply(oldValue);
|
|
|
|
if (result == null) {
|
|
|
|
return this.removeValueOrDelete(oldBucket);
|
|
|
|
} else {
|
|
|
|
return this.insertValueOrCreate(oldBucket, result);
|
|
|
|
}
|
2023-02-09 23:34:25 +01:00
|
|
|
});
|
|
|
|
return LLUtils.mapDelta(delta, this::extractValue);
|
2021-05-08 03:09:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2023-02-09 23:34:25 +01:00
|
|
|
public void clear() {
|
|
|
|
this.update(prev -> null, UpdateReturnMode.NOTHING);
|
2021-05-08 03:09:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2023-02-09 23:34:25 +01:00
|
|
|
public V clearAndGetPrevious() {
|
2021-05-08 03:09:00 +02:00
|
|
|
return this.update(prev -> null, UpdateReturnMode.GET_OLD_VALUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2023-02-09 23:34:25 +01:00
|
|
|
public boolean clearAndGetStatus() {
|
|
|
|
return LLUtils.isDeltaChanged(this.updateAndGetDelta(prev -> null));
|
2021-05-08 03:09:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2023-02-09 23:34:25 +01:00
|
|
|
public long leavesCount(@Nullable CompositeSnapshot snapshot, boolean fast) {
|
|
|
|
return this.get(snapshot) != null ? 1L : 0L;
|
2021-05-08 03:09:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2023-02-09 23:34:25 +01:00
|
|
|
public boolean isEmpty(@Nullable CompositeSnapshot snapshot) {
|
|
|
|
return this.get(snapshot) == null;
|
2021-05-08 03:09:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public DatabaseStageEntry<V> entry() {
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
2021-06-26 02:35:33 +02:00
|
|
|
@Override
|
2023-10-10 00:39:41 +02:00
|
|
|
public Stream<DbProgress<SSTVerificationProgress>> verifyChecksum() {
|
2023-09-26 01:18:24 +02:00
|
|
|
return bucketStage.verifyChecksum();
|
2021-06-26 02:35:33 +02:00
|
|
|
}
|
|
|
|
|
2021-05-08 03:09:00 +02:00
|
|
|
@Nullable
|
|
|
|
private V extractValue(Set<Entry<K, V>> entries) {
|
|
|
|
if (entries == null) return null;
|
|
|
|
for (Entry<K, V> entry : entries) {
|
|
|
|
if (Objects.equals(entry.getKey(), key)) {
|
|
|
|
return entry.getValue();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
@NotNull
|
2021-07-13 22:58:08 +02:00
|
|
|
private ObjectArraySet<Entry<K, V>> insertValueOrCreate(@Nullable ObjectArraySet<Entry<K, V>> entries, V value) {
|
2021-05-08 03:09:00 +02:00
|
|
|
if (entries != null) {
|
2021-07-13 22:58:08 +02:00
|
|
|
var clonedEntries = entries.clone();
|
|
|
|
var it = clonedEntries.iterator();
|
2021-05-08 03:09:00 +02:00
|
|
|
while (it.hasNext()) {
|
|
|
|
var entry = it.next();
|
|
|
|
if (Objects.equals(entry.getKey(), key)) {
|
|
|
|
it.remove();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-07-13 22:58:08 +02:00
|
|
|
clonedEntries.add(Map.entry(key, value));
|
|
|
|
return clonedEntries;
|
2021-05-08 03:09:00 +02:00
|
|
|
} else {
|
2021-07-13 22:58:08 +02:00
|
|
|
var oas = new ObjectArraySet<Entry<K, V>>(1);
|
2021-05-17 04:10:41 +02:00
|
|
|
oas.add(Map.entry(key, value));
|
|
|
|
return oas;
|
2021-05-08 03:09:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Nullable
|
2021-07-13 22:58:08 +02:00
|
|
|
private ObjectArraySet<Entry<K, V>> removeValueOrDelete(@Nullable ObjectArraySet<Entry<K, V>> entries) {
|
2021-05-08 03:09:00 +02:00
|
|
|
if (entries != null) {
|
2021-07-13 22:58:08 +02:00
|
|
|
var clonedEntries = entries.clone();
|
|
|
|
var it = clonedEntries.iterator();
|
2021-05-08 03:09:00 +02:00
|
|
|
while (it.hasNext()) {
|
|
|
|
var entry = it.next();
|
|
|
|
if (Objects.equals(entry.getKey(), key)) {
|
|
|
|
it.remove();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2021-07-13 22:58:08 +02:00
|
|
|
if (clonedEntries.size() == 0) {
|
2021-05-08 03:09:00 +02:00
|
|
|
return null;
|
|
|
|
} else {
|
2021-07-13 22:58:08 +02:00
|
|
|
return clonedEntries;
|
2021-05-08 03:09:00 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|