This is an automated email from the ASF dual-hosted git repository.
ashishkumar50 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new d14bc0f5fc1 HDDS-15637. Container Replica Debugger Tool improvements
and minor bug fixes (#10574)
d14bc0f5fc1 is described below
commit d14bc0f5fc10caad177c144c3648a7c10d7a860f
Author: sreejasahithi <[email protected]>
AuthorDate: Wed Jul 8 10:31:48 2026 +0530
HDDS-15637. Container Replica Debugger Tool improvements and minor bug
fixes (#10574)
---
.../logs/container/ContainerLogController.java | 3 +
.../debug/logs/container/ContainerLogParser.java | 16 +++++-
.../container/DuplicateOpenContainersCommand.java | 9 ++-
.../ozone/debug/logs/container/ListContainers.java | 33 ++++++++---
.../container/utils/ContainerDatanodeDatabase.java | 63 ++++++++++++---------
.../container/utils/ContainerLogFileParser.java | 65 +++++++++++++++-------
.../debug/logs/container/utils/SQLDBConstants.java | 58 +++++++++++--------
7 files changed, 164 insertions(+), 83 deletions(-)
diff --git
a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/ContainerLogController.java
b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/ContainerLogController.java
index 1a6cdafea63..05bc9d59cae 100644
---
a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/ContainerLogController.java
+++
b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/ContainerLogController.java
@@ -75,6 +75,9 @@ public Path resolveDbPath() {
throw new IllegalArgumentException("The parent directory of the
provided database " +
"path does not exist: " + parentDir);
}
+ if (!Files.exists(resolvedPath) || !Files.isRegularFile(resolvedPath)) {
+ throw new IllegalArgumentException("Database file does not exist: " +
resolvedPath);
+ }
}
return resolvedPath;
diff --git
a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/ContainerLogParser.java
b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/ContainerLogParser.java
index cac2518b381..1972e87914f 100644
---
a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/ContainerLogParser.java
+++
b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/ContainerLogParser.java
@@ -90,7 +90,21 @@ public Void call() throws Exception {
cdd.insertLatestContainerLogData();
cdd.createIndexes();
- out().println("Successfully parsed the log files and updated the
respective tables");
+
+ int failures = parser.getParseFailureCount();
+ int successes = parser.getParseSuccessCount();
+ if (successes == 0 && failures == 0) {
+ err().println("No container log files were found to parse (expected
dn-container[...].log.<datanodeId>).");
+ out().println("Database tables were created but are empty.");
+ } else if (failures == 0) {
+ out().println("Successfully parsed the log files and updated the
respective tables");
+ } else if (successes == 0) {
+ err().println(failures + " log file(s) could not be parsed. No log data
was loaded into the database.");
+ out().println("Database tables were created but are empty.");
+ } else {
+ err().println(failures + " log file(s) could not be parsed and were
excluded.");
+ out().println("Database tables were updated from successfully parsed
files.");
+ }
return null;
}
diff --git
a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/DuplicateOpenContainersCommand.java
b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/DuplicateOpenContainersCommand.java
index a0fb8371ecd..8ca07fa3de8 100644
---
a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/DuplicateOpenContainersCommand.java
+++
b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/DuplicateOpenContainersCommand.java
@@ -19,7 +19,9 @@
import java.nio.file.Path;
import java.util.concurrent.Callable;
+import org.apache.hadoop.hdds.cli.AbstractSubcommand;
import
org.apache.hadoop.ozone.debug.logs.container.utils.ContainerDatanodeDatabase;
+import org.apache.hadoop.ozone.shell.ListLimitOptions;
import picocli.CommandLine;
/**
@@ -31,8 +33,11 @@
description = "List all containers which have duplicate open states." +
"Outputs the container ID along with the count of OPEN state entries."
)
-public class DuplicateOpenContainersCommand implements Callable<Void> {
+public class DuplicateOpenContainersCommand extends AbstractSubcommand
implements Callable<Void> {
+ @CommandLine.Mixin
+ private ListLimitOptions listOptions;
+
@CommandLine.ParentCommand
private ContainerLogController parent;
@@ -41,7 +46,7 @@ public Void call() throws Exception {
Path dbPath = parent.resolveDbPath();
ContainerDatanodeDatabase cdd = new
ContainerDatanodeDatabase(dbPath.toString());
- cdd.findDuplicateOpenContainer();
+ cdd.findDuplicateOpenContainer(listOptions.getLimit());
return null;
}
diff --git
a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/ListContainers.java
b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/ListContainers.java
index f4c72c720f1..1292b1bfa3a 100644
---
a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/ListContainers.java
+++
b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/ListContainers.java
@@ -17,16 +17,10 @@
package org.apache.hadoop.ozone.debug.logs.container;
-import static
org.apache.hadoop.hdds.scm.container.ContainerHealthState.OVER_REPLICATED;
-import static
org.apache.hadoop.hdds.scm.container.ContainerHealthState.QUASI_CLOSED_STUCK;
-import static
org.apache.hadoop.hdds.scm.container.ContainerHealthState.UNDER_REPLICATED;
-import static
org.apache.hadoop.hdds.scm.container.ContainerHealthState.UNHEALTHY;
-
import java.nio.file.Path;
import java.util.concurrent.Callable;
import org.apache.hadoop.hdds.cli.AbstractSubcommand;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
-import org.apache.hadoop.hdds.scm.container.ContainerHealthState;
import
org.apache.hadoop.ozone.debug.logs.container.utils.ContainerDatanodeDatabase;
import org.apache.hadoop.ozone.shell.ListLimitOptions;
import picocli.CommandLine;
@@ -53,12 +47,23 @@ public class ListContainers extends AbstractSubcommand
implements Callable<Void>
private static final class ExclusiveOptions {
@CommandLine.Option(names = {"--lifecycle"},
- description = "Life cycle state of the container.")
+ description = "Replicas whose latest state equals the given value are
shown. " +
+ "Prints one row per matching replica.")
private HddsProtos.LifeCycleState lifecycleState;
@CommandLine.Option(names = {"--health"},
- description = "Health state of the container.")
- private ContainerHealthState healthState;
+ description = "Log-derived health filter.%n"
+ + " UNDER_REPLICATED: containers where healthy replica count
(latest state of replica not UNHEALTHY or"
+ + " DELETED) is below the configured replication factor. Count =
total active (non-DELETED) replicas.%n"
+ + " OVER_REPLICATED: containers where active replica count exceeds
configured replication factor and"
+ + " healthy replica count is at least equal to configured
replication factor. Count = total active"
+ + " (non-DELETED) replicas.%n"
+ + " UNHEALTHY: containers where every active replica is UNHEALTHY
(no healthy replicas remain).%n"
+ + " Count = number of UNHEALTHY replicas.%n"
+ + " QUASI_CLOSED_STUCK: approximate log heuristic only (not SCM
quasi-closed stuck): containers"
+ + " with at least three datanodes whose QUASI_CLOSED log entry is
not superseded by CLOSED or"
+ + " DELETED on that datanode.")
+ private LogHealthFilter healthState;
}
@Override
@@ -89,4 +94,14 @@ public Void call() throws Exception {
return null;
}
+
+ /**
+ * Log-derived health filters supported by {@code list --health}.
+ */
+ enum LogHealthFilter {
+ UNDER_REPLICATED,
+ OVER_REPLICATED,
+ UNHEALTHY,
+ QUASI_CLOSED_STUCK
+ }
}
diff --git
a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/utils/ContainerDatanodeDatabase.java
b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/utils/ContainerDatanodeDatabase.java
index 60e764237fb..62ce8771702 100644
---
a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/utils/ContainerDatanodeDatabase.java
+++
b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/utils/ContainerDatanodeDatabase.java
@@ -304,7 +304,7 @@ public void listContainersByState(String state, Integer
limit) throws SQLExcepti
while (rs.next()) {
if (limitProvided && count >= limit) {
- out.println("Note: There might be more containers. Use -all
option to list all entries");
+ out.println("Note: There might be more replica rows. Use --all
option to list all entries");
break;
}
String timestamp = rs.getString("timestamp");
@@ -320,9 +320,9 @@ public void listContainersByState(String state, Integer
limit) throws SQLExcepti
}
if (count == 0) {
- out.printf("No containers found for state: %s%n", state);
+ out.printf("No replicas found with latest state %s%n", state);
} else {
- out.printf("Number of containers listed: %d%n", count);
+ out.printf("Number of replica rows listed: %d%n", count);
}
}
}
@@ -410,6 +410,7 @@ private void analyzeContainerHealth(Long containerID,
Set<String> unhealthyReplicas = new HashSet<>();
Set<String> closedReplicas = new HashSet<>();
Set<String> openReplicas = new HashSet<>();
+ Set<String> closingReplicas = new HashSet<>();
Set<String> quasiclosedReplicas = new HashSet<>();
Set<String> deletedReplicas = new HashSet<>();
Set<Long> bcsids = new HashSet<>();
@@ -444,6 +445,7 @@ private void analyzeContainerHealth(Long containerID,
otherTimestamps.add(stateTimestamp);
break;
case CLOSING:
+ closingReplicas.add(datanodeId);
otherTimestamps.add(stateTimestamp);
break;
case CLOSED:
@@ -474,7 +476,7 @@ private void analyzeContainerHealth(Long containerID,
out.println("Container " + containerID + " has MISMATCHED REPLICATION as
there are multiple" +
" CLOSED containers with varying BCSIDs.");
} else if (closedCount == DEFAULT_REPLICATION_FACTOR && allClosedNewer) {
- out.println("Container " + containerID + " has enough replicas.");
+ out.println("Container " + containerID + " has enough closed replicas.");
} else if (closedCount > DEFAULT_REPLICATION_FACTOR && allClosedNewer) {
out.println("Container " + containerID + " is OVER-REPLICATED.");
} else if (closedCount < DEFAULT_REPLICATION_FACTOR && closedCount != 0 &&
allClosedNewer) {
@@ -499,6 +501,12 @@ private void analyzeContainerHealth(Long containerID,
out.println("Container " + containerID + " has enough replicas.");
}
}
+
+ out.println();
+ out.println("Log summary (latest per datanode, Replication Factor=" +
DEFAULT_REPLICATION_FACTOR + "):");
+ out.printf(" CLOSED=%d, QUASI_CLOSED=%d, CLOSING=%d, OPEN=%d, DELETED=%d,
UNHEALTHY=%d%n",
+ closedReplicas.size(), quasiclosedReplicas.size(),
closingReplicas.size(), openReplicas.size(),
+ deletedReplicas.size(), unhealthyReplicas.size());
}
/**
@@ -564,8 +572,9 @@ private List<DatanodeContainerInfo>
getContainerLogData(Long containerID, Connec
return logEntries;
}
- public void findDuplicateOpenContainer() throws SQLException {
+ public void findDuplicateOpenContainer(Integer limit) throws SQLException {
String sql = SQLDBConstants.SELECT_DISTINCT_CONTAINER_IDS_QUERY;
+ boolean limitProvided = limit != Integer.MAX_VALUE;
try (Connection connection = getConnection()) {
@@ -576,8 +585,11 @@ public void findDuplicateOpenContainer() throws
SQLException {
while (resultSet.next()) {
Long containerID = resultSet.getLong("container_id");
List<DatanodeContainerInfo> logEntries =
getContainerLogDataForOpenContainers(containerID, connection);
- boolean hasIssue = checkForMultipleOpenStates(logEntries);
- if (hasIssue) {
+ if (checkForMultipleOpenStates(logEntries)) {
+ if (limitProvided && count >= limit) {
+ err.println("Note: There might be more containers. Use --all
option to list all entries.");
+ break;
+ }
int openStateCount = (int) logEntries.stream()
.filter(entry -> "OPEN".equalsIgnoreCase(entry.getState()))
.count();
@@ -624,37 +636,36 @@ private List<DatanodeContainerInfo>
getContainerLogDataForOpenContainers(Long co
*/
public void listReplicatedContainers(String overOrUnder, Integer limit)
throws SQLException {
- String operator;
- if ("OVER_REPLICATED".equalsIgnoreCase(overOrUnder)) {
- operator = ">";
+ String query;
+ boolean overReplicated = "OVER_REPLICATED".equalsIgnoreCase(overOrUnder);
+ if (overReplicated) {
+ query = SQLDBConstants.SELECT_OVER_REPLICATED_CONTAINERS;
} else if ("UNDER_REPLICATED".equalsIgnoreCase(overOrUnder)) {
- operator = "<";
+ query = SQLDBConstants.SELECT_UNDER_REPLICATED_CONTAINERS;
} else {
err.println("Invalid type. Use OVER_REPLICATED or UNDER_REPLICATED.");
return;
}
-
- String rawQuery = SQLDBConstants.SELECT_REPLICATED_CONTAINERS;
-
- if (!rawQuery.contains("{operator}")) {
- err.println("Query not defined correctly.");
- return;
- }
-
- String finalQuery = rawQuery.replace("{operator}", operator);
boolean limitProvided = limit != Integer.MAX_VALUE;
if (limitProvided) {
- finalQuery += " LIMIT ?";
+ query += " LIMIT ?";
}
try (Connection connection = getConnection();
- PreparedStatement pstmt = connection.prepareStatement(finalQuery)) {
+ PreparedStatement pstmt = connection.prepareStatement(query)) {
- pstmt.setInt(1, DEFAULT_REPLICATION_FACTOR);
-
- if (limitProvided) {
- pstmt.setInt(2, limit + 1);
+ if (overReplicated) {
+ pstmt.setInt(1, DEFAULT_REPLICATION_FACTOR);
+ pstmt.setInt(2, DEFAULT_REPLICATION_FACTOR);
+ if (limitProvided) {
+ pstmt.setInt(3, limit + 1);
+ }
+ } else {
+ pstmt.setInt(1, DEFAULT_REPLICATION_FACTOR);
+ if (limitProvided) {
+ pstmt.setInt(2, limit + 1);
+ }
}
try (ResultSet rs = pstmt.executeQuery()) {
diff --git
a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/utils/ContainerLogFileParser.java
b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/utils/ContainerLogFileParser.java
index f0f6649b305..457515011b1 100644
---
a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/utils/ContainerLogFileParser.java
+++
b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/utils/ContainerLogFileParser.java
@@ -26,10 +26,13 @@
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
+import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
-import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -42,18 +45,33 @@ public class ContainerLogFileParser {
private static final int MAX_OBJ_IN_LIST = 5000;
- private static final String LOG_FILE_MARKER = ".log.";
+ /**
+ * Matches {@code dn-container.log.<datanodeId>} and
+ * {@code dn-container-<roll>.log.<datanodeId>}.
+ */
+ private static final Pattern CONTAINER_LOG_FILE_PATTERN =
+ Pattern.compile("^dn-container(?:-(.+))?\\.log\\.(.+)$");
private static final String LOG_LINE_SPLIT_REGEX = " \\| ";
private static final String KEY_VALUE_SPLIT_REGEX = "=";
private static final String KEY_ID = "ID";
private static final String KEY_BCSID = "BCSID";
private static final String KEY_STATE = "State";
private static final String KEY_INDEX = "Index";
- private final AtomicBoolean hasErrorOccurred = new AtomicBoolean(false);
+ private final AtomicInteger parseSuccessCount = new AtomicInteger(0);
+ private final AtomicInteger parseFailureCount = new AtomicInteger(0);
+
+ public int getParseSuccessCount() {
+ return parseSuccessCount.get();
+ }
+
+ public int getParseFailureCount() {
+ return parseFailureCount.get();
+ }
/**
* Scans the specified log directory, processes each file in a separate
thread.
- * Expects each log filename to follow the format: dn-container-<roll over
number>.log.<datanodeId>
+ * Expects each log filename to follow the format:
dn-container.log.<datanodeId> or
+ * dn-container-<roll over number>.log.<datanodeId>
*
* @param logDirectoryPath Path to the directory containing container log
files.
* @param dbstore Database object used to persist parsed container data.
@@ -61,7 +79,7 @@ public class ContainerLogFileParser {
*/
public void processLogEntries(String logDirectoryPath,
ContainerDatanodeDatabase dbstore, int threadCount)
- throws SQLException, IOException, InterruptedException {
+ throws IOException, InterruptedException {
try (Stream<Path> paths = Files.walk(Paths.get(logDirectoryPath))) {
List<Path> files =
paths.filter(Files::isRegularFile).collect(Collectors.toList());
@@ -73,18 +91,14 @@ public void processLogEntries(String logDirectoryPath,
ContainerDatanodeDatabase
Path fileNamePath = file.getFileName();
String fileName = (fileNamePath != null) ? fileNamePath.toString() :
"";
- int pos = fileName.indexOf(LOG_FILE_MARKER);
- if (pos == -1) {
- System.out.println("Filename format is incorrect (missing .log.): "
+ fileName);
- continue;
- }
-
- String datanodeId = fileName.substring(pos + 5);
-
- if (datanodeId.isEmpty()) {
- System.out.println("Filename format is incorrect, datanodeId is
missing or empty: " + fileName);
+ Optional<String> datanodeIdOpt = extractDatanodeId(fileName);
+ if (!datanodeIdOpt.isPresent()) {
+ System.out.println("Skipping non-container log file (expected
dn-container[...].log.<datanodeId>): "
+ + fileName);
+ latch.countDown();
continue;
}
+ String datanodeId = datanodeIdOpt.get();
executorService.submit(() -> {
@@ -92,10 +106,11 @@ public void processLogEntries(String logDirectoryPath,
ContainerDatanodeDatabase
try {
System.out.println(threadName + " is starting to process file: " +
file.toString());
processFile(file.toString(), dbstore, datanodeId);
+ parseSuccessCount.incrementAndGet();
} catch (Exception e) {
+ parseFailureCount.incrementAndGet();
System.err.println("Thread " + threadName + " is stopping to
process the file: " + file.toString() +
- " due to SQLException: " + e.getMessage());
- hasErrorOccurred.set(true);
+ " due to : " + e.getMessage());
} finally {
try {
latch.countDown();
@@ -110,12 +125,16 @@ public void processLogEntries(String logDirectoryPath,
ContainerDatanodeDatabase
latch.await();
executorService.shutdown();
-
- if (hasErrorOccurred.get()) {
- throw new SQLException("Log file processing failed.");
- }
+ }
+ }
+ static Optional<String> extractDatanodeId(String fileName) {
+ Matcher matcher = CONTAINER_LOG_FILE_PATTERN.matcher(fileName);
+ if (!matcher.matches()) {
+ return Optional.empty();
}
+ String datanodeId = matcher.group(2);
+ return datanodeId.isEmpty() ? Optional.empty() : Optional.of(datanodeId);
}
/**
@@ -135,6 +154,10 @@ private void processFile(String logFilePath,
ContainerDatanodeDatabase dbstore,
String line;
while ((line = reader.readLine()) != null) {
String[] parts = line.split(LOG_LINE_SPLIT_REGEX);
+ if (parts.length < 2) {
+ System.err.println("Skipping malformed log line: " + line);
+ continue;
+ }
String timestamp = parts[0].trim();
String logLevel = parts[1].trim();
String id = null, index = null;
diff --git
a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/utils/SQLDBConstants.java
b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/utils/SQLDBConstants.java
index 0e159a1bbe9..4d76c06684c 100644
---
a/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/utils/SQLDBConstants.java
+++
b/hadoop-ozone/cli-debug/src/main/java/org/apache/hadoop/ozone/debug/logs/container/utils/SQLDBConstants.java
@@ -86,31 +86,41 @@ public final class SQLDBConstants {
public static final String CREATE_DCL_STATE_CONTAINER_DATANODE_TIME_INDEX =
"CREATE INDEX IF NOT EXISTS idx_dcl_state_container_datanode_time " +
"ON DatanodeContainerLogTable(container_state, container_id,
datanode_id, timestamp DESC);";
- public static final String SELECT_REPLICATED_CONTAINERS =
- "SELECT container_id, COUNT(DISTINCT datanode_id) AS
replica_count\n" +
- "FROM ContainerLogTable\n" +
- "WHERE latest_state != '" + DELETED_STATE + "'\n" +
- " GROUP BY container_id\n" +
- "HAVING COUNT(DISTINCT datanode_id) {operator} ?";
+
+ private static final String REPLICA_COUNTS_CTE =
+ " SELECT\n" +
+ " container_id,\n" +
+ " SUM(CASE WHEN latest_state != '" + UNHEALTHY_STATE + "' THEN 1 ELSE
0 END) AS count_a,\n" +
+ " SUM(CASE WHEN latest_state = '" + UNHEALTHY_STATE + "' THEN 1 ELSE
0 END) AS count_b,\n" +
+ " COUNT(DISTINCT datanode_id) AS count_c\n" +
+ " FROM ContainerLogTable\n" +
+ " WHERE latest_state != '" + DELETED_STATE + "'\n" +
+ " GROUP BY container_id\n";
+
+ public static final String SELECT_UNDER_REPLICATED_CONTAINERS =
+ "WITH replica_counts AS (\n" +
+ REPLICA_COUNTS_CTE +
+ ")\n" +
+ "SELECT container_id, count_c AS replica_count\n" +
+ "FROM replica_counts\n" +
+ "WHERE count_a < ?\n" +
+ "ORDER BY container_id";
+ public static final String SELECT_OVER_REPLICATED_CONTAINERS =
+ "WITH replica_counts AS (\n" +
+ REPLICA_COUNTS_CTE +
+ ")\n" +
+ "SELECT container_id, count_c AS replica_count\n" +
+ "FROM replica_counts\n" +
+ "WHERE count_c > ? AND count_a >= ?\n" +
+ "ORDER BY container_id";
public static final String SELECT_UNHEALTHY_CONTAINERS =
- "SELECT u.container_id, COUNT(*) AS unhealthy_replica_count\n" +
- "FROM (\n" +
- " SELECT container_id, datanode_id, MAX(timestamp) AS
latest_unhealthy_timestamp\n" +
- " FROM DatanodeContainerLogTable\n" +
- " WHERE container_state = '" + UNHEALTHY_STATE + "'\n" +
- " GROUP BY container_id, datanode_id\n" +
- ") AS u\n" +
- "LEFT JOIN (\n" +
- " SELECT container_id, datanode_id, MAX(timestamp) AS
latest_closed_timestamp\n" +
- " FROM DatanodeContainerLogTable\n" +
- " WHERE container_state IN ('" + CLOSED_STATE + "', '" +
DELETED_STATE + "')\n" +
- " GROUP BY container_id, datanode_id\n" +
- ") AS c\n" +
- "ON u.container_id = c.container_id AND u.datanode_id =
c.datanode_id\n" +
- "WHERE c.latest_closed_timestamp IS NULL \n" +
- " OR u.latest_unhealthy_timestamp > c.latest_closed_timestamp\n" +
- "GROUP BY u.container_id\n" +
- "ORDER BY u.container_id";
+ "WITH replica_counts AS (\n" +
+ REPLICA_COUNTS_CTE +
+ ")\n" +
+ "SELECT container_id, count_b AS unhealthy_replica_count\n" +
+ "FROM replica_counts\n" +
+ "WHERE count_b = count_c AND count_c > 0\n" +
+ "ORDER BY container_id";
public static final String SELECT_QUASI_CLOSED_STUCK_CONTAINERS =
"WITH quasi_closed_replicas AS ( " +
" SELECT container_id, datanode_id, MAX(timestamp) AS
latest_quasi_closed_timestamp\n" +
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]