Avoid race conditions in close method

This commit is contained in:
Andrea Cavalli 2024-12-24 01:51:22 +01:00
parent 4616498d7f
commit 2437116daa

View File

@ -6,6 +6,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.rocksdb.AbstractImmutableNativeReference;
import org.rocksdb.ColumnFamilyDescriptor;
import org.rocksdb.ColumnFamilyHandle;
import org.rocksdb.FlushOptions;
@ -107,6 +108,8 @@ public sealed interface TransactionalDB extends Closeable {
private final DatabaseTasks databaseTasks;
private final List<ColumnFamilyDescriptor> descriptors;
private final ArrayList<ColumnFamilyHandle> handles;
private final Object closeLock = new Object();
private volatile boolean closed = false;
public BaseTransactionalDB(String path, RDB db,
List<ColumnFamilyDescriptor> descriptors,
@ -143,6 +146,14 @@ public sealed interface TransactionalDB extends Closeable {
@Override
public void close() throws IOException {
if (this.closed) {
return;
}
synchronized (this.closeLock) {
if (this.closed) {
return;
}
this.closed = true;
List<Exception> exceptions = new ArrayList<>();
try {
databaseTasks.close();
@ -158,14 +169,17 @@ public sealed interface TransactionalDB extends Closeable {
}
try (var options = new FlushOptions().setWaitForFlush(true).setAllowWriteStall(true)) {
if (db.isOwningHandle()) {
db.flush(options, handles);
var openHandles = handles.stream().filter(AbstractImmutableNativeReference::isOwningHandle).toList();
db.flush(options, openHandles);
}
} catch (RocksDBException e) {
exceptions.add(e);
}
for (ColumnFamilyHandle handle : handles) {
try {
if (handle.isOwningHandle()) {
handle.close();
}
} catch (Exception ex) {
exceptions.add(ex);
}
@ -189,6 +203,7 @@ public sealed interface TransactionalDB extends Closeable {
}
}
}
}
final class PessimisticTransactionalDB extends BaseTransactionalDB<TransactionDB> {