Skip to content

Commit 63aeed9

Browse files
committed
feat(db/rocksdb): improve resource management with try-with-resources
1 parent 48cad61 commit 63aeed9

File tree

10 files changed

+86
-21
lines changed

10 files changed

+86
-21
lines changed

chainbase/src/main/java/org/tron/common/storage/rocksdb/RocksDbDataSourceImpl.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -308,7 +308,9 @@ public void updateByBatch(Map<byte[], byte[]> rows, WriteOptionsWrapper optionsW
308308

309309
@Override
310310
public void updateByBatch(Map<byte[], byte[]> rows) {
311-
this.updateByBatch(rows, new WriteOptions());
311+
try (WriteOptions writeOptions = new WriteOptions()) {
312+
this.updateByBatch(rows, writeOptions);
313+
}
312314
}
313315

314316
private void updateByBatch(Map<byte[], byte[]> rows, WriteOptions options) {
@@ -419,6 +421,22 @@ public void backup(String dir) throws RocksDBException {
419421
}
420422
}
421423

424+
/**
425+
* Returns an iterator over the database.
426+
*
427+
* <p><b>CRITICAL:</b> The returned iterator holds native resources and <b>MUST</b> be closed
428+
* after use to prevent memory leaks. It is strongly recommended to use a try-with-resources
429+
* statement.
430+
*
431+
* <p>Example of correct usage:
432+
* <pre>{@code
433+
* try (RocksIterator iterator = getRocksIterator()) {
434+
* // do something
435+
* }
436+
* }</pre>
437+
*
438+
* @return a new database iterator that must be closed.
439+
*/
422440
private RocksIterator getRocksIterator() {
423441
try (ReadOptions readOptions = new ReadOptions().setFillCache(false)) {
424442
throwIfNotAlive();

common/src/main/java/org/tron/common/setting/RocksDbSettings.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,21 @@ public static LRUCache getCache() {
163163
return cache;
164164
}
165165

166+
/**
167+
* Creates a new RocksDB Options.
168+
*
169+
* <p><b>CRITICAL:</b> Must be closed after use to prevent native memory leaks.
170+
* Use try-with-resources.
171+
*
172+
* <pre>{@code
173+
* try (Options options = getOptionsByDbName(dbName)) {
174+
* // do something
175+
* }
176+
* }</pre>
177+
*
178+
* @param dbName db name
179+
* @return a new Options instance that must be closed
180+
*/
166181
public static Options getOptionsByDbName(String dbName) {
167182
RocksDbSettings settings = getSettings();
168183

plugins/src/main/java/common/org/tron/plugins/DbConvert.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,8 @@ private void batchInsert(RocksDB rocks, List<byte[]> keys, List<byte[]> values)
223223
* @throws Exception RocksDBException
224224
*/
225225
private void write(RocksDB rocks, org.rocksdb.WriteBatch batch) throws Exception {
226-
try {
227-
rocks.write(new org.rocksdb.WriteOptions(), batch);
226+
try (org.rocksdb.WriteOptions writeOptions = new org.rocksdb.WriteOptions()) {
227+
rocks.write(writeOptions, batch);
228228
} catch (RocksDBException e) {
229229
// retry
230230
if (maybeRetry(e)) {

plugins/src/main/java/common/org/tron/plugins/DbLite.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -656,12 +656,13 @@ private boolean isLite(String databaseDir) throws RocksDBException, IOException
656656
private long getSecondBlock(String databaseDir) throws RocksDBException, IOException {
657657
long num = 0;
658658
DBInterface sourceBlockIndexDb = DbTool.getDB(databaseDir, BLOCK_INDEX_DB_NAME);
659-
DBIterator iterator = sourceBlockIndexDb.iterator();
660-
iterator.seek(ByteArray.fromLong(1));
661-
if (iterator.hasNext()) {
662-
num = Longs.fromByteArray(iterator.getKey());
659+
try (DBIterator iterator = sourceBlockIndexDb.iterator()) {
660+
iterator.seek(ByteArray.fromLong(1));
661+
if (iterator.hasNext()) {
662+
num = Longs.fromByteArray(iterator.getKey());
663+
}
664+
return num;
663665
}
664-
return num;
665666
}
666667

667668
private DBInterface getCheckpointDb(String sourceDir) throws IOException, RocksDBException {

plugins/src/main/java/common/org/tron/plugins/utils/DBUtils.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,21 @@ public static org.iq80.leveldb.Options newDefaultLevelDbOptions() {
8888
return dbOptions;
8989
}
9090

91+
/**
92+
* Creates a new RocksDB Options.
93+
*
94+
* <p><b>CRITICAL:</b> Must be closed after use to prevent native memory leaks.
95+
* Use try-with-resources.
96+
*
97+
* <pre>{@code
98+
* try (Options options = newDefaultRocksDbOptions(false)) {
99+
* // do something
100+
* }
101+
* }</pre>
102+
*
103+
* @param forBulkLoad if true, optimizes for bulk loading
104+
* @return a new Options instance that must be closed
105+
*/
91106
private static Options newDefaultRocksDbOptions(boolean forBulkLoad) {
92107
Options options = new Options();
93108
options.setCreateIfMissing(true);

plugins/src/main/java/common/org/tron/plugins/utils/db/DBInterface.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,22 @@ public interface DBInterface extends Closeable {
1212

1313
void delete(byte[] key);
1414

15+
/**
16+
* Returns an iterator over the database.
17+
*
18+
* <p><b>CRITICAL:</b> The returned iterator holds native resources and <b>MUST</b> be closed
19+
* after use to prevent memory leaks. It is strongly recommended to use a try-with-resources
20+
* statement.
21+
*
22+
* <p>Example of correct usage:
23+
* <pre>{@code
24+
* try (DBIterator iterator = db.iterator()) {
25+
* // do something
26+
* }
27+
* }</pre>
28+
*
29+
* @return a new database iterator that must be closed.
30+
*/
1531
DBIterator iterator();
1632

1733
long size();

plugins/src/main/java/common/org/tron/plugins/utils/db/LevelDBImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public DBIterator iterator() {
4141

4242
@Override
4343
public long size() {
44-
return Streams.stream(leveldb.iterator()).count();
44+
return Streams.stream(this.iterator()).count();
4545
}
4646

4747
@Override

plugins/src/main/java/common/org/tron/plugins/utils/db/RockDBIterator.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,18 @@
22

33
import java.io.IOException;
44
import java.util.Map;
5+
import org.rocksdb.ReadOptions;
6+
import org.rocksdb.RocksDB;
57
import org.rocksdb.RocksIterator;
68

79
public class RockDBIterator implements DBIterator {
810

911
private final RocksIterator iterator;
12+
private final ReadOptions readOptions;
1013

11-
public RockDBIterator(RocksIterator iterator) {
12-
this.iterator = iterator;
14+
public RockDBIterator(RocksDB rocksdb) {
15+
this.readOptions = new ReadOptions().setFillCache(false);
16+
this.iterator = rocksdb.newIterator(readOptions);
1317
}
1418

1519
@Override
@@ -73,5 +77,6 @@ public byte[] setValue(byte[] value) {
7377
@Override
7478
public void close() throws IOException {
7579
iterator.close();
80+
readOptions.close();
7681
}
7782
}

plugins/src/main/java/common/org/tron/plugins/utils/db/RocksDBImpl.java

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package org.tron.plugins.utils.db;
22

3+
import com.google.common.collect.Streams;
34
import java.io.IOException;
45
import lombok.Getter;
56
import org.rocksdb.RocksDBException;
6-
import org.rocksdb.RocksIterator;
77

88
public class RocksDBImpl implements DBInterface {
99

@@ -47,19 +47,12 @@ public void delete(byte[] key) {
4747

4848
@Override
4949
public DBIterator iterator() {
50-
return new RockDBIterator(rocksDB.newIterator(
51-
new org.rocksdb.ReadOptions().setFillCache(false)));
50+
return new RockDBIterator(rocksDB);
5251
}
5352

5453
@Override
5554
public long size() {
56-
RocksIterator iterator = rocksDB.newIterator();
57-
long size = 0;
58-
for (iterator.seekToFirst(); iterator.isValid(); iterator.next()) {
59-
size++;
60-
}
61-
iterator.close();
62-
return size;
55+
return Streams.stream(this.iterator()).count();
6356
}
6457

6558
@Override

plugins/src/test/java/org/tron/plugins/DbTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.nio.charset.StandardCharsets;
66
import java.nio.file.Paths;
77
import java.util.UUID;
8+
import org.junit.Assert;
89
import org.junit.Rule;
910
import org.junit.rules.TemporaryFolder;
1011
import org.rocksdb.RocksDBException;
@@ -83,6 +84,7 @@ private static void initDB(String sourceDir, String dbName, DbTool.DbType dbType
8384
db.put(bytes, bytes);
8485
}
8586
}
87+
Assert.assertTrue(db.size() > 0);
8688
}
8789
}
8890

0 commit comments

Comments
 (0)