Skip to content

Commit 274d72f

Browse files
zhaizhibozhaizhibo
authored andcommitted
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 <zhaizhibo@kuaishou.com> (cherry picked from commit 2831ed3)
1 parent 5e6e6e3 commit 274d72f

File tree

2 files changed

+40
-2
lines changed

2 files changed

+40
-2
lines changed

bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/storage/ldb/KeyValueStorageRocksDB.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import java.util.List;
3939
import java.util.Map.Entry;
4040
import java.util.concurrent.TimeUnit;
41+
import java.util.concurrent.locks.ReentrantReadWriteLock;
4142
import org.apache.bookkeeper.bookie.storage.ldb.KeyValueStorageFactory.DbConfigType;
4243
import org.apache.bookkeeper.conf.ServerConfiguration;
4344
import org.apache.commons.lang3.StringUtils;
@@ -73,6 +74,8 @@ public class KeyValueStorageRocksDB implements KeyValueStorage {
7374
static KeyValueStorageFactory factory = (defaultBasePath, subPath, dbConfigType, conf) ->
7475
new KeyValueStorageRocksDB(defaultBasePath, subPath, dbConfigType, conf);
7576

77+
private volatile boolean closed = true;
78+
private final ReentrantReadWriteLock closedLock = new ReentrantReadWriteLock();
7679
private final RocksDB db;
7780
private RocksObject options;
7881
private List<ColumnFamilyDescriptor> columnFamilyDescriptors;
@@ -144,6 +147,7 @@ public KeyValueStorageRocksDB(String basePath, String subPath, DbConfigType dbCo
144147
optionDontCache.setFillCache(false);
145148

146149
this.writeBatchMaxSize = conf.getMaxOperationNumbersInSingleRocksDBBatch();
150+
this.closed = false;
147151
}
148152

149153
private RocksDB initializeRocksDBWithConfFile(String basePath, String subPath, DbConfigType dbConfigType,
@@ -284,7 +288,13 @@ private RocksDB initializeRocksDBWithBookieConf(String basePath, String subPath,
284288

285289
@Override
286290
public void close() throws IOException {
287-
db.close();
291+
try {
292+
closedLock.writeLock().lock();
293+
closed = true;
294+
db.close();
295+
} finally {
296+
closedLock.writeLock().unlock();
297+
}
288298
if (cache != null) {
289299
cache.close();
290300
}
@@ -475,7 +485,18 @@ public void close() {
475485
@Override
476486
public long count() throws IOException {
477487
try {
478-
return db.getLongProperty("rocksdb.estimate-num-keys");
488+
if (closed) {
489+
throw new IOException("RocksDB is closed");
490+
}
491+
try {
492+
closedLock.readLock().lock();
493+
if (!closed) {
494+
return db.getLongProperty("rocksdb.estimate-num-keys");
495+
}
496+
throw new IOException("RocksDB is closed");
497+
} finally {
498+
closedLock.readLock().unlock();
499+
}
479500
} catch (RocksDBException e) {
480501
throw new IOException("Error in getting records count", e);
481502
}

bookkeeper-server/src/test/java/org/apache/bookkeeper/bookie/storage/ldb/KeyValueStorageRocksDBTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@
2121
import static org.junit.Assert.assertEquals;
2222
import static org.junit.Assert.assertNotNull;
2323
import static org.junit.Assert.assertNull;
24+
import static org.junit.Assert.assertThrows;
2425
import static org.junit.Assert.assertTrue;
2526

2627
import java.io.File;
28+
import java.io.IOException;
2729
import java.net.URL;
2830
import java.nio.file.Files;
2931
import java.nio.file.Paths;
@@ -118,4 +120,19 @@ public void testReadChecksumTypeFromConfigurationFile() throws Exception {
118120
// After the PR: https://github.com/facebook/rocksdb/pull/10826 merge, we can turn on this test.
119121
assertEquals(ChecksumType.kxxHash, ((BlockBasedTableConfig) familyOptions.tableFormatConfig()).checksumType());
120122
}
123+
124+
@Test
125+
public void testCallCountAfterClose() throws IOException {
126+
ServerConfiguration configuration = new ServerConfiguration();
127+
URL url = getClass().getClassLoader().getResource("test_entry_location_rocksdb.conf");
128+
configuration.setEntryLocationRocksdbConf(url.getPath());
129+
File tmpDir = Files.createTempDirectory("bk-kv-rocksdbtest-file").toFile();
130+
Files.createDirectory(Paths.get(tmpDir.toString(), "subDir"));
131+
KeyValueStorageRocksDB rocksDB = new KeyValueStorageRocksDB(tmpDir.toString(), "subDir",
132+
KeyValueStorageFactory.DbConfigType.EntryLocation, configuration);
133+
assertNotNull(rocksDB.getColumnFamilyDescriptors());
134+
rocksDB.close();
135+
IOException exception = assertThrows(IOException.class, rocksDB::count);
136+
assertEquals("RocksDB is closed", exception.getMessage());
137+
}
121138
}

0 commit comments

Comments
 (0)