From 7243c66412f9bc84f84d83d84487ad44e40bd223 Mon Sep 17 00:00:00 2001
From: Valery Kharseko <vharseko@3a-systems.ru>
Date: Wed, 16 Sep 2026 18:18:52 +0000
Subject: [PATCH] [#995] Classify the failure of a task on the message that reports it (#996)
---
opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/InstallerHelper.java | 95 ++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 93 insertions(+), 2 deletions(-)
diff --git a/opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/InstallerHelper.java b/opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/InstallerHelper.java
index 919ff3d..3c5e499 100644
--- a/opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/InstallerHelper.java
+++ b/opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/InstallerHelper.java
@@ -20,8 +20,10 @@
import static com.forgerock.opendj.cli.Utils.*;
import static com.forgerock.opendj.util.OperatingSystem.*;
+import static org.opends.admin.ads.util.ConnectionUtils.allValuesAsStrings;
import static org.opends.messages.QuickSetupMessages.*;
import static org.opends.quicksetup.Installation.*;
+import static org.opends.server.config.ConfigConstants.ATTR_TASK_LOG_MESSAGES;
import static org.opends.server.types.ExistingFileBehavior.*;
import static org.opends.server.types.HostPort.*;
@@ -36,6 +38,7 @@
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
@@ -53,6 +56,7 @@
import org.forgerock.opendj.config.PropertyException;
import org.forgerock.opendj.config.server.ConfigException;
import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.Entry;
import org.forgerock.opendj.server.config.client.BackendCfgClient;
import org.forgerock.opendj.server.config.client.CryptoManagerCfgClient;
import org.forgerock.opendj.server.config.client.LocalBackendCfgClient;
@@ -70,6 +74,7 @@
import org.opends.messages.BackendMessages;
import org.opends.messages.CoreMessages;
import org.opends.messages.ReplicationMessages;
+import org.opends.messages.Severity;
import org.opends.quicksetup.Application;
import org.opends.quicksetup.ApplicationException;
import org.opends.quicksetup.JavaArguments;
@@ -106,6 +111,23 @@
private static final long ONE_MEGABYTE = 1024L * 1024;
/**
+ * The severity field of a message logged by a task with an error severity, as rendered by
+ * {@code org.opends.server.backends.task.Task#addLogMessage}: it follows the timestamp and
+ * precedes the message count, so it cannot be mistaken for the text of the message.
+ */
+ private static final String ERROR_SEVERITY_FIELD =
+ "] severity=\"" + Severity.ERROR.name() + "\" msgCount=";
+ /**
+ * The message id field of the peers not found error, as rendered by
+ * {@code org.opends.server.backends.task.Task#addLogMessage}: a message is identified in a task
+ * log by its resource name and its ordinal, not by its ordinal alone, and the field ends where
+ * the message text starts, so the ordinal is matched whole.
+ */
+ private static final String PEERS_NOT_FOUND_MSG_ID_FIELD = "msgID="
+ + ReplicationMessages.ERR_NO_REACHABLE_PEER_IN_THE_DOMAIN.resourceName() + "-"
+ + ReplicationMessages.ERR_NO_REACHABLE_PEER_IN_THE_DOMAIN.ordinal() + " message=\"";
+
+ /**
* Invokes the method ConfigureDS.configMain with the provided parameters.
* @param args the arguments to be passed to ConfigureDS.configMain.
* @return the return code of the ConfigureDS.configMain method.
@@ -675,17 +697,86 @@
}
/**
+ * Returns the messages logged by the task described by the provided entry, in the order the
+ * server logged them.
+ *
+ * @param taskEntry
+ * the entry of the task.
+ * @return the messages logged by the task, an empty list if it logged none.
+ */
+ public static List<String> getTaskLogMessages(Entry taskEntry)
+ {
+ return allValuesAsStrings(taskEntry, ATTR_TASK_LOG_MESSAGES);
+ }
+
+ /**
+ * Returns the message that best describes the outcome of a task among the messages it logged.
+ * <p>
+ * This is the last message logged with the {@link Severity#ERROR} severity when there is one:
+ * a task keeps logging after it failed - the task scheduler itself appends a completion notice
+ * once the task is over - and those trailing messages hide the cause of the failure. It is the
+ * last message logged otherwise.
+ *
+ * @param logMsgs
+ * the messages logged by the task, as returned by {@link #getTaskLogMessages(Entry)}.
+ * @return the most relevant message, {@code null} if the task logged none.
+ */
+ public static String getRelevantLogMessage(List<String> logMsgs)
+ {
+ String lastErrorMsg = null;
+ for (String logMsg : logMsgs)
+ {
+ if (logMsg.contains(ERROR_SEVERITY_FIELD))
+ {
+ lastErrorMsg = logMsg;
+ }
+ }
+ if (lastErrorMsg != null)
+ {
+ return lastErrorMsg;
+ }
+ return !logMsgs.isEmpty() ? logMsgs.get(logMsgs.size() - 1) : null;
+ }
+
+ /**
* Tells whether the provided log message corresponds to a peers not found
* error during the initialization of a replica or not.
+ * <p>
+ * The message is recognized by the id a task logs it with, which is made of the name of the
+ * resource the message belongs to and of its ordinal within that resource.
*
* @param logMsg
- * the log message.
+ * the log message, may be {@code null}.
* @return {@code true} if the log message corresponds to a peers not
* found error during initialization, {@code false} otherwise.
*/
public boolean isPeersNotFoundError(String logMsg)
{
- return logMsg.contains("=" + ReplicationMessages.ERR_NO_REACHABLE_PEER_IN_THE_DOMAIN.ordinal());
+ return logMsg != null && logMsg.contains(PEERS_NOT_FOUND_MSG_ID_FIELD);
+ }
+
+ /**
+ * Tells whether one of the provided log messages corresponds to a peers not found error during
+ * the initialization of a replica or not.
+ * <p>
+ * All the messages must be tested: the message reporting the failure is neither the first one
+ * logged by the task nor, since the task scheduler appends a completion notice, the last one.
+ *
+ * @param logMsgs
+ * the log messages of the task, as returned by {@link #getTaskLogMessages(Entry)}.
+ * @return {@code true} if one of the log messages corresponds to a peers not
+ * found error during initialization, {@code false} otherwise.
+ */
+ public boolean isPeersNotFoundError(Collection<String> logMsgs)
+ {
+ for (String logMsg : logMsgs)
+ {
+ if (isPeersNotFoundError(logMsg))
+ {
+ return true;
+ }
+ }
+ return false;
}
/**
--
Gitblit v1.10.0