aryangupta1998 commented on code in PR #8264:
URL: https://github.com/apache/ozone/pull/8264#discussion_r2049254810
##########
hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/containerlog/parser/ContainerDatanodeDatabase.java:
##########
@@ -233,5 +237,173 @@ private void dropTable(String tableName, Statement stmt)
throws SQLException {
stmt.executeUpdate(dropTableSQL);
}
+ /**
+ * Displays detailed information about a container based on its ID,
including its state, BCSID,
+ * timestamp, message, and index value. It also checks for issues such as
UNHEALTHY
+ * replicas, under-replication, over-replication, OPEN_UNHEALTHY,
OUASI_CLOSED_STUCK, mismatched replication
+ * and duplicate open.
+ *
+ * @param containerID The ID of the container to display details for.
+ */
+
+ public void showContainerDetails(Long containerID) throws SQLException {
+
+ try (Connection connection = getConnection()) {
+ List<DatanodeContainerInfo> logEntries =
getContainerLogData(containerID, connection);
+
+ if (logEntries.isEmpty()) {
+ System.out.println("Missing container with ID: " + containerID);
+ return;
+ }
+
+ System.out.printf("%-25s | %-15s | %-35s | %-20s | %-10s | %-30s |
%-12s%n",
+ "Timestamp", "Container ID", "Datanode ID", "Container State",
"BCSID", "Message", "Index Value");
+
System.out.println("-----------------------------------------------------------------------------------"
+
+
"-------------------------------------------------------------------------------------------------");
+
+ for (DatanodeContainerInfo entry : logEntries) {
+ System.out.printf("%-25s | %-15d | %-35s | %-20s | %-10d | %-30s |
%-12d%n",
+ entry.getTimestamp(),
+ entry.getContainerId(),
+ entry.getDatanodeId(),
+ entry.getState(),
+ entry.getBcsid(),
+ entry.getErrorMessage(),
+ entry.getIndexValue());
+ }
+
+ if (checkForMultipleOpenStates(logEntries)) {
+ System.out.println("Container " + containerID + " might have duplicate
OPEN state.");
+ return;
+ }
+
+ Map<String, DatanodeContainerInfo> latestPerDatanode = new HashMap<>();
+ for (DatanodeContainerInfo entry : logEntries) {
+ String datanodeId = entry.getDatanodeId();
+ DatanodeContainerInfo existing = latestPerDatanode.get(datanodeId);
+ if (existing == null ||
entry.getTimestamp().compareTo(existing.getTimestamp()) > 0) {
+ latestPerDatanode.put(datanodeId, entry);
+ }
+ }
+
+ Set<String> unhealthyReplicas = new HashSet<>();
+ Set<String> closedReplicas = new HashSet<>();
+ Set<String> openReplicas = new HashSet<>();
+ Set<String> quasiclosedReplicas = new HashSet<>();
+ Set<String> deletedReplicas = new HashSet<>();
+ Set<Long> bcsids = new HashSet<>();
+ Set<String> datanodeIds = new HashSet<>();
+
+ for (DatanodeContainerInfo entry : latestPerDatanode.values()) {
+ String datanodeId = entry.getDatanodeId();
+ String state = entry.getState();
+ long bcsid = entry.getBcsid();
+
+ datanodeIds.add(datanodeId);
+
+ switch (state.toUpperCase()) {
+ case "UNHEALTHY": unhealthyReplicas.add(datanodeId); break;
+ case "CLOSED": closedReplicas.add(datanodeId); bcsids.add(bcsid);
break;
+ case "OPEN": openReplicas.add(datanodeId); break;
+ case "QUASI_CLOSED": quasiclosedReplicas.add(datanodeId); break;
+ case "DELETED": deletedReplicas.add(datanodeId); bcsids.add(bcsid);
break;
+ default:
+ break;
+ }
+ }
+
+ int unhealthyCount = unhealthyReplicas.size();
+ int replicaCount = datanodeIds.size();
+ int expectedReplicationFactor = 3;
+
+ if (!deletedReplicas.isEmpty() && !closedReplicas.isEmpty() &&
bcsids.size() > 1) {
+ System.out.println("Container " + containerID + " has MISMATCHED
REPLICATION.");
+ } else if (unhealthyCount == replicaCount) {
+ System.out.println("Container " + containerID + " is UNHEALTHY across
all datanodes.");
+ } else if (unhealthyCount >= 2 && closedReplicas.size() == replicaCount
- unhealthyCount) {
+ System.out.println("Container " + containerID + " is both UNHEALTHY
and UNDER-REPLICATED.");
+ } else if (unhealthyCount == 1 && closedReplicas.size() == replicaCount
- unhealthyCount) {
+ System.out.println("Container " + containerID + " is
UNDER-REPLICATED.");
+ } else if ((!openReplicas.isEmpty() && openReplicas.size() < 3) &&
+ (closedReplicas.size() == replicaCount - openReplicas.size() ||
+ unhealthyCount == replicaCount - openReplicas.size())) {
+ System.out.println("Container " + containerID + " is OPEN_UNHEALTHY.");
+ } else if (quasiclosedReplicas.size() >= 3) {
+ System.out.println("Container " + containerID + " is
QUASI_CLOSED_STUCK.");
+ } else if (replicaCount - deletedReplicas.size() <
expectedReplicationFactor) {
+ System.out.println("Container " + containerID + " is
UNDER-REPLICATED.");
+ } else if (replicaCount - deletedReplicas.size() >
expectedReplicationFactor) {
+ System.out.println("Container " + containerID + " is
OVER-REPLICATED.");
+ } else {
+ System.out.println("Container " + containerID + " has enough
replicas.");
+ }
+ } catch (SQLException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * Checks whether the specified container has multiple "OPEN" states.
+ * If multiple "OPEN" states are found, it returns {@code true}.
+ *
+ * @param entries The list of {@link DatanodeContainerInfo} entries to check
for multiple "OPEN" states.
+ * @return {@code true} if multiple "OPEN" states are found, {@code false}
otherwise.
+ */
+
+ private boolean checkForMultipleOpenStates(List<DatanodeContainerInfo>
entries) {
+ List<String> firstOpenTimestamps = new ArrayList<>();
+ Set<String> firstOpenDatanodes = new HashSet<>();
+ boolean issueFound = false;
+
+ for (DatanodeContainerInfo entry : entries) {
+ if ("OPEN".equalsIgnoreCase(entry.getState())) {
+ if (firstOpenTimestamps.size() < 3 &&
!firstOpenDatanodes.contains(entry.getDatanodeId())) {
Review Comment:
I'm assuming you're using 3 here, as the default replication factor is 3.
I'm not sure if we can fetch the replication factor dynamically, but let's use
a variable instead of hard-coding.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]