From 9c779118b97aaa45c325f62ca9fda3f60dca38b3 Mon Sep 17 00:00:00 2001 From: Peng Lu Date: Tue, 23 Jun 2026 23:32:06 +0800 Subject: [PATCH 1/2] HBASE-30252 `hbase snapshot info` display inaccurate snapshot TTL information messages --- .../hadoop/hbase/snapshot/SnapshotInfo.java | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/SnapshotInfo.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/SnapshotInfo.java index 0a57aeb4c02e..852f6c5ac962 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/SnapshotInfo.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/SnapshotInfo.java @@ -17,6 +17,8 @@ */ package org.apache.hadoop.hbase.snapshot; +import static org.apache.hadoop.hbase.HConstants.DEFAULT_SNAPSHOT_TTL; + import java.io.FileNotFoundException; import java.io.IOException; import java.net.URI; @@ -71,6 +73,10 @@ public final class SnapshotInfo extends AbstractHBaseTool { private static final Logger LOG = LoggerFactory.getLogger(SnapshotInfo.class); + private static final String EXPIRED_LABEL = "Yes"; + private static final String NOT_EXPIRED_LABEL = "No"; + private static final String TTL_FOREVER = "FOREVER"; + static final class Options { static final Option SNAPSHOT = new Option(null, "snapshot", true, "The name of the snapshot to be detailed."); @@ -391,11 +397,17 @@ public int doWork() throws IOException, InterruptedException { // List Available Snapshots if (listSnapshots) { SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); - System.out.printf("%-20s | %-20s | %-20s | %s%n", "SNAPSHOT", "CREATION TIME", "TTL IN SEC", - "TABLE NAME"); - for (SnapshotDescription desc : getSnapshotList(conf)) { - System.out.printf("%-20s | %20s | %20s | %s%n", desc.getName(), - df.format(new Date(desc.getCreationTime())), desc.getTtl(), desc.getTableNameAsString()); + List snapshotDescriptions = getSnapshotList(conf); + System.out.printf("%-20s | %-20s | %-20s | %-20s | %s%n", "SNAPSHOT", "CREATION TIME", + "TTL(Sec)", "EXPIRED", "TABLE NAME"); + for (SnapshotDescription desc : snapshotDescriptions) { + String ttlInfo = + desc.getTtl() == DEFAULT_SNAPSHOT_TTL ? TTL_FOREVER : String.valueOf(desc.getTtl()); + String expired = SnapshotDescriptionUtils.isExpiredSnapshot(desc.getTtl(), + desc.getCreationTime(), System.currentTimeMillis()) ? EXPIRED_LABEL : NOT_EXPIRED_LABEL; + System.out.printf("%-20s | %20s | %20s | %20s | %s%n", desc.getName(), + df.format(new Date(desc.getCreationTime())), ttlInfo, expired, + desc.getTableNameAsString()); } return 0; } @@ -443,15 +455,23 @@ private boolean loadSnapshotInfo(final String snapshotName) throws IOException { private void printInfo() { SnapshotProtos.SnapshotDescription snapshotDesc = snapshotManifest.getSnapshotDescription(); SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + String ttlInfo = snapshotDesc.getTtl() == DEFAULT_SNAPSHOT_TTL + ? TTL_FOREVER + : String.valueOf(snapshotDesc.getTtl()); + String expired = SnapshotDescriptionUtils.isExpiredSnapshot(snapshotDesc.getTtl(), + snapshotDesc.getCreationTime(), System.currentTimeMillis()) + ? EXPIRED_LABEL + : NOT_EXPIRED_LABEL; System.out.println("Snapshot Info"); - System.out.println("----------------------------------------"); - System.out.println(" Name: " + snapshotDesc.getName()); - System.out.println(" Type: " + snapshotDesc.getType()); - System.out.println(" Table: " + snapshotDesc.getTable()); - System.out.println(" Format: " + snapshotDesc.getVersion()); - System.out.println("Created: " + df.format(new Date(snapshotDesc.getCreationTime()))); - System.out.println(" Ttl: " + snapshotDesc.getTtl()); - System.out.println(" Owner: " + snapshotDesc.getOwner()); + System.out.println("-----------------------------------------"); + System.out.println(" Name: " + snapshotDesc.getName()); + System.out.println(" Type: " + snapshotDesc.getType()); + System.out.println(" Table: " + snapshotDesc.getTable()); + System.out.println(" Format: " + snapshotDesc.getVersion()); + System.out.println(" Created: " + df.format(new Date(snapshotDesc.getCreationTime()))); + System.out.println("Ttl(Sec): " + ttlInfo); + System.out.println(" Expired: " + expired); + System.out.println(" Owner: " + snapshotDesc.getOwner()); System.out.println(); } From 6ffefe5e765521a172c08c95c0839fcee6006e6a Mon Sep 17 00:00:00 2001 From: Peng Lu Date: Wed, 24 Jun 2026 18:25:33 +0800 Subject: [PATCH 2/2] Moving System.currentTimeMillis() outside the loop --- .../java/org/apache/hadoop/hbase/snapshot/SnapshotInfo.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/SnapshotInfo.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/SnapshotInfo.java index 852f6c5ac962..707519ddd46d 100644 --- a/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/SnapshotInfo.java +++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/snapshot/SnapshotInfo.java @@ -400,11 +400,12 @@ public int doWork() throws IOException, InterruptedException { List snapshotDescriptions = getSnapshotList(conf); System.out.printf("%-20s | %-20s | %-20s | %-20s | %s%n", "SNAPSHOT", "CREATION TIME", "TTL(Sec)", "EXPIRED", "TABLE NAME"); + long currentTime = System.currentTimeMillis(); for (SnapshotDescription desc : snapshotDescriptions) { String ttlInfo = desc.getTtl() == DEFAULT_SNAPSHOT_TTL ? TTL_FOREVER : String.valueOf(desc.getTtl()); String expired = SnapshotDescriptionUtils.isExpiredSnapshot(desc.getTtl(), - desc.getCreationTime(), System.currentTimeMillis()) ? EXPIRED_LABEL : NOT_EXPIRED_LABEL; + desc.getCreationTime(), currentTime) ? EXPIRED_LABEL : NOT_EXPIRED_LABEL; System.out.printf("%-20s | %20s | %20s | %20s | %s%n", desc.getName(), df.format(new Date(desc.getCreationTime())), ttlInfo, expired, desc.getTableNameAsString());