Skip to content

Commit 3795f55

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 <[email protected]> (cherry picked from commit 2831ed3)
1 parent a01aa11 commit 3795f55

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;
@@ -74,6 +75,8 @@ public class KeyValueStorageRocksDB implements KeyValueStorage {
7475
static KeyValueStorageFactory factory = (defaultBasePath, subPath, dbConfigType, conf) ->
7576
new KeyValueStorageRocksDB(defaultBasePath, subPath, dbConfigType, conf);
7677

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

149152
this.writeBatchMaxSize = conf.getMaxOperationNumbersInSingleRocksDBBatch();
153+
this.closed = false;
150154
}
151155

152156
private RocksDB initializeRocksDBWithConfFile(String basePath, String subPath, DbConfigType dbConfigType,
@@ -287,7 +291,13 @@ private RocksDB initializeRocksDBWithBookieConf(String basePath, String subPath,
287291

288292
@Override
289293
public void close() throws IOException {
290-
db.close();
294+
try {
295+
closedLock.writeLock().lock();
296+
closed = true;
297+
db.close();
298+
} finally {
299+
closedLock.writeLock().unlock();
300+
}
291301
if (cache != null) {
292302
cache.close();
293303
}
@@ -513,7 +523,18 @@ public void close() {
513523
@Override
514524
public long count() throws IOException {
515525
try {
516-
return db.getLongProperty("rocksdb.estimate-num-keys");
526+
if (closed) {
527+
throw new IOException("RocksDB is closed");
528+
}
529+
try {
530+
closedLock.readLock().lock();
531+
if (!closed) {
532+
return db.getLongProperty("rocksdb.estimate-num-keys");
533+
}
534+
throw new IOException("RocksDB is closed");
535+
} finally {
536+
closedLock.readLock().unlock();
537+
}
517538
} catch (RocksDBException e) {
518539
throw new IOException("Error in getting records count", e);
519540
}

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;
@@ -131,4 +133,19 @@ public void testLevelCompactionDynamicLevelBytesFromConfigurationFile() throws E
131133
ColumnFamilyOptions familyOptions = columnFamilyDescriptorList.get(0).getOptions();
132134
assertEquals(true, familyOptions.levelCompactionDynamicLevelBytes());
133135
}
136+
137+
@Test
138+
public void testCallCountAfterClose() throws IOException {
139+
ServerConfiguration configuration = new ServerConfiguration();
140+
URL url = getClass().getClassLoader().getResource("test_entry_location_rocksdb.conf");
141+
configuration.setEntryLocationRocksdbConf(url.getPath());
142+
File tmpDir = Files.createTempDirectory("bk-kv-rocksdbtest-file").toFile();
143+
Files.createDirectory(Paths.get(tmpDir.toString(), "subDir"));
144+
KeyValueStorageRocksDB rocksDB = new KeyValueStorageRocksDB(tmpDir.toString(), "subDir",
145+
KeyValueStorageFactory.DbConfigType.EntryLocation, configuration);
146+
assertNotNull(rocksDB.getColumnFamilyDescriptors());
147+
rocksDB.close();
148+
IOException exception = assertThrows(IOException.class, rocksDB::count);
149+
assertEquals("RocksDB is closed", exception.getMessage());
150+
}
134151
}

0 commit comments

Comments
 (0)