@@ -52,6 +52,7 @@ public class RocksDbDataSourceImpl extends DbStat implements DbSourceInter<byte[
5252 private volatile boolean alive ;
5353 private String parentPath ;
5454 private ReadWriteLock resetDbLock = new ReentrantReadWriteLock ();
55+ private Options options ;
5556
5657 public RocksDbDataSourceImpl (String parentPath , String name ) {
5758 this .dataBaseName = name ;
@@ -78,6 +79,9 @@ public void closeDB() {
7879 if (!isAlive ()) {
7980 return ;
8081 }
82+ if (this .options != null ) {
83+ this .options .close ();
84+ }
8185 database .close ();
8286 alive = false ;
8387 } catch (Exception e ) {
@@ -117,7 +121,8 @@ private static void checkArgNotNull(Object value, String name) {
117121 @ Override
118122 public Set <byte []> allKeys () throws RuntimeException {
119123 resetDbLock .readLock ().lock ();
120- try (final RocksIterator iter = getRocksIterator ()) {
124+ try (final ReadOptions readOptions = getReadOptions ();
125+ final RocksIterator iter = getRocksIterator (readOptions )) {
121126 Set <byte []> result = Sets .newHashSet ();
122127 for (iter .seekToFirst (); iter .isValid (); iter .next ()) {
123128 result .add (iter .key ());
@@ -133,7 +138,8 @@ public Set<byte[]> allKeys() throws RuntimeException {
133138 @ Override
134139 public Set <byte []> allValues () throws RuntimeException {
135140 resetDbLock .readLock ().lock ();
136- try (final RocksIterator iter = getRocksIterator ()) {
141+ try (final ReadOptions readOptions = getReadOptions ();
142+ final RocksIterator iter = getRocksIterator (readOptions )) {
137143 Set <byte []> result = Sets .newHashSet ();
138144 for (iter .seekToFirst (); iter .isValid (); iter .next ()) {
139145 result .add (iter .value ());
@@ -149,7 +155,8 @@ public Set<byte[]> allValues() throws RuntimeException {
149155 @ Override
150156 public long getTotal () throws RuntimeException {
151157 resetDbLock .readLock ().lock ();
152- try (final RocksIterator iter = getRocksIterator ()) {
158+ try (final ReadOptions readOptions = getReadOptions ();
159+ final RocksIterator iter = getRocksIterator (readOptions )) {
153160 long total = 0 ;
154161 for (iter .seekToFirst (); iter .isValid (); iter .next ()) {
155162 total ++;
@@ -180,7 +187,7 @@ private void initDB() {
180187 throw new IllegalArgumentException ("No name set to the dbStore" );
181188 }
182189
183- try ( Options options = RocksDbSettings . getOptionsByDbName ( dataBaseName )) {
190+ try {
184191 logger .debug ("Opening database {}." , dataBaseName );
185192 final Path dbPath = getDbPath ();
186193
@@ -191,14 +198,19 @@ private void initDB() {
191198 try {
192199 DbSourceInter .checkOrInitEngine (getEngine (), dbPath .toString (),
193200 TronError .ErrCode .ROCKSDB_INIT );
194- database = RocksDB .open (options , dbPath .toString ());
201+ this .options = RocksDbSettings .getOptionsByDbName (dataBaseName );
202+ database = RocksDB .open (this .options , dbPath .toString ());
195203 } catch (RocksDBException e ) {
196204 if (Objects .equals (e .getStatus ().getCode (), Status .Code .Corruption )) {
197205 logger .error ("Database {} corrupted, please delete database directory({}) "
198206 + "and restart." , dataBaseName , parentPath , e );
199207 } else {
200208 logger .error ("Open Database {} failed" , dataBaseName , e );
201209 }
210+
211+ if (this .options != null ) {
212+ this .options .close ();
213+ }
202214 throw new TronError (e , TronError .ErrCode .ROCKSDB_INIT );
203215 }
204216
@@ -282,7 +294,8 @@ public boolean flush() {
282294 */
283295 @ Override
284296 public org .tron .core .db .common .iterator .DBIterator iterator () {
285- return new RockStoreIterator (getRocksIterator ());
297+ ReadOptions readOptions = getReadOptions ();
298+ return new RockStoreIterator (getRocksIterator (readOptions ), readOptions );
286299 }
287300
288301 private void updateByBatchInner (Map <byte [], byte []> rows , WriteOptions options )
@@ -333,7 +346,8 @@ public List<byte[]> getKeysNext(byte[] key, long limit) {
333346 return new ArrayList <>();
334347 }
335348 resetDbLock .readLock ().lock ();
336- try (RocksIterator iter = getRocksIterator ()) {
349+ try (final ReadOptions readOptions = getReadOptions ();
350+ final RocksIterator iter = getRocksIterator (readOptions )) {
337351 List <byte []> result = new ArrayList <>();
338352 long i = 0 ;
339353 for (iter .seek (key ); iter .isValid () && i < limit ; iter .next (), i ++) {
@@ -350,7 +364,8 @@ public Map<byte[], byte[]> getNext(byte[] key, long limit) {
350364 return Collections .emptyMap ();
351365 }
352366 resetDbLock .readLock ().lock ();
353- try (RocksIterator iter = getRocksIterator ()) {
367+ try (final ReadOptions readOptions = getReadOptions ();
368+ final RocksIterator iter = getRocksIterator (readOptions )) {
354369 Map <byte [], byte []> result = new HashMap <>();
355370 long i = 0 ;
356371 for (iter .seek (key ); iter .isValid () && i < limit ; iter .next (), i ++) {
@@ -365,7 +380,8 @@ public Map<byte[], byte[]> getNext(byte[] key, long limit) {
365380 @ Override
366381 public Map <WrappedByteArray , byte []> prefixQuery (byte [] key ) {
367382 resetDbLock .readLock ().lock ();
368- try (RocksIterator iterator = getRocksIterator ()) {
383+ try (final ReadOptions readOptions = getReadOptions ();
384+ final RocksIterator iterator = getRocksIterator (readOptions )) {
369385 Map <WrappedByteArray , byte []> result = new HashMap <>();
370386 for (iterator .seek (key ); iterator .isValid (); iterator .next ()) {
371387 if (Bytes .indexOf (iterator .key (), key ) == 0 ) {
@@ -385,7 +401,8 @@ public Set<byte[]> getlatestValues(long limit) {
385401 return Sets .newHashSet ();
386402 }
387403 resetDbLock .readLock ().lock ();
388- try (RocksIterator iter = getRocksIterator ()) {
404+ try (final ReadOptions readOptions = getReadOptions ();
405+ final RocksIterator iter = getRocksIterator (readOptions )) {
389406 Set <byte []> result = Sets .newHashSet ();
390407 long i = 0 ;
391408 for (iter .seekToLast (); iter .isValid () && i < limit ; iter .prev (), i ++) {
@@ -402,7 +419,8 @@ public Set<byte[]> getValuesNext(byte[] key, long limit) {
402419 return Sets .newHashSet ();
403420 }
404421 resetDbLock .readLock ().lock ();
405- try (RocksIterator iter = getRocksIterator ()) {
422+ try (final ReadOptions readOptions = getReadOptions ();
423+ final RocksIterator iter = getRocksIterator (readOptions )) {
406424 Set <byte []> result = Sets .newHashSet ();
407425 long i = 0 ;
408426 for (iter .seek (key ); iter .isValid () && i < limit ; iter .next (), i ++) {
@@ -430,18 +448,41 @@ public void backup(String dir) throws RocksDBException {
430448 *
431449 * <p>Example of correct usage:
432450 * <pre>{@code
433- * try (RocksIterator iterator = getRocksIterator()) {
451+ * try ( ReadOptions readOptions = new ReadOptions().setFillCache(false);
452+ * RocksIterator iterator = getRocksIterator(readOptions)) {
453+ * iterator.seekToFirst();
434454 * // do something
435455 * }
436456 * }</pre>
437457 *
438458 * @return a new database iterator that must be closed.
439459 */
440- private RocksIterator getRocksIterator () {
441- try (ReadOptions readOptions = new ReadOptions ().setFillCache (false )) {
442- throwIfNotAlive ();
443- return database .newIterator (readOptions );
444- }
460+ private RocksIterator getRocksIterator (ReadOptions readOptions ) {
461+ throwIfNotAlive ();
462+ return database .newIterator (readOptions );
463+ }
464+
465+ /**
466+ * Returns an ReadOptions.
467+ *
468+ * <p><b>CRITICAL:</b> The returned ReadOptions holds native resources and <b>MUST</b> be closed
469+ * after use to prevent memory leaks. It is strongly recommended to use a try-with-resources
470+ * statement.
471+ *
472+ * <p>Example of correct usage:
473+ * <pre>{@code
474+ * try (ReadOptions readOptions = getReadOptions();
475+ * RocksIterator iterator = getRocksIterator(readOptions)) {
476+ * iterator.seekToFirst();
477+ * // do something
478+ * }
479+ * }</pre>
480+ *
481+ * @return a new database iterator that must be closed.
482+ */
483+ private ReadOptions getReadOptions () {
484+ throwIfNotAlive ();
485+ return new ReadOptions ().setFillCache (false );
445486 }
446487
447488 public boolean deleteDbBakPath (String dir ) {
0 commit comments