This is an automated email from the ASF dual-hosted git repository.
yiguolei pushed a commit to branch branch-4.0
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/branch-4.0 by this push:
new cf95c944142 branch-4.0: [fix](test) Fix BDB JE resource leak in
BDBEnvironmentTest causing FE UT timeout #61404 (#61412)
cf95c944142 is described below
commit cf95c9441429497e198933ab9f54df22aab205e7
Author: github-actions[bot]
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Wed Mar 18 09:26:09 2026 +0800
branch-4.0: [fix](test) Fix BDB JE resource leak in BDBEnvironmentTest
causing FE UT timeout #61404 (#61412)
Cherry-picked from #61404
Co-authored-by: Mingyu Chen (Rayner) <[email protected]>
---
.../doris/journal/bdbje/BDBEnvironmentTest.java | 324 +++++++++++----------
1 file changed, 167 insertions(+), 157 deletions(-)
diff --git
a/fe/fe-core/src/test/java/org/apache/doris/journal/bdbje/BDBEnvironmentTest.java
b/fe/fe-core/src/test/java/org/apache/doris/journal/bdbje/BDBEnvironmentTest.java
index b93766b3c9d..cae2ec0f699 100644
---
a/fe/fe-core/src/test/java/org/apache/doris/journal/bdbje/BDBEnvironmentTest.java
+++
b/fe/fe-core/src/test/java/org/apache/doris/journal/bdbje/BDBEnvironmentTest.java
@@ -501,124 +501,127 @@ public class BDBEnvironmentTest {
followersInfo.add(Pair.of(followerEnvironment, new
NodeInfo(nodeName, nodeHostPort, nodeDir)));
}
- Pair<BDBEnvironment, NodeInfo> masterPair = findMaster(followersInfo);
- String beginDbName = String.valueOf(0L);
- Database masterDb = masterPair.first.openDatabase(beginDbName);
- DatabaseEntry key = new DatabaseEntry(randomBytes());
- DatabaseEntry value = new DatabaseEntry(randomBytes());
- Assertions.assertEquals(OperationStatus.SUCCESS, masterDb.put(null,
key, value));
- Assertions.assertEquals(1,
masterEnvironment.getDatabaseNames().size());
- LOG.info("master is {} | {}", masterPair.second.name,
masterPair.second.dir);
-
- for (Pair<BDBEnvironment, NodeInfo> entryPair : followersInfo) {
- if (entryPair.second.dir.equals(masterPair.second.dir)) {
- LOG.info("skip {}", entryPair.second.name);
- return;
- }
+ try {
+ Pair<BDBEnvironment, NodeInfo> masterPair =
findMaster(followersInfo);
+ String beginDbName = String.valueOf(0L);
+ Database masterDb = masterPair.first.openDatabase(beginDbName);
+ DatabaseEntry key = new DatabaseEntry(randomBytes());
+ DatabaseEntry value = new DatabaseEntry(randomBytes());
+ Assertions.assertEquals(OperationStatus.SUCCESS,
masterDb.put(null, key, value));
+ Assertions.assertEquals(1,
masterEnvironment.getDatabaseNames().size());
+ LOG.info("master is {} | {}", masterPair.second.name,
masterPair.second.dir);
- Assertions.assertEquals(1,
entryPair.first.getDatabaseNames().size());
- Database followerDb = entryPair.first.openDatabase(beginDbName);
- DatabaseEntry readValue = new DatabaseEntry();
- Assertions.assertEquals(OperationStatus.SUCCESS,
followerDb.get(null, key, readValue, LockMode.DEFAULT));
- Assertions.assertEquals(new String(value.getData()), new
String(readValue.getData()));
- followerDb.close();
- }
+ for (Pair<BDBEnvironment, NodeInfo> entryPair : followersInfo) {
+ if (entryPair.second.dir.equals(masterPair.second.dir)) {
+ LOG.info("skip {}", entryPair.second.name);
+ return;
+ }
- masterDb.close();
- masterEnvironment.getEpochDB().close();
+ Assertions.assertEquals(1,
entryPair.first.getDatabaseNames().size());
+ Database followerDb =
entryPair.first.openDatabase(beginDbName);
+ DatabaseEntry readValue = new DatabaseEntry();
+ Assertions.assertEquals(OperationStatus.SUCCESS,
followerDb.get(null, key, readValue, LockMode.DEFAULT));
+ Assertions.assertEquals(new String(value.getData()), new
String(readValue.getData()));
+ followerDb.close();
+ }
- followersInfo.stream().forEach(entryPair -> {
- entryPair.first.close();
- LOG.info("close {} | {}", entryPair.second.name,
entryPair.second.dir);
- });
+ masterDb.close();
+ masterEnvironment.getEpochDB().close();
- // all follower closed
- for (Pair<BDBEnvironment, NodeInfo> entryPair : followersInfo) {
- String followerCopyDir = entryPair.second.dir + "_copy";
- LOG.info("Copy from {} to {}", entryPair.second.dir,
followerCopyDir);
- FileUtils.copyDirectory(new File(entryPair.second.dir), new
File(followerCopyDir));
- }
+ followersInfo.stream().forEach(entryPair -> {
+ entryPair.first.close();
+ LOG.info("close {} | {}", entryPair.second.name,
entryPair.second.dir);
+ });
- followersInfo.stream().forEach(entryPair -> {
- entryPair.first.openReplicatedEnvironment(new
File(entryPair.second.dir));
- LOG.info("open {} | {}", entryPair.second.name,
entryPair.second.dir);
- });
+ // all follower closed
+ for (Pair<BDBEnvironment, NodeInfo> entryPair : followersInfo) {
+ String followerCopyDir = entryPair.second.dir + "_copy";
+ LOG.info("Copy from {} to {}", entryPair.second.dir,
followerCopyDir);
+ FileUtils.copyDirectory(new File(entryPair.second.dir), new
File(followerCopyDir));
+ }
- masterPair = findMaster(followersInfo);
+ followersInfo.stream().forEach(entryPair -> {
+ entryPair.first.openReplicatedEnvironment(new
File(entryPair.second.dir));
+ LOG.info("open {} | {}", entryPair.second.name,
entryPair.second.dir);
+ });
- masterDb = masterPair.first.openDatabase(String.valueOf(1L));
- for (int i = 0; i < 2 * Config.txn_rollback_limit + 10; i++) {
- // for (int i = 0; i < 10; i++) {
- OperationStatus status = masterDb.put(null, new
DatabaseEntry(randomBytes()), new DatabaseEntry(randomBytes()));
- Assertions.assertEquals(OperationStatus.SUCCESS, status);
- }
- Assertions.assertEquals(2, masterPair.first.getDatabaseNames().size());
- Assertions.assertEquals(0, masterPair.first.getDatabaseNames().get(0));
- Assertions.assertEquals(1, masterPair.first.getDatabaseNames().get(1));
+ masterPair = findMaster(followersInfo);
- followersInfo.stream().forEach(entryPair -> {
- entryPair.first.close();
- LOG.info("close {} | {}", entryPair.second.name,
entryPair.second.dir);
- });
-
- // Restore follower's (not new master) bdbje dir
- for (Pair<BDBEnvironment, NodeInfo> entryPair : followersInfo) {
- if (entryPair.second.dir.equals(masterDir)) {
- String masterCopyDir = entryPair.second.dir + "_copy";
- FileUtils.deleteDirectory(new File(masterCopyDir));
- continue;
+ masterDb = masterPair.first.openDatabase(String.valueOf(1L));
+ for (int i = 0; i < 2 * Config.txn_rollback_limit + 10; i++) {
+ // for (int i = 0; i < 10; i++) {
+ OperationStatus status = masterDb.put(null, new
DatabaseEntry(randomBytes()), new DatabaseEntry(randomBytes()));
+ Assertions.assertEquals(OperationStatus.SUCCESS, status);
}
- LOG.info("Delete followerDir {} ", entryPair.second.dir);
- FileUtils.deleteDirectory(new File(entryPair.second.dir));
- // FileUtils.moveDirectory(new File(entryPair.second.dir), new
File(entryPair.second.dir + "_copy2"));
- String followerCopyDir = entryPair.second.dir + "_copy";
- LOG.info("Move {} to {}", followerCopyDir, entryPair.second.dir);
- FileUtils.moveDirectory(new File(followerCopyDir), new
File(entryPair.second.dir));
- }
+ Assertions.assertEquals(2,
masterPair.first.getDatabaseNames().size());
+ Assertions.assertEquals(0,
masterPair.first.getDatabaseNames().get(0));
+ Assertions.assertEquals(1,
masterPair.first.getDatabaseNames().get(1));
- Thread.sleep(1000);
- for (Pair<BDBEnvironment, NodeInfo> entryPair : followersInfo) {
- if (entryPair.second.dir.equals(masterPair.second.dir)) {
- LOG.info("skip open {} | {}", entryPair.second.name,
entryPair.second.dir);
- continue;
+ followersInfo.stream().forEach(entryPair -> {
+ entryPair.first.close();
+ LOG.info("close {} | {}", entryPair.second.name,
entryPair.second.dir);
+ });
+
+ // Restore follower's (not new master) bdbje dir
+ for (Pair<BDBEnvironment, NodeInfo> entryPair : followersInfo) {
+ if (entryPair.second.dir.equals(masterDir)) {
+ String masterCopyDir = entryPair.second.dir + "_copy";
+ FileUtils.deleteDirectory(new File(masterCopyDir));
+ continue;
+ }
+ LOG.info("Delete followerDir {} ", entryPair.second.dir);
+ FileUtils.deleteDirectory(new File(entryPair.second.dir));
+ // FileUtils.moveDirectory(new File(entryPair.second.dir), new
File(entryPair.second.dir + "_copy2"));
+ String followerCopyDir = entryPair.second.dir + "_copy";
+ LOG.info("Move {} to {}", followerCopyDir,
entryPair.second.dir);
+ FileUtils.moveDirectory(new File(followerCopyDir), new
File(entryPair.second.dir));
}
- entryPair.first.openReplicatedEnvironment(new
File(entryPair.second.dir));
- LOG.info("open {} | {}", entryPair.second.name,
entryPair.second.dir);
- }
- BDBEnvironment newMasterEnvironment = null;
- boolean found = false;
- for (int i = 0; i < 300; i++) {
+ Thread.sleep(1000);
for (Pair<BDBEnvironment, NodeInfo> entryPair : followersInfo) {
if (entryPair.second.dir.equals(masterPair.second.dir)) {
+ LOG.info("skip open {} | {}", entryPair.second.name,
entryPair.second.dir);
continue;
}
+ entryPair.first.openReplicatedEnvironment(new
File(entryPair.second.dir));
+ LOG.info("open {} | {}", entryPair.second.name,
entryPair.second.dir);
+ }
- LOG.info("name:{} state:{} dir:{}",
entryPair.first.getReplicatedEnvironment().getNodeName(),
- entryPair.first.getReplicatedEnvironment().getState(),
- entryPair.second.dir);
- if
(entryPair.first.getReplicatedEnvironment().getState().equals(ReplicatedEnvironment.State.MASTER))
{
- newMasterEnvironment = entryPair.first;
- found = true;
+ BDBEnvironment newMasterEnvironment = null;
+ boolean found = false;
+ for (int i = 0; i < 300; i++) {
+ for (Pair<BDBEnvironment, NodeInfo> entryPair : followersInfo)
{
+ if (entryPair.second.dir.equals(masterPair.second.dir)) {
+ continue;
+ }
+
+ LOG.info("name:{} state:{} dir:{}",
entryPair.first.getReplicatedEnvironment().getNodeName(),
+
entryPair.first.getReplicatedEnvironment().getState(),
+ entryPair.second.dir);
+ if
(entryPair.first.getReplicatedEnvironment().getState().equals(ReplicatedEnvironment.State.MASTER))
{
+ newMasterEnvironment = entryPair.first;
+ found = true;
+ break;
+ }
+ }
+ if (found) {
break;
}
+ Thread.sleep(1000);
}
- if (found) {
- break;
- }
- Thread.sleep(1000);
+ Assertions.assertNotNull(newMasterEnvironment);
+
+ masterDb = newMasterEnvironment.openDatabase(beginDbName);
+ Assertions.assertEquals(OperationStatus.SUCCESS,
masterDb.put(null, new DatabaseEntry(randomBytes()), new
DatabaseEntry(randomBytes())));
+ Assertions.assertEquals(1,
newMasterEnvironment.getDatabaseNames().size());
+ // // old master
+ masterEnvironment.openReplicatedEnvironment(new File(masterDir));
+ } finally {
+ followersInfo.stream().forEach(entryPair -> {
+ entryPair.first.close();
+ LOG.info("close {} | {}", entryPair.second.name,
entryPair.second.dir);
+ });
}
- Assertions.assertNotNull(newMasterEnvironment);
-
- masterDb = newMasterEnvironment.openDatabase(beginDbName);
- Assertions.assertEquals(OperationStatus.SUCCESS, masterDb.put(null,
new DatabaseEntry(randomBytes()), new DatabaseEntry(randomBytes())));
- Assertions.assertEquals(1,
newMasterEnvironment.getDatabaseNames().size());
- // // old master
- masterEnvironment.openReplicatedEnvironment(new File(masterDir));
- followersInfo.stream().forEach(entryPair -> {
- entryPair.first.close();
- LOG.info("close {} | {}", entryPair.second.name,
entryPair.second.dir);
- });
LOG.info("end");
}
@@ -670,73 +673,80 @@ public class BDBEnvironmentTest {
followersInfo.add(Pair.of(followerEnvironment, new
NodeInfo(nodeName, nodeHostPort, nodeDir)));
}
- Pair<BDBEnvironment, NodeInfo> masterPair = findMaster(followersInfo);
- String beginDbName = String.valueOf(0L);
- Database masterDb = masterPair.first.openDatabase(beginDbName);
- DatabaseEntry key = new DatabaseEntry(randomBytes());
- DatabaseEntry value = new DatabaseEntry(randomBytes());
- Assertions.assertEquals(OperationStatus.SUCCESS, masterDb.put(null,
key, value));
- Assertions.assertEquals(1,
masterEnvironment.getDatabaseNames().size());
- LOG.info("master is {} | {}", masterPair.second.name,
masterPair.second.dir);
+ try {
+ Pair<BDBEnvironment, NodeInfo> masterPair =
findMaster(followersInfo);
+ String beginDbName = String.valueOf(0L);
+ Database masterDb = masterPair.first.openDatabase(beginDbName);
+ DatabaseEntry key = new DatabaseEntry(randomBytes());
+ DatabaseEntry value = new DatabaseEntry(randomBytes());
+ Assertions.assertEquals(OperationStatus.SUCCESS,
masterDb.put(null, key, value));
+ Assertions.assertEquals(1,
masterEnvironment.getDatabaseNames().size());
+ LOG.info("master is {} | {}", masterPair.second.name,
masterPair.second.dir);
- for (Pair<BDBEnvironment, NodeInfo> entryPair : followersInfo) {
- if (entryPair.second.dir.equals(masterPair.second.dir)) {
- LOG.info("skip {}", entryPair.second.name);
- continue;
- }
-
- Assertions.assertEquals(1,
entryPair.first.getDatabaseNames().size());
- Database followerDb = entryPair.first.openDatabase(beginDbName);
- DatabaseEntry readValue = new DatabaseEntry();
- Assertions.assertEquals(OperationStatus.SUCCESS,
followerDb.get(null, key, readValue, LockMode.DEFAULT));
- Assertions.assertEquals(new String(value.getData()), new
String(readValue.getData()));
- }
+ for (Pair<BDBEnvironment, NodeInfo> entryPair : followersInfo) {
+ if (entryPair.second.dir.equals(masterPair.second.dir)) {
+ LOG.info("skip {}", entryPair.second.name);
+ continue;
+ }
- Field envImplField =
ReplicatedEnvironment.class.getDeclaredField("repEnvironmentImpl");
- envImplField.setAccessible(true);
- RepImpl impl = (RepImpl)
envImplField.get(masterPair.first.getReplicatedEnvironment());
- Assertions.assertNotNull(impl);
-
- new Expectations(impl) {{
- // Below method will replicate log item to followers.
- impl.registerVLSN(withNotNull());
- // Below method will wait until the logs are replicated.
- impl.postLogCommitHook(withNotNull(), withNotNull());
- result = new InsufficientAcksException("mocked");
- }};
-
- long count = masterDb.count();
- final Database oldMasterDb = masterDb;
- Assertions.assertThrows(InsufficientAcksException.class, () -> {
- // Since this key is not replicated to any replicas, it should not
be read.
- DatabaseEntry k = new DatabaseEntry(new byte[]{1, 2, 3});
- DatabaseEntry v = new DatabaseEntry(new byte[]{4, 5, 6});
- oldMasterDb.put(null, k, v);
- });
+ Assertions.assertEquals(1,
entryPair.first.getDatabaseNames().size());
+ Database followerDb =
entryPair.first.openDatabase(beginDbName);
+ DatabaseEntry readValue = new DatabaseEntry();
+ Assertions.assertEquals(OperationStatus.SUCCESS,
followerDb.get(null, key, readValue, LockMode.DEFAULT));
+ Assertions.assertEquals(new String(value.getData()), new
String(readValue.getData()));
+ }
- LOG.info("close old master {} | {}", masterPair.second.name,
masterPair.second.dir);
- masterDb.close();
- masterEnvironment.getEpochDB().close();
- masterEnvironment.close();
+ Field envImplField =
ReplicatedEnvironment.class.getDeclaredField("repEnvironmentImpl");
+ envImplField.setAccessible(true);
+ RepImpl impl = (RepImpl)
envImplField.get(masterPair.first.getReplicatedEnvironment());
+ Assertions.assertNotNull(impl);
+
+ new Expectations(impl) {{
+ // Below method will replicate log item to followers.
+ impl.registerVLSN(withNotNull());
+ // Below method will wait until the logs are replicated.
+ impl.postLogCommitHook(withNotNull(), withNotNull());
+ result = new InsufficientAcksException("mocked");
+ }};
+
+ long count = masterDb.count();
+ final Database oldMasterDb = masterDb;
+ Assertions.assertThrows(InsufficientAcksException.class, () -> {
+ // Since this key is not replicated to any replicas, it should
not be read.
+ DatabaseEntry k = new DatabaseEntry(new byte[]{1, 2, 3});
+ DatabaseEntry v = new DatabaseEntry(new byte[]{4, 5, 6});
+ oldMasterDb.put(null, k, v);
+ });
+
+ LOG.info("close old master {} | {}", masterPair.second.name,
masterPair.second.dir);
+ masterDb.close();
+ masterEnvironment.getEpochDB().close();
+ masterEnvironment.close();
- for (Pair<BDBEnvironment, NodeInfo> entryPair : followersInfo) {
- if (entryPair.second.dir.equals(masterPair.second.dir)) {
- LOG.info("skip {}", entryPair.second.name);
- continue;
+ for (Pair<BDBEnvironment, NodeInfo> entryPair : followersInfo) {
+ if (entryPair.second.dir.equals(masterPair.second.dir)) {
+ LOG.info("skip {}", entryPair.second.name);
+ continue;
+ }
+ LOG.info("close follower {} | {}", entryPair.second.name,
entryPair.second.dir);
+ entryPair.first.close();
}
- LOG.info("close follower {} | {}", entryPair.second.name,
entryPair.second.dir);
- entryPair.first.close();
- }
- masterPair.first.openReplicatedEnvironment(new
File(masterPair.second.dir));
- masterDb = masterPair.first.openDatabase(beginDbName);
- LOG.info("open {} | {}", masterPair.second.name,
masterPair.second.dir);
+ masterPair.first.openReplicatedEnvironment(new
File(masterPair.second.dir));
+ masterDb = masterPair.first.openDatabase(beginDbName);
+ LOG.info("open {} | {}", masterPair.second.name,
masterPair.second.dir);
- // The local commit txn is readable!!!
- Assertions.assertEquals(count + 1, masterDb.count());
+ // The local commit txn is readable!!!
+ Assertions.assertEquals(count + 1, masterDb.count());
- key = new DatabaseEntry(new byte[]{1, 2, 3});
- DatabaseEntry readValue = new DatabaseEntry();
- Assertions.assertEquals(OperationStatus.SUCCESS, masterDb.get(null,
key, readValue, LockMode.DEFAULT));
+ key = new DatabaseEntry(new byte[]{1, 2, 3});
+ DatabaseEntry readValue = new DatabaseEntry();
+ Assertions.assertEquals(OperationStatus.SUCCESS,
masterDb.get(null, key, readValue, LockMode.DEFAULT));
+ } finally {
+ followersInfo.stream().forEach(entryPair -> {
+ entryPair.first.close();
+ LOG.info("close {} | {}", entryPair.second.name,
entryPair.second.dir);
+ });
+ }
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]