This is an automated email from the ASF dual-hosted git repository.

w41ter pushed a commit to branch branch-4.0-cherry-pr60738
in repository https://gitbox.apache.org/repos/asf/doris.git

commit 808ef4c83559e51a64e2414f5a35a38565567730
Author: w41ter <[email protected]>
AuthorDate: Mon Feb 9 16:06:59 2026 +0800

    [feat](fe) add recovery_journal_id to truncate bdbje logs
    
    It only works for metadata_failure_recovery mode
---
 bin/start_fe.sh                                    | 12 ++-
 .../src/main/java/org/apache/doris/DorisFE.java    | 12 +++
 .../java/org/apache/doris/common/FeConstants.java  |  1 +
 .../apache/doris/journal/bdbje/BDBEnvironment.java | 72 ++++++++++++++++++
 .../apache/doris/journal/bdbje/BDBJEJournal.java   | 75 +++++++++++++++++++
 .../doris/journal/bdbje/BDBEnvironmentTest.java    | 66 ++++++++++++++++
 .../doris/journal/bdbje/BDBJEJournalTest.java      | 87 ++++++++++++++++++++++
 7 files changed, 322 insertions(+), 3 deletions(-)

diff --git a/bin/start_fe.sh b/bin/start_fe.sh
index cae195aee80..85f97696f9b 100755
--- a/bin/start_fe.sh
+++ b/bin/start_fe.sh
@@ -33,6 +33,7 @@ OPTS="$(getopt \
     -l 'image:' \
     -l 'version' \
     -l 'metadata_failure_recovery' \
+    -l 'recovery_journal_id:' \
     -l 'console' \
     -l 'cluster_snapshot:' \
     -- "$@")"
@@ -46,6 +47,7 @@ IMAGE_PATH=''
 IMAGE_TOOL=''
 OPT_VERSION=''
 METADATA_FAILURE_RECOVERY=''
+RECOVERY_JOURNAL_ID=''
 CLUSTER_SNAPSHOT=''
 while true; do
     case "$1" in
@@ -65,6 +67,10 @@ while true; do
         METADATA_FAILURE_RECOVERY="-r"
         shift
         ;;
+    --recovery_journal_id)
+        RECOVERY_JOURNAL_ID="--recovery_journal_id $2"
+        shift 2
+        ;;
     --helper)
         HELPER="$2"
         shift 2
@@ -418,12 +424,12 @@ if [[ "${IMAGE_TOOL}" -eq 1 ]]; then
         echo "Internal error, USE IMAGE_TOOL like: ./start_fe.sh --image 
image_path"
     fi
 elif [[ "${RUN_DAEMON}" -eq 1 ]]; then
-    nohup ${LIMIT:+${LIMIT}} "${JAVA}" ${final_java_opt:+${final_java_opt}} 
-XX:-OmitStackTraceInFastThrow -XX:OnOutOfMemoryError="kill -9 %p" 
${coverage_opt:+${coverage_opt}} org.apache.doris.DorisFE ${HELPER:+${HELPER}} 
"${METADATA_FAILURE_RECOVERY}" "${CLUSTER_SNAPSHOT}" "$@" >>"${STDOUT_LOGGER}" 
2>&1 </dev/null &
+    nohup ${LIMIT:+${LIMIT}} "${JAVA}" ${final_java_opt:+${final_java_opt}} 
-XX:-OmitStackTraceInFastThrow -XX:OnOutOfMemoryError="kill -9 %p" 
${coverage_opt:+${coverage_opt}} org.apache.doris.DorisFE ${HELPER:+${HELPER}} 
"${METADATA_FAILURE_RECOVERY}" "${RECOVERY_JOURNAL_ID:+${RECOVERY_JOURNAL_ID}}" 
"${CLUSTER_SNAPSHOT}" "$@" >>"${STDOUT_LOGGER}" 2>&1 </dev/null &
 elif [[ "${RUN_CONSOLE}" -eq 1 ]]; then
     export DORIS_LOG_TO_STDERR=1
-    ${LIMIT:+${LIMIT}} "${JAVA}" ${final_java_opt:+${final_java_opt}} 
-XX:-OmitStackTraceInFastThrow -XX:OnOutOfMemoryError="kill -9 %p" 
${coverage_opt:+${coverage_opt}} org.apache.doris.DorisFE ${HELPER:+${HELPER}} 
${OPT_VERSION:+${OPT_VERSION}} "${METADATA_FAILURE_RECOVERY}" 
"${CLUSTER_SNAPSHOT}" "$@" </dev/null
+    ${LIMIT:+${LIMIT}} "${JAVA}" ${final_java_opt:+${final_java_opt}} 
-XX:-OmitStackTraceInFastThrow -XX:OnOutOfMemoryError="kill -9 %p" 
${coverage_opt:+${coverage_opt}} org.apache.doris.DorisFE ${HELPER:+${HELPER}} 
${OPT_VERSION:+${OPT_VERSION}} "${METADATA_FAILURE_RECOVERY}" 
"${RECOVERY_JOURNAL_ID:+${RECOVERY_JOURNAL_ID}}" "${CLUSTER_SNAPSHOT}" "$@" 
</dev/null
 else
-    ${LIMIT:+${LIMIT}} "${JAVA}" ${final_java_opt:+${final_java_opt}} 
-XX:-OmitStackTraceInFastThrow -XX:OnOutOfMemoryError="kill -9 %p" 
${coverage_opt:+${coverage_opt}} org.apache.doris.DorisFE ${HELPER:+${HELPER}} 
${OPT_VERSION:+${OPT_VERSION}} "${METADATA_FAILURE_RECOVERY}" 
"${CLUSTER_SNAPSHOT}" "$@" >>"${STDOUT_LOGGER}" 2>&1 </dev/null
+    ${LIMIT:+${LIMIT}} "${JAVA}" ${final_java_opt:+${final_java_opt}} 
-XX:-OmitStackTraceInFastThrow -XX:OnOutOfMemoryError="kill -9 %p" 
${coverage_opt:+${coverage_opt}} org.apache.doris.DorisFE ${HELPER:+${HELPER}} 
${OPT_VERSION:+${OPT_VERSION}} "${METADATA_FAILURE_RECOVERY}" 
"${RECOVERY_JOURNAL_ID:+${RECOVERY_JOURNAL_ID}}" "${CLUSTER_SNAPSHOT}" "$@" 
>>"${STDOUT_LOGGER}" 2>&1 </dev/null
 fi
 
 if [[ "${OPT_VERSION}" != "" ]]; then
diff --git a/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java 
b/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java
index 14299a60de5..26f9389741c 100755
--- a/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java
@@ -51,6 +51,7 @@ import io.netty.util.internal.logging.Log4JLoggerFactory;
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.CommandLineParser;
 import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.Option;
 import org.apache.commons.cli.Options;
 import org.apache.commons.cli.ParseException;
 import org.apache.logging.log4j.LogManager;
@@ -345,6 +346,9 @@ public class DorisFE {
         options.addOption("m", "metaversion", true, "Specify the meta version 
to decode log value");
         options.addOption("r", FeConstants.METADATA_FAILURE_RECOVERY_KEY, 
false,
                 "Check if the specified metadata recover is valid");
+        
options.addOption(Option.builder().longOpt(FeConstants.RECOVERY_JOURNAL_ID_KEY).hasArg()
+                .desc("Specify the recovery truncate journal id, and journals 
greater than this id will be removed")
+                .build());
         options.addOption("c", "cluster_snapshot", true, "Specify the cluster 
snapshot json file");
 
         CommandLine cmd = null;
@@ -382,6 +386,14 @@ public class DorisFE {
         if (cmd.hasOption('r') || 
cmd.hasOption(FeConstants.METADATA_FAILURE_RECOVERY_KEY)) {
             System.setProperty(FeConstants.METADATA_FAILURE_RECOVERY_KEY, 
"true");
         }
+        if (cmd.hasOption(FeConstants.RECOVERY_JOURNAL_ID_KEY)) {
+            String recoveryJournalId = 
cmd.getOptionValue(FeConstants.RECOVERY_JOURNAL_ID_KEY);
+            if (Strings.isNullOrEmpty(recoveryJournalId)) {
+                System.err.println("recovery_journal_id is missing");
+                System.exit(-1);
+            }
+            System.setProperty(FeConstants.RECOVERY_JOURNAL_ID_KEY, 
recoveryJournalId.trim());
+        }
         if (cmd.hasOption('b') || cmd.hasOption("bdb")) {
             if (cmd.hasOption('l') || cmd.hasOption("listdb")) {
                 // list bdb je databases
diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/FeConstants.java 
b/fe/fe-core/src/main/java/org/apache/doris/common/FeConstants.java
index 491a8e036af..dc2e2aafbdc 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/FeConstants.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/FeConstants.java
@@ -67,4 +67,5 @@ public class FeConstants {
     public static final String INTERNAL_FILE_CACHE_HOTSPOT_TABLE_NAME = 
"cloud_cache_hotspot";
 
     public static String METADATA_FAILURE_RECOVERY_KEY = 
"metadata_failure_recovery";
+    public static String RECOVERY_JOURNAL_ID_KEY = "recovery_journal_id";
 }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBEnvironment.java 
b/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBEnvironment.java
index 1dc965a603e..e94889ecbf0 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBEnvironment.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBEnvironment.java
@@ -26,8 +26,11 @@ import org.apache.doris.ha.HAProtocol;
 import org.apache.doris.system.Frontend;
 
 import com.google.common.collect.ImmutableList;
+import com.sleepycat.bind.tuple.TupleBinding;
+import com.sleepycat.je.Cursor;
 import com.sleepycat.je.Database;
 import com.sleepycat.je.DatabaseConfig;
+import com.sleepycat.je.DatabaseEntry;
 import com.sleepycat.je.DatabaseException;
 import com.sleepycat.je.DatabaseNotFoundException;
 import com.sleepycat.je.Durability;
@@ -35,6 +38,8 @@ import com.sleepycat.je.Durability.ReplicaAckPolicy;
 import com.sleepycat.je.Durability.SyncPolicy;
 import com.sleepycat.je.EnvironmentConfig;
 import com.sleepycat.je.EnvironmentFailureException;
+import com.sleepycat.je.LockMode;
+import com.sleepycat.je.OperationStatus;
 import com.sleepycat.je.rep.InsufficientLogException;
 import com.sleepycat.je.rep.NetworkRestore;
 import com.sleepycat.je.rep.NetworkRestoreConfig;
@@ -335,6 +340,73 @@ public class BDBEnvironment {
         }
     }
 
+    // Remove journals whose id is greater than truncateToJournalId.
+    public void truncateJournalsGreaterThan(long truncateToJournalId) {
+        lock.writeLock().lock();
+        try {
+            List<Long> dbNames = getDatabaseNames();
+            if (dbNames == null || dbNames.isEmpty()) {
+                return;
+            }
+
+            Long minJournalId = dbNames.get(0);
+            Long targetDbName = null;
+            for (Long dbName : dbNames) {
+                if (dbName <= truncateToJournalId) {
+                    targetDbName = dbName;
+                } else {
+                    break;
+                }
+            }
+
+            if (targetDbName == null) {
+                throw new IllegalArgumentException("truncate journal id " + 
truncateToJournalId
+                        + " is smaller than min journal id " + minJournalId);
+            }
+
+            for (Long dbName : dbNames) {
+                if (dbName > truncateToJournalId) {
+                    removeDatabase(dbName.toString());
+                }
+            }
+
+            long deletedCount = truncateTailInDb(targetDbName.toString(), 
truncateToJournalId);
+            LOG.info("truncate journals greater than {} finished, targetDb {}, 
deleted {} keys in target db",
+                    truncateToJournalId, targetDbName, deletedCount);
+        } finally {
+            lock.writeLock().unlock();
+        }
+    }
+
+    private long truncateTailInDb(String dbName, long truncateToJournalId) {
+        Database db = openDatabase(dbName);
+        if (db == null) {
+            throw new IllegalStateException("failed to open target database " 
+ dbName + " for truncate");
+        }
+
+        long deletedCount = 0;
+        TupleBinding<Long> idBinding = 
TupleBinding.getPrimitiveBinding(Long.class);
+        Cursor cursor = null;
+        try {
+            cursor = db.openCursor(null, null);
+            DatabaseEntry key = new DatabaseEntry();
+            DatabaseEntry value = new DatabaseEntry();
+            while (cursor.getNext(key, value, LockMode.READ_COMMITTED) == 
OperationStatus.SUCCESS) {
+                long journalId = idBinding.entryToObject(key);
+                if (journalId > truncateToJournalId) {
+                    cursor.delete();
+                    deletedCount++;
+                }
+            }
+        } finally {
+            if (cursor != null) {
+                cursor.close();
+            }
+        }
+
+        return deletedCount;
+    }
+
     // get journal db names and sort the names
     public List<Long> getDatabaseNames() {
         // The operation before may set the current thread as interrupted.
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBJEJournal.java 
b/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBJEJournal.java
index 46c4c5f5517..f4234cc462a 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBJEJournal.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/journal/bdbje/BDBJEJournal.java
@@ -74,6 +74,7 @@ public class BDBJEJournal implements Journal { // CHECKSTYLE 
IGNORE THIS LINE: B
     public static final Logger LOG = LogManager.getLogger(BDBJEJournal.class);
     private static final int OUTPUT_BUFFER_INIT_SIZE = 128;
     private static final int RETRY_TIME = 3;
+    private static final long RECOVERY_JOURNAL_ID_UNSET = -1L;
 
     private String environmentPath = null;
     private String selfNodeName;
@@ -519,6 +520,8 @@ public class BDBJEJournal implements Journal { // 
CHECKSTYLE IGNORE THIS LINE: B
                 LOG.error("catch an exception when setup bdb environment. will 
exit.", e);
                 System.exit(-1);
             }
+
+            truncateRecoveryJournalsIfNeeded(metadataFailureRecovery);
         }
 
         // Open a new journal database or get last existing one as current 
journal
@@ -593,6 +596,78 @@ public class BDBJEJournal implements Journal { // 
CHECKSTYLE IGNORE THIS LINE: B
                 NetUtils.getHostPortInAccessibleFormat(helperNode.getHost(), 
helperNode.getPort()));
     }
 
+    private void truncateRecoveryJournalsIfNeeded(boolean 
metadataFailureRecovery) {
+        if (!metadataFailureRecovery) {
+            return;
+        }
+
+        long recoveryJournalId = getRecoveryJournalIdOrUnset();
+        if (recoveryJournalId == RECOVERY_JOURNAL_ID_UNSET) {
+            return;
+        }
+
+        long maxJournalId = getMaxJournalIdWithoutCheck();
+        if (maxJournalId < 0) {
+            String msg = String.format("invalid metadata recovery truncate 
target %d, no journals in bdb",
+                    recoveryJournalId);
+            LOG.error(msg);
+            LogUtils.stderr(msg);
+            System.exit(-1);
+        }
+
+        if (recoveryJournalId >= maxJournalId) {
+            String msg = String.format("metadata recovery truncate target %d 
>= max journal id %d, no-op",
+                    recoveryJournalId, maxJournalId);
+            LOG.info(msg);
+            LogUtils.stdout(msg);
+            return;
+        }
+
+        long minJournalId = getMinJournalId();
+        if (minJournalId < 0 || recoveryJournalId < minJournalId) {
+            String msg = String.format("invalid metadata recovery truncate 
target %d, min journal id is %d",
+                    recoveryJournalId, minJournalId);
+            LOG.error(msg);
+            LogUtils.stderr(msg);
+            System.exit(-1);
+        }
+
+        try {
+            bdbEnvironment.truncateJournalsGreaterThan(recoveryJournalId);
+        } catch (Exception e) {
+            String msg = String.format("failed to truncate journals greater 
than %d in metadata recovery mode",
+                    recoveryJournalId);
+            LOG.error(msg, e);
+            LogUtils.stderr(msg + ", reason: " + e.getMessage());
+            System.exit(-1);
+        }
+        String msg = String.format("metadata recovery truncate finished, kept 
journals <= %d", recoveryJournalId);
+        LOG.info(msg);
+        LogUtils.stdout(msg);
+    }
+
+    private long getRecoveryJournalIdOrUnset() {
+        String journalIdStr = 
System.getProperty(FeConstants.RECOVERY_JOURNAL_ID_KEY);
+        if (journalIdStr == null || journalIdStr.trim().isEmpty()) {
+            return RECOVERY_JOURNAL_ID_UNSET;
+        }
+
+        String trimmedJournalId = journalIdStr.trim();
+        try {
+            long journalId = Long.parseLong(trimmedJournalId);
+            if (journalId < 0) {
+                throw new NumberFormatException("recovery_journal_id must not 
be negative");
+            }
+            return journalId;
+        } catch (NumberFormatException e) {
+            String msg = String.format("invalid recovery_journal_id: %s", 
trimmedJournalId);
+            LOG.error(msg, e);
+            LogUtils.stderr(msg);
+            System.exit(-1);
+        }
+        return RECOVERY_JOURNAL_ID_UNSET;
+    }
+
     @Override
     public long getJournalNum() {
         return currentJournalDB.count();
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 68f01981a9a..d3836e145a2 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
@@ -26,6 +26,7 @@ import org.apache.doris.system.Frontend;
 
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
+import com.sleepycat.bind.tuple.TupleBinding;
 import com.sleepycat.je.Database;
 import com.sleepycat.je.DatabaseEntry;
 import com.sleepycat.je.Durability;
@@ -124,6 +125,13 @@ public class BDBEnvironmentTest {
         return byteArray;
     }
 
+    private static DatabaseEntry longToEntry(long value) {
+        DatabaseEntry key = new DatabaseEntry();
+        TupleBinding<Long> idBinding = 
TupleBinding.getPrimitiveBinding(Long.class);
+        idBinding.objectToEntry(value, key);
+        return key;
+    }
+
     // @Test
     @RepeatedTest(1)
     public void testSetup() throws Exception {
@@ -283,6 +291,64 @@ public class BDBEnvironmentTest {
         bdbEnvironment.close();
     }
 
+    @RepeatedTest(1)
+    public void testTruncateJournalsGreaterThan() throws Exception {
+        int port = findValidPort();
+        String selfNodeName = Env.genFeNodeName("127.0.0.1", port, false);
+        String selfNodeHostPort = "127.0.0.1:" + port;
+
+        File homeFile = new File(createTmpDir());
+        BDBEnvironment bdbEnvironment = new BDBEnvironment(true, false);
+        bdbEnvironment.setup(homeFile, selfNodeName, selfNodeHostPort, 
selfNodeHostPort);
+
+        Database db1 = bdbEnvironment.openDatabase("1");
+        Database db11 = bdbEnvironment.openDatabase("11");
+        Database db21 = bdbEnvironment.openDatabase("21");
+        for (long i = 1; i <= 10; i++) {
+            Assertions.assertEquals(OperationStatus.SUCCESS, db1.put(null, 
longToEntry(i), new DatabaseEntry(randomBytes())));
+        }
+        for (long i = 11; i <= 20; i++) {
+            Assertions.assertEquals(OperationStatus.SUCCESS, db11.put(null, 
longToEntry(i), new DatabaseEntry(randomBytes())));
+        }
+        for (long i = 21; i <= 30; i++) {
+            Assertions.assertEquals(OperationStatus.SUCCESS, db21.put(null, 
longToEntry(i), new DatabaseEntry(randomBytes())));
+        }
+
+        bdbEnvironment.truncateJournalsGreaterThan(17);
+
+        List<Long> dbNames = bdbEnvironment.getDatabaseNames();
+        Assertions.assertEquals(2, dbNames.size());
+        Assertions.assertEquals(1L, dbNames.get(0));
+        Assertions.assertEquals(11L, dbNames.get(1));
+
+        Database db11AfterTruncate = bdbEnvironment.openDatabase("11");
+        Assertions.assertEquals(7, db11AfterTruncate.count());
+        Assertions.assertEquals(OperationStatus.NOTFOUND,
+                db11AfterTruncate.get(null, longToEntry(18), new 
DatabaseEntry(), LockMode.READ_COMMITTED));
+        Assertions.assertEquals(OperationStatus.SUCCESS,
+                db11AfterTruncate.get(null, longToEntry(17), new 
DatabaseEntry(), LockMode.READ_COMMITTED));
+        bdbEnvironment.close();
+    }
+
+    @RepeatedTest(1)
+    public void testTruncateJournalsGreaterThanInvalidBound() throws Exception 
{
+        int port = findValidPort();
+        String selfNodeName = Env.genFeNodeName("127.0.0.1", port, false);
+        String selfNodeHostPort = "127.0.0.1:" + port;
+
+        File homeFile = new File(createTmpDir());
+        BDBEnvironment bdbEnvironment = new BDBEnvironment(true, false);
+        bdbEnvironment.setup(homeFile, selfNodeName, selfNodeHostPort, 
selfNodeHostPort);
+
+        Database db1 = bdbEnvironment.openDatabase("1");
+        Assertions.assertEquals(OperationStatus.SUCCESS, db1.put(null, 
longToEntry(1), new DatabaseEntry(randomBytes())));
+
+        IllegalArgumentException exception = 
Assertions.assertThrows(IllegalArgumentException.class,
+                () -> bdbEnvironment.truncateJournalsGreaterThan(0));
+        Assertions.assertTrue(exception.getMessage().contains("smaller than 
min journal id"));
+        bdbEnvironment.close();
+    }
+
     /**
      * Test build a BDBEnvironment cluster (1 master + 2 follower + 1 observer)
      * @throws Exception
diff --git 
a/fe/fe-core/src/test/java/org/apache/doris/journal/bdbje/BDBJEJournalTest.java 
b/fe/fe-core/src/test/java/org/apache/doris/journal/bdbje/BDBJEJournalTest.java
index 3b2c404e8e7..bb263a426df 100644
--- 
a/fe/fe-core/src/test/java/org/apache/doris/journal/bdbje/BDBJEJournalTest.java
+++ 
b/fe/fe-core/src/test/java/org/apache/doris/journal/bdbje/BDBJEJournalTest.java
@@ -18,6 +18,7 @@
 package org.apache.doris.journal.bdbje;
 
 import org.apache.doris.catalog.Env;
+import org.apache.doris.common.FeConstants;
 import org.apache.doris.common.Pair;
 import org.apache.doris.common.io.Text;
 import org.apache.doris.common.io.Writable;
@@ -226,6 +227,92 @@ public class BDBJEJournalTest { // CHECKSTYLE IGNORE THIS 
LINE: BDBJE should use
         journal.close();
     }
 
+    @RepeatedTest(1)
+    public void testRecoveryJournalIdNoEffectWithoutMetadataRecovery() throws 
Exception {
+        int port = findValidPort();
+        Preconditions.checkArgument(((port > 0) && (port < 65535)));
+        String nodeName = Env.genFeNodeName("127.0.0.1", port, false);
+        long replayedJournalId = 0;
+        File tmpDir = createTmpDir();
+        new MockUp<Env>() {
+            HostInfo selfNode = new HostInfo("127.0.0.1", port);
+            @Mock
+            public String getBdbDir() {
+                return tmpDir.getAbsolutePath();
+            }
+
+            @Mock
+            public HostInfo getSelfNode() {
+                return this.selfNode;
+            }
+
+            @Mock
+            public HostInfo getHelperNode() {
+                return this.selfNode;
+            }
+
+            @Mock
+            public boolean isElectable() {
+                return true;
+            }
+
+            @Mock
+            public long getReplayedJournalId() {
+                return replayedJournalId;
+            }
+        };
+
+        String oldRecovery = 
System.getProperty(FeConstants.RECOVERY_JOURNAL_ID_KEY);
+        String oldMetadataRecovery = 
System.getProperty(FeConstants.METADATA_FAILURE_RECOVERY_KEY);
+        BDBJEJournal journal = new BDBJEJournal(nodeName);
+        try {
+            System.clearProperty(FeConstants.METADATA_FAILURE_RECOVERY_KEY);
+            System.setProperty(FeConstants.RECOVERY_JOURNAL_ID_KEY, "5");
+
+            journal.open();
+            for (int i = 0; i < 10; i++) {
+                if 
(journal.getBDBEnvironment().getReplicatedEnvironment().getState()
+                        .equals(ReplicatedEnvironment.State.MASTER)) {
+                    break;
+                }
+                Thread.sleep(1000);
+            }
+            Assertions.assertEquals(ReplicatedEnvironment.State.MASTER,
+                    
journal.getBDBEnvironment().getReplicatedEnvironment().getState());
+            for (int i = 0; i < 10; i++) {
+                journal.write(OperationType.OP_TIMESTAMP, new Timestamp());
+            }
+            Assertions.assertEquals(10, journal.getMaxJournalId());
+            journal.close();
+
+            journal.open();
+            for (int i = 0; i < 10; i++) {
+                if 
(journal.getBDBEnvironment().getReplicatedEnvironment().getState()
+                        .equals(ReplicatedEnvironment.State.MASTER)) {
+                    break;
+                }
+                Thread.sleep(1000);
+            }
+            Assertions.assertEquals(ReplicatedEnvironment.State.MASTER,
+                    
journal.getBDBEnvironment().getReplicatedEnvironment().getState());
+            Assertions.assertEquals(10, journal.getMaxJournalId());
+        } finally {
+            if (journal.getBDBEnvironment() != null) {
+                journal.close();
+            }
+            if (oldRecovery == null) {
+                System.clearProperty(FeConstants.RECOVERY_JOURNAL_ID_KEY);
+            } else {
+                System.setProperty(FeConstants.RECOVERY_JOURNAL_ID_KEY, 
oldRecovery);
+            }
+            if (oldMetadataRecovery == null) {
+                
System.clearProperty(FeConstants.METADATA_FAILURE_RECOVERY_KEY);
+            } else {
+                System.setProperty(FeConstants.METADATA_FAILURE_RECOVERY_KEY, 
oldMetadataRecovery);
+            }
+        }
+    }
+
     @RepeatedTest(1)
     public void testJournalBatch() throws Exception {
         int port = findValidPort();


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to