Repository: hbase
Updated Branches:
  refs/heads/master 423a0ab71 -> 9e9db3245


HBASE-20630 B&R: Delete command enhancements

Signed-off-by: tedyu <yuzhih...@gmail.com>


Project: http://git-wip-us.apache.org/repos/asf/hbase/repo
Commit: http://git-wip-us.apache.org/repos/asf/hbase/commit/9e9db324
Tree: http://git-wip-us.apache.org/repos/asf/hbase/tree/9e9db324
Diff: http://git-wip-us.apache.org/repos/asf/hbase/diff/9e9db324

Branch: refs/heads/master
Commit: 9e9db3245f2d825837f231c004eac99f83829a95
Parents: 423a0ab
Author: Vladimir Rodionov <vrodio...@hortonworks.com>
Authored: Wed Jun 6 16:49:15 2018 -0700
Committer: tedyu <yuzhih...@gmail.com>
Committed: Wed Jun 13 18:46:48 2018 -0700

----------------------------------------------------------------------
 .../hadoop/hbase/backup/BackupDriver.java       |  9 ++-
 .../hbase/backup/BackupRestoreConstants.java    |  7 +-
 .../hbase/backup/impl/BackupCommands.java       | 85 +++++++++++++++++---
 .../hadoop/hbase/backup/TestBackupDelete.java   | 58 ++++++++++++-
 4 files changed, 146 insertions(+), 13 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/9e9db324/hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/BackupDriver.java
----------------------------------------------------------------------
diff --git 
a/hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/BackupDriver.java 
b/hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/BackupDriver.java
index 8baf2f0..6644d89 100644
--- 
a/hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/BackupDriver.java
+++ 
b/hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/BackupDriver.java
@@ -17,10 +17,14 @@
  */
 package org.apache.hadoop.hbase.backup;
 
+import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_BACKUP_LIST_DESC;
 import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_BANDWIDTH;
 import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_BANDWIDTH_DESC;
 import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_DEBUG;
 import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_DEBUG_DESC;
+import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_KEEP;
+import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_KEEP_DESC;
+import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_LIST;
 import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_PATH;
 import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_PATH_DESC;
 import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_RECORD_NUMBER;
@@ -46,14 +50,13 @@ import org.apache.hadoop.hbase.backup.impl.BackupManager;
 import org.apache.hadoop.hbase.util.AbstractHBaseTool;
 import org.apache.hadoop.hbase.util.FSUtils;
 import org.apache.hadoop.util.ToolRunner;
+import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;
 import org.apache.log4j.Level;
 import org.apache.log4j.LogManager;
 import org.apache.yetus.audience.InterfaceAudience;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;
-
 /**
  *
  * Command-line entry point for backup operation
@@ -152,10 +155,12 @@ public class BackupDriver extends AbstractHBaseTool {
     addOptNoArg(OPTION_DEBUG, OPTION_DEBUG_DESC);
     addOptWithArg(OPTION_TABLE, OPTION_TABLE_DESC);
     addOptWithArg(OPTION_BANDWIDTH, OPTION_BANDWIDTH_DESC);
+    addOptWithArg(OPTION_LIST, OPTION_BACKUP_LIST_DESC);
     addOptWithArg(OPTION_WORKERS, OPTION_WORKERS_DESC);
     addOptWithArg(OPTION_RECORD_NUMBER, OPTION_RECORD_NUMBER_DESC);
     addOptWithArg(OPTION_SET, OPTION_SET_DESC);
     addOptWithArg(OPTION_PATH, OPTION_PATH_DESC);
+    addOptWithArg(OPTION_KEEP, OPTION_KEEP_DESC);
     addOptWithArg(OPTION_YARN_QUEUE_NAME, OPTION_YARN_QUEUE_NAME_DESC);
 
   }

http://git-wip-us.apache.org/repos/asf/hbase/blob/9e9db324/hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/BackupRestoreConstants.java
----------------------------------------------------------------------
diff --git 
a/hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/BackupRestoreConstants.java
 
b/hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/BackupRestoreConstants.java
index eaeef22..16ec3d2 100644
--- 
a/hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/BackupRestoreConstants.java
+++ 
b/hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/BackupRestoreConstants.java
@@ -65,8 +65,9 @@ public interface BackupRestoreConstants {
   String OPTION_TABLE_DESC = "Table name. If specified, only backup images,"
       + " which contain this table will be listed.";
 
-  String OPTION_TABLE_LIST = "l";
+  String OPTION_LIST = "l";
   String OPTION_TABLE_LIST_DESC = "Table name list, comma-separated.";
+  String OPTION_BACKUP_LIST_DESC = "Backup ids list, comma-separated.";
 
   String OPTION_BANDWIDTH = "b";
   String OPTION_BANDWIDTH_DESC = "Bandwidth per task (MapReduce task) in MB/s";
@@ -80,6 +81,10 @@ public interface BackupRestoreConstants {
   String OPTION_PATH = "p";
   String OPTION_PATH_DESC = "Backup destination root directory path";
 
+  String OPTION_KEEP = "k";
+  String OPTION_KEEP_DESC = "Specifies maximum age of backup (in days) to keep 
during bulk delete";
+
+
   String OPTION_TABLE_MAPPING = "m";
   String OPTION_TABLE_MAPPING_DESC =
       "A comma separated list of target tables. "

http://git-wip-us.apache.org/repos/asf/hbase/blob/9e9db324/hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupCommands.java
----------------------------------------------------------------------
diff --git 
a/hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupCommands.java
 
b/hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupCommands.java
index 3e28f51..fc2f1a2 100644
--- 
a/hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupCommands.java
+++ 
b/hbase-backup/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupCommands.java
@@ -18,10 +18,14 @@
 
 package org.apache.hadoop.hbase.backup.impl;
 
+import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_BACKUP_LIST_DESC;
 import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_BANDWIDTH;
 import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_BANDWIDTH_DESC;
 import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_DEBUG;
 import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_DEBUG_DESC;
+import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_KEEP;
+import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_KEEP_DESC;
+import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_LIST;
 import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_PATH;
 import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_PATH_DESC;
 import static 
org.apache.hadoop.hbase.backup.BackupRestoreConstants.OPTION_RECORD_NUMBER;
@@ -61,11 +65,11 @@ import org.apache.hadoop.hbase.backup.util.BackupUtils;
 import org.apache.hadoop.hbase.client.Connection;
 import org.apache.hadoop.hbase.client.ConnectionFactory;
 import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
-import org.apache.yetus.audience.InterfaceAudience;
 import org.apache.hbase.thirdparty.com.google.common.collect.Lists;
 import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;
 import org.apache.hbase.thirdparty.org.apache.commons.cli.HelpFormatter;
 import org.apache.hbase.thirdparty.org.apache.commons.cli.Options;
+import org.apache.yetus.audience.InterfaceAudience;
 
 /**
  * General backup commands, options and usage messages
@@ -105,8 +109,7 @@ public final class BackupCommands {
 
   public static final String HISTORY_CMD_USAGE = "Usage: hbase backup history 
[options]";
 
-  public static final String DELETE_CMD_USAGE = "Usage: hbase backup delete 
<backup_id>\n"
-      + "  backup_id       Backup image id\n";
+  public static final String DELETE_CMD_USAGE = "Usage: hbase backup delete 
[options]";
 
   public static final String REPAIR_CMD_USAGE = "Usage: hbase backup repair\n";
 
@@ -560,29 +563,93 @@ public final class BackupCommands {
 
     @Override
     public void execute() throws IOException {
-      if (cmdline == null || cmdline.getArgs() == null || 
cmdline.getArgs().length < 2) {
+
+      if (cmdline == null || cmdline.getArgs() == null || 
cmdline.getArgs().length < 1) {
         printUsage();
         throw new IOException(INCORRECT_USAGE);
       }
 
+      if (!cmdline.hasOption(OPTION_KEEP) && !cmdline.hasOption(OPTION_LIST)) {
+        printUsage();
+        throw new IOException(INCORRECT_USAGE);
+      }
       super.execute();
+      if (cmdline.hasOption(OPTION_KEEP)) {
+        executeDeleteOlderThan(cmdline);
+      } else if (cmdline.hasOption(OPTION_LIST)) {
+        executeDeleteListOfBackups(cmdline);
+      }
+    }
+
+    private void executeDeleteOlderThan(CommandLine cmdline) throws 
IOException {
+      String value = cmdline.getOptionValue(OPTION_KEEP);
+      int days = 0;
+      try {
+        days = Integer.parseInt(value);
+      } catch (NumberFormatException e) {
+        throw new IOException(value + " is not an integer number");
+      }
+      final long fdays = days;
+      BackupInfo.Filter dateFilter = new BackupInfo.Filter() {
+        @Override
+        public boolean apply(BackupInfo info) {
+          long currentTime = EnvironmentEdgeManager.currentTime();
+          long maxTsToDelete = currentTime - fdays * 24 * 3600 * 1000;
+          return info.getCompleteTs() <= maxTsToDelete;
+        }
+      };
+      List<BackupInfo> history = null;
+      try (final BackupSystemTable sysTable = new BackupSystemTable(conn);
+          BackupAdminImpl admin = new BackupAdminImpl(conn)) {
+        history = sysTable.getBackupHistory(-1, dateFilter);
+        String[] backupIds = convertToBackupIds(history);
+        int deleted = admin.deleteBackups(backupIds);
+        System.out.println("Deleted " + deleted + " backups. Total older than 
" + days + " days: "
+            + backupIds.length);
+      } catch (IOException e) {
+        System.err.println("Delete command FAILED. Please run backup repair 
tool to restore backup "
+            + "system integrity");
+        throw e;
+      }
+    }
+
+    private String[] convertToBackupIds(List<BackupInfo> history) {
+      String[] ids = new String[history.size()];
+      for (int i = 0; i < ids.length; i++) {
+        ids[i] = history.get(i).getBackupId();
+      }
+      return ids;
+    }
+
+    private void executeDeleteListOfBackups(CommandLine cmdline) throws 
IOException {
+      String value = cmdline.getOptionValue(OPTION_LIST);
+      String[] backupIds = value.split(",");
 
-      String[] args = cmdline.getArgs();
-      String[] backupIds = new String[args.length - 1];
-      System.arraycopy(args, 1, backupIds, 0, backupIds.length);
       try (BackupAdminImpl admin = new BackupAdminImpl(conn)) {
         int deleted = admin.deleteBackups(backupIds);
-        System.out.println("Deleted " + deleted + " backups. Total requested: 
" + (args.length -1));
+        System.out.println("Deleted " + deleted + " backups. Total requested: 
" + backupIds.length);
       } catch (IOException e) {
         System.err.println("Delete command FAILED. Please run backup repair 
tool to restore backup "
-                + "system integrity");
+            + "system integrity");
         throw e;
       }
+
     }
 
     @Override
     protected void printUsage() {
       System.out.println(DELETE_CMD_USAGE);
+      Options options = new Options();
+      options.addOption(OPTION_KEEP, true, OPTION_KEEP_DESC);
+      options.addOption(OPTION_LIST, true, OPTION_BACKUP_LIST_DESC);
+
+      HelpFormatter helpFormatter = new HelpFormatter();
+      helpFormatter.setLeftPadding(2);
+      helpFormatter.setDescPadding(8);
+      helpFormatter.setWidth(100);
+      helpFormatter.setSyntaxPrefix("Options:");
+      helpFormatter.printHelp(" ", null, options, USAGE_FOOTER);
+
     }
   }
 

http://git-wip-us.apache.org/repos/asf/hbase/blob/9e9db324/hbase-backup/src/test/java/org/apache/hadoop/hbase/backup/TestBackupDelete.java
----------------------------------------------------------------------
diff --git 
a/hbase-backup/src/test/java/org/apache/hadoop/hbase/backup/TestBackupDelete.java
 
b/hbase-backup/src/test/java/org/apache/hadoop/hbase/backup/TestBackupDelete.java
index 9e67ff7..bc8b346 100644
--- 
a/hbase-backup/src/test/java/org/apache/hadoop/hbase/backup/TestBackupDelete.java
+++ 
b/hbase-backup/src/test/java/org/apache/hadoop/hbase/backup/TestBackupDelete.java
@@ -28,7 +28,10 @@ import org.apache.hadoop.hbase.HBaseClassTestRule;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.backup.impl.BackupSystemTable;
 import org.apache.hadoop.hbase.testclassification.LargeTests;
+import org.apache.hadoop.hbase.util.EnvironmentEdge;
+import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
 import org.apache.hadoop.util.ToolRunner;
+import org.junit.Assert;
 import org.junit.ClassRule;
 import org.junit.Test;
 import org.junit.experimental.categories.Category;
@@ -90,7 +93,7 @@ public class TestBackupDelete extends TestBackupBase {
     ByteArrayOutputStream baos = new ByteArrayOutputStream();
     System.setOut(new PrintStream(baos));
 
-    String[] args = new String[] { "delete", backupId };
+    String[] args = new String[] { "delete", "-l", backupId };
     // Run backup
 
     try {
@@ -104,4 +107,57 @@ public class TestBackupDelete extends TestBackupBase {
     LOG.info(baos.toString());
     assertTrue(output.indexOf("Deleted 1 backups") >= 0);
   }
+
+  @Test
+  public void testBackupPurgeOldBackupsCommand() throws Exception {
+    LOG.info("test backup delete (purge old backups) on a single table with 
data: command-line");
+    List<TableName> tableList = Lists.newArrayList(table1);
+    EnvironmentEdgeManager.injectEdge(new EnvironmentEdge() {
+      // time - 2 days
+      @Override
+      public long currentTime() {
+        return System.currentTimeMillis() - 2 * 24 * 3600 * 1000 ;
+      }
+    });
+    String backupId = fullTableBackup(tableList);
+    assertTrue(checkSucceeded(backupId));
+
+    EnvironmentEdgeManager.reset();
+
+    LOG.info("backup complete");
+    ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    System.setOut(new PrintStream(baos));
+
+    // Purge all backups which are older than 3 days
+    // Must return 0 (no backups were purged)
+    String[] args = new String[] { "delete", "-k", "3" };
+    // Run backup
+
+    try {
+      int ret = ToolRunner.run(conf1, new BackupDriver(), args);
+      assertTrue(ret == 0);
+    } catch (Exception e) {
+      LOG.error("failed", e);
+      Assert.fail(e.getMessage());
+    }
+    String output = baos.toString();
+    LOG.info(baos.toString());
+    assertTrue(output.indexOf("Deleted 0 backups") >= 0);
+
+    // Purge all backups which are older than 1 days
+    // Must return 1 deleted backup
+    args = new String[] { "delete", "-k", "1" };
+    // Run backup
+    baos.reset();
+    try {
+      int ret = ToolRunner.run(conf1, new BackupDriver(), args);
+      assertTrue(ret == 0);
+    } catch (Exception e) {
+      LOG.error("failed", e);
+      Assert.fail(e.getMessage());
+    }
+    output = baos.toString();
+    LOG.info(baos.toString());
+    assertTrue(output.indexOf("Deleted 1 backups") >= 0);
+  }
 }

Reply via email to