This is an automated email from the ASF dual-hosted git repository. lhotari pushed a commit to branch branch-4.16 in repository https://gitbox.apache.org/repos/asf/bookkeeper.git
The following commit(s) were added to refs/heads/branch-4.16 by this push: new 3795f559e0 Fix the coredump that occurs when calling KeyValueStorageRocksDB.count after rocksdb has been closed (#4581) 3795f559e0 is described below commit 3795f559e006726cc0d500e5f98386693b47bdb5 Author: zzb <48124861+zhaizh...@users.noreply.github.com> 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 <zhaizh...@kuaishou.com> (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()); + } }