This is an automated email from the ASF dual-hosted git repository.
lhotari pushed a commit to branch branch-4.17
in repository https://gitbox.apache.org/repos/asf/bookkeeper.git
The following commit(s) were added to refs/heads/branch-4.17 by this push:
new 9d067f41c6 Fix the coredump that occurs when calling
KeyValueStorageRocksDB.count after rocksdb has been closed (#4581)
9d067f41c6 is described below
commit 9d067f41c6344ce9e00c798f3b140d4a8ed1e901
Author: zzb <[email protected]>
AuthorDate: Thu Apr 17 16:33:04 2025 +0800
Fix the coredump that occurs when calling KeyValueStorageRocksDB.count
after rocksdb has been closed (#4581)
* Fix the coredump that occurs when calling KeyValueStorageRocksDB.count()
(possibly triggered by Prometheus) after RocksDB has been closed(#4243)
* fix race when count op in process and db gets closed.
---------
Co-authored-by: zhaizhibo <[email protected]>
(cherry picked from commit 2831ed3405069f2212e2c6204f645e503319ba69)
---
.../bookie/storage/ldb/KeyValueStorageRocksDB.java | 25 ++++++++++++++++++++--
.../storage/ldb/KeyValueStorageRocksDBTest.java | 17 +++++++++++++++
2 files changed, 40 insertions(+), 2 deletions(-)
diff --git
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/KeyValueStorageRocksDB.java
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/KeyValueStorageRocksDB.java
index c9e72847fb..b870fb5939 100644
---
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/KeyValueStorageRocksDB.java
+++
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/KeyValueStorageRocksDB.java
@@ -38,6 +38,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import
org.apache.bookkeeper.bookie.storage.ldb.KeyValueStorageFactory.DbConfigType;
import org.apache.bookkeeper.conf.ServerConfiguration;
import org.apache.commons.lang3.StringUtils;
@@ -74,6 +75,8 @@ public class KeyValueStorageRocksDB implements
KeyValueStorage {
static KeyValueStorageFactory factory = (defaultBasePath, subPath,
dbConfigType, conf) ->
new KeyValueStorageRocksDB(defaultBasePath, subPath, dbConfigType,
conf);
+ private volatile boolean closed = true;
+ private final ReentrantReadWriteLock closedLock = new
ReentrantReadWriteLock();
private final RocksDB db;
private RocksObject options;
private List<ColumnFamilyDescriptor> columnFamilyDescriptors;
@@ -147,6 +150,7 @@ public class KeyValueStorageRocksDB implements
KeyValueStorage {
optionDontCache.setFillCache(false);
this.writeBatchMaxSize =
conf.getMaxOperationNumbersInSingleRocksDBBatch();
+ this.closed = false;
}
private RocksDB initializeRocksDBWithConfFile(String basePath, String
subPath, DbConfigType dbConfigType,
@@ -287,7 +291,13 @@ public class KeyValueStorageRocksDB implements
KeyValueStorage {
@Override
public void close() throws IOException {
- db.close();
+ try {
+ closedLock.writeLock().lock();
+ closed = true;
+ db.close();
+ } finally {
+ closedLock.writeLock().unlock();
+ }
if (cache != null) {
cache.close();
}
@@ -513,7 +523,18 @@ public class KeyValueStorageRocksDB implements
KeyValueStorage {
@Override
public long count() throws IOException {
try {
- return db.getLongProperty("rocksdb.estimate-num-keys");
+ if (closed) {
+ throw new IOException("RocksDB is closed");
+ }
+ try {
+ closedLock.readLock().lock();
+ if (!closed) {
+ return db.getLongProperty("rocksdb.estimate-num-keys");
+ }
+ throw new IOException("RocksDB is closed");
+ } finally {
+ closedLock.readLock().unlock();
+ }
} catch (RocksDBException e) {
throw new IOException("Error in getting records count", e);
}
diff --git
a/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/storage/ldb/KeyValueStorageRocksDBTest.java
b/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/storage/ldb/KeyValueStorageRocksDBTest.java
index 2ef3e010f8..97be7ae7c7 100644
---
a/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/storage/ldb/KeyValueStorageRocksDBTest.java
+++
b/bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/storage/ldb/KeyValueStorageRocksDBTest.java
@@ -21,9 +21,11 @@ package org.apache.bookkeeper.bookie.storage.ldb;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import java.io.File;
+import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Paths;
@@ -131,4 +133,19 @@ public class KeyValueStorageRocksDBTest {
ColumnFamilyOptions familyOptions =
columnFamilyDescriptorList.get(0).getOptions();
assertEquals(true, familyOptions.levelCompactionDynamicLevelBytes());
}
+
+ @Test
+ public void testCallCountAfterClose() throws IOException {
+ ServerConfiguration configuration = new ServerConfiguration();
+ URL url =
getClass().getClassLoader().getResource("test_entry_location_rocksdb.conf");
+ configuration.setEntryLocationRocksdbConf(url.getPath());
+ File tmpDir =
Files.createTempDirectory("bk-kv-rocksdbtest-file").toFile();
+ Files.createDirectory(Paths.get(tmpDir.toString(), "subDir"));
+ KeyValueStorageRocksDB rocksDB = new
KeyValueStorageRocksDB(tmpDir.toString(), "subDir",
+ KeyValueStorageFactory.DbConfigType.EntryLocation,
configuration);
+ assertNotNull(rocksDB.getColumnFamilyDescriptors());
+ rocksDB.close();
+ IOException exception = assertThrows(IOException.class,
rocksDB::count);
+ assertEquals("RocksDB is closed", exception.getMessage());
+ }
}