Skip to content

Commit 8d0deec

Browse files
authored
Merge pull request #4669 from halibobo1205/fix/db_iterator
fix(db): db iterator
2 parents 82c40b4 + f947f83 commit 8d0deec

File tree

3 files changed

+111
-5
lines changed

3 files changed

+111
-5
lines changed

chainbase/src/main/java/org/tron/core/db/common/iterator/RockStoreIterator.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55
import java.util.NoSuchElementException;
66
import lombok.extern.slf4j.Slf4j;
77
import org.rocksdb.RocksIterator;
8-
import org.tron.common.error.TronDBException;
98

109

1110
@Slf4j(topic = "DB")
1211
public final class RockStoreIterator implements DBIterator {
1312

14-
private RocksIterator dbIterator;
13+
private final RocksIterator dbIterator;
1514
private boolean first = true;
1615

16+
private boolean valid = true;
17+
1718
public RockStoreIterator(RocksIterator dbIterator) {
1819
this.dbIterator = dbIterator;
1920
}
@@ -25,6 +26,9 @@ public void close() throws IOException {
2526

2627
@Override
2728
public boolean hasNext() {
29+
if (!valid) {
30+
return false;
31+
}
2832
boolean hasNext = false;
2933
// true is first item
3034
try {
@@ -34,6 +38,7 @@ public boolean hasNext() {
3438
}
3539
if (!(hasNext = dbIterator.isValid())) { // false is last item
3640
dbIterator.close();
41+
valid = false;
3742
}
3843
} catch (Exception e) {
3944
logger.error(e.getMessage(), e);
@@ -48,7 +53,7 @@ public boolean hasNext() {
4853

4954
@Override
5055
public Entry<byte[], byte[]> next() {
51-
if (!dbIterator.isValid()) {
56+
if (!valid) {
5257
throw new NoSuchElementException();
5358
}
5459
byte[] key = dbIterator.key();

chainbase/src/main/java/org/tron/core/db/common/iterator/StoreIterator.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,19 @@
22

33
import java.io.IOException;
44
import java.util.Map.Entry;
5+
import java.util.NoSuchElementException;
56
import lombok.extern.slf4j.Slf4j;
67
import org.iq80.leveldb.DBIterator;
7-
import org.tron.common.error.TronDBException;
8+
89

910
@Slf4j(topic = "DB")
1011
public final class StoreIterator implements org.tron.core.db.common.iterator.DBIterator {
1112

12-
private DBIterator dbIterator;
13+
private final DBIterator dbIterator;
1314
private boolean first = true;
1415

16+
private boolean valid = true;
17+
1518
public StoreIterator(DBIterator dbIterator) {
1619
this.dbIterator = dbIterator;
1720
}
@@ -23,6 +26,10 @@ public void close() throws IOException {
2326

2427
@Override
2528
public boolean hasNext() {
29+
if (!valid) {
30+
return false;
31+
}
32+
2633
boolean hasNext = false;
2734
// true is first item
2835
try {
@@ -33,6 +40,7 @@ public boolean hasNext() {
3340

3441
if (!(hasNext = dbIterator.hasNext())) { // false is last item
3542
dbIterator.close();
43+
valid = false;
3644
}
3745
} catch (Exception e) {
3846
logger.error(e.getMessage(), e);
@@ -43,6 +51,9 @@ public boolean hasNext() {
4351

4452
@Override
4553
public Entry<byte[], byte[]> next() {
54+
if (!valid) {
55+
throw new NoSuchElementException();
56+
}
4657
return dbIterator.next();
4758
}
4859

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package org.tron.core.db;
2+
3+
import static org.fusesource.leveldbjni.JniDBFactory.factory;
4+
5+
import java.io.File;
6+
import java.io.IOException;
7+
import java.nio.charset.StandardCharsets;
8+
import java.nio.file.Paths;
9+
import java.util.NoSuchElementException;
10+
import org.iq80.leveldb.DB;
11+
import org.iq80.leveldb.Options;
12+
import org.junit.AfterClass;
13+
import org.junit.Assert;
14+
import org.junit.BeforeClass;
15+
import org.junit.Test;
16+
import org.rocksdb.RocksDB;
17+
import org.rocksdb.RocksDBException;
18+
import org.tron.common.utils.FileUtil;
19+
import org.tron.core.db.common.iterator.RockStoreIterator;
20+
import org.tron.core.db.common.iterator.StoreIterator;
21+
22+
public class DBIteratorTest {
23+
24+
@BeforeClass
25+
public static void init() {
26+
File file = Paths.get("database-iterator").toFile();
27+
if (!file.exists()) {
28+
file.mkdirs();
29+
}
30+
}
31+
32+
@AfterClass
33+
public static void clear() {
34+
File file = Paths.get("database-iterator").toFile();
35+
if (file.exists()) {
36+
FileUtil.deleteDir(Paths.get("database-iterator").toFile());
37+
}
38+
}
39+
40+
41+
@Test
42+
public void testLevelDb() throws IOException {
43+
File file = new File("database-iterator/testLevelDb");
44+
try {
45+
DB db = factory.open(file, new Options().createIfMissing(true));
46+
db.put("1".getBytes(StandardCharsets.UTF_8), "1".getBytes(StandardCharsets.UTF_8));
47+
db.put("2".getBytes(StandardCharsets.UTF_8), "2".getBytes(StandardCharsets.UTF_8));
48+
StoreIterator iterator = new StoreIterator(db.iterator());
49+
while (iterator.hasNext()) {
50+
iterator.next();
51+
}
52+
Assert.assertFalse(iterator.hasNext());
53+
try {
54+
iterator.next();
55+
} catch (Exception e) {
56+
Assert.assertTrue(e instanceof NoSuchElementException);
57+
}
58+
db.close();
59+
} finally {
60+
factory.destroy(file, new Options());
61+
}
62+
63+
64+
}
65+
66+
@Test
67+
public void testRocksDb() throws RocksDBException {
68+
File file = new File("database-iterator/testRocksDb");
69+
try (org.rocksdb.Options options = new org.rocksdb.Options().setCreateIfMissing(true)) {
70+
RocksDB db = RocksDB.open(options, file.toString());
71+
db.put("1".getBytes(StandardCharsets.UTF_8), "1".getBytes(StandardCharsets.UTF_8));
72+
db.put("2".getBytes(StandardCharsets.UTF_8), "2".getBytes(StandardCharsets.UTF_8));
73+
RockStoreIterator iterator = new RockStoreIterator(db.newIterator());
74+
while (iterator.hasNext()) {
75+
iterator.next();
76+
}
77+
Assert.assertFalse(iterator.hasNext());
78+
try {
79+
iterator.next();
80+
} catch (Exception e) {
81+
Assert.assertTrue(e instanceof NoSuchElementException);
82+
}
83+
db.close();
84+
} finally {
85+
RocksDB.destroyDB(file.toString(), new org.rocksdb.Options());
86+
}
87+
88+
}
89+
90+
}

0 commit comments

Comments
 (0)