You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by te...@apache.org on 2016/04/02 00:02:23 UTC

[1/6] hbase git commit: HBASE-15411 Rewrite backup with Procedure V2 - phase 1

Repository: hbase
Updated Branches:
  refs/heads/HBASE-7912 1e9470dd7 -> b37cc7606


http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupBoundaryTests.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupBoundaryTests.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupBoundaryTests.java
index 21bf63c..7f5846c 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupBoundaryTests.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupBoundaryTests.java
@@ -46,9 +46,7 @@ public class TestBackupBoundaryTests extends TestBackupBase {
 
     LOG.info("create full backup image on single table");
     List<TableName> tables = Lists.newArrayList(table3);
-    String backupId = getBackupClient().create(BackupType.FULL, tables, BACKUP_ROOT_DIR);
-    LOG.info("Finished Backup");
-    assertTrue(checkSucceeded(backupId));
+    LOG.info("Finished Backup " + fullTableBackup(tables));
   }
 
   /**
@@ -60,8 +58,7 @@ public class TestBackupBoundaryTests extends TestBackupBase {
     LOG.info("create full backup image on mulitple empty tables");
 
     List<TableName> tables = Lists.newArrayList(table3, table4);
-    String backupId = getBackupClient().create(BackupType.FULL, tables, BACKUP_ROOT_DIR);
-    assertTrue(checkSucceeded(backupId));
+    fullTableBackup(tables);
   }
 
   /**
@@ -73,8 +70,7 @@ public class TestBackupBoundaryTests extends TestBackupBase {
 
     LOG.info("test full backup fails on a single table that does not exist");
     List<TableName> tables = toList("tabledne");
-    String backupId = getBackupClient().create(BackupType.FULL, tables, BACKUP_ROOT_DIR);
-    assertTrue(checkSucceeded(backupId));
+    fullTableBackup(tables);
   }
 
   /**
@@ -86,8 +82,7 @@ public class TestBackupBoundaryTests extends TestBackupBase {
 
     LOG.info("test full backup fails on multiple tables that do not exist");
     List<TableName> tables = toList("table1dne", "table2dne");
-    String backupId = getBackupClient().create(BackupType.FULL, tables, BACKUP_ROOT_DIR);
-    assertTrue(checkSucceeded(backupId));
+    fullTableBackup(tables);
   }
 
   /**
@@ -99,7 +94,6 @@ public class TestBackupBoundaryTests extends TestBackupBase {
     LOG.info("create full backup fails on tableset containing real and fake table");
 
     List<TableName> tables = toList(table1.getNameAsString(), "tabledne");
-    String backupId = getBackupClient().create(BackupType.FULL, tables, BACKUP_ROOT_DIR);
-    //assertTrue(checkSucceeded(backupId)); // TODO
+    fullTableBackup(tables);
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupLogCleaner.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupLogCleaner.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupLogCleaner.java
index 899f53b..175bce0 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupLogCleaner.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupLogCleaner.java
@@ -80,9 +80,8 @@ public class TestBackupLogCleaner extends TestBackupBase {
       assertTrue(Iterables.size(deletable) == walFiles.size());
 
       systemTable.addWALFiles(swalFiles, "backup");
-      String backupIdFull = getBackupClient().create(BackupType.FULL, tableSetFullList,
-        BACKUP_ROOT_DIR);
-      assertTrue(checkSucceeded(backupIdFull));
+      String backupIdFull = fullTableBackup(tableSetFullList);
+      // getBackupClient().create(BackupType.FULL, tableSetFullList, BACKUP_ROOT_DIR);
       // Check one more time
       deletable = cleaner.getDeletableFiles(walFiles);
       // We can delete wal files because they were saved into hbase:backup table
@@ -122,9 +121,8 @@ public class TestBackupLogCleaner extends TestBackupBase {
       // #3 - incremental backup for multiple tables
 
       List<TableName> tableSetIncList = Lists.newArrayList(table1, table2, table3);
-      String backupIdIncMultiple =
-          getBackupClient().create(BackupType.INCREMENTAL, tableSetIncList, BACKUP_ROOT_DIR);
-      assertTrue(checkSucceeded(backupIdIncMultiple));
+      String backupIdIncMultiple = backupTables(BackupType.INCREMENTAL, tableSetIncList,
+        BACKUP_ROOT_DIR);
       deletable = cleaner.getDeletableFiles(newWalFiles);
 
       assertTrue(Iterables.size(deletable) == newWalFiles.size());

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupSystemTable.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupSystemTable.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupSystemTable.java
index 17d5013..f775c65 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupSystemTable.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupSystemTable.java
@@ -39,8 +39,9 @@ import org.apache.hadoop.hbase.HBaseTestingUtility;
 import org.apache.hadoop.hbase.MiniHBaseCluster;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.backup.impl.BackupContext;
-import org.apache.hadoop.hbase.backup.impl.BackupHandler.BackupState;
+import org.apache.hadoop.hbase.backup.impl.BackupContext.BackupState;
 import org.apache.hadoop.hbase.backup.impl.BackupSystemTable;
+import org.apache.hadoop.hbase.backup.impl.BackupSystemTableHelper;
 import org.apache.hadoop.hbase.backup.impl.BackupUtil.BackupCompleteData;
 import org.apache.hadoop.hbase.client.Admin;
 import org.apache.hadoop.hbase.client.Connection;
@@ -188,7 +189,8 @@ public class TestBackupSystemTable {
     tables2.add(TableName.valueOf("t5"));
 
     table.addIncrementalBackupTableSet(tables1);
-    TreeSet<TableName> res1 = (TreeSet<TableName>) table.getIncrementalBackupTableSet();
+    TreeSet<TableName> res1 = (TreeSet<TableName>) BackupSystemTableHelper
+        .getIncrementalBackupTableSet(conn);
     assertTrue(tables1.size() == res1.size());
     Iterator<TableName> desc1 = tables1.descendingIterator();
     Iterator<TableName> desc2 = res1.descendingIterator();
@@ -197,7 +199,8 @@ public class TestBackupSystemTable {
     }
 
     table.addIncrementalBackupTableSet(tables2);
-    TreeSet<TableName> res2 = (TreeSet<TableName>) table.getIncrementalBackupTableSet();
+    TreeSet<TableName> res2 = (TreeSet<TableName>) BackupSystemTableHelper
+        .getIncrementalBackupTableSet(conn);
     assertTrue((tables2.size() + tables1.size() - 1) == res2.size());
 
     tables1.addAll(tables2);

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestFullBackup.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestFullBackup.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestFullBackup.java
index d9bade1..9dda967 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestFullBackup.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestFullBackup.java
@@ -11,8 +11,6 @@
 
 package org.apache.hadoop.hbase.backup;
 
-import static org.junit.Assert.assertTrue;
-
 import java.util.List;
 
 import org.apache.commons.logging.Log;
@@ -37,9 +35,8 @@ public class TestFullBackup extends TestBackupBase {
   public void testFullBackupSingle() throws Exception {
     LOG.info("test full backup on a single table with data");
     List<TableName> tables = Lists.newArrayList(table1);
-    String backupId = getBackupClient().create(BackupType.FULL, tables, BACKUP_ROOT_DIR);
-    assertTrue(checkSucceeded(backupId));
-    LOG.info("backup complete");
+    String backupId = fullTableBackup(tables);
+    LOG.info("backup complete for " + backupId);
   }
 
   /**
@@ -50,8 +47,7 @@ public class TestFullBackup extends TestBackupBase {
   public void testFullBackupMultiple() throws Exception {
     LOG.info("create full backup image on multiple tables with data");
     List<TableName> tables = Lists.newArrayList(table1, table1);
-    String backupId = getBackupClient().create(BackupType.FULL, tables, BACKUP_ROOT_DIR);
-    assertTrue(checkSucceeded(backupId));
+    String backupId = fullTableBackup(tables);
   }
 
   /**
@@ -61,7 +57,6 @@ public class TestFullBackup extends TestBackupBase {
   @Test
   public void testFullBackupAll() throws Exception {
     LOG.info("create full backup image on all tables");
-    String backupId = getBackupClient().create(BackupType.FULL, null, BACKUP_ROOT_DIR);
-    assertTrue(checkSucceeded(backupId));
+    String backupId = fullTableBackup(null);
   }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestFullRestore.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestFullRestore.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestFullRestore.java
index e4c4a07..3139134 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestFullRestore.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestFullRestore.java
@@ -18,7 +18,6 @@ import java.util.List;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.client.HBaseAdmin;
 import org.apache.hadoop.hbase.testclassification.LargeTests;
@@ -42,14 +41,11 @@ public class TestFullRestore extends TestBackupBase {
     LOG.info("test full restore on a single table empty table");
 
     List<TableName> tables = Lists.newArrayList(table1);
-    String backupId = getBackupClient().create(BackupType.FULL, tables, BACKUP_ROOT_DIR);
-    assertTrue(checkSucceeded(backupId));
+    String backupId = fullTableBackup(tables);
     LOG.info("backup complete");
 
     TableName[] tableset = new TableName[] { table1 };
     TableName[] tablemap = new TableName[] { table1_restore };
-    Path path = new Path(BACKUP_ROOT_DIR);
-    HBackupFileSystem hbfs = new HBackupFileSystem(conf1, path, backupId);
     RestoreClient client = getRestoreClient();
     client.restore(BACKUP_ROOT_DIR, backupId, false, false, tableset, tablemap, false);
     HBaseAdmin hba = TEST_UTIL.getHBaseAdmin();
@@ -66,13 +62,10 @@ public class TestFullRestore extends TestBackupBase {
   public void testFullRestoreMultiple() throws Exception {
     LOG.info("create full backup image on multiple tables");
     List<TableName> tables = Lists.newArrayList(table2, table3);
-    String backupId = getBackupClient().create(BackupType.FULL, tables, BACKUP_ROOT_DIR);
-    assertTrue(checkSucceeded(backupId));
+    String backupId = fullTableBackup(tables);
 
     TableName[] restore_tableset = new TableName[] { table2, table3 };
     TableName[] tablemap = new TableName[] { table2_restore, table3_restore };
-    Path path = new Path(BACKUP_ROOT_DIR);
-    HBackupFileSystem hbfs = new HBackupFileSystem(conf1, path, backupId);
     RestoreClient client = getRestoreClient();
     client.restore(BACKUP_ROOT_DIR, backupId, false, false,
       restore_tableset, tablemap, false);
@@ -93,13 +86,10 @@ public class TestFullRestore extends TestBackupBase {
 
     LOG.info("test full restore on a single table empty table");
     List<TableName> tables = Lists.newArrayList(table1);
-    String backupId = getBackupClient().create(BackupType.FULL, tables, BACKUP_ROOT_DIR);
-    assertTrue(checkSucceeded(backupId));
+    String backupId = fullTableBackup(tables);
     LOG.info("backup complete");
 
     TableName[] tableset = new TableName[] { table1 };
-    Path path = new Path(BACKUP_ROOT_DIR);
-    HBackupFileSystem hbfs = new HBackupFileSystem(conf1, path, backupId);
     RestoreClient client = getRestoreClient();
     client.restore(BACKUP_ROOT_DIR, backupId, false, false, tableset, null,
       true);
@@ -114,12 +104,9 @@ public class TestFullRestore extends TestBackupBase {
     LOG.info("create full backup image on multiple tables");
 
     List<TableName> tables = Lists.newArrayList(table2, table3);
-    String backupId = getBackupClient().create(BackupType.FULL, tables, BACKUP_ROOT_DIR);
-    assertTrue(checkSucceeded(backupId));
+    String backupId = fullTableBackup(tables);
 
     TableName[] restore_tableset = new TableName[] { table2, table3 };
-    Path path = new Path(BACKUP_ROOT_DIR);
-    HBackupFileSystem hbfs = new HBackupFileSystem(conf1, path, backupId);
     RestoreClient client = getRestoreClient();
     client.restore(BACKUP_ROOT_DIR, backupId, false,
       false, restore_tableset, null, true);
@@ -134,14 +121,12 @@ public class TestFullRestore extends TestBackupBase {
 
     LOG.info("test restore fails on a single table that does not exist");
     List<TableName> tables = Lists.newArrayList(table1);
-    String backupId = getBackupClient().create(BackupType.FULL, tables, BACKUP_ROOT_DIR);
-    assertTrue(checkSucceeded(backupId));
+    String backupId = fullTableBackup(tables);
+
     LOG.info("backup complete");
 
     TableName[] tableset = new TableName[] { TableName.valueOf("faketable") };
     TableName[] tablemap = new TableName[] { table1_restore };
-    Path path = new Path(BACKUP_ROOT_DIR);
-    HBackupFileSystem hbfs = new HBackupFileSystem(conf1, path, backupId);
     RestoreClient client = getRestoreClient();
     client.restore(BACKUP_ROOT_DIR, backupId, false, false, tableset, tablemap,
       false);
@@ -157,14 +142,11 @@ public class TestFullRestore extends TestBackupBase {
     LOG.info("test restore fails on multiple tables that do not exist");
 
     List<TableName> tables = Lists.newArrayList(table2, table3);
-    String backupId = getBackupClient().create(BackupType.FULL, tables, BACKUP_ROOT_DIR);
-    assertTrue(checkSucceeded(backupId));
+    String backupId = fullTableBackup(tables);
 
     TableName[] restore_tableset
       = new TableName[] { TableName.valueOf("faketable1"), TableName.valueOf("faketable2") };
     TableName[] tablemap = new TableName[] { table2_restore, table3_restore };
-    Path path = new Path(BACKUP_ROOT_DIR);
-    HBackupFileSystem hbfs = new HBackupFileSystem(conf1, path, backupId);
     RestoreClient client = getRestoreClient();
     client.restore(BACKUP_ROOT_DIR, backupId, false,
       false, restore_tableset, tablemap, false);

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestIncrementalBackup.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestIncrementalBackup.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestIncrementalBackup.java
index 23b1af1..6669612 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestIncrementalBackup.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestIncrementalBackup.java
@@ -46,17 +46,20 @@ public class TestIncrementalBackup extends TestBackupBase {
   //implement all testcases in 1 test since incremental backup/restore has dependencies
   @Test
   public void TestIncBackupRestore() throws Exception {
-    HBackupFileSystem hbfs;
-
     // #1 - create full backup for all tables
     LOG.info("create full backup image for all tables");
 
     List<TableName> tables = Lists.newArrayList(table1, table2, table3, table4);
-    String backupIdFull = getBackupClient().create(BackupType.FULL, tables, BACKUP_ROOT_DIR);
+    HBaseAdmin admin = null;
+    Connection conn = ConnectionFactory.createConnection(conf1);
+    admin = (HBaseAdmin) conn.getAdmin();
+
+    BackupRequest request = new BackupRequest();
+    request.setBackupType(BackupType.FULL).setTableList(tables).setTargetRootDir(BACKUP_ROOT_DIR);
+    String backupIdFull = admin.backupTables(request);
 
     assertTrue(checkSucceeded(backupIdFull));
 
-    Connection conn = ConnectionFactory.createConnection(conf1);
     // #2 - insert some data to table
     HTable t1 = (HTable) conn.getTable(table1);
     Put p1;
@@ -81,13 +84,11 @@ public class TestIncrementalBackup extends TestBackupBase {
     t2.close();
 
     // #3 - incremental backup for multiple tables
-
-
     tables = Lists.newArrayList(table1, table2, table3);
-    String backupIdIncMultiple = getBackupClient().create(BackupType.INCREMENTAL,
-      tables, BACKUP_ROOT_DIR);
-    assertTrue(checkSucceeded(backupIdIncMultiple));
-
+    request = new BackupRequest();
+    request.setBackupType(BackupType.INCREMENTAL).setTableList(tables)
+    .setTargetRootDir(BACKUP_ROOT_DIR);
+    String backupIdIncMultiple = admin.backupTables(request);
 
     // #4 - restore full backup for all tables, without overwrite
     TableName[] tablesRestoreFull =
@@ -96,7 +97,6 @@ public class TestIncrementalBackup extends TestBackupBase {
     TableName[] tablesMapFull =
         new TableName[] { table1_restore, table2_restore, table3_restore, table4_restore };
 
-    hbfs = new HBackupFileSystem(conf1, new Path(BACKUP_ROOT_DIR), backupIdFull);
     RestoreClient client = getRestoreClient();
     client.restore(BACKUP_ROOT_DIR, backupIdFull, false, false,
       tablesRestoreFull,
@@ -133,7 +133,7 @@ public class TestIncrementalBackup extends TestBackupBase {
         new TableName[] { table1, table2, table3 };
     TableName[] tablesMapIncMultiple =
         new TableName[] { table1_restore, table2_restore, table3_restore };
-    hbfs = new HBackupFileSystem(conf1, new Path(BACKUP_ROOT_DIR), backupIdIncMultiple);
+    LOG.info("restore inc backup " + backupIdIncMultiple);
     client = getRestoreClient();
     client.restore(BACKUP_ROOT_DIR, backupIdIncMultiple, false, false,
       tablesRestoreIncMultiple, tablesMapIncMultiple, true);
@@ -153,15 +153,15 @@ public class TestIncrementalBackup extends TestBackupBase {
     // #7 - incremental backup for single, empty table
 
     tables = toList(table4.getNameAsString());
-    String backupIdIncEmpty =
-        getBackupClient().create(BackupType.INCREMENTAL, tables, BACKUP_ROOT_DIR);
-    assertTrue(checkSucceeded(backupIdIncEmpty));
+    request = new BackupRequest();
+    request.setBackupType(BackupType.INCREMENTAL).setTableList(tables)
+    .setTargetRootDir(BACKUP_ROOT_DIR);
+    String backupIdIncEmpty = admin.backupTables(request);
 
 
     // #8 - restore incremental backup for single empty table, with overwrite
     TableName[] tablesRestoreIncEmpty = new TableName[] { table4 };
     TableName[] tablesMapIncEmpty = new TableName[] { table4_restore };
-    hbfs = new HBackupFileSystem(conf1, new Path(BACKUP_ROOT_DIR), backupIdIncEmpty);
 
     getRestoreClient().restore(BACKUP_ROOT_DIR, backupIdIncEmpty, false, false,
       tablesRestoreIncEmpty,
@@ -170,8 +170,8 @@ public class TestIncrementalBackup extends TestBackupBase {
     hTable = (HTable) conn.getTable(table4_restore);
     Assert.assertThat(TEST_UTIL.countRows(hTable), CoreMatchers.equalTo(0));
     hTable.close();
+    admin.close();
     conn.close();
-
   }
 
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestRemoteBackup.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestRemoteBackup.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestRemoteBackup.java
index 035188c..f97f30a 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestRemoteBackup.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestRemoteBackup.java
@@ -11,8 +11,6 @@
 
 package org.apache.hadoop.hbase.backup;
 
-import static org.junit.Assert.assertTrue;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.hbase.testclassification.LargeTests;
@@ -35,11 +33,9 @@ public class TestRemoteBackup extends TestBackupBase {
 
     LOG.info("test remote full backup on a single table");
 
-    String backupId =
-        getBackupClient().create(BackupType.FULL,
-          Lists.newArrayList(table1), BACKUP_REMOTE_ROOT_DIR);
-    LOG.info("backup complete");
-    assertTrue(checkSucceeded(backupId));
+    String backupId = backupTables(BackupType.FULL,
+      Lists.newArrayList(table1), BACKUP_REMOTE_ROOT_DIR);
+    LOG.info("backup complete " + backupId);
   }
 
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestRemoteRestore.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestRemoteRestore.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestRemoteRestore.java
index 6a66a0d..cd597e1 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestRemoteRestore.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestRemoteRestore.java
@@ -35,15 +35,12 @@ public class TestRemoteRestore extends TestBackupBase {
   public void testFullRestoreRemote() throws Exception {
 
     LOG.info("test remote full backup on a single table");
-    String backupId =
-        getBackupClient().create(BackupType.FULL, toList(table1.getNameAsString()),
-          BACKUP_REMOTE_ROOT_DIR);
+    String backupId = backupTables(BackupType.FULL, toList(table1.getNameAsString()),
+      BACKUP_REMOTE_ROOT_DIR);
     LOG.info("backup complete");
-    assertTrue(checkSucceeded(backupId));
     TableName[] tableset = new TableName[] { table1 };
     TableName[] tablemap = new TableName[] { table1_restore };
     Path path = new Path(BACKUP_REMOTE_ROOT_DIR);
-    HBackupFileSystem hbfs = new HBackupFileSystem(conf1, path, backupId);
     getRestoreClient().restore(BACKUP_REMOTE_ROOT_DIR, backupId, false, false, tableset,
       tablemap, false);
     HBaseAdmin hba = TEST_UTIL.getHBaseAdmin();

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestRestoreBoundaryTests.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestRestoreBoundaryTests.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestRestoreBoundaryTests.java
index 6f9b3c7..acded77 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestRestoreBoundaryTests.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestRestoreBoundaryTests.java
@@ -43,15 +43,10 @@ public class TestRestoreBoundaryTests extends TestBackupBase {
   @Test
   public void testFullRestoreSingleEmpty() throws Exception {
     LOG.info("test full restore on a single table empty table");
-    String backupId =
-        getBackupClient().create(BackupType.FULL, toList(table1.getNameAsString()),
-            BACKUP_ROOT_DIR);
+    String backupId = fullTableBackup(toList(table1.getNameAsString()));
     LOG.info("backup complete");
-    assertTrue(checkSucceeded(backupId));
     TableName[] tableset = new TableName[] { table1 };
     TableName[] tablemap = new TableName[] { table1_restore };
-    Path path = new Path(BACKUP_ROOT_DIR);
-    HBackupFileSystem hbfs = new HBackupFileSystem(conf1, path, backupId);
     getRestoreClient().restore(BACKUP_ROOT_DIR, backupId, false, false, tableset, tablemap,
       false);
     HBaseAdmin hba = TEST_UTIL.getHBaseAdmin();
@@ -68,12 +63,9 @@ public class TestRestoreBoundaryTests extends TestBackupBase {
     LOG.info("create full backup image on multiple tables");
 
     List<TableName> tables = toList(table2.getNameAsString(), table3.getNameAsString());
-    String backupId = getBackupClient().create(BackupType.FULL, tables,BACKUP_ROOT_DIR);
-    assertTrue(checkSucceeded(backupId));
+    String backupId = fullTableBackup(tables);
     TableName[] restore_tableset = new TableName[] { table2, table3};
     TableName[] tablemap = new TableName[] { table2_restore, table3_restore };
-    Path path = new Path(BACKUP_ROOT_DIR);
-    HBackupFileSystem hbfs = new HBackupFileSystem(conf1, path, backupId);
     getRestoreClient().restore(BACKUP_ROOT_DIR, backupId, false, false, restore_tableset,
       tablemap,
       false);

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java
index 3090488..d3d5357 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/master/TestCatalogJanitor.java
@@ -53,6 +53,7 @@ import org.apache.hadoop.hbase.ServerName;
 import org.apache.hadoop.hbase.TableDescriptor;
 import org.apache.hadoop.hbase.TableDescriptors;
 import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.backup.BackupType;
 import org.apache.hadoop.hbase.client.ClusterConnection;
 import org.apache.hadoop.hbase.client.HConnectionTestingUtility;
 import org.apache.hadoop.hbase.client.Result;
@@ -85,6 +86,7 @@ import org.apache.hadoop.hbase.testclassification.SmallTests;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.hadoop.hbase.util.FSUtils;
 import org.apache.hadoop.hbase.util.HFileArchiveUtil;
+import org.apache.hadoop.hbase.util.Pair;
 import org.apache.hadoop.hbase.util.Triple;
 import org.apache.hadoop.hbase.zookeeper.MetaTableLocator;
 import org.apache.hadoop.hbase.zookeeper.ZooKeeperWatcher;
@@ -430,6 +432,16 @@ public class TestCatalogJanitor {
     }
 
     @Override
+    public Pair<Long, String> backupTables(
+        final BackupType type,
+        final List<TableName> tableList,
+        final String targetRootDir, final int workers,
+        final long bandwidth) throws IOException {
+      return null;
+    }
+
+
+    @Override
     public List<HTableDescriptor> listTableDescriptorsByNamespace(String name) throws IOException {
       return null;  //To change body of implemented methods use File | Settings | File Templates.
     }


[6/6] hbase git commit: HBASE-15411 Rewrite backup with Procedure V2 - phase 1

Posted by te...@apache.org.
HBASE-15411 Rewrite backup with Procedure V2 - phase 1


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

Branch: refs/heads/HBASE-7912
Commit: b37cc7606f498eef7190998a528be2e18d206a06
Parents: 1e9470d
Author: tedyu <yu...@gmail.com>
Authored: Fri Apr 1 15:02:22 2016 -0700
Committer: tedyu <yu...@gmail.com>
Committed: Fri Apr 1 15:02:22 2016 -0700

----------------------------------------------------------------------
 .../hadoop/hbase/backup/BackupRequest.java      |   82 +
 .../org/apache/hadoop/hbase/client/Admin.java   |   31 +
 .../hbase/client/ConnectionImplementation.java  |    7 +
 .../apache/hadoop/hbase/client/HBaseAdmin.java  |  121 +-
 .../hadoop/hbase/protobuf/ProtobufUtil.java     |    6 +
 .../hadoop/hbase/protobuf/RequestConverter.java |   18 +
 .../hbase/protobuf/generated/BackupProtos.java  | 6099 ++++++++++++------
 .../hbase/protobuf/generated/MasterProtos.java  | 2567 +++++++-
 hbase-protocol/src/main/protobuf/Backup.proto   |   24 +
 hbase-protocol/src/main/protobuf/Master.proto   |   20 +-
 .../hadoop/hbase/backup/BackupClient.java       |   40 -
 .../hbase/backup/BackupRestoreFactory.java      |   16 -
 .../hadoop/hbase/backup/HBackupFileSystem.java  |  340 +-
 .../hbase/backup/impl/BackupClientImpl.java     |  183 -
 .../hbase/backup/impl/BackupCommands.java       |   21 +-
 .../hadoop/hbase/backup/impl/BackupContext.java |   46 +-
 .../hadoop/hbase/backup/impl/BackupHandler.java |  702 --
 .../hadoop/hbase/backup/impl/BackupManager.java |   37 +-
 .../hbase/backup/impl/BackupSnapshotCopy.java   |    8 +-
 .../hbase/backup/impl/BackupSystemTable.java    |   31 +-
 .../backup/impl/BackupSystemTableHelper.java    |   34 +-
 .../hadoop/hbase/backup/impl/BackupUtil.java    |   49 +-
 .../backup/impl/FullTableBackupProcedure.java   |  745 +++
 .../impl/IncrementalTableBackupProcedure.java   |  325 +
 .../hbase/backup/impl/RestoreClientImpl.java    |    3 +-
 .../hadoop/hbase/backup/impl/RestoreUtil.java   |  347 +-
 .../mapreduce/MapReduceBackupCopyService.java   |   25 +-
 .../org/apache/hadoop/hbase/master/HMaster.java |   74 +
 .../hadoop/hbase/master/MasterRpcServices.java  |   20 +
 .../hadoop/hbase/master/MasterServices.java     |   20 +
 .../master/procedure/MasterProcedureUtil.java   |   69 +
 .../procedure/TableProcedureInterface.java      |    2 +-
 .../hadoop/hbase/backup/TestBackupBase.java     |   36 +-
 .../hbase/backup/TestBackupBoundaryTests.java   |   16 +-
 .../hbase/backup/TestBackupLogCleaner.java      |   10 +-
 .../hbase/backup/TestBackupSystemTable.java     |    9 +-
 .../hadoop/hbase/backup/TestFullBackup.java     |   13 +-
 .../hadoop/hbase/backup/TestFullRestore.java    |   32 +-
 .../hbase/backup/TestIncrementalBackup.java     |   34 +-
 .../hadoop/hbase/backup/TestRemoteBackup.java   |   10 +-
 .../hadoop/hbase/backup/TestRemoteRestore.java  |    7 +-
 .../hbase/backup/TestRestoreBoundaryTests.java  |   12 +-
 .../hadoop/hbase/master/TestCatalogJanitor.java |   12 +
 43 files changed, 8341 insertions(+), 3962 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-client/src/main/java/org/apache/hadoop/hbase/backup/BackupRequest.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/backup/BackupRequest.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/backup/BackupRequest.java
new file mode 100644
index 0000000..bbf421c
--- /dev/null
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/backup/BackupRequest.java
@@ -0,0 +1,82 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.backup;
+
+import java.util.List;
+
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.backup.BackupType;
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
+import org.apache.hadoop.hbase.classification.InterfaceStability;
+
+/**
+ * POJO class for backup request
+ */
+@InterfaceAudience.Public
+@InterfaceStability.Evolving
+public final class BackupRequest {
+  private BackupType type;
+  private List<TableName> tableList;
+  private String targetRootDir;
+  private int workers = -1;
+  private long bandwidth = -1L;
+
+  public BackupRequest() {
+  }
+
+  public BackupRequest setBackupType(BackupType type) {
+    this.type = type;
+    return this;
+  }
+  public BackupType getBackupType() {
+    return this.type;
+  }
+
+  public BackupRequest setTableList(List<TableName> tableList) {
+    this.tableList = tableList;
+    return this;
+  }
+  public List<TableName> getTableList() {
+    return this.tableList;
+  }
+
+  public BackupRequest setTargetRootDir(String targetRootDir) {
+    this.targetRootDir = targetRootDir;
+    return this;
+  }
+  public String getTargetRootDir() {
+    return this.targetRootDir;
+  }
+
+  public BackupRequest setWorkers(int workers) {
+    this.workers = workers;
+    return this;
+  }
+  public int getWorkers() {
+    return this.workers;
+  }
+
+  public BackupRequest setBandwidth(long bandwidth) {
+    this.bandwidth = bandwidth;
+    return this;
+  }
+  public long getBandwidth() {
+    return this.bandwidth;
+  }
+}

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java
index c3b524b..02ffc18 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/Admin.java
@@ -37,6 +37,8 @@ import org.apache.hadoop.hbase.ServerName;
 import org.apache.hadoop.hbase.TableExistsException;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.TableNotFoundException;
+import org.apache.hadoop.hbase.backup.BackupRequest;
+import org.apache.hadoop.hbase.backup.BackupType;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.classification.InterfaceStability;
 import org.apache.hadoop.hbase.client.security.SecurityCapability;
@@ -913,6 +915,35 @@ public interface Admin extends Abortable, Closeable {
     throws IOException;
 
   /**
+   * Backs up given list of tables fully. Asynchronous operation. This means that
+   * it may be a while before all your tables are backed up.
+   * You can use Future.get(long, TimeUnit) to wait on the operation to complete.
+   * 
+   * @param request BackupRequest instance which contains the following members:
+   *  type whether the backup is full or incremental
+   *  tableList list of tables to backup
+   *  targetRootDir root dir for saving the backup
+   *  workers number of paralle workers. -1 - system defined
+   *  bandwidth bandwidth per worker in MB per sec. -1 - unlimited
+   * @return the result of the async backup. You can use Future.get(long, TimeUnit) to wait on the
+   *     operation to complete
+   */
+  public Future<String> backupTablesAsync(final BackupRequest request) throws IOException;
+
+  /**
+   * Backs up given list of tables fully. Synchronous operation.
+   * 
+   * @param request BackupRequest instance which contains the following members:
+   *  type whether the backup is full or incremental
+   *  tableList list of tables to backup
+   *  targetRootDir root dir for saving the backup
+   *  workers number of paralle workers. -1 - system defined
+   *  bandwidth bandwidth per worker in MB per sec. -1 - unlimited
+   * @return the backup Id
+   */
+  public String backupTables(final BackupRequest request) throws IOException;
+
+  /**
    * Modify an existing table, more IRB friendly version. Asynchronous operation.  This means that
    * it may be a while before your schema change is updated across all of the table.
    * You can use Future.get(long, TimeUnit) to wait on the operation to complete.

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java
index 64eb9fb..c245ef4 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/ConnectionImplementation.java
@@ -1401,6 +1401,13 @@ class ConnectionImplementation implements ClusterConnection, Closeable {
       }
 
       @Override
+      public MasterProtos.BackupTablesResponse backupTables(
+          RpcController controller,
+          MasterProtos.BackupTablesRequest request)  throws ServiceException {
+        return stub.backupTables(controller, request);
+      }
+
+      @Override
       public MasterProtos.AddColumnResponse addColumn(
           RpcController controller,
           MasterProtos.AddColumnRequest request) throws ServiceException {

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
index c2a0bb8..f19da53 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java
@@ -61,6 +61,8 @@ import org.apache.hadoop.hbase.TableNotDisabledException;
 import org.apache.hadoop.hbase.TableNotFoundException;
 import org.apache.hadoop.hbase.UnknownRegionException;
 import org.apache.hadoop.hbase.ZooKeeperConnectionException;
+import org.apache.hadoop.hbase.backup.BackupRequest;
+import org.apache.hadoop.hbase.backup.BackupClientUtil;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.classification.InterfaceStability;
 import org.apache.hadoop.hbase.client.security.SecurityCapability;
@@ -83,6 +85,8 @@ import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.RollWALWriterReque
 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.RollWALWriterResponse;
 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.StopServerRequest;
 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.UpdateConfigurationRequest;
+import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest;
+import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse;
 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.NameStringPair;
 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.ProcedureDescription;
@@ -418,14 +422,6 @@ public class HBaseAdmin implements Admin {
       throw new TableNotFoundException(tableName.getNameAsString());
   }
 
-  private long getPauseTime(int tries) {
-    int triesCount = tries;
-    if (triesCount >= HConstants.RETRY_BACKOFF.length) {
-      triesCount = HConstants.RETRY_BACKOFF.length - 1;
-    }
-    return this.pause * HConstants.RETRY_BACKOFF[triesCount];
-  }
-
   @Override
   public void createTable(HTableDescriptor desc)
   throws IOException {
@@ -690,7 +686,7 @@ public class HBaseAdmin implements Admin {
       if (enabled) {
         break;
       }
-      long sleep = getPauseTime(tries);
+      long sleep = getPauseTime(tries, pause);
       if (LOG.isDebugEnabled()) {
         LOG.debug("Sleeping= " + sleep + "ms, waiting for all regions to be " +
           "enabled in " + tableName);
@@ -1568,6 +1564,73 @@ public class HBaseAdmin implements Admin {
   }
 
   @Override
+  public Future<String> backupTablesAsync(final BackupRequest userRequest) throws IOException {
+    BackupClientUtil.checkTargetDir(userRequest.getTargetRootDir(), conf);
+    if (userRequest.getTableList() != null) {
+      for (TableName table : userRequest.getTableList()) {
+        if (!tableExists(table)) {
+          throw new DoNotRetryIOException(table + "does not exist");
+        }
+      }
+    }
+
+    BackupTablesResponse response = executeCallable(
+      new MasterCallable<BackupTablesResponse>(getConnection()) {
+        @Override
+        public BackupTablesResponse call(int callTimeout) throws ServiceException {
+          BackupTablesRequest request = RequestConverter.buildBackupTablesRequest(
+            userRequest.getBackupType(), userRequest.getTableList(), userRequest.getTargetRootDir(),
+            userRequest.getWorkers(), userRequest.getBandwidth());
+          return master.backupTables(null, request);
+        }
+      });
+    return new TableBackupFuture(this, TableName.BACKUP_TABLE_NAME, response);
+  }
+
+  @Override
+  public String backupTables(final BackupRequest userRequest) throws IOException {
+    return get(
+      backupTablesAsync(userRequest),
+      syncWaitTimeout,
+      TimeUnit.MILLISECONDS);
+  }
+
+  public static class TableBackupFuture extends TableFuture<String> {
+    String backupId;
+    public TableBackupFuture(final HBaseAdmin admin, final TableName tableName,
+        final BackupTablesResponse response) {
+      super(admin, tableName,
+          (response != null && response.hasProcId()) ? response.getProcId() : null);
+      backupId = response.getBackupId();
+    }
+
+    String getBackupId() {
+      return backupId;
+    }
+
+    @Override
+    public String getOperationType() {
+      return "BACKUP";
+    }
+
+    @Override
+    protected String convertResult(final GetProcedureResultResponse response) throws IOException {
+      if (response.hasException()) {
+        throw ForeignExceptionUtil.toIOException(response.getException());
+      }
+      ByteString result = response.getResult();
+      if (result == null) return null;
+      return Bytes.toStringBinary(result.toByteArray());
+    }
+
+    @Override
+    protected String postOperationResult(final String result,
+      final long deadlineTs) throws IOException, TimeoutException {
+      return result;
+    }
+  }
+
+  @Override
   public Future<Void> modifyTable(final TableName tableName, final HTableDescriptor htd)
   throws IOException {
     if (!tableName.equals(htd.getTableName())) {
@@ -2173,17 +2236,13 @@ public class HBaseAdmin implements Admin {
     snapshot(builder.build());
   }
 
-  @Override
-  public void snapshot(SnapshotDescription snapshot) throws IOException, SnapshotCreationException,
-      IllegalArgumentException {
-    // actually take the snapshot
-    SnapshotResponse response = takeSnapshotAsync(snapshot);
+  public void waitForSnapshot(SnapshotDescription snapshot, long max,
+      HConnection conn) throws IOException {
     final IsSnapshotDoneRequest request = IsSnapshotDoneRequest.newBuilder().setSnapshot(snapshot)
         .build();
     IsSnapshotDoneResponse done = null;
     long start = EnvironmentEdgeManager.currentTime();
-    long max = response.getExpectedTimeout();
-    long maxPauseTime = max / this.numRetries;
+    long maxPauseTime = max / numRetries;
     int tries = 0;
     LOG.debug("Waiting a max of " + max + " ms for snapshot '" +
         ClientSnapshotDescriptionUtils.toString(snapshot) + "'' to complete. (max " +
@@ -2192,7 +2251,7 @@ public class HBaseAdmin implements Admin {
         || ((EnvironmentEdgeManager.currentTime() - start) < max && !done.getDone())) {
       try {
         // sleep a backoff <= pauseTime amount
-        long sleep = getPauseTime(tries++);
+        long sleep = getPauseTime(tries++, pause);
         sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
         LOG.debug("(#" + tries + ") Sleeping: " + sleep +
           "ms while waiting for snapshot completion.");
@@ -2201,7 +2260,7 @@ public class HBaseAdmin implements Admin {
         throw (InterruptedIOException)new InterruptedIOException("Interrupted").initCause(e);
       }
       LOG.debug("Getting current status of snapshot from master...");
-      done = executeCallable(new MasterCallable<IsSnapshotDoneResponse>(getConnection()) {
+      done = executeCallable(new MasterCallable<IsSnapshotDoneResponse>(conn) {
         @Override
         public IsSnapshotDoneResponse call(int callTimeout) throws ServiceException {
           return master.isSnapshotDone(null, request);
@@ -2215,6 +2274,14 @@ public class HBaseAdmin implements Admin {
   }
 
   @Override
+  public void snapshot(SnapshotDescription snapshot) throws IOException, SnapshotCreationException,
+      IllegalArgumentException {
+    // actually take the snapshot
+    SnapshotResponse response = takeSnapshotAsync(snapshot);
+    waitForSnapshot(snapshot, response.getExpectedTimeout(), getConnection());
+  }
+
+  @Override
   public SnapshotResponse takeSnapshotAsync(SnapshotDescription snapshot) throws IOException,
       SnapshotCreationException {
     ClientSnapshotDescriptionUtils.assertSnapshotRequestIsValid(snapshot);
@@ -2377,6 +2444,14 @@ public class HBaseAdmin implements Admin {
     return response.hasReturnData() ? response.getReturnData().toByteArray() : null;
   }
 
+  public static long getPauseTime(int tries, long pause) {
+    int triesCount = tries;
+    if (triesCount >= HConstants.RETRY_BACKOFF.length) {
+      triesCount = HConstants.RETRY_BACKOFF.length - 1;
+    }
+    return pause * HConstants.RETRY_BACKOFF[triesCount];
+  }
+
   @Override
   public void execProcedure(String signature, String instance, Map<String, String> props)
       throws IOException {
@@ -2410,7 +2485,7 @@ public class HBaseAdmin implements Admin {
         || ((EnvironmentEdgeManager.currentTime() - start) < max && !done)) {
       try {
         // sleep a backoff <= pauseTime amount
-        long sleep = getPauseTime(tries++);
+        long sleep = getPauseTime(tries++, pause);
         sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
         LOG.debug("(#" + tries + ") Sleeping: " + sleep +
           "ms while waiting for procedure completion.");
@@ -2475,7 +2550,7 @@ public class HBaseAdmin implements Admin {
     while (!done.getDone()) {
       try {
         // sleep a backoff <= pauseTime amount
-        long sleep = getPauseTime(tries++);
+        long sleep = getPauseTime(tries++, pause);
         sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
         LOG.debug(tries + ") Sleeping: " + sleep
             + " ms while we wait for snapshot restore to complete.");
@@ -3042,7 +3117,7 @@ public class HBaseAdmin implements Admin {
         }
 
         try {
-          Thread.sleep(getAdmin().getPauseTime(tries++));
+          Thread.sleep(getPauseTime(tries++, getAdmin().pause));
         } catch (InterruptedException e) {
           throw new InterruptedException(
             "Interrupted while waiting for the result of proc " + procId);
@@ -3144,7 +3219,7 @@ public class HBaseAdmin implements Admin {
           serverEx = e;
         }
         try {
-          Thread.sleep(getAdmin().getPauseTime(tries++));
+          Thread.sleep(getPauseTime(tries++, getAdmin().pause));
         } catch (InterruptedException e) {
           callable.throwInterruptedException();
         }
@@ -3321,7 +3396,7 @@ public class HBaseAdmin implements Admin {
         }
 
         try {
-          Thread.sleep(getAdmin().getPauseTime(tries++));
+          Thread.sleep(getPauseTime(tries++, getAdmin().pause));
         } catch (InterruptedException e) {
           throw new InterruptedIOException("Interrupted when opening" + " regions; "
               + actualRegCount.get() + " of " + numRegs + " regions processed so far");

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java
index 261a9aa..1ba3af2 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/ProtobufUtil.java
@@ -56,6 +56,7 @@ import org.apache.hadoop.hbase.ServerName;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.Tag;
 import org.apache.hadoop.hbase.TagUtil;
+import org.apache.hadoop.hbase.backup.BackupType;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.client.Append;
 import org.apache.hadoop.hbase.client.Consistency;
@@ -93,6 +94,7 @@ import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.ServerInfo;
 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.SplitRegionRequest;
 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.WarmupRegionRequest;
 import org.apache.hadoop.hbase.protobuf.generated.AuthenticationProtos;
+import org.apache.hadoop.hbase.protobuf.generated.BackupProtos;
 import org.apache.hadoop.hbase.protobuf.generated.CellProtos;
 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos;
 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.BulkLoadHFileRequest;
@@ -2727,6 +2729,10 @@ public final class ProtobufUtil {
     return tableNames;
   }
 
+  public static BackupProtos.BackupType toProtoBackupType(BackupType type) {
+    return BackupProtos.BackupType.valueOf(type.name());
+  }
+
   /**
    * Convert a protocol buffer CellVisibility to a client CellVisibility
    *

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/RequestConverter.java
----------------------------------------------------------------------
diff --git a/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/RequestConverter.java b/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/RequestConverter.java
index 99e993d..5babfb8 100644
--- a/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/RequestConverter.java
+++ b/hbase-client/src/main/java/org/apache/hadoop/hbase/protobuf/RequestConverter.java
@@ -29,6 +29,7 @@ import org.apache.hadoop.hbase.HRegionInfo;
 import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.ServerName;
 import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.backup.BackupType;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.client.Action;
 import org.apache.hadoop.hbase.client.Admin;
@@ -62,6 +63,7 @@ import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.StopServerRequest;
 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.UpdateFavoredNodesRequest;
 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.UpdateFavoredNodesRequest.RegionUpdateInfo;
 import org.apache.hadoop.hbase.protobuf.generated.AdminProtos.WarmupRegionRequest;
+import org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest;
 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos;
 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.BulkLoadHFileRequest;
 import org.apache.hadoop.hbase.protobuf.generated.ClientProtos.BulkLoadHFileRequest.FamilyPath;
@@ -1268,6 +1270,22 @@ public final class RequestConverter {
     return builder.build();
   }
 
+  public static BackupTablesRequest buildBackupTablesRequest(
+      final BackupType type, List<TableName> tableList, String targetRootDir, final int workers,
+      final long bandwidth) {
+    BackupTablesRequest.Builder builder = BackupTablesRequest.newBuilder();
+    builder.setType(ProtobufUtil.toProtoBackupType(type));
+    builder.setTargetRootDir(targetRootDir);
+    builder.setWorkers(workers);
+    builder.setBandwidth(bandwidth);
+    if (tableList != null) {
+      for (TableName table : tableList) {
+        builder.addTables(ProtobufUtil.toProtoTableName(table));
+      }
+    }
+    return builder.build();
+  }
+
   /**
    * Creates a protocol buffer GetSchemaAlterStatusRequest
    *


[3/6] hbase git commit: HBASE-15411 Rewrite backup with Procedure V2 - phase 1

Posted by te...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-protocol/src/main/protobuf/Backup.proto
----------------------------------------------------------------------
diff --git a/hbase-protocol/src/main/protobuf/Backup.proto b/hbase-protocol/src/main/protobuf/Backup.proto
index 383b990..c17ad06 100644
--- a/hbase-protocol/src/main/protobuf/Backup.proto
+++ b/hbase-protocol/src/main/protobuf/Backup.proto
@@ -27,6 +27,24 @@ option optimize_for = SPEED;
 
 import "HBase.proto";
 
+enum FullTableBackupState {
+  PRE_SNAPSHOT_TABLE = 1;
+  SNAPSHOT_TABLES = 2;
+  SNAPSHOT_COPY = 3;
+  BACKUP_COMPLETE = 4;
+}
+
+enum IncrementalTableBackupState {
+  PREPARE_INCREMENTAL = 1;
+  INCREMENTAL_COPY = 2;
+  INCR_BACKUP_COMPLETE = 3;
+}
+
+message SnapshotTableStateData {
+  required TableName table = 1;
+  required string snapshotName = 2;
+}
+
 enum BackupType {
   FULL = 0;
   INCREMENTAL = 1;
@@ -103,3 +121,9 @@ message BackupContext {
     STORE_MANIFEST = 5;
   } 
 }
+
+message BackupProcContext {
+  required BackupContext ctx = 1;
+  repeated ServerTimestamp server_timestamp = 2;
+}
+

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-protocol/src/main/protobuf/Master.proto
----------------------------------------------------------------------
diff --git a/hbase-protocol/src/main/protobuf/Master.proto b/hbase-protocol/src/main/protobuf/Master.proto
index 79bb862..6431c73 100644
--- a/hbase-protocol/src/main/protobuf/Master.proto
+++ b/hbase-protocol/src/main/protobuf/Master.proto
@@ -27,6 +27,7 @@ option java_generate_equals_and_hash = true;
 option optimize_for = SPEED;
 
 import "HBase.proto";
+import "Backup.proto";
 import "Client.proto";
 import "ClusterStatus.proto";
 import "ErrorHandling.proto";
@@ -485,7 +486,7 @@ message GetProcedureResultResponse {
 
 message AbortProcedureRequest {
   required uint64 proc_id = 1;
-  optional bool mayInterruptIfRunning = 2 [default = true];
+  optional bool may_interrupt_if_running = 2 [default = true];
 }
 
 message AbortProcedureResponse {
@@ -540,6 +541,19 @@ message SecurityCapabilitiesResponse {
   repeated Capability capabilities = 1;
 }
 
+message BackupTablesRequest {
+  required BackupType type = 1;
+  repeated TableName tables = 2;
+  required string target_root_dir = 3;
+  optional int64 workers = 4;
+  optional int64 bandwidth = 5;
+}
+
+message BackupTablesResponse {
+  optional uint64 proc_id = 1;
+  optional string backup_id = 2;
+}
+
 service MasterService {
   /** Used by the client to get the number of regions that have received the updated schema */
   rpc GetSchemaAlterStatus(GetSchemaAlterStatusRequest)
@@ -814,4 +828,8 @@ service MasterService {
   /** returns a list of procedures */
   rpc ListProcedures(ListProceduresRequest)
     returns(ListProceduresResponse);
+
+  /** backup table set */
+  rpc backupTables(BackupTablesRequest)
+    returns(BackupTablesResponse);
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/BackupClient.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/BackupClient.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/BackupClient.java
deleted file mode 100644
index 7c8ea39..0000000
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/BackupClient.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.hbase.backup;
-
-import java.io.IOException;
-import java.util.List;
-
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.TableName;
-
-public interface BackupClient {
-
-  public void setConf(Configuration conf);
-
-  /**
-   * Send backup request to server, and monitor the progress if necessary
-   * @param backupType : full or incremental
-   * @param targetRootDir : the root path specified by user
-   * @param tableList : the table list specified by user
-   * @return backupId backup id
-   * @throws IOException exception
-   */
- public String create(BackupType backupType, List<TableName> tableList,
-      String targetRootDir) throws IOException;
- }

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/BackupRestoreFactory.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/BackupRestoreFactory.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/BackupRestoreFactory.java
index 6fbfe18..e0c6483 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/BackupRestoreFactory.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/BackupRestoreFactory.java
@@ -18,7 +18,6 @@
 package org.apache.hadoop.hbase.backup;
 
 import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.hbase.backup.impl.BackupClientImpl;
 import org.apache.hadoop.hbase.backup.impl.BackupCopyService;
 import org.apache.hadoop.hbase.backup.impl.IncrementalRestoreService;
 import org.apache.hadoop.hbase.backup.impl.RestoreClientImpl;
@@ -34,7 +33,6 @@ public final class BackupRestoreFactory {
 
   public final static String HBASE_INCR_RESTORE_IMPL_CLASS = "hbase.incremental.restore.class";
   public final static String HBASE_BACKUP_COPY_IMPL_CLASS = "hbase.backup.copy.class";
-  public final static String HBASE_BACKUP_CLIENT_IMPL_CLASS = "hbase.backup.client.class";
   public final static String HBASE_RESTORE_CLIENT_IMPL_CLASS = "hbase.restore.client.class";
 
   private BackupRestoreFactory(){
@@ -66,20 +64,6 @@ public final class BackupRestoreFactory {
   }
   
   /**
-   * Gets backup client implementation
-   * @param conf - configuration
-   * @return backup client
-   */
-  public static BackupClient getBackupClient(Configuration conf) {
-    Class<? extends BackupClient> cls =
-        conf.getClass(HBASE_BACKUP_CLIENT_IMPL_CLASS, BackupClientImpl.class,
-          BackupClient.class);
-    BackupClient client = ReflectionUtils.newInstance(cls, conf);
-    client.setConf(conf);
-    return client;
-  }
-  
-  /**
    * Gets restore client implementation
    * @param conf - configuration
    * @return backup client

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/HBackupFileSystem.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/HBackupFileSystem.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/HBackupFileSystem.java
index 6e5a355..4e88125 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/HBackupFileSystem.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/HBackupFileSystem.java
@@ -19,36 +19,19 @@
 
 package org.apache.hadoop.hbase.backup;
 
-import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.TreeMap;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FileStatus;
 import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.FileUtil;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hbase.HConstants;
-import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.backup.impl.BackupManifest;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.classification.InterfaceStability;
-import org.apache.hadoop.hbase.io.HFileLink;
-import org.apache.hadoop.hbase.io.hfile.CacheConfig;
-import org.apache.hadoop.hbase.io.hfile.HFile;
-import org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles;
-import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
-import org.apache.hadoop.hbase.regionserver.HRegionFileSystem;
-import org.apache.hadoop.hbase.regionserver.HStore;
-import org.apache.hadoop.hbase.regionserver.StoreFileInfo;
-import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
-import org.apache.hadoop.hbase.snapshot.SnapshotManifest;
-import org.apache.hadoop.hbase.util.Bytes;
 
 /**
  * View to an on-disk Backup Image FileSytem
@@ -59,56 +42,10 @@ import org.apache.hadoop.hbase.util.Bytes;
 public class HBackupFileSystem {
   public static final Log LOG = LogFactory.getLog(HBackupFileSystem.class);
 
-  private final String RESTORE_TMP_PATH = "/tmp";
-  private final String[] ignoreDirs = { "recovered.edits" };
-
-  private final Configuration conf;
-  private final FileSystem fs;
-  private final Path backupRootPath;
-  private final Path restoreTmpPath;
-  private final String backupId;
-
-  /**
-   * Create a view to the on-disk Backup Image.
-   * @param conf  to use
-   * @param backupPath  to where the backup Image stored
-   * @param backupId represent backup Image
-   */
-  public HBackupFileSystem(final Configuration conf, final Path backupRootPath, final String backupId)
-      throws IOException {
-    this.conf = conf;
-    this.fs = backupRootPath.getFileSystem(conf);
-    this.backupRootPath = backupRootPath;
-    this.backupId = backupId; // the backup ID for the lead backup Image
-    this.restoreTmpPath = new Path(conf.get("hbase.fs.tmp.dir") != null?
-          conf.get("hbase.fs.tmp.dir"): RESTORE_TMP_PATH,
-        "restore");
-  }
-
-  public Path getBackupRootPath() {
-    return backupRootPath;
-  }
-
-  public String getBackupId() {
-    return backupId;
-  }
-
   /**
-   * @param tableName is the table backed up
-   * @return {@link HTableDescriptor} saved in backup image of the table
+   * This is utility class.
    */
-  public HTableDescriptor getTableDesc(TableName tableName)
-      throws FileNotFoundException, IOException {
-    Path tableInfoPath = this.getTableInfoPath(tableName);
-    SnapshotDescription desc = SnapshotDescriptionUtils.readSnapshotInfo(fs, tableInfoPath);
-    SnapshotManifest manifest = SnapshotManifest.open(conf, fs, tableInfoPath, desc);
-    HTableDescriptor tableDescriptor = manifest.getTableDescriptor();
-    if (!tableDescriptor.getNameAsString().equals(tableName)) {
-      LOG.error("couldn't find Table Desc for table: " + tableName + " under tableInfoPath: "
-          + tableInfoPath.toString());
-      LOG.error("tableDescriptor.getNameAsString() = " + tableDescriptor.getNameAsString());
-    }
-    return tableDescriptor;
+  private HBackupFileSystem() {
   }
 
   /**
@@ -141,69 +78,6 @@ public class HBackupFileSystem {
   }
 
   /**
-   * return value represent path for:
-   * ".../user/biadmin/backup1/default/t1_dn/backup_1396650096738/.hbase-snapshot"
-   * @param backupRootPath backup root path
-   * @param tableName table name
-   * @param backupId backup Id
-   * @return path for snapshot
-   */
-  public static Path getTableSnapshotPath(Path backupRootPath, TableName tableName,
-      String backupId) {
-    return new Path(getTableBackupPath(backupRootPath, tableName, backupId),
-      HConstants.SNAPSHOT_DIR_NAME);
-  }
-
-  /**
-   * return value represent path for:
-   * "..../default/t1_dn/backup_1396650096738/.hbase-snapshot/snapshot_1396650097621_default_t1_dn"
-   * this path contains .snapshotinfo, .tabledesc (0.96 and 0.98) this path contains .snapshotinfo,
-   * .data.manifest (trunk)
-   * @param tableName table name
-   * @return path to table info
-   * @throws FileNotFoundException exception
-   * @throws IOException exception
-   */
-  public Path getTableInfoPath(TableName tableName)
-      throws FileNotFoundException, IOException {
-    Path tableSnapShotPath = getTableSnapshotPath(backupRootPath, tableName, backupId);
-    Path tableInfoPath = null;
-
-    // can't build the path directly as the timestamp values are different
-    FileStatus[] snapshots = fs.listStatus(tableSnapShotPath);
-    for (FileStatus snapshot : snapshots) {
-      tableInfoPath = snapshot.getPath();
-      // SnapshotManifest.DATA_MANIFEST_NAME = "data.manifest";
-      if (tableInfoPath.getName().endsWith("data.manifest")) {
-        break;
-      }
-    }
-    return tableInfoPath;
-  }
-
-  /**
-   * return value represent path for:
-   * ".../user/biadmin/backup1/default/t1_dn/backup_1396650096738/archive/data/default/t1_dn"
-   * @param tabelName table name
-   * @return path to table archive
-   * @throws IOException exception
-   */
-  public Path getTableArchivePath(TableName tableName)
-      throws IOException {
-    Path baseDir = new Path(getTableBackupPath(backupRootPath, tableName, backupId),
-      HConstants.HFILE_ARCHIVE_DIRECTORY);
-    Path dataDir = new Path(baseDir, HConstants.BASE_NAMESPACE_DIR);
-    Path archivePath = new Path(dataDir, tableName.getNamespaceAsString());
-    Path tableArchivePath =
-        new Path(archivePath, tableName.getQualifierAsString());
-    if (!fs.exists(tableArchivePath) || !fs.getFileStatus(tableArchivePath).isDirectory()) {
-      LOG.debug("Folder tableArchivePath: " + tableArchivePath.toString() + " does not exists");
-      tableArchivePath = null; // empty table has no archive
-    }
-    return tableArchivePath;
-  }
-
-  /**
    * Given the backup root dir and the backup id, return the log file location for an incremental
    * backup.
    * @param backupRootDir backup root directory
@@ -246,216 +120,6 @@ public class HBackupFileSystem {
   }
 
   /**
-   * Gets region list
-   * @param tableName table name
-   * @return RegionList region list
-   * @throws FileNotFoundException exception
-   * @throws IOException exception
-   */
-
-  public ArrayList<Path> getRegionList(TableName tableName)
-      throws FileNotFoundException, IOException {
-    Path tableArchivePath = this.getTableArchivePath(tableName);
-    ArrayList<Path> regionDirList = new ArrayList<Path>();
-    FileStatus[] children = fs.listStatus(tableArchivePath);
-    for (FileStatus childStatus : children) {
-      // here child refer to each region(Name)
-      Path child = childStatus.getPath();
-      regionDirList.add(child);
-    }
-    return regionDirList;
-  }
-
-  /**
-   * Gets region list
-   * @param tableArchivePath table archive path
-   * @return RegionList region list
-   * @throws FileNotFoundException exception
-   * @throws IOException exception
-   */
-  public ArrayList<Path> getRegionList(Path tableArchivePath) throws FileNotFoundException,
-  IOException {
-    ArrayList<Path> regionDirList = new ArrayList<Path>();
-    FileStatus[] children = fs.listStatus(tableArchivePath);
-    for (FileStatus childStatus : children) {
-      // here child refer to each region(Name)
-      Path child = childStatus.getPath();
-      regionDirList.add(child);
-    }
-    return regionDirList;
-  }
-
-  /**
-   * Counts the number of files in all subdirectories of an HBase tables, i.e. HFiles. And finds the
-   * maximum number of files in one HBase table.
-   * @param tableArchivePath archive path
-   * @return the maximum number of files found in 1 HBase table
-   * @throws IOException exception
-   */
-  public int getMaxNumberOfFilesInSubDir(Path tableArchivePath) throws IOException {
-    int result = 1;
-    ArrayList<Path> regionPathList = this.getRegionList(tableArchivePath);
-    // tableArchivePath = this.getTableArchivePath(tableName);
-
-    if (regionPathList == null || regionPathList.size() == 0) {
-      throw new IllegalStateException("Cannot restore hbase table because directory '"
-          + tableArchivePath + "' is not a directory.");
-    }
-
-    for (Path regionPath : regionPathList) {
-      result = Math.max(result, getNumberOfFilesInDir(regionPath));
-    }
-    return result;
-  }
-
-  /**
-   * Counts the number of files in all subdirectories of an HBase table, i.e. HFiles.
-   * @param regionPath Path to an HBase table directory
-   * @return the number of files all directories
-   * @throws IOException exception
-   */
-  public int getNumberOfFilesInDir(Path regionPath) throws IOException {
-    int result = 0;
-
-    if (!fs.exists(regionPath) || !fs.getFileStatus(regionPath).isDirectory()) {
-      throw new IllegalStateException("Cannot restore hbase table because directory '"
-          + regionPath.toString() + "' is not a directory.");
-    }
-
-    FileStatus[] tableDirContent = fs.listStatus(regionPath);
-    for (FileStatus subDirStatus : tableDirContent) {
-      FileStatus[] colFamilies = fs.listStatus(subDirStatus.getPath());
-      for (FileStatus colFamilyStatus : colFamilies) {
-        FileStatus[] colFamilyContent = fs.listStatus(colFamilyStatus.getPath());
-        result += colFamilyContent.length;
-      }
-    }
-    return result;
-  }
-
-  /**
-   * Duplicate the backup image if it's on local cluster
-   * @see HStore#bulkLoadHFile(String, long)
-   * @see HRegionFileSystem#bulkLoadStoreFile(String familyName, Path srcPath, long seqNum)
-   * @param tableArchivePath archive path
-   * @return the new tableArchivePath
-   * @throws IOException exception
-   */
-  public Path checkLocalAndBackup(Path tableArchivePath) throws IOException {
-    // Move the file if it's on local cluster
-    boolean isCopyNeeded = false;
-
-    FileSystem srcFs = tableArchivePath.getFileSystem(conf);
-    FileSystem desFs = FileSystem.get(conf);
-    if (tableArchivePath.getName().startsWith("/")) {
-      isCopyNeeded = true;
-    } else {
-      // This should match what is done in @see HRegionFileSystem#bulkLoadStoreFile(String, Path,
-      // long)
-      if (srcFs.getUri().equals(desFs.getUri())) {
-        LOG.debug("cluster hold the backup image: " + srcFs.getUri() + "; local cluster node: "
-            + desFs.getUri());
-        isCopyNeeded = true;
-      }
-    }
-    if (isCopyNeeded) {
-      LOG.debug("File " + tableArchivePath + " on local cluster, back it up before restore");
-      if (desFs.exists(restoreTmpPath)) {
-        try {
-          desFs.delete(restoreTmpPath, true);
-        } catch (IOException e) {
-          LOG.debug("Failed to delete path: " + restoreTmpPath
-            + ", need to check whether restore target DFS cluster is healthy");
-        }
-      }
-      FileUtil.copy(srcFs, tableArchivePath, desFs, restoreTmpPath, false, conf);
-      LOG.debug("Copied to temporary path on local cluster: " + restoreTmpPath);
-      tableArchivePath = restoreTmpPath;
-    }
-    return tableArchivePath;
-  }
-
-  /**
-   * Calculate region boundaries and add all the column families to the table descriptor
-   * @param regionDirList region dir list
-   * @return a set of keys to store the boundaries
-   */
-  public byte[][] generateBoundaryKeys(ArrayList<Path> regionDirList)
-      throws FileNotFoundException, IOException {
-    TreeMap<byte[], Integer> map = new TreeMap<byte[], Integer>(Bytes.BYTES_COMPARATOR);
-    // Build a set of keys to store the boundaries
-    byte[][] keys = null;
-    // calculate region boundaries and add all the column families to the table descriptor
-    for (Path regionDir : regionDirList) {
-      LOG.debug("Parsing region dir: " + regionDir);
-      Path hfofDir = regionDir;
-
-      if (!fs.exists(hfofDir)) {
-        LOG.warn("HFileOutputFormat dir " + hfofDir + " not found");
-      }
-
-      FileStatus[] familyDirStatuses = fs.listStatus(hfofDir);
-      if (familyDirStatuses == null) {
-        throw new IOException("No families found in " + hfofDir);
-      }
-
-      for (FileStatus stat : familyDirStatuses) {
-        if (!stat.isDirectory()) {
-          LOG.warn("Skipping non-directory " + stat.getPath());
-          continue;
-        }
-        boolean isIgnore = false;
-        String pathName = stat.getPath().getName();
-        for (String ignore : ignoreDirs) {
-          if (pathName.contains(ignore)) {
-            LOG.warn("Skipping non-family directory" + pathName);
-            isIgnore = true;
-            break;
-          }
-        }
-        if (isIgnore) {
-          continue;
-        }
-        Path familyDir = stat.getPath();
-        LOG.debug("Parsing family dir [" + familyDir.toString() + " in region [" + regionDir + "]");
-        // Skip _logs, etc
-        if (familyDir.getName().startsWith("_") || familyDir.getName().startsWith(".")) {
-          continue;
-        }
-
-        // start to parse hfile inside one family dir
-        Path[] hfiles = FileUtil.stat2Paths(fs.listStatus(familyDir));
-        for (Path hfile : hfiles) {
-          if (hfile.getName().startsWith("_") || hfile.getName().startsWith(".")
-              || StoreFileInfo.isReference(hfile.getName())
-              || HFileLink.isHFileLink(hfile.getName())) {
-            continue;
-          }
-          HFile.Reader reader = HFile.createReader(fs, hfile, new CacheConfig(conf), conf);
-          final byte[] first, last;
-          try {
-            reader.loadFileInfo();
-            first = reader.getFirstRowKey();
-            last = reader.getLastRowKey();
-            LOG.debug("Trying to figure out region boundaries hfile=" + hfile + " first="
-                + Bytes.toStringBinary(first) + " last=" + Bytes.toStringBinary(last));
-
-            // To eventually infer start key-end key boundaries
-            Integer value = map.containsKey(first) ? (Integer) map.get(first) : 0;
-            map.put(first, value + 1);
-            value = map.containsKey(last) ? (Integer) map.get(last) : 0;
-            map.put(last, value - 1);
-          } finally {
-            reader.close();
-          }
-        }
-      }
-    }
-    keys = LoadIncrementalHFiles.inferBoundaries(map);
-    return keys;
-  }
-
-  /**
    * Check whether the backup image path and there is manifest file in the path.
    * @param backupManifestMap If all the manifests are found, then they are put into this map
    * @param tableArray the tables involved

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupClientImpl.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupClientImpl.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupClientImpl.java
deleted file mode 100644
index bf33cfb..0000000
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupClientImpl.java
+++ /dev/null
@@ -1,183 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.hadoop.hbase.backup.impl;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.hbase.DoNotRetryIOException;
-import org.apache.hadoop.hbase.TableName;
-import org.apache.hadoop.hbase.backup.BackupClient;
-import org.apache.hadoop.hbase.backup.BackupType;
-import org.apache.hadoop.hbase.backup.BackupClientUtil;
-import org.apache.hadoop.hbase.backup.HBackupFileSystem;
-import org.apache.hadoop.hbase.classification.InterfaceAudience;
-import org.apache.hadoop.hbase.classification.InterfaceStability;
-import org.apache.hadoop.hbase.client.Connection;
-import org.apache.hadoop.hbase.client.ConnectionFactory;
-import org.apache.hadoop.hbase.client.HBaseAdmin;
-import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
-
-import com.google.common.collect.Lists;
-
-/**
- * Backup HBase tables locally or on a remote cluster Serve as client entry point for the following
- * features: - Full Backup provide local and remote back/restore for a list of tables - Incremental
- * backup to build on top of full backup as daily/weekly backup - Convert incremental backup WAL
- * files into hfiles - Merge several backup images into one(like merge weekly into monthly) - Add
- * and remove table to and from Backup image - Cancel a backup process - Describe information of
- * a backup image
- */
-@InterfaceAudience.Public
-@InterfaceStability.Evolving
-public final class BackupClientImpl implements BackupClient {
-  private static final Log LOG = LogFactory.getLog(BackupClientImpl.class);
-  private Configuration conf;
-  private BackupManager backupManager;
-
-  public BackupClientImpl() {
-  }
-
-  @Override
-  public void setConf(Configuration conf) {
-    this.conf = conf;
-  }
-
-  /**
-   * Prepare and submit Backup request
-   * @param backupId : backup_timestame (something like backup_1398729212626)
-   * @param backupType : full or incremental
-   * @param tableList : tables to be backuped
-   * @param targetRootDir : specified by user
-   * @throws IOException exception
-   */
-  protected void requestBackup(String backupId, BackupType backupType, List<TableName> tableList,
-      String targetRootDir) throws IOException {
-
-    BackupContext backupContext = null;
-
-    HBaseAdmin hbadmin = null;
-    Connection conn = null;
-    try {
-      backupManager = new BackupManager(conf);
-      if (backupType == BackupType.INCREMENTAL) {
-        Set<TableName> incrTableSet = backupManager.getIncrementalBackupTableSet();
-        if (incrTableSet.isEmpty()) {
-          LOG.warn("Incremental backup table set contains no table.\n"
-              + "Use 'backup create full' or 'backup stop' to \n "
-              + "change the tables covered by incremental backup.");
-          throw new DoNotRetryIOException("No table covered by incremental backup.");
-        }
-
-        LOG.info("Incremental backup for the following table set: " + incrTableSet);
-        tableList = Lists.newArrayList(incrTableSet);
-      }
-
-      // check whether table exists first before starting real request
-      if (tableList != null) {
-        ArrayList<TableName> nonExistingTableList = null;
-        conn = ConnectionFactory.createConnection(conf);
-        hbadmin = (HBaseAdmin) conn.getAdmin();
-        for (TableName tableName : tableList) {
-          if (!hbadmin.tableExists(tableName)) {
-            if (nonExistingTableList == null) {
-              nonExistingTableList = new ArrayList<>();
-            }
-            nonExistingTableList.add(tableName);
-          }
-        }
-        if (nonExistingTableList != null) {
-          if (backupType == BackupType.INCREMENTAL ) {
-            LOG.warn("Incremental backup table set contains non-exising table: "
-                + nonExistingTableList);
-          } else {
-            // Throw exception only in full mode - we try to backup non-existing table
-            throw new DoNotRetryIOException("Non-existing tables found in the table list: "
-                + nonExistingTableList);
-          }
-        }
-      }
-
-      // if any target table backup dir already exist, then no backup action taken
-      if (tableList != null) {
-        for (TableName table : tableList) {
-          String targetTableBackupDir =
-              HBackupFileSystem.getTableBackupDir(targetRootDir, backupId, table);
-          Path targetTableBackupDirPath = new Path(targetTableBackupDir);
-          FileSystem outputFs = FileSystem.get(targetTableBackupDirPath.toUri(), conf);
-          if (outputFs.exists(targetTableBackupDirPath)) {
-            throw new DoNotRetryIOException("Target backup directory " + targetTableBackupDir
-              + " exists already.");
-          }
-        }
-      }
-      backupContext =
-          backupManager.createBackupContext(backupId, backupType, tableList, targetRootDir);
-      backupManager.initialize();
-      backupManager.dispatchRequest(backupContext);
-    } catch (BackupException e) {
-      // suppress the backup exception wrapped within #initialize or #dispatchRequest, backup
-      // exception has already been handled normally
-      LOG.error("Backup Exception ", e);
-    } finally {
-      if (hbadmin != null) {
-        hbadmin.close();
-      }
-      if (conn != null) {
-        conn.close();
-      }
-    }
-  }
-
-  @Override
-  public String create(BackupType backupType, List<TableName> tableList, String backupRootPath)
-      throws IOException {
-
-    String backupId = BackupRestoreConstants.BACKUPID_PREFIX + EnvironmentEdgeManager.currentTime();
-    BackupClientUtil.checkTargetDir(backupRootPath, conf);
-
-    // table list specified for backup, trigger backup on specified tables
-    try {
-      requestBackup(backupId, backupType, tableList, backupRootPath);
-    } catch (RuntimeException e) {
-      String errMsg = e.getMessage();
-      if (errMsg != null
-          && (errMsg.startsWith("Non-existing tables found") || errMsg
-              .startsWith("Snapshot is not found"))) {
-        LOG.error(errMsg + ", please check your command");
-        throw e;
-      } else {
-        throw e;
-      }
-    } finally{
-      if(backupManager != null) {
-        backupManager.close();
-      }
-    }
-    return backupId;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupCommands.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupCommands.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupCommands.java
index 56e26fa..1789cdf 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupCommands.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupCommands.java
@@ -22,12 +22,14 @@ import java.io.IOException;
 import org.apache.commons.cli.CommandLine;
 import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.conf.Configured;
-import org.apache.hadoop.hbase.backup.BackupClient;
-import org.apache.hadoop.hbase.backup.BackupRestoreFactory;
+import org.apache.hadoop.hbase.backup.BackupRequest;
 import org.apache.hadoop.hbase.backup.BackupType;
 import org.apache.hadoop.hbase.backup.impl.BackupRestoreConstants.BackupCommand;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.classification.InterfaceStability;
+import org.apache.hadoop.hbase.client.Admin;
+import org.apache.hadoop.hbase.client.Connection;
+import org.apache.hadoop.hbase.client.ConnectionFactory;
 
 import com.google.common.collect.Lists;
 
@@ -108,12 +110,15 @@ public final class BackupCommands {
 
       String tables = (args.length == 3) ? args[2] : null;
 
-      try {
-        BackupClient client = BackupRestoreFactory.getBackupClient(getConf());
-        client.create(BackupType.valueOf(args[0].toUpperCase()),
-          Lists.newArrayList(BackupUtil.parseTableNames(tables)), args[1]);
-      } catch (RuntimeException e) {
-        System.out.println("ERROR: " + e.getMessage());
+      try (Connection conn = ConnectionFactory.createConnection(getConf());
+          Admin admin = conn.getAdmin();) {
+        BackupRequest request = new BackupRequest();
+        request.setBackupType(BackupType.valueOf(args[0].toUpperCase()))
+        .setTableList(Lists.newArrayList(BackupUtil.parseTableNames(tables)))
+        .setTargetRootDir(args[1]);
+        admin.backupTables(request);
+      } catch (IOException e) {
+        System.err.println("ERROR: " + e.getMessage());
         System.exit(-1);
       }
     }

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupContext.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupContext.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupContext.java
index 1be0c3b..06e66dc 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupContext.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupContext.java
@@ -19,6 +19,7 @@
 package org.apache.hadoop.hbase.backup.impl;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -29,7 +30,6 @@ import java.util.Set;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.backup.BackupType;
 import org.apache.hadoop.hbase.backup.HBackupFileSystem;
-import org.apache.hadoop.hbase.backup.impl.BackupHandler.BackupState;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.classification.InterfaceStability;
 import org.apache.hadoop.hbase.protobuf.ProtobufUtil;
@@ -77,10 +77,21 @@ public class BackupContext {
     this.totalBytesCopied = totalBytesCopied;
   }
 
+  // backup status flag
+  public static enum BackupState {
+    RUNNING, COMPLETE, FAILED, CANCELLED;
+  }
+
   public void setCancelled(boolean cancelled) {
     this.state = BackupState.CANCELLED;;
   }
 
+  // backup phase
+  // for overall backup (for table list, some table may go online, while some may go offline)
+  protected static enum BackupPhase {
+    SNAPSHOTCOPY, INCREMENTAL_COPY, STORE_MANIFEST;
+  }
+
   // backup id: a timestamp when we request the backup
   private String backupId;
 
@@ -91,10 +102,10 @@ public class BackupContext {
   private String targetRootDir;
 
   // overall backup state
-  private BackupHandler.BackupState state;
+  private BackupState state;
 
   // overall backup phase
-  private BackupHandler.BackupPhase phase;
+  private BackupPhase phase;
 
   // overall backup failure message
   private String failedMsg;
@@ -210,19 +221,19 @@ public class BackupContext {
     return totalBytesCopied;
   }
 
-  public BackupHandler.BackupState getState() {
+  public BackupState getState() {
     return state;
   }
 
-  public void setState(BackupHandler.BackupState flag) {
+  public void setState(BackupState flag) {
     this.state = flag;
   }
 
-  public BackupHandler.BackupPhase getPhase() {
+  public BackupPhase getPhase() {
     return phase;
   }
 
-  public void setPhase(BackupHandler.BackupPhase phase) {
+  public void setPhase(BackupPhase phase) {
     this.phase = phase;
   }
 
@@ -308,7 +319,7 @@ public class BackupContext {
     return null;
   }
 
-  public byte[] toByteArray() throws IOException {
+  BackupProtos.BackupContext toBackupContext() {
     BackupProtos.BackupContext.Builder builder =
         BackupProtos.BackupContext.newBuilder();
     builder.setBackupId(getBackupId());
@@ -332,8 +343,11 @@ public class BackupContext {
     builder.setTargetRootDir(getTargetRootDir());
     builder.setTotalBytesCopied(getTotalBytesCopied());
     builder.setType(BackupProtos.BackupType.valueOf(getType().name()));
-    byte[] data = builder.build().toByteArray();
-    return data;
+    return builder.build();
+  }
+
+  public byte[] toByteArray() throws IOException {
+    return toBackupContext().toByteArray();
   }
 
   private void setBackupStatusMap(Builder builder) {
@@ -343,9 +357,15 @@ public class BackupContext {
   }
 
   public static BackupContext fromByteArray(byte[] data) throws IOException {
+    return fromProto(BackupProtos.BackupContext.parseFrom(data));
+  }
+  
+  public static BackupContext fromStream(final InputStream stream) throws IOException {
+    return fromProto(BackupProtos.BackupContext.parseDelimitedFrom(stream));
+  }
 
+  static BackupContext fromProto(BackupProtos.BackupContext proto) {
     BackupContext context = new BackupContext();
-    BackupProtos.BackupContext proto = BackupProtos.BackupContext.parseFrom(data);
     context.setBackupId(proto.getBackupId());
     context.setBackupStatusMap(toMap(proto.getTableBackupStatusList()));
     context.setEndTs(proto.getEndTs());
@@ -353,13 +373,13 @@ public class BackupContext {
       context.setFailedMsg(proto.getFailedMessage());
     }
     if(proto.hasState()) {
-      context.setState(BackupHandler.BackupState.valueOf(proto.getState().name()));
+      context.setState(BackupContext.BackupState.valueOf(proto.getState().name()));
     }
     if(proto.hasHlogTargetDir()) {
       context.setHlogTargetDir(proto.getHlogTargetDir());
     }
     if(proto.hasPhase()) {
-      context.setPhase(BackupHandler.BackupPhase.valueOf(proto.getPhase().name()));
+      context.setPhase(BackupPhase.valueOf(proto.getPhase().name()));
     }
     if(proto.hasProgress()) {
       context.setProgress(proto.getProgress());

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupHandler.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupHandler.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupHandler.java
deleted file mode 100644
index b9d71f6..0000000
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupHandler.java
+++ /dev/null
@@ -1,702 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.hadoop.hbase.backup.impl;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.concurrent.Callable;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.fs.FileStatus;
-import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.Path;
-import org.apache.hadoop.hbase.TableName;
-import org.apache.hadoop.hbase.backup.BackupRestoreFactory;
-import org.apache.hadoop.hbase.backup.BackupType;
-import org.apache.hadoop.hbase.backup.BackupClientUtil;
-import org.apache.hadoop.hbase.backup.HBackupFileSystem;
-import org.apache.hadoop.hbase.backup.impl.BackupManifest.BackupImage;
-import org.apache.hadoop.hbase.backup.master.LogRollMasterProcedureManager;
-import org.apache.hadoop.hbase.classification.InterfaceAudience;
-import org.apache.hadoop.hbase.classification.InterfaceStability;
-import org.apache.hadoop.hbase.client.Admin;
-import org.apache.hadoop.hbase.client.Connection;
-import org.apache.hadoop.hbase.client.ConnectionFactory;
-import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
-import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
-import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
-import org.apache.hadoop.hbase.util.FSUtils;
-import org.apache.zookeeper.KeeperException.NoNodeException;
-
-/**
- * A Handler to carry the operations of backup progress
- */
-@InterfaceAudience.Private
-@InterfaceStability.Evolving
-public class BackupHandler implements Callable<Void> {
-  private static final Log LOG = LogFactory.getLog(BackupHandler.class);
-
-  // backup phase
-  // for overall backup (for table list, some table may go online, while some may go offline)
-  protected static enum BackupPhase {
-    REQUEST, SNAPSHOT, PREPARE_INCREMENTAL, SNAPSHOTCOPY, INCREMENTAL_COPY, STORE_MANIFEST;
-  }
-
-  // backup status flag
-  public static enum BackupState {
-    WAITING, RUNNING, COMPLETE, FAILED, CANCELLED;
-  }
-
-  protected final BackupContext backupContext;
-  private final BackupManager backupManager;
-  private final Configuration conf;
-  private final Connection conn;
-
-  public BackupHandler(BackupContext backupContext,
-      BackupManager backupManager, Configuration conf, Connection connection) {
-    this.backupContext = backupContext;
-    this.backupManager = backupManager;
-    this.conf = conf;
-    this.conn = connection;
-  }
-
-  public BackupContext getBackupContext() {
-    return backupContext;
-  }
-
-  @Override
-  public Void call() throws Exception {
-    try(Admin admin = conn.getAdmin()) {
-      // overall backup begin
-      this.beginBackup(backupContext);
-      HashMap<String, Long> newTimestamps = null;
-      // handle full or incremental backup for table or table list
-      if (backupContext.getType() == BackupType.FULL) {
-        String savedStartCode = null;
-        boolean firstBackup = false;
-        // do snapshot for full table backup
-
-        try {
-          savedStartCode = backupManager.readBackupStartCode();
-          firstBackup = savedStartCode == null;
-          if (firstBackup) {
-            // This is our first backup. Let's put some marker on ZK so that we can hold the logs
-            // while we do the backup.
-            backupManager.writeBackupStartCode(0L);
-          }
-          // We roll log here before we do the snapshot. It is possible there is duplicate data
-          // in the log that is already in the snapshot. But if we do it after the snapshot, we
-          // could have data loss.
-          // A better approach is to do the roll log on each RS in the same global procedure as
-          // the snapshot.
-          LOG.info("Execute roll log procedure for full backup ...");
-          admin.execProcedure(LogRollMasterProcedureManager.ROLLLOG_PROCEDURE_SIGNATURE,
-            LogRollMasterProcedureManager.ROLLLOG_PROCEDURE_NAME, new HashMap<String, String>());
-          newTimestamps = backupManager.readRegionServerLastLogRollResult();
-          if (firstBackup) {
-            // Updates registered log files
-            // We record ALL old WAL files as registered, because
-            // this is a first full backup in the system and these
-            // files are not needed for next incremental backup
-            List<String> logFiles = BackupUtil.getWALFilesOlderThan(conf, newTimestamps);
-            backupManager.recordWALFiles(logFiles);
-          }
-          this.snapshotForFullBackup(backupContext);
-        } catch (BackupException e) {
-          // fail the overall backup and return
-          this.failBackup(backupContext, e, "Unexpected BackupException : ");
-          return null;
-        }
-
-        // update the faked progress currently for snapshot done
-        updateProgress(backupContext, backupManager, 10, 0);
-        // do snapshot copy
-        try {
-          this.snapshotCopy(backupContext);
-        } catch (Exception e) {
-          // fail the overall backup and return
-          this.failBackup(backupContext, e, "Unexpected BackupException : ");
-          return null;
-        }
-        // Updates incremental backup table set
-        backupManager.addIncrementalBackupTableSet(backupContext.getTables());
-
-      } else if (backupContext.getType() == BackupType.INCREMENTAL) {
-        LOG.debug("For incremental backup, current table set is "
-            + backupManager.getIncrementalBackupTableSet());
-        // do incremental table backup preparation
-        backupContext.setPhase(BackupPhase.PREPARE_INCREMENTAL);
-        // avoid action if has been cancelled
-        if (backupContext.isCancelled()) {
-          return null;
-        }
-        try {
-          IncrementalBackupManager incrBackupManager = new IncrementalBackupManager(backupManager);
-
-          newTimestamps = incrBackupManager.getIncrBackupLogFileList(backupContext);
-        } catch (Exception e) {
-          // fail the overall backup and return
-          this.failBackup(backupContext, e, "Unexpected Exception : ");
-          return null;
-        }
-        // update the faked progress currently for incremental preparation done
-        updateProgress(backupContext, backupManager, 10, 0);
-
-        // do incremental copy
-        try {
-          // copy out the table and region info files for each table
-          BackupUtil.copyTableRegionInfo(backupContext, conf);
-          this.incrementalCopy(backupContext);
-          // Save list of WAL files copied
-          backupManager.recordWALFiles(backupContext.getIncrBackupFileList());
-        } catch (Exception e) {
-          // fail the overall backup and return
-          this.failBackup(backupContext, e, "Unexpected exception doing incremental copy : ");
-          return null;
-        }
-      }
-
-      // set overall backup status: complete. Here we make sure to complete the backup. After this
-      // checkpoint, even if entering cancel process, will let the backup finished
-      backupContext.setState(BackupState.COMPLETE);
-
-      if (backupContext.getType() == BackupType.INCREMENTAL) {
-        // Set the previousTimestampMap which is before this current log roll to the manifest.
-        HashMap<TableName, HashMap<String, Long>> previousTimestampMap =
-            backupManager.readLogTimestampMap();
-        backupContext.setIncrTimestampMap(previousTimestampMap);
-      }
-
-      // The table list in backupContext is good for both full backup and incremental backup.
-      // For incremental backup, it contains the incremental backup table set.
-      backupManager.writeRegionServerLogTimestamp(backupContext.getTables(), newTimestamps);
-
-      HashMap<TableName, HashMap<String, Long>> newTableSetTimestampMap =
-          backupManager.readLogTimestampMap();
-
-      Long newStartCode =
-          BackupClientUtil.getMinValue(BackupUtil.getRSLogTimestampMins(newTableSetTimestampMap));
-      backupManager.writeBackupStartCode(newStartCode);
-
-      // backup complete
-      this.completeBackup(backupContext);
-    } catch (Exception e) {
-      // even during completing backup (#completeBackup(backupContext)), exception may occur, or
-      // exception occur during other process, fail the backup finally
-      this.failBackup(backupContext, e, "Error caught during backup progress: ");
-    }
-    return null;
-  }
-
-  /**
-   * Begin the overall backup.
-   * @param backupContext backup context
-   * @throws IOException exception
-   */
-  private void beginBackup(BackupContext backupContext) throws IOException {
-    // set the start timestamp of the overall backup
-    long startTs = EnvironmentEdgeManager.currentTime();
-    backupContext.setStartTs(startTs);
-    // set overall backup status: ongoing
-    backupContext.setState(BackupState.RUNNING);
-    LOG.info("Backup " + backupContext.getBackupId() + " started at " + startTs + ".");
-
-    backupManager.updateBackupStatus(backupContext);
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("Backup session " + backupContext.getBackupId() + " has been started.");
-    }
-  }
-
-  /**
-   * Snapshot for full table backup.
-   * @param backupContext backup context
-   * @throws IOException exception
-   */
-  private void snapshotForFullBackup(BackupContext backupContext) throws IOException {
-    LOG.info("HBase snapshot full backup for " + backupContext.getBackupId());
-
-    // avoid action if has been cancelled
-    if (backupContext.isCancelled()) {
-      return;
-    }
-
-    try (Admin admin = conn.getAdmin()) {
-      // we do HBase snapshot for tables in the table list one by one currently
-      for (TableName table : backupContext.getTables()) {
-        // avoid action if it has been cancelled
-        if (backupContext.isCancelled()) {
-          return;
-        }
-
-        HBaseProtos.SnapshotDescription backupSnapshot;
-
-        // wrap a SnapshotDescription for offline/online snapshot
-        backupSnapshot = this.wrapSnapshotDescription(table);
-
-        try {
-          // Kick off snapshot for backup
-          admin.snapshot(backupSnapshot);
-        } catch (Exception e) {
-          LOG.error("Snapshot failed to create " + getMessage(e));
-
-          // currently, we fail the overall backup if any table in the list failed, so throw the
-          // exception out for overall backup failing
-          throw new BackupException("Backup snapshot failed on table " + table, e);
-        }
-
-        // set the snapshot name in BackupStatus of this table, only after snapshot success.
-        backupContext.setSnapshotName(table, backupSnapshot.getName());
-      }
-    }
-  }
-
-  /**
-   * Fail the overall backup.
-   * @param backupContext backup context
-   * @param e exception
-   * @throws Exception exception
-   */
-  private void failBackup(BackupContext backupContext, Exception e, String msg) throws Exception {
-    LOG.error(msg + getMessage(e));
-    // If this is a cancel exception, then we've already cleaned.
-
-    if (this.backupContext.getState().equals(BackupState.CANCELLED)) {
-      return;
-    }
-
-    // set the failure timestamp of the overall backup
-    backupContext.setEndTs(EnvironmentEdgeManager.currentTime());
-
-    // set failure message
-    backupContext.setFailedMsg(e.getMessage());
-
-    // set overall backup status: failed
-    backupContext.setState(BackupState.FAILED);
-
-    // compose the backup failed data
-    String backupFailedData =
-        "BackupId=" + backupContext.getBackupId() + ",startts=" + backupContext.getStartTs()
-        + ",failedts=" + backupContext.getEndTs() + ",failedphase=" + backupContext.getPhase()
-        + ",failedmessage=" + backupContext.getFailedMsg();
-    LOG.error(backupFailedData);
-
-    backupManager.updateBackupStatus(backupContext);
-
-    // if full backup, then delete HBase snapshots if there already have snapshots taken
-    // and also clean up export snapshot log files if exist
-    if (backupContext.getType() == BackupType.FULL) {
-      this.deleteSnapshot(backupContext);
-      this.cleanupExportSnapshotLog();
-    } /*
-     * else { // support incremental backup code in future jira // TODO. See HBASE-14124 }
-     */
-
-    // clean up the uncompleted data at target directory if the ongoing backup has already entered
-    // the copy phase
-    // For incremental backup, DistCp logs will be cleaned with the targetDir.
-    this.cleanupTargetDir();
-
-    LOG.info("Backup " + backupContext.getBackupId() + " failed.");
-  }
-
-  /**
-   * Update the ongoing back token znode with new progress.
-   * @param backupContext backup context
-   * 
-   * @param newProgress progress
-   * @param bytesCopied bytes copied
-   * @throws NoNodeException exception
-   */
-  public static void updateProgress(BackupContext backupContext, BackupManager backupManager,
-      int newProgress, long bytesCopied) throws IOException {
-    // compose the new backup progress data, using fake number for now
-    String backupProgressData = newProgress + "%";
-
-    backupContext.setProgress(newProgress);
-    backupManager.updateBackupStatus(backupContext);
-    LOG.debug("Backup progress data \"" + backupProgressData
-      + "\" has been updated to hbase:backup for " + backupContext.getBackupId());
-  }
-
-  /**
-   * Complete the overall backup.
-   * @param backupContext backup context
-   * @throws Exception exception
-   */
-  private void completeBackup(BackupContext backupContext) throws Exception {
-
-    // set the complete timestamp of the overall backup
-    backupContext.setEndTs(EnvironmentEdgeManager.currentTime());
-    // set overall backup status: complete
-    backupContext.setState(BackupState.COMPLETE);
-    // add and store the manifest for the backup
-    this.addManifest(backupContext);
-
-    // after major steps done and manifest persisted, do convert if needed for incremental backup
-    /* in-fly convert code here, provided by future jira */
-    LOG.debug("in-fly convert code here, provided by future jira");
-
-    // compose the backup complete data
-    String backupCompleteData =
-        this.obtainBackupMetaDataStr(backupContext) + ",startts=" + backupContext.getStartTs()
-        + ",completets=" + backupContext.getEndTs() + ",bytescopied="
-        + backupContext.getTotalBytesCopied();
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("Backup " + backupContext.getBackupId() + " finished: " + backupCompleteData);
-    }
-    backupManager.updateBackupStatus(backupContext);
-
-    // when full backup is done:
-    // - delete HBase snapshot
-    // - clean up directories with prefix "exportSnapshot-", which are generated when exporting
-    // snapshots
-    if (backupContext.getType() == BackupType.FULL) {
-      this.deleteSnapshot(backupContext);
-      this.cleanupExportSnapshotLog();
-    } else if (backupContext.getType() == BackupType.INCREMENTAL) {
-      this.cleanupDistCpLog();
-    }
-
-    LOG.info("Backup " + backupContext.getBackupId() + " completed.");
-  }
-
-  /**
-   * Get backup request meta data dir as string.
-   * @param backupContext backup context
-   * @return meta data dir
-   */
-  private String obtainBackupMetaDataStr(BackupContext backupContext) {
-    StringBuffer sb = new StringBuffer();
-    sb.append("type=" + backupContext.getType() + ",tablelist=");
-    for (TableName table : backupContext.getTables()) {
-      sb.append(table + ";");
-    }
-    if (sb.lastIndexOf(";") > 0) {
-      sb.delete(sb.lastIndexOf(";"), sb.lastIndexOf(";") + 1);
-    }
-    sb.append(",targetRootDir=" + backupContext.getTargetRootDir());
-
-    return sb.toString();
-  }
-
-  /**
-   * Do snapshot copy.
-   * @param backupContext backup context
-   * @throws Exception exception
-   */
-  private void snapshotCopy(BackupContext backupContext) throws Exception {
-    LOG.info("Snapshot copy is starting.");
-
-    // set overall backup phase: snapshot_copy
-    backupContext.setPhase(BackupPhase.SNAPSHOTCOPY);
-
-    // avoid action if has been cancelled
-    if (backupContext.isCancelled()) {
-      return;
-    }
-
-    // call ExportSnapshot to copy files based on hbase snapshot for backup
-    // ExportSnapshot only support single snapshot export, need loop for multiple tables case
-    BackupCopyService copyService = BackupRestoreFactory.getBackupCopyService(conf);
-
-    // number of snapshots matches number of tables
-    float numOfSnapshots = backupContext.getSnapshotNames().size();
-
-    LOG.debug("There are " + (int) numOfSnapshots + " snapshots to be copied.");
-
-    for (TableName table : backupContext.getTables()) {
-      // Currently we simply set the sub copy tasks by counting the table snapshot number, we can
-      // calculate the real files' size for the percentage in the future.
-      // TODO this below
-      // backupCopier.setSubTaskPercntgInWholeTask(1f / numOfSnapshots);
-      int res = 0;
-      String[] args = new String[4];
-      args[0] = "-snapshot";
-      args[1] = backupContext.getSnapshotName(table);
-      args[2] = "-copy-to";
-      args[3] = backupContext.getBackupStatus(table).getTargetDir();
-
-      LOG.debug("Copy snapshot " + args[1] + " to " + args[3]);
-      res = copyService.copy(backupContext, backupManager, conf, BackupCopyService.Type.FULL, args);
-      // if one snapshot export failed, do not continue for remained snapshots
-      if (res != 0) {
-        LOG.error("Exporting Snapshot " + args[1] + " failed with return code: " + res + ".");
-
-        throw new IOException("Failed of exporting snapshot " + args[1] + " to " + args[3]
-            + " with reason code " + res);
-      }
-
-      LOG.info("Snapshot copy " + args[1] + " finished.");
-    }
-  }
-
-  /**
-   * Wrap a SnapshotDescription for a target table.
-   * @param table table
-   * @return a SnapshotDescription especially for backup.
-   */
-  private SnapshotDescription wrapSnapshotDescription(TableName tableName) {
-    // Mock a SnapshotDescription from backupContext to call SnapshotManager function,
-    // Name it in the format "snapshot_<timestamp>_<table>"
-    HBaseProtos.SnapshotDescription.Builder builder = HBaseProtos.SnapshotDescription.newBuilder();
-    builder.setTable(tableName.getNameAsString());
-    builder.setName("snapshot_" + Long.toString(EnvironmentEdgeManager.currentTime()) + "_"
-        + tableName.getNamespaceAsString() + "_" + tableName.getQualifierAsString());
-    HBaseProtos.SnapshotDescription backupSnapshot = builder.build();
-
-    LOG.debug("Wrapped a SnapshotDescription " + backupSnapshot.getName()
-      + " from backupContext to request snapshot for backup.");
-
-    return backupSnapshot;
-  }
-
-  /**
-   * Delete HBase snapshot for backup.
-   * @param backupCtx backup context
-   * @throws Exception exception
-   */
-  private void deleteSnapshot(BackupContext backupCtx) throws IOException {
-
-    LOG.debug("Trying to delete snapshot for full backup.");
-    Connection conn = null;
-    Admin admin = null;
-    try {
-      conn = ConnectionFactory.createConnection(conf);
-      admin = conn.getAdmin();
-      for (String snapshotName : backupCtx.getSnapshotNames()) {
-        if (snapshotName == null) {
-          continue;
-        }
-        LOG.debug("Trying to delete snapshot: " + snapshotName);
-        admin.deleteSnapshot(snapshotName);
-        LOG.debug("Deleting the snapshot " + snapshotName + " for backup "
-            + backupCtx.getBackupId() + " succeeded.");
-      }
-    } finally {
-      if (admin != null) {
-        admin.close();
-      }
-      if (conn != null) {
-        conn.close();
-      }
-    }
-  }
-
-  /**
-   * Clean up directories with prefix "exportSnapshot-", which are generated when exporting
-   * snapshots.
-   * @throws IOException exception
-   */
-  private void cleanupExportSnapshotLog() throws IOException {
-    FileSystem fs = FSUtils.getCurrentFileSystem(conf);
-    Path stagingDir =
-        new Path(conf.get(BackupRestoreConstants.CONF_STAGING_ROOT, fs.getWorkingDirectory()
-          .toString()));
-    FileStatus[] files = FSUtils.listStatus(fs, stagingDir);
-    if (files == null) {
-      return;
-    }
-    for (FileStatus file : files) {
-      if (file.getPath().getName().startsWith("exportSnapshot-")) {
-        LOG.debug("Delete log files of exporting snapshot: " + file.getPath().getName());
-        if (FSUtils.delete(fs, file.getPath(), true) == false) {
-          LOG.warn("Can not delete " + file.getPath());
-        }
-      }
-    }
-  }
-
-  /**
-   * Clean up directories with prefix "_distcp_logs-", which are generated when DistCp copying
-   * hlogs.
-   * @throws IOException exception
-   */
-  private void cleanupDistCpLog() throws IOException {
-    Path rootPath = new Path(backupContext.getHLogTargetDir()).getParent();
-    FileSystem fs = FileSystem.get(rootPath.toUri(), conf);
-    FileStatus[] files = FSUtils.listStatus(fs, rootPath);
-    if (files == null) {
-      return;
-    }
-    for (FileStatus file : files) {
-      if (file.getPath().getName().startsWith("_distcp_logs")) {
-        LOG.debug("Delete log files of DistCp: " + file.getPath().getName());
-        FSUtils.delete(fs, file.getPath(), true);
-      }
-    }
-  }
-
-  /**
-   * Clean up the uncompleted data at target directory if the ongoing backup has already entered the
-   * copy phase.
-   */
-  private void cleanupTargetDir() {
-    try {
-      // clean up the uncompleted data at target directory if the ongoing backup has already entered
-      // the copy phase
-      LOG.debug("Trying to cleanup up target dir. Current backup phase: "
-          + backupContext.getPhase());
-      if (backupContext.getPhase().equals(BackupPhase.SNAPSHOTCOPY)
-          || backupContext.getPhase().equals(BackupPhase.INCREMENTAL_COPY)
-          || backupContext.getPhase().equals(BackupPhase.STORE_MANIFEST)) {
-        FileSystem outputFs =
-            FileSystem.get(new Path(backupContext.getTargetRootDir()).toUri(), conf);
-
-        // now treat one backup as a transaction, clean up data that has been partially copied at
-        // table level
-        for (TableName table : backupContext.getTables()) {
-          Path targetDirPath =
-              new Path(HBackupFileSystem.getTableBackupDir(backupContext.getTargetRootDir(),
-                backupContext.getBackupId(), table));
-          if (outputFs.delete(targetDirPath, true)) {
-            LOG.info("Cleaning up uncompleted backup data at " + targetDirPath.toString()
-              + " done.");
-          } else {
-            LOG.info("No data has been copied to " + targetDirPath.toString() + ".");
-          }
-
-          Path tableDir = targetDirPath.getParent();
-          FileStatus[] backups = FSUtils.listStatus(outputFs, tableDir);
-          if (backups == null || backups.length == 0) {
-            outputFs.delete(tableDir, true);
-            LOG.debug(tableDir.toString() + " is empty, remove it.");
-          }
-        }
-      }
-
-    } catch (IOException e1) {
-      LOG.error("Cleaning up uncompleted backup data of " + backupContext.getBackupId() + " at "
-          + backupContext.getTargetRootDir() + " failed due to " + e1.getMessage() + ".");
-    }
-  }
-
-  /**
-   * Add manifest for the current backup. The manifest is stored
-   * within the table backup directory.
-   * @param backupContext The current backup context
-   * @throws IOException exception
-   * @throws BackupException exception
-   */
-  private void addManifest(BackupContext backupContext) throws IOException, BackupException {
-    // set the overall backup phase : store manifest
-    backupContext.setPhase(BackupPhase.STORE_MANIFEST);
-
-    // avoid action if has been cancelled
-    if (backupContext.isCancelled()) {
-      return;
-    }
-
-    BackupManifest manifest;
-
-    // Since we have each table's backup in its own directory structure,
-    // we'll store its manifest with the table directory.
-    for (TableName table : backupContext.getTables()) {
-      manifest = new BackupManifest(backupContext, table);
-      ArrayList<BackupImage> ancestors = this.backupManager.getAncestors(backupContext, table);
-      for (BackupImage image : ancestors) {
-        manifest.addDependentImage(image);
-      }
-
-      if (backupContext.getType() == BackupType.INCREMENTAL) {
-        // We'll store the log timestamps for this table only in its manifest.
-        HashMap<TableName, HashMap<String, Long>> tableTimestampMap =
-            new HashMap<TableName, HashMap<String, Long>>();
-        tableTimestampMap.put(table, backupContext.getIncrTimestampMap().get(table));
-        manifest.setIncrTimestampMap(tableTimestampMap);
-      }
-      manifest.store(conf);
-    }
-
-    // For incremental backup, we store a overall manifest in
-    // <backup-root-dir>/WALs/<backup-id>
-    // This is used when created the next incremental backup
-    if (backupContext.getType() == BackupType.INCREMENTAL) {
-      manifest = new BackupManifest(backupContext);
-      // set the table region server start and end timestamps for incremental backup
-      manifest.setIncrTimestampMap(backupContext.getIncrTimestampMap());
-      ArrayList<BackupImage> ancestors = this.backupManager.getAncestors(backupContext);
-      for (BackupImage image : ancestors) {
-        manifest.addDependentImage(image);
-      }
-      manifest.store(conf);
-    }
-  }
-
-  /**
-   * Do incremental copy.
-   * @param backupContext backup context
-   */
-  private void incrementalCopy(BackupContext backupContext) throws Exception {
-
-    LOG.info("Incremental copy is starting.");
-
-    // set overall backup phase: incremental_copy
-    backupContext.setPhase(BackupPhase.INCREMENTAL_COPY);
-
-    // avoid action if has been cancelled
-    if (backupContext.isCancelled()) {
-      return;
-    }
-
-    // get incremental backup file list and prepare parms for DistCp
-    List<String> incrBackupFileList = backupContext.getIncrBackupFileList();
-    // filter missing files out (they have been copied by previous backups)
-    incrBackupFileList = filterMissingFiles(incrBackupFileList);
-    String[] strArr = incrBackupFileList.toArray(new String[incrBackupFileList.size() + 1]);
-    strArr[strArr.length - 1] = backupContext.getHLogTargetDir();
-
-    BackupCopyService copyService = BackupRestoreFactory.getBackupCopyService(conf);
-    int res = copyService.copy(backupContext, backupManager, conf,
-      BackupCopyService.Type.INCREMENTAL, strArr);
-
-    if (res != 0) {
-      LOG.error("Copy incremental log files failed with return code: " + res + ".");
-      throw new IOException("Failed of Hadoop Distributed Copy from " + incrBackupFileList + " to "
-          + backupContext.getHLogTargetDir());
-    }
-    LOG.info("Incremental copy from " + incrBackupFileList + " to "
-        + backupContext.getHLogTargetDir() + " finished.");
-
-  }
-
-  private List<String> filterMissingFiles(List<String> incrBackupFileList) throws IOException {
-    FileSystem fs = FileSystem.get(conf);
-    List<String> list = new ArrayList<String>();
-    for(String file : incrBackupFileList){
-      if(fs.exists(new Path(file))){
-        list.add(file);
-      } else{
-        LOG.warn("Can't find file: "+file);
-      }
-    }
-    return list;
-  }
-
-  private String getMessage(Exception e) {
-    String msg = e.getMessage();
-    if (msg == null || msg.equals("")) {
-      msg = e.getClass().getName();
-    }
-    return msg;
-  }
-}

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupManager.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupManager.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupManager.java
index a4b0a0a..b4d47d3 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupManager.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupManager.java
@@ -44,7 +44,7 @@ import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.backup.BackupType;
 import org.apache.hadoop.hbase.backup.HBackupFileSystem;
-import org.apache.hadoop.hbase.backup.impl.BackupHandler.BackupState;
+import org.apache.hadoop.hbase.backup.impl.BackupContext.BackupState;
 import org.apache.hadoop.hbase.backup.impl.BackupManifest.BackupImage;
 import org.apache.hadoop.hbase.backup.impl.BackupUtil.BackupCompleteData;
 import org.apache.hadoop.hbase.backup.master.BackupLogCleaner;
@@ -204,7 +204,7 @@ public class BackupManager implements Closeable {
       throw new BackupException("Wrong backup request parameter: target backup root directory");
     }
 
-    if (type == BackupType.FULL && tableList == null) {
+    if (type == BackupType.FULL && (tableList == null || tableList.isEmpty())) {
       // If table list is null for full backup, which means backup all tables. Then fill the table
       // list with all user tables from meta. It no table available, throw the request exception.
 
@@ -270,37 +270,8 @@ public class BackupManager implements Closeable {
     ((ThreadPoolExecutor) pool).allowCoreThreadTimeOut(true);
   }
 
-  /**
-   * Dispatch and handle a backup request.
-   * @param backupContext backup context
-   * @throws BackupException exception
-   */
-  public void dispatchRequest(BackupContext backupContext) throws BackupException {
-
+  public void setBackupContext(BackupContext backupContext) {
     this.backupContext = backupContext;
-
-    LOG.info("Got a backup request: " + "Type: " + backupContext.getType() + "; Tables: "
-        + backupContext.getTableNames() + "; TargetRootDir: " + backupContext.getTargetRootDir());
-
-    // dispatch the request to a backup handler and put it handler map
-
-    BackupHandler handler = new BackupHandler(this.backupContext, this, conf, this.conn);
-    Future<Void> future = this.pool.submit(handler);
-    // wait for the execution to complete
-    try {
-      future.get();
-    } catch (InterruptedException e) {
-      throw new BackupException(e);
-    } catch (CancellationException e) {
-      throw new BackupException(e);
-    } catch (ExecutionException e) {
-      throw new BackupException(e);
-    }
-
-    // mark the backup complete for exit handler's processing
-    backupComplete = true;
-
-    LOG.info("Backup request " + backupContext.getBackupId() + " has been executed.");
   }
 
   /**
@@ -476,7 +447,7 @@ public class BackupManager implements Closeable {
    * @throws IOException exception
    */
   public Set<TableName> getIncrementalBackupTableSet() throws IOException {
-    return systemTable.getIncrementalBackupTableSet();
+    return BackupSystemTableHelper.getIncrementalBackupTableSet(getConnection());
   }
 
   /**

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupSnapshotCopy.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupSnapshotCopy.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupSnapshotCopy.java
index 8b8a83f..731ccd3 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupSnapshotCopy.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupSnapshotCopy.java
@@ -22,19 +22,13 @@ import org.apache.hadoop.hbase.snapshot.ExportSnapshot;
 
 /* this class will be extended in future jira to support progress report */
 public class BackupSnapshotCopy extends ExportSnapshot {
-  private BackupHandler backupHandler;
   private String table;
 
-  public BackupSnapshotCopy(BackupHandler backupHandler, String table) {
+  public BackupSnapshotCopy(String table) {
     super();
-    this.backupHandler = backupHandler;
     this.table = table;
   }
 
-  public BackupHandler getBackupHandler() {
-    return this.backupHandler;
-  }
-
   public String getTable() {
     return this.table;
   }

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupSystemTable.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupSystemTable.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupSystemTable.java
index f4d6761..c104dd8 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupSystemTable.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupSystemTable.java
@@ -36,7 +36,7 @@ import org.apache.hadoop.hbase.HColumnDescriptor;
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.TableName;
-import org.apache.hadoop.hbase.backup.impl.BackupHandler.BackupState;
+import org.apache.hadoop.hbase.backup.impl.BackupContext.BackupState;
 import org.apache.hadoop.hbase.backup.impl.BackupUtil.BackupCompleteData;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.classification.InterfaceStability;
@@ -412,32 +412,6 @@ public final class BackupSystemTable implements Closeable {
   }
 
   /**
-   * Return the current tables covered by incremental backup.
-   * @return set of tableNames
-   * @throws IOException exception
-   */
-  public Set<TableName> getIncrementalBackupTableSet() throws IOException {
-    if (LOG.isDebugEnabled()) {
-      LOG.debug("get incr backup table set from hbase:backup");
-    }
-    TreeSet<TableName> set = new TreeSet<>();
-
-    try (Table table = connection.getTable(tableName)) {
-      Get get = BackupSystemTableHelper.createGetForIncrBackupTableSet();
-      Result res = table.get(get);
-      if (res.isEmpty()) {
-        return set;
-      }
-      List<Cell> cells = res.listCells();
-      for (Cell cell : cells) {
-        // qualifier = table name - we use table names as qualifiers
-        set.add(TableName.valueOf(CellUtil.cloneQualifier(cell)));
-      }
-      return set;
-    }
-  }
-
-  /**
    * Add tables to global incremental backup set
    * @param tables - set of tables
    * @throws IOException exception
@@ -445,6 +419,9 @@ public final class BackupSystemTable implements Closeable {
   public void addIncrementalBackupTableSet(Set<TableName> tables) throws IOException {
     if (LOG.isDebugEnabled()) {
       LOG.debug("add incr backup table set to hbase:backup");
+      for (TableName table : tables) {
+        LOG.debug(table);
+      }
     }
     try (Table table = connection.getTable(tableName)) {
       Put put = BackupSystemTableHelper.createPutForIncrBackupTableSet(tables);

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupSystemTableHelper.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupSystemTableHelper.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupSystemTableHelper.java
index ac096b7..04ccbdc 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupSystemTableHelper.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupSystemTableHelper.java
@@ -22,17 +22,22 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
+import java.util.TreeSet;
 
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.hbase.Cell;
 import org.apache.hadoop.hbase.CellUtil;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.classification.InterfaceStability;
+import org.apache.hadoop.hbase.client.Connection;
 import org.apache.hadoop.hbase.client.Delete;
 import org.apache.hadoop.hbase.client.Get;
 import org.apache.hadoop.hbase.client.Put;
 import org.apache.hadoop.hbase.client.Result;
 import org.apache.hadoop.hbase.client.Scan;
+import org.apache.hadoop.hbase.client.Table;
 import org.apache.hadoop.hbase.util.Bytes;
 
 
@@ -43,7 +48,7 @@ import org.apache.hadoop.hbase.util.Bytes;
 @InterfaceAudience.Private
 @InterfaceStability.Evolving
 public final class BackupSystemTableHelper {
-
+  private static final Log LOG = LogFactory.getLog(BackupSystemTableHelper.class);
   /**
    * hbase:backup schema:
    * 1. Backup sessions rowkey= "session." + backupId; value = serialized
@@ -157,6 +162,33 @@ public final class BackupSystemTableHelper {
   }
 
   /**
+   * Return the current tables covered by incremental backup.
+   * @return set of tableNames
+   * @throws IOException exception
+   */
+  public static Set<TableName> getIncrementalBackupTableSet(Connection connection)
+      throws IOException {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("get incr backup table set from hbase:backup");
+    }
+    TreeSet<TableName> set = new TreeSet<>();
+
+    try (Table table = connection.getTable(TableName.BACKUP_TABLE_NAME)) {
+      Get get = BackupSystemTableHelper.createGetForIncrBackupTableSet();
+      Result res = table.get(get);
+      if (res.isEmpty()) {
+        return set;
+      }
+      List<Cell> cells = res.listCells();
+      for (Cell cell : cells) {
+        // qualifier = table name - we use table names as qualifiers
+        set.add(TableName.valueOf(CellUtil.cloneQualifier(cell)));
+      }
+      return set;
+    }
+  }
+
+  /**
    * Creates Put to store incremental backup table set
    * @param tables tables
    * @return put operation

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupUtil.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupUtil.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupUtil.java
index 96812c9..660a14f 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupUtil.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupUtil.java
@@ -18,11 +18,9 @@
 
 package org.apache.hadoop.hbase.backup.impl;
 
-import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.net.URLDecoder;
+import java.io.InterruptedIOException;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -35,25 +33,27 @@ import org.apache.hadoop.conf.Configuration;
 import org.apache.hadoop.fs.FSDataOutputStream;
 import org.apache.hadoop.fs.FileStatus;
 import org.apache.hadoop.fs.FileSystem;
-import org.apache.hadoop.fs.LocatedFileStatus;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.fs.PathFilter;
-import org.apache.hadoop.fs.RemoteIterator;
 import org.apache.hadoop.fs.permission.FsPermission;
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.HRegionInfo;
 import org.apache.hadoop.hbase.ServerName;
 import org.apache.hadoop.hbase.TableDescriptor;
 import org.apache.hadoop.hbase.TableName;
-import org.apache.hadoop.hbase.backup.HBackupFileSystem;
+import org.apache.hadoop.hbase.backup.BackupClientUtil;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.classification.InterfaceStability;
-import org.apache.hadoop.hbase.backup.BackupClientUtil;
 import org.apache.hadoop.hbase.client.Admin;
 import org.apache.hadoop.hbase.client.Connection;
 import org.apache.hadoop.hbase.client.ConnectionFactory;
 import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.master.snapshot.SnapshotManager;
+import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
 import org.apache.hadoop.hbase.regionserver.HRegion;
+import org.apache.hadoop.hbase.snapshot.ClientSnapshotDescriptionUtils;
+import org.apache.hadoop.hbase.snapshot.SnapshotCreationException;
+import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
 import org.apache.hadoop.hbase.util.FSTableDescriptors;
 import org.apache.hadoop.hbase.util.FSUtils;
 import org.apache.hadoop.hbase.wal.DefaultWALProvider;
@@ -71,6 +71,40 @@ public final class BackupUtil {
     throw new AssertionError("Instantiating utility class...");
   }
 
+  public static void waitForSnapshot(SnapshotDescription snapshot, long max,
+      SnapshotManager snapshotMgr, Configuration conf) throws IOException {
+    boolean done = false;
+    long start = EnvironmentEdgeManager.currentTime();
+    int numRetries = conf.getInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER,
+      HConstants.DEFAULT_HBASE_CLIENT_RETRIES_NUMBER);
+    long maxPauseTime = max / numRetries;
+    int tries = 0;
+    LOG.debug("Waiting a max of " + max + " ms for snapshot '" +
+        ClientSnapshotDescriptionUtils.toString(snapshot) + "'' to complete. (max " +
+        maxPauseTime + " ms per retry)");
+    while (tries == 0
+        || ((EnvironmentEdgeManager.currentTime() - start) < max && !done)) {
+      try {
+        // sleep a backoff <= pauseTime amount
+        long pause = conf.getLong(HConstants.HBASE_CLIENT_PAUSE,
+          HConstants.DEFAULT_HBASE_CLIENT_PAUSE);
+        long sleep = HBaseAdmin.getPauseTime(tries++, pause);
+        sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
+        LOG.debug("(#" + tries + ") Sleeping: " + sleep +
+          "ms while waiting for snapshot completion.");
+        Thread.sleep(sleep);
+      } catch (InterruptedException e) {
+        throw (InterruptedIOException)new InterruptedIOException("Interrupted").initCause(e);
+      }
+      LOG.debug("Getting current status of snapshot ...");
+      done = snapshotMgr.isSnapshotDone(snapshot);
+    }
+    if (!done) {
+      throw new SnapshotCreationException("Snapshot '" + snapshot.getName()
+          + "' wasn't completed in expectedTime:" + max + " ms", snapshot);
+    }
+  }
+
   /**
    * Loop through the RS log timestamp map for the tables, for each RS, find the min timestamp
    * value for the RS among the tables.
@@ -139,7 +173,6 @@ public final class BackupUtil {
       descriptors.createTableDescriptorForTableDirectory(target, orig, false);
       LOG.debug("Finished copying tableinfo.");
 
-      HBaseAdmin hbadmin = null;
       // TODO: optimize
       List<HRegionInfo> regions = null;
       try(Connection conn = ConnectionFactory.createConnection(conf);


[4/6] hbase git commit: HBASE-15411 Rewrite backup with Procedure V2 - phase 1

Posted by te...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/MasterProtos.java
----------------------------------------------------------------------
diff --git a/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/MasterProtos.java b/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/MasterProtos.java
index 073eba9..b5b6b4c 100644
--- a/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/MasterProtos.java
+++ b/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/MasterProtos.java
@@ -52880,13 +52880,13 @@ public final class MasterProtos {
      */
     long getProcId();
 
-    // optional bool mayInterruptIfRunning = 2 [default = true];
+    // optional bool may_interrupt_if_running = 2 [default = true];
     /**
-     * <code>optional bool mayInterruptIfRunning = 2 [default = true];</code>
+     * <code>optional bool may_interrupt_if_running = 2 [default = true];</code>
      */
     boolean hasMayInterruptIfRunning();
     /**
-     * <code>optional bool mayInterruptIfRunning = 2 [default = true];</code>
+     * <code>optional bool may_interrupt_if_running = 2 [default = true];</code>
      */
     boolean getMayInterruptIfRunning();
   }
@@ -53007,17 +53007,17 @@ public final class MasterProtos {
       return procId_;
     }
 
-    // optional bool mayInterruptIfRunning = 2 [default = true];
-    public static final int MAYINTERRUPTIFRUNNING_FIELD_NUMBER = 2;
+    // optional bool may_interrupt_if_running = 2 [default = true];
+    public static final int MAY_INTERRUPT_IF_RUNNING_FIELD_NUMBER = 2;
     private boolean mayInterruptIfRunning_;
     /**
-     * <code>optional bool mayInterruptIfRunning = 2 [default = true];</code>
+     * <code>optional bool may_interrupt_if_running = 2 [default = true];</code>
      */
     public boolean hasMayInterruptIfRunning() {
       return ((bitField0_ & 0x00000002) == 0x00000002);
     }
     /**
-     * <code>optional bool mayInterruptIfRunning = 2 [default = true];</code>
+     * <code>optional bool may_interrupt_if_running = 2 [default = true];</code>
      */
     public boolean getMayInterruptIfRunning() {
       return mayInterruptIfRunning_;
@@ -53117,7 +53117,7 @@ public final class MasterProtos {
         hash = (53 * hash) + hashLong(getProcId());
       }
       if (hasMayInterruptIfRunning()) {
-        hash = (37 * hash) + MAYINTERRUPTIFRUNNING_FIELD_NUMBER;
+        hash = (37 * hash) + MAY_INTERRUPT_IF_RUNNING_FIELD_NUMBER;
         hash = (53 * hash) + hashBoolean(getMayInterruptIfRunning());
       }
       hash = (29 * hash) + getUnknownFields().hashCode();
@@ -53355,22 +53355,22 @@ public final class MasterProtos {
         return this;
       }
 
-      // optional bool mayInterruptIfRunning = 2 [default = true];
+      // optional bool may_interrupt_if_running = 2 [default = true];
       private boolean mayInterruptIfRunning_ = true;
       /**
-       * <code>optional bool mayInterruptIfRunning = 2 [default = true];</code>
+       * <code>optional bool may_interrupt_if_running = 2 [default = true];</code>
        */
       public boolean hasMayInterruptIfRunning() {
         return ((bitField0_ & 0x00000002) == 0x00000002);
       }
       /**
-       * <code>optional bool mayInterruptIfRunning = 2 [default = true];</code>
+       * <code>optional bool may_interrupt_if_running = 2 [default = true];</code>
        */
       public boolean getMayInterruptIfRunning() {
         return mayInterruptIfRunning_;
       }
       /**
-       * <code>optional bool mayInterruptIfRunning = 2 [default = true];</code>
+       * <code>optional bool may_interrupt_if_running = 2 [default = true];</code>
        */
       public Builder setMayInterruptIfRunning(boolean value) {
         bitField0_ |= 0x00000002;
@@ -53379,7 +53379,7 @@ public final class MasterProtos {
         return this;
       }
       /**
-       * <code>optional bool mayInterruptIfRunning = 2 [default = true];</code>
+       * <code>optional bool may_interrupt_if_running = 2 [default = true];</code>
        */
       public Builder clearMayInterruptIfRunning() {
         bitField0_ = (bitField0_ & ~0x00000002);
@@ -59215,6 +59215,1789 @@ public final class MasterProtos {
     // @@protoc_insertion_point(class_scope:hbase.pb.SecurityCapabilitiesResponse)
   }
 
+  public interface BackupTablesRequestOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required .hbase.pb.BackupType type = 1;
+    /**
+     * <code>required .hbase.pb.BackupType type = 1;</code>
+     */
+    boolean hasType();
+    /**
+     * <code>required .hbase.pb.BackupType type = 1;</code>
+     */
+    org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType getType();
+
+    // repeated .hbase.pb.TableName tables = 2;
+    /**
+     * <code>repeated .hbase.pb.TableName tables = 2;</code>
+     */
+    java.util.List<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName> 
+        getTablesList();
+    /**
+     * <code>repeated .hbase.pb.TableName tables = 2;</code>
+     */
+    org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName getTables(int index);
+    /**
+     * <code>repeated .hbase.pb.TableName tables = 2;</code>
+     */
+    int getTablesCount();
+    /**
+     * <code>repeated .hbase.pb.TableName tables = 2;</code>
+     */
+    java.util.List<? extends org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder> 
+        getTablesOrBuilderList();
+    /**
+     * <code>repeated .hbase.pb.TableName tables = 2;</code>
+     */
+    org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder getTablesOrBuilder(
+        int index);
+
+    // required string target_root_dir = 3;
+    /**
+     * <code>required string target_root_dir = 3;</code>
+     */
+    boolean hasTargetRootDir();
+    /**
+     * <code>required string target_root_dir = 3;</code>
+     */
+    java.lang.String getTargetRootDir();
+    /**
+     * <code>required string target_root_dir = 3;</code>
+     */
+    com.google.protobuf.ByteString
+        getTargetRootDirBytes();
+
+    // optional int64 workers = 4;
+    /**
+     * <code>optional int64 workers = 4;</code>
+     */
+    boolean hasWorkers();
+    /**
+     * <code>optional int64 workers = 4;</code>
+     */
+    long getWorkers();
+
+    // optional int64 bandwidth = 5;
+    /**
+     * <code>optional int64 bandwidth = 5;</code>
+     */
+    boolean hasBandwidth();
+    /**
+     * <code>optional int64 bandwidth = 5;</code>
+     */
+    long getBandwidth();
+  }
+  /**
+   * Protobuf type {@code hbase.pb.BackupTablesRequest}
+   */
+  public static final class BackupTablesRequest extends
+      com.google.protobuf.GeneratedMessage
+      implements BackupTablesRequestOrBuilder {
+    // Use BackupTablesRequest.newBuilder() to construct.
+    private BackupTablesRequest(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private BackupTablesRequest(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final BackupTablesRequest defaultInstance;
+    public static BackupTablesRequest getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public BackupTablesRequest getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private BackupTablesRequest(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 8: {
+              int rawValue = input.readEnum();
+              org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType value = org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType.valueOf(rawValue);
+              if (value == null) {
+                unknownFields.mergeVarintField(1, rawValue);
+              } else {
+                bitField0_ |= 0x00000001;
+                type_ = value;
+              }
+              break;
+            }
+            case 18: {
+              if (!((mutable_bitField0_ & 0x00000002) == 0x00000002)) {
+                tables_ = new java.util.ArrayList<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName>();
+                mutable_bitField0_ |= 0x00000002;
+              }
+              tables_.add(input.readMessage(org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.PARSER, extensionRegistry));
+              break;
+            }
+            case 26: {
+              bitField0_ |= 0x00000002;
+              targetRootDir_ = input.readBytes();
+              break;
+            }
+            case 32: {
+              bitField0_ |= 0x00000004;
+              workers_ = input.readInt64();
+              break;
+            }
+            case 40: {
+              bitField0_ |= 0x00000008;
+              bandwidth_ = input.readInt64();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        if (((mutable_bitField0_ & 0x00000002) == 0x00000002)) {
+          tables_ = java.util.Collections.unmodifiableList(tables_);
+        }
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.internal_static_hbase_pb_BackupTablesRequest_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.internal_static_hbase_pb_BackupTablesRequest_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest.class, org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<BackupTablesRequest> PARSER =
+        new com.google.protobuf.AbstractParser<BackupTablesRequest>() {
+      public BackupTablesRequest parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new BackupTablesRequest(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<BackupTablesRequest> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // required .hbase.pb.BackupType type = 1;
+    public static final int TYPE_FIELD_NUMBER = 1;
+    private org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType type_;
+    /**
+     * <code>required .hbase.pb.BackupType type = 1;</code>
+     */
+    public boolean hasType() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required .hbase.pb.BackupType type = 1;</code>
+     */
+    public org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType getType() {
+      return type_;
+    }
+
+    // repeated .hbase.pb.TableName tables = 2;
+    public static final int TABLES_FIELD_NUMBER = 2;
+    private java.util.List<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName> tables_;
+    /**
+     * <code>repeated .hbase.pb.TableName tables = 2;</code>
+     */
+    public java.util.List<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName> getTablesList() {
+      return tables_;
+    }
+    /**
+     * <code>repeated .hbase.pb.TableName tables = 2;</code>
+     */
+    public java.util.List<? extends org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder> 
+        getTablesOrBuilderList() {
+      return tables_;
+    }
+    /**
+     * <code>repeated .hbase.pb.TableName tables = 2;</code>
+     */
+    public int getTablesCount() {
+      return tables_.size();
+    }
+    /**
+     * <code>repeated .hbase.pb.TableName tables = 2;</code>
+     */
+    public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName getTables(int index) {
+      return tables_.get(index);
+    }
+    /**
+     * <code>repeated .hbase.pb.TableName tables = 2;</code>
+     */
+    public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder getTablesOrBuilder(
+        int index) {
+      return tables_.get(index);
+    }
+
+    // required string target_root_dir = 3;
+    public static final int TARGET_ROOT_DIR_FIELD_NUMBER = 3;
+    private java.lang.Object targetRootDir_;
+    /**
+     * <code>required string target_root_dir = 3;</code>
+     */
+    public boolean hasTargetRootDir() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>required string target_root_dir = 3;</code>
+     */
+    public java.lang.String getTargetRootDir() {
+      java.lang.Object ref = targetRootDir_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          targetRootDir_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>required string target_root_dir = 3;</code>
+     */
+    public com.google.protobuf.ByteString
+        getTargetRootDirBytes() {
+      java.lang.Object ref = targetRootDir_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        targetRootDir_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    // optional int64 workers = 4;
+    public static final int WORKERS_FIELD_NUMBER = 4;
+    private long workers_;
+    /**
+     * <code>optional int64 workers = 4;</code>
+     */
+    public boolean hasWorkers() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>optional int64 workers = 4;</code>
+     */
+    public long getWorkers() {
+      return workers_;
+    }
+
+    // optional int64 bandwidth = 5;
+    public static final int BANDWIDTH_FIELD_NUMBER = 5;
+    private long bandwidth_;
+    /**
+     * <code>optional int64 bandwidth = 5;</code>
+     */
+    public boolean hasBandwidth() {
+      return ((bitField0_ & 0x00000008) == 0x00000008);
+    }
+    /**
+     * <code>optional int64 bandwidth = 5;</code>
+     */
+    public long getBandwidth() {
+      return bandwidth_;
+    }
+
+    private void initFields() {
+      type_ = org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType.FULL;
+      tables_ = java.util.Collections.emptyList();
+      targetRootDir_ = "";
+      workers_ = 0L;
+      bandwidth_ = 0L;
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      if (!hasType()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      if (!hasTargetRootDir()) {
+        memoizedIsInitialized = 0;
+        return false;
+      }
+      for (int i = 0; i < getTablesCount(); i++) {
+        if (!getTables(i).isInitialized()) {
+          memoizedIsInitialized = 0;
+          return false;
+        }
+      }
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeEnum(1, type_.getNumber());
+      }
+      for (int i = 0; i < tables_.size(); i++) {
+        output.writeMessage(2, tables_.get(i));
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeBytes(3, getTargetRootDirBytes());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        output.writeInt64(4, workers_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        output.writeInt64(5, bandwidth_);
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeEnumSize(1, type_.getNumber());
+      }
+      for (int i = 0; i < tables_.size(); i++) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeMessageSize(2, tables_.get(i));
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(3, getTargetRootDirBytes());
+      }
+      if (((bitField0_ & 0x00000004) == 0x00000004)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(4, workers_);
+      }
+      if (((bitField0_ & 0x00000008) == 0x00000008)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeInt64Size(5, bandwidth_);
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    @java.lang.Override
+    public boolean equals(final java.lang.Object obj) {
+      if (obj == this) {
+       return true;
+      }
+      if (!(obj instanceof org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest)) {
+        return super.equals(obj);
+      }
+      org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest other = (org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest) obj;
+
+      boolean result = true;
+      result = result && (hasType() == other.hasType());
+      if (hasType()) {
+        result = result &&
+            (getType() == other.getType());
+      }
+      result = result && getTablesList()
+          .equals(other.getTablesList());
+      result = result && (hasTargetRootDir() == other.hasTargetRootDir());
+      if (hasTargetRootDir()) {
+        result = result && getTargetRootDir()
+            .equals(other.getTargetRootDir());
+      }
+      result = result && (hasWorkers() == other.hasWorkers());
+      if (hasWorkers()) {
+        result = result && (getWorkers()
+            == other.getWorkers());
+      }
+      result = result && (hasBandwidth() == other.hasBandwidth());
+      if (hasBandwidth()) {
+        result = result && (getBandwidth()
+            == other.getBandwidth());
+      }
+      result = result &&
+          getUnknownFields().equals(other.getUnknownFields());
+      return result;
+    }
+
+    private int memoizedHashCode = 0;
+    @java.lang.Override
+    public int hashCode() {
+      if (memoizedHashCode != 0) {
+        return memoizedHashCode;
+      }
+      int hash = 41;
+      hash = (19 * hash) + getDescriptorForType().hashCode();
+      if (hasType()) {
+        hash = (37 * hash) + TYPE_FIELD_NUMBER;
+        hash = (53 * hash) + hashEnum(getType());
+      }
+      if (getTablesCount() > 0) {
+        hash = (37 * hash) + TABLES_FIELD_NUMBER;
+        hash = (53 * hash) + getTablesList().hashCode();
+      }
+      if (hasTargetRootDir()) {
+        hash = (37 * hash) + TARGET_ROOT_DIR_FIELD_NUMBER;
+        hash = (53 * hash) + getTargetRootDir().hashCode();
+      }
+      if (hasWorkers()) {
+        hash = (37 * hash) + WORKERS_FIELD_NUMBER;
+        hash = (53 * hash) + hashLong(getWorkers());
+      }
+      if (hasBandwidth()) {
+        hash = (37 * hash) + BANDWIDTH_FIELD_NUMBER;
+        hash = (53 * hash) + hashLong(getBandwidth());
+      }
+      hash = (29 * hash) + getUnknownFields().hashCode();
+      memoizedHashCode = hash;
+      return hash;
+    }
+
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code hbase.pb.BackupTablesRequest}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequestOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.internal_static_hbase_pb_BackupTablesRequest_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.internal_static_hbase_pb_BackupTablesRequest_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest.class, org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest.Builder.class);
+      }
+
+      // Construct using org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+          getTablesFieldBuilder();
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        type_ = org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType.FULL;
+        bitField0_ = (bitField0_ & ~0x00000001);
+        if (tablesBuilder_ == null) {
+          tables_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000002);
+        } else {
+          tablesBuilder_.clear();
+        }
+        targetRootDir_ = "";
+        bitField0_ = (bitField0_ & ~0x00000004);
+        workers_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000008);
+        bandwidth_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000010);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.internal_static_hbase_pb_BackupTablesRequest_descriptor;
+      }
+
+      public org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest getDefaultInstanceForType() {
+        return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest.getDefaultInstance();
+      }
+
+      public org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest build() {
+        org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest buildPartial() {
+        org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest result = new org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.type_ = type_;
+        if (tablesBuilder_ == null) {
+          if (((bitField0_ & 0x00000002) == 0x00000002)) {
+            tables_ = java.util.Collections.unmodifiableList(tables_);
+            bitField0_ = (bitField0_ & ~0x00000002);
+          }
+          result.tables_ = tables_;
+        } else {
+          result.tables_ = tablesBuilder_.build();
+        }
+        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.targetRootDir_ = targetRootDir_;
+        if (((from_bitField0_ & 0x00000008) == 0x00000008)) {
+          to_bitField0_ |= 0x00000004;
+        }
+        result.workers_ = workers_;
+        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
+          to_bitField0_ |= 0x00000008;
+        }
+        result.bandwidth_ = bandwidth_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest) {
+          return mergeFrom((org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest other) {
+        if (other == org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest.getDefaultInstance()) return this;
+        if (other.hasType()) {
+          setType(other.getType());
+        }
+        if (tablesBuilder_ == null) {
+          if (!other.tables_.isEmpty()) {
+            if (tables_.isEmpty()) {
+              tables_ = other.tables_;
+              bitField0_ = (bitField0_ & ~0x00000002);
+            } else {
+              ensureTablesIsMutable();
+              tables_.addAll(other.tables_);
+            }
+            onChanged();
+          }
+        } else {
+          if (!other.tables_.isEmpty()) {
+            if (tablesBuilder_.isEmpty()) {
+              tablesBuilder_.dispose();
+              tablesBuilder_ = null;
+              tables_ = other.tables_;
+              bitField0_ = (bitField0_ & ~0x00000002);
+              tablesBuilder_ = 
+                com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
+                   getTablesFieldBuilder() : null;
+            } else {
+              tablesBuilder_.addAllMessages(other.tables_);
+            }
+          }
+        }
+        if (other.hasTargetRootDir()) {
+          bitField0_ |= 0x00000004;
+          targetRootDir_ = other.targetRootDir_;
+          onChanged();
+        }
+        if (other.hasWorkers()) {
+          setWorkers(other.getWorkers());
+        }
+        if (other.hasBandwidth()) {
+          setBandwidth(other.getBandwidth());
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasType()) {
+          
+          return false;
+        }
+        if (!hasTargetRootDir()) {
+          
+          return false;
+        }
+        for (int i = 0; i < getTablesCount(); i++) {
+          if (!getTables(i).isInitialized()) {
+            
+            return false;
+          }
+        }
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // required .hbase.pb.BackupType type = 1;
+      private org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType type_ = org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType.FULL;
+      /**
+       * <code>required .hbase.pb.BackupType type = 1;</code>
+       */
+      public boolean hasType() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>required .hbase.pb.BackupType type = 1;</code>
+       */
+      public org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType getType() {
+        return type_;
+      }
+      /**
+       * <code>required .hbase.pb.BackupType type = 1;</code>
+       */
+      public Builder setType(org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType value) {
+        if (value == null) {
+          throw new NullPointerException();
+        }
+        bitField0_ |= 0x00000001;
+        type_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required .hbase.pb.BackupType type = 1;</code>
+       */
+      public Builder clearType() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        type_ = org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType.FULL;
+        onChanged();
+        return this;
+      }
+
+      // repeated .hbase.pb.TableName tables = 2;
+      private java.util.List<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName> tables_ =
+        java.util.Collections.emptyList();
+      private void ensureTablesIsMutable() {
+        if (!((bitField0_ & 0x00000002) == 0x00000002)) {
+          tables_ = new java.util.ArrayList<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName>(tables_);
+          bitField0_ |= 0x00000002;
+         }
+      }
+
+      private com.google.protobuf.RepeatedFieldBuilder<
+          org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder> tablesBuilder_;
+
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public java.util.List<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName> getTablesList() {
+        if (tablesBuilder_ == null) {
+          return java.util.Collections.unmodifiableList(tables_);
+        } else {
+          return tablesBuilder_.getMessageList();
+        }
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public int getTablesCount() {
+        if (tablesBuilder_ == null) {
+          return tables_.size();
+        } else {
+          return tablesBuilder_.getCount();
+        }
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName getTables(int index) {
+        if (tablesBuilder_ == null) {
+          return tables_.get(index);
+        } else {
+          return tablesBuilder_.getMessage(index);
+        }
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public Builder setTables(
+          int index, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName value) {
+        if (tablesBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureTablesIsMutable();
+          tables_.set(index, value);
+          onChanged();
+        } else {
+          tablesBuilder_.setMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public Builder setTables(
+          int index, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder builderForValue) {
+        if (tablesBuilder_ == null) {
+          ensureTablesIsMutable();
+          tables_.set(index, builderForValue.build());
+          onChanged();
+        } else {
+          tablesBuilder_.setMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public Builder addTables(org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName value) {
+        if (tablesBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureTablesIsMutable();
+          tables_.add(value);
+          onChanged();
+        } else {
+          tablesBuilder_.addMessage(value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public Builder addTables(
+          int index, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName value) {
+        if (tablesBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          ensureTablesIsMutable();
+          tables_.add(index, value);
+          onChanged();
+        } else {
+          tablesBuilder_.addMessage(index, value);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public Builder addTables(
+          org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder builderForValue) {
+        if (tablesBuilder_ == null) {
+          ensureTablesIsMutable();
+          tables_.add(builderForValue.build());
+          onChanged();
+        } else {
+          tablesBuilder_.addMessage(builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public Builder addTables(
+          int index, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder builderForValue) {
+        if (tablesBuilder_ == null) {
+          ensureTablesIsMutable();
+          tables_.add(index, builderForValue.build());
+          onChanged();
+        } else {
+          tablesBuilder_.addMessage(index, builderForValue.build());
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public Builder addAllTables(
+          java.lang.Iterable<? extends org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName> values) {
+        if (tablesBuilder_ == null) {
+          ensureTablesIsMutable();
+          super.addAll(values, tables_);
+          onChanged();
+        } else {
+          tablesBuilder_.addAllMessages(values);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public Builder clearTables() {
+        if (tablesBuilder_ == null) {
+          tables_ = java.util.Collections.emptyList();
+          bitField0_ = (bitField0_ & ~0x00000002);
+          onChanged();
+        } else {
+          tablesBuilder_.clear();
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public Builder removeTables(int index) {
+        if (tablesBuilder_ == null) {
+          ensureTablesIsMutable();
+          tables_.remove(index);
+          onChanged();
+        } else {
+          tablesBuilder_.remove(index);
+        }
+        return this;
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder getTablesBuilder(
+          int index) {
+        return getTablesFieldBuilder().getBuilder(index);
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder getTablesOrBuilder(
+          int index) {
+        if (tablesBuilder_ == null) {
+          return tables_.get(index);  } else {
+          return tablesBuilder_.getMessageOrBuilder(index);
+        }
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public java.util.List<? extends org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder> 
+           getTablesOrBuilderList() {
+        if (tablesBuilder_ != null) {
+          return tablesBuilder_.getMessageOrBuilderList();
+        } else {
+          return java.util.Collections.unmodifiableList(tables_);
+        }
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder addTablesBuilder() {
+        return getTablesFieldBuilder().addBuilder(
+            org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder addTablesBuilder(
+          int index) {
+        return getTablesFieldBuilder().addBuilder(
+            index, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.getDefaultInstance());
+      }
+      /**
+       * <code>repeated .hbase.pb.TableName tables = 2;</code>
+       */
+      public java.util.List<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder> 
+           getTablesBuilderList() {
+        return getTablesFieldBuilder().getBuilderList();
+      }
+      private com.google.protobuf.RepeatedFieldBuilder<
+          org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder> 
+          getTablesFieldBuilder() {
+        if (tablesBuilder_ == null) {
+          tablesBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
+              org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder>(
+                  tables_,
+                  ((bitField0_ & 0x00000002) == 0x00000002),
+                  getParentForChildren(),
+                  isClean());
+          tables_ = null;
+        }
+        return tablesBuilder_;
+      }
+
+      // required string target_root_dir = 3;
+      private java.lang.Object targetRootDir_ = "";
+      /**
+       * <code>required string target_root_dir = 3;</code>
+       */
+      public boolean hasTargetRootDir() {
+        return ((bitField0_ & 0x00000004) == 0x00000004);
+      }
+      /**
+       * <code>required string target_root_dir = 3;</code>
+       */
+      public java.lang.String getTargetRootDir() {
+        java.lang.Object ref = targetRootDir_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          targetRootDir_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>required string target_root_dir = 3;</code>
+       */
+      public com.google.protobuf.ByteString
+          getTargetRootDirBytes() {
+        java.lang.Object ref = targetRootDir_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          targetRootDir_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>required string target_root_dir = 3;</code>
+       */
+      public Builder setTargetRootDir(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        targetRootDir_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string target_root_dir = 3;</code>
+       */
+      public Builder clearTargetRootDir() {
+        bitField0_ = (bitField0_ & ~0x00000004);
+        targetRootDir_ = getDefaultInstance().getTargetRootDir();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>required string target_root_dir = 3;</code>
+       */
+      public Builder setTargetRootDirBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000004;
+        targetRootDir_ = value;
+        onChanged();
+        return this;
+      }
+
+      // optional int64 workers = 4;
+      private long workers_ ;
+      /**
+       * <code>optional int64 workers = 4;</code>
+       */
+      public boolean hasWorkers() {
+        return ((bitField0_ & 0x00000008) == 0x00000008);
+      }
+      /**
+       * <code>optional int64 workers = 4;</code>
+       */
+      public long getWorkers() {
+        return workers_;
+      }
+      /**
+       * <code>optional int64 workers = 4;</code>
+       */
+      public Builder setWorkers(long value) {
+        bitField0_ |= 0x00000008;
+        workers_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int64 workers = 4;</code>
+       */
+      public Builder clearWorkers() {
+        bitField0_ = (bitField0_ & ~0x00000008);
+        workers_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      // optional int64 bandwidth = 5;
+      private long bandwidth_ ;
+      /**
+       * <code>optional int64 bandwidth = 5;</code>
+       */
+      public boolean hasBandwidth() {
+        return ((bitField0_ & 0x00000010) == 0x00000010);
+      }
+      /**
+       * <code>optional int64 bandwidth = 5;</code>
+       */
+      public long getBandwidth() {
+        return bandwidth_;
+      }
+      /**
+       * <code>optional int64 bandwidth = 5;</code>
+       */
+      public Builder setBandwidth(long value) {
+        bitField0_ |= 0x00000010;
+        bandwidth_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional int64 bandwidth = 5;</code>
+       */
+      public Builder clearBandwidth() {
+        bitField0_ = (bitField0_ & ~0x00000010);
+        bandwidth_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:hbase.pb.BackupTablesRequest)
+    }
+
+    static {
+      defaultInstance = new BackupTablesRequest(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:hbase.pb.BackupTablesRequest)
+  }
+
+  public interface BackupTablesResponseOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // optional uint64 proc_id = 1;
+    /**
+     * <code>optional uint64 proc_id = 1;</code>
+     */
+    boolean hasProcId();
+    /**
+     * <code>optional uint64 proc_id = 1;</code>
+     */
+    long getProcId();
+
+    // optional string backup_id = 2;
+    /**
+     * <code>optional string backup_id = 2;</code>
+     */
+    boolean hasBackupId();
+    /**
+     * <code>optional string backup_id = 2;</code>
+     */
+    java.lang.String getBackupId();
+    /**
+     * <code>optional string backup_id = 2;</code>
+     */
+    com.google.protobuf.ByteString
+        getBackupIdBytes();
+  }
+  /**
+   * Protobuf type {@code hbase.pb.BackupTablesResponse}
+   */
+  public static final class BackupTablesResponse extends
+      com.google.protobuf.GeneratedMessage
+      implements BackupTablesResponseOrBuilder {
+    // Use BackupTablesResponse.newBuilder() to construct.
+    private BackupTablesResponse(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private BackupTablesResponse(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final BackupTablesResponse defaultInstance;
+    public static BackupTablesResponse getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public BackupTablesResponse getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private BackupTablesResponse(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 8: {
+              bitField0_ |= 0x00000001;
+              procId_ = input.readUInt64();
+              break;
+            }
+            case 18: {
+              bitField0_ |= 0x00000002;
+              backupId_ = input.readBytes();
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.internal_static_hbase_pb_BackupTablesResponse_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.internal_static_hbase_pb_BackupTablesResponse_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse.class, org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<BackupTablesResponse> PARSER =
+        new com.google.protobuf.AbstractParser<BackupTablesResponse>() {
+      public BackupTablesResponse parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new BackupTablesResponse(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<BackupTablesResponse> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // optional uint64 proc_id = 1;
+    public static final int PROC_ID_FIELD_NUMBER = 1;
+    private long procId_;
+    /**
+     * <code>optional uint64 proc_id = 1;</code>
+     */
+    public boolean hasProcId() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>optional uint64 proc_id = 1;</code>
+     */
+    public long getProcId() {
+      return procId_;
+    }
+
+    // optional string backup_id = 2;
+    public static final int BACKUP_ID_FIELD_NUMBER = 2;
+    private java.lang.Object backupId_;
+    /**
+     * <code>optional string backup_id = 2;</code>
+     */
+    public boolean hasBackupId() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>optional string backup_id = 2;</code>
+     */
+    public java.lang.String getBackupId() {
+      java.lang.Object ref = backupId_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          backupId_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>optional string backup_id = 2;</code>
+     */
+    public com.google.protobuf.ByteString
+        getBackupIdBytes() {
+      java.lang.Object ref = backupId_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        backupId_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    private void initFields() {
+      procId_ = 0L;
+      backupId_ = "";
+    }
+    private byte memoizedIsInitialized = -1;
+    public final boolean isInitialized() {
+      byte isInitialized = memoizedIsInitialized;
+      if (isInitialized != -1) return isInitialized == 1;
+
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeUInt64(1, procId_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        output.writeBytes(2, getBackupIdBytes());
+      }
+      getUnknownFields().writeTo(output);
+    }
+
+    private int memoizedSerializedSize = -1;
+    public int getSerializedSize() {
+      int size = memoizedSerializedSize;
+      if (size != -1) return size;
+
+      size = 0;
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeUInt64Size(1, procId_);
+      }
+      if (((bitField0_ & 0x00000002) == 0x00000002)) {
+        size += com.google.protobuf.CodedOutputStream
+          .computeBytesSize(2, getBackupIdBytes());
+      }
+      size += getUnknownFields().getSerializedSize();
+      memoizedSerializedSize = size;
+      return size;
+    }
+
+    private static final long serialVersionUID = 0L;
+    @java.lang.Override
+    protected java.lang.Object writeReplace()
+        throws java.io.ObjectStreamException {
+      return super.writeReplace();
+    }
+
+    @java.lang.Override
+    public boolean equals(final java.lang.Object obj) {
+      if (obj == this) {
+       return true;
+      }
+      if (!(obj instanceof org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse)) {
+        return super.equals(obj);
+      }
+      org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse other = (org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse) obj;
+
+      boolean result = true;
+      result = result && (hasProcId() == other.hasProcId());
+      if (hasProcId()) {
+        result = result && (getProcId()
+            == other.getProcId());
+      }
+      result = result && (hasBackupId() == other.hasBackupId());
+      if (hasBackupId()) {
+        result = result && getBackupId()
+            .equals(other.getBackupId());
+      }
+      result = result &&
+          getUnknownFields().equals(other.getUnknownFields());
+      return result;
+    }
+
+    private int memoizedHashCode = 0;
+    @java.lang.Override
+    public int hashCode() {
+      if (memoizedHashCode != 0) {
+        return memoizedHashCode;
+      }
+      int hash = 41;
+      hash = (19 * hash) + getDescriptorForType().hashCode();
+      if (hasProcId()) {
+        hash = (37 * hash) + PROC_ID_FIELD_NUMBER;
+        hash = (53 * hash) + hashLong(getProcId());
+      }
+      if (hasBackupId()) {
+        hash = (37 * hash) + BACKUP_ID_FIELD_NUMBER;
+        hash = (53 * hash) + getBackupId().hashCode();
+      }
+      hash = (29 * hash) + getUnknownFields().hashCode();
+      memoizedHashCode = hash;
+      return hash;
+    }
+
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse parseFrom(
+        com.google.protobuf.ByteString data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse parseFrom(
+        com.google.protobuf.ByteString data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse parseFrom(byte[] data)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse parseFrom(
+        byte[] data,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      return PARSER.parseFrom(data, extensionRegistry);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse parseFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse parseFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse parseDelimitedFrom(java.io.InputStream input)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse parseDelimitedFrom(
+        java.io.InputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseDelimitedFrom(input, extensionRegistry);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse parseFrom(
+        com.google.protobuf.CodedInputStream input)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input);
+    }
+    public static org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse parseFrom(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws java.io.IOException {
+      return PARSER.parseFrom(input, extensionRegistry);
+    }
+
+    public static Builder newBuilder() { return Builder.create(); }
+    public Builder newBuilderForType() { return newBuilder(); }
+    public static Builder newBuilder(org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse prototype) {
+      return newBuilder().mergeFrom(prototype);
+    }
+    public Builder toBuilder() { return newBuilder(this); }
+
+    @java.lang.Override
+    protected Builder newBuilderForType(
+        com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+      Builder builder = new Builder(parent);
+      return builder;
+    }
+    /**
+     * Protobuf type {@code hbase.pb.BackupTablesResponse}
+     */
+    public static final class Builder extends
+        com.google.protobuf.GeneratedMessage.Builder<Builder>
+       implements org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponseOrBuilder {
+      public static final com.google.protobuf.Descriptors.Descriptor
+          getDescriptor() {
+        return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.internal_static_hbase_pb_BackupTablesResponse_descriptor;
+      }
+
+      protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+          internalGetFieldAccessorTable() {
+        return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.internal_static_hbase_pb_BackupTablesResponse_fieldAccessorTable
+            .ensureFieldAccessorsInitialized(
+                org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse.class, org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse.Builder.class);
+      }
+
+      // Construct using org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse.newBuilder()
+      private Builder() {
+        maybeForceBuilderInitialization();
+      }
+
+      private Builder(
+          com.google.protobuf.GeneratedMessage.BuilderParent parent) {
+        super(parent);
+        maybeForceBuilderInitialization();
+      }
+      private void maybeForceBuilderInitialization() {
+        if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
+        }
+      }
+      private static Builder create() {
+        return new Builder();
+      }
+
+      public Builder clear() {
+        super.clear();
+        procId_ = 0L;
+        bitField0_ = (bitField0_ & ~0x00000001);
+        backupId_ = "";
+        bitField0_ = (bitField0_ & ~0x00000002);
+        return this;
+      }
+
+      public Builder clone() {
+        return create().mergeFrom(buildPartial());
+      }
+
+      public com.google.protobuf.Descriptors.Descriptor
+          getDescriptorForType() {
+        return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.internal_static_hbase_pb_BackupTablesResponse_descriptor;
+      }
+
+      public org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse getDefaultInstanceForType() {
+        return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse.getDefaultInstance();
+      }
+
+      public org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse build() {
+        org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse result = buildPartial();
+        if (!result.isInitialized()) {
+          throw newUninitializedMessageException(result);
+        }
+        return result;
+      }
+
+      public org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse buildPartial() {
+        org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse result = new org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse(this);
+        int from_bitField0_ = bitField0_;
+        int to_bitField0_ = 0;
+        if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
+          to_bitField0_ |= 0x00000001;
+        }
+        result.procId_ = procId_;
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
+        }
+        result.backupId_ = backupId_;
+        result.bitField0_ = to_bitField0_;
+        onBuilt();
+        return result;
+      }
+
+      public Builder mergeFrom(com.google.protobuf.Message other) {
+        if (other instanceof org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse) {
+          return mergeFrom((org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse)other);
+        } else {
+          super.mergeFrom(other);
+          return this;
+        }
+      }
+
+      public Builder mergeFrom(org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse other) {
+        if (other == org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse.getDefaultInstance()) return this;
+        if (other.hasProcId()) {
+          setProcId(other.getProcId());
+        }
+        if (other.hasBackupId()) {
+          bitField0_ |= 0x00000002;
+          backupId_ = other.backupId_;
+          onChanged();
+        }
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        return true;
+      }
+
+      public Builder mergeFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws java.io.IOException {
+        org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse parsedMessage = null;
+        try {
+          parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
+        } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+          parsedMessage = (org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse) e.getUnfinishedMessage();
+          throw e;
+        } finally {
+          if (parsedMessage != null) {
+            mergeFrom(parsedMessage);
+          }
+        }
+        return this;
+      }
+      private int bitField0_;
+
+      // optional uint64 proc_id = 1;
+      private long procId_ ;
+      /**
+       * <code>optional uint64 proc_id = 1;</code>
+       */
+      public boolean hasProcId() {
+        return ((bitField0_ & 0x00000001) == 0x00000001);
+      }
+      /**
+       * <code>optional uint64 proc_id = 1;</code>
+       */
+      public long getProcId() {
+        return procId_;
+      }
+      /**
+       * <code>optional uint64 proc_id = 1;</code>
+       */
+      public Builder setProcId(long value) {
+        bitField0_ |= 0x00000001;
+        procId_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional uint64 proc_id = 1;</code>
+       */
+      public Builder clearProcId() {
+        bitField0_ = (bitField0_ & ~0x00000001);
+        procId_ = 0L;
+        onChanged();
+        return this;
+      }
+
+      // optional string backup_id = 2;
+      private java.lang.Object backupId_ = "";
+      /**
+       * <code>optional string backup_id = 2;</code>
+       */
+      public boolean hasBackupId() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
+      }
+      /**
+       * <code>optional string backup_id = 2;</code>
+       */
+      public java.lang.String getBackupId() {
+        java.lang.Object ref = backupId_;
+        if (!(ref instanceof java.lang.String)) {
+          java.lang.String s = ((com.google.protobuf.ByteString) ref)
+              .toStringUtf8();
+          backupId_ = s;
+          return s;
+        } else {
+          return (java.lang.String) ref;
+        }
+      }
+      /**
+       * <code>optional string backup_id = 2;</code>
+       */
+      public com.google.protobuf.ByteString
+          getBackupIdBytes() {
+        java.lang.Object ref = backupId_;
+        if (ref instanceof String) {
+          com.google.protobuf.ByteString b = 
+              com.google.protobuf.ByteString.copyFromUtf8(
+                  (java.lang.String) ref);
+          backupId_ = b;
+          return b;
+        } else {
+          return (com.google.protobuf.ByteString) ref;
+        }
+      }
+      /**
+       * <code>optional string backup_id = 2;</code>
+       */
+      public Builder setBackupId(
+          java.lang.String value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        backupId_ = value;
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string backup_id = 2;</code>
+       */
+      public Builder clearBackupId() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        backupId_ = getDefaultInstance().getBackupId();
+        onChanged();
+        return this;
+      }
+      /**
+       * <code>optional string backup_id = 2;</code>
+       */
+      public Builder setBackupIdBytes(
+          com.google.protobuf.ByteString value) {
+        if (value == null) {
+    throw new NullPointerException();
+  }
+  bitField0_ |= 0x00000002;
+        backupId_ = value;
+        onChanged();
+        return this;
+      }
+
+      // @@protoc_insertion_point(builder_scope:hbase.pb.BackupTablesResponse)
+    }
+
+    static {
+      defaultInstance = new BackupTablesResponse(true);
+      defaultInstance.initFields();
+    }
+
+    // @@protoc_insertion_point(class_scope:hbase.pb.BackupTablesResponse)
+  }
+
   /**
    * Protobuf service {@code hbase.pb.MasterService}
    */
@@ -59936,6 +61719,18 @@ public final class MasterProtos {
           org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresRequest request,
           com.google.protobuf.RpcCallback<org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresResponse> done);
 
+      /**
+       * <code>rpc backupTables(.hbase.pb.BackupTablesRequest) returns (.hbase.pb.BackupTablesResponse);</code>
+       *
+       * <pre>
+       ** backup table set 
+       * </pre>
+       */
+      public abstract void backupTables(
+          com.google.protobuf.RpcController controller,
+          org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest request,
+          com.google.protobuf.RpcCallback<org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse> done);
+
     }
 
     public static com.google.protobuf.Service newReflectiveService(
@@ -60397,6 +62192,14 @@ public final class MasterProtos {
           impl.listProcedures(controller, request, done);
         }
 
+        @java.lang.Override
+        public  void backupTables(
+            com.google.protobuf.RpcController controller,
+            org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest request,
+            com.google.protobuf.RpcCallback<org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse> done) {
+          impl.backupTables(controller, request, done);
+        }
+
       };
     }
 
@@ -60533,6 +62336,8 @@ public final class MasterProtos {
               return impl.abortProcedure(controller, (org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AbortProcedureRequest)request);
             case 56:
               return impl.listProcedures(controller, (org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresRequest)request);
+            case 57:
+              return impl.backupTables(controller, (org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest)request);
             default:
               throw new java.lang.AssertionError("Can't get here.");
           }
@@ -60661,6 +62466,8 @@ public final class MasterProtos {
               return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AbortProcedureRequest.getDefaultInstance();
             case 56:
               return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresRequest.getDefaultInstance();
+            case 57:
+              return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest.getDefaultInstance();
             default:
               throw new java.lang.AssertionError("Can't get here.");
           }
@@ -60789,6 +62596,8 @@ public final class MasterProtos {
               return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AbortProcedureResponse.getDefaultInstance();
             case 56:
               return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresResponse.getDefaultInstance();
+            case 57:
+              return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse.getDefaultInstance();
             default:
               throw new java.lang.AssertionError("Can't get here.");
           }
@@ -61510,6 +63319,18 @@ public final class MasterProtos {
         org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresRequest request,
         com.google.protobuf.RpcCallback<org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresResponse> done);
 
+    /**
+     * <code>rpc backupTables(.hbase.pb.BackupTablesRequest) returns (.hbase.pb.BackupTablesResponse);</code>
+     *
+     * <pre>
+     ** backup table set 
+     * </pre>
+     */
+    public abstract void backupTables(
+        com.google.protobuf.RpcController controller,
+        org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest request,
+        com.google.protobuf.RpcCallback<org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse> done);
+
     public static final
         com.google.protobuf.Descriptors.ServiceDescriptor
         getDescriptor() {
@@ -61817,6 +63638,11 @@ public final class MasterProtos {
             com.google.protobuf.RpcUtil.<org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresResponse>specializeCallback(
               done));
           return;
+        case 57:
+          this.backupTables(controller, (org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest)request,
+            com.google.protobuf.RpcUtil.<org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse>specializeCallback(
+              done));
+          return;
         default:
           throw new java.lang.AssertionError("Can't get here.");
       }
@@ -61945,6 +63771,8 @@ public final class MasterProtos {
           return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AbortProcedureRequest.getDefaultInstance();
         case 56:
           return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresRequest.getDefaultInstance();
+        case 57:
+          return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest.getDefaultInstance();
         default:
           throw new java.lang.AssertionError("Can't get here.");
       }
@@ -62073,6 +63901,8 @@ public final class MasterProtos {
           return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.AbortProcedureResponse.getDefaultInstance();
         case 56:
           return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresResponse.getDefaultInstance();
+        case 57:
+          return org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse.getDefaultInstance();
         default:
           throw new java.lang.AssertionError("Can't get here.");
       }
@@ -62948,6 +64778,21 @@ public final class MasterProtos {
             org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresResponse.class,
             org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresResponse.getDefaultInstance()));
       }
+
+      public  void backupTables(
+          com.google.protobuf.RpcController controller,
+          org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest request,
+          com.google.protobuf.RpcCallback<org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse> done) {
+        channel.callMethod(
+          getDescriptor().getMethods().get(57),
+          controller,
+          request,
+          org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse.getDefaultInstance(),
+          com.google.protobuf.RpcUtil.generalizeCallback(
+            done,
+            org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse.class,
+            org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse.getDefaultInstance()));
+      }
     }
 
     public static BlockingInterface newBlockingStub(
@@ -63240,6 +65085,11 @@ public final class MasterProtos {
           com.google.protobuf.RpcController controller,
           org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresRequest request)
           throws com.google.protobuf.ServiceException;
+
+      public org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse backupTables(
+          com.google.protobuf.RpcController controller,
+          org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest request)
+          throws com.google.protobuf.ServiceException;
     }
 
     private static final class BlockingStub implements BlockingInterface {
@@ -63932,6 +65782,18 @@ public final class MasterProtos {
           org.apache.hadoop.hbase.protobuf.generated.MasterProtos.ListProceduresResponse.getDefaultInstance());
       }
 
+
+      public org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse backupTables(
+          com.google.protobuf.RpcController controller,
+          org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesRequest request)
+          throws com.google.protobuf.ServiceException {
+        return (org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse) channel.callBlockingMethod(
+          getDescriptor().getMethods().get(57),
+          controller,
+          request,
+          org.apache.hadoop.hbase.protobuf.generated.MasterProtos.BackupTablesResponse.getDefaultInstance());
+      }
+
     }
 
     // @@protoc_insertion_point(class_scope:hbase.pb.MasterService)
@@ -64482,6 +66344,16 @@ public final class MasterProtos {
   private static
     com.google.protobuf.GeneratedMessage.FieldAccessorTable
       internal_static_hbase_pb_SecurityCapabilitiesResponse_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_hbase_pb_BackupTablesRequest_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_hbase_pb_BackupTablesRequest_fieldAccessorTable;
+  private static com.google.protobuf.Descriptors.Descriptor
+    internal_static_hbase_pb_BackupTablesResponse_descriptor;
+  private static
+    com.google.protobuf.GeneratedMessage.FieldAccessorTable
+      internal_static_hbase_pb_BackupTablesResponse_fieldAccessorTable;
 
   public static com.google.protobuf.Descriptors.FileDescriptor
       getDescriptor() {
@@ -64491,331 +66363,339 @@ public final class MasterProtos {
       descriptor;
   static {
     java.lang.String[] descriptorData = {
-      "\n\014Master.proto\022\010hbase.pb\032\013HBase.proto\032\014C" +
-      "lient.proto\032\023ClusterStatus.proto\032\023ErrorH" +
-      "andling.proto\032\017Procedure.proto\032\013Quota.pr" +
-      "oto\"\234\001\n\020AddColumnRequest\022\'\n\ntable_name\030\001" +
-      " \002(\0132\023.hbase.pb.TableName\0225\n\017column_fami" +
-      "lies\030\002 \002(\0132\034.hbase.pb.ColumnFamilySchema" +
-      "\022\026\n\013nonce_group\030\003 \001(\004:\0010\022\020\n\005nonce\030\004 \001(\004:" +
-      "\0010\"$\n\021AddColumnResponse\022\017\n\007proc_id\030\001 \001(\004" +
-      "\"}\n\023DeleteColumnRequest\022\'\n\ntable_name\030\001 " +
-      "\002(\0132\023.hbase.pb.TableName\022\023\n\013column_name\030",
-      "\002 \002(\014\022\026\n\013nonce_group\030\003 \001(\004:\0010\022\020\n\005nonce\030\004" +
-      " \001(\004:\0010\"\'\n\024DeleteColumnResponse\022\017\n\007proc_" +
-      "id\030\001 \001(\004\"\237\001\n\023ModifyColumnRequest\022\'\n\ntabl" +
-      "e_name\030\001 \002(\0132\023.hbase.pb.TableName\0225\n\017col" +
-      "umn_families\030\002 \002(\0132\034.hbase.pb.ColumnFami" +
-      "lySchema\022\026\n\013nonce_group\030\003 \001(\004:\0010\022\020\n\005nonc" +
-      "e\030\004 \001(\004:\0010\"\'\n\024ModifyColumnResponse\022\017\n\007pr" +
-      "oc_id\030\001 \001(\004\"n\n\021MoveRegionRequest\022)\n\006regi" +
-      "on\030\001 \002(\0132\031.hbase.pb.RegionSpecifier\022.\n\020d" +
-      "est_server_name\030\002 \001(\0132\024.hbase.pb.ServerN",
-      "ame\"\024\n\022MoveRegionResponse\"\222\001\n\035DispatchMe" +
-      "rgingRegionsRequest\022+\n\010region_a\030\001 \002(\0132\031." +
-      "hbase.pb.RegionSpecifier\022+\n\010region_b\030\002 \002" +
-      "(\0132\031.hbase.pb.RegionSpecifier\022\027\n\010forcibl" +
-      "e\030\003 \001(\010:\005false\" \n\036DispatchMergingRegions" +
-      "Response\"@\n\023AssignRegionRequest\022)\n\006regio" +
-      "n\030\001 \002(\0132\031.hbase.pb.RegionSpecifier\"\026\n\024As" +
-      "signRegionResponse\"X\n\025UnassignRegionRequ" +
-      "est\022)\n\006region\030\001 \002(\0132\031.hbase.pb.RegionSpe" +
-      "cifier\022\024\n\005force\030\002 \001(\010:\005false\"\030\n\026Unassign",
-      "RegionResponse\"A\n\024OfflineRegionRequest\022)" +
-      "\n\006region\030\001 \002(\0132\031.hbase.pb.RegionSpecifie" +
-      "r\"\027\n\025OfflineRegionResponse\"\177\n\022CreateTabl" +
-      "eRequest\022+\n\014table_schema\030\001 \002(\0132\025.hbase.p" +
-      "b.TableSchema\022\022\n\nsplit_keys\030\002 \003(\014\022\026\n\013non" +
-      "ce_group\030\003 \001(\004:\0010\022\020\n\005nonce\030\004 \001(\004:\0010\"&\n\023C" +
-      "reateTableResponse\022\017\n\007proc_id\030\001 \001(\004\"g\n\022D" +
-      "eleteTableRequest\022\'\n\ntable_name\030\001 \002(\0132\023." +
-      "hbase.pb.TableName\022\026\n\013nonce_group\030\002 \001(\004:" +
-      "\0010\022\020\n\005nonce\030\003 \001(\004:\0010\"&\n\023DeleteTableRespo",
-      "nse\022\017\n\007proc_id\030\001 \001(\004\"\207\001\n\024TruncateTableRe" +
-      "quest\022&\n\ttableName\030\001 \002(\0132\023.hbase.pb.Tabl" +
-      "eName\022\035\n\016preserveSplits\030\002 \001(\010:\005false\022\026\n\013" +
-      "nonce_group\030\003 \001(\004:\0010\022\020\n\005nonce\030\004 \001(\004:\0010\"(" +
-      "\n\025TruncateTableResponse\022\017\n\007proc_id\030\001 \001(\004" +
-      "\"g\n\022EnableTableRequest\022\'\n\ntable_name\030\001 \002" +
+      "\n\014Master.proto\022\010hbase.pb\032\013HBase.proto\032\014B" +
+      "ackup.proto\032\014Client.proto\032\023ClusterStatus" +
+      ".proto\032\023ErrorHandling.proto\032\017Procedure.p" +
+      "roto\032\013Quota.proto\"\234\001\n\020AddColumnRequest\022\'" +
+      "\n\ntable_name\030\001 \002(\0132\023.hbase.pb.TableName\022" +
+      "5\n\017column_families\030\002 \002(\0132\034.hbase.pb.Colu" +
+      "mnFamilySchema\022\026\n\013nonce_group\030\003 \001(\004:\0010\022\020" +
+      "\n\005nonce\030\004 \001(\004:\0010\"$\n\021AddColumnResponse\022\017\n" +
+      "\007proc_id\030\001 \001(\004\"}\n\023DeleteColumnRequest\022\'\n" +
+      "\ntable_name\030\001 \002(\0132\023.hbase.pb.TableName\022\023",
+      "\n\013column_name\030\002 \002(\014\022\026\n\013nonce_group\030\003 \001(\004" +
+      ":\0010\022\020\n\005nonce\030\004 \001(\004:\0010\"\'\n\024DeleteColumnRes" +
+      "ponse\022\017\n\007proc_id\030\001 \001(\004\"\237\001\n\023ModifyColumnR" +
+      "equest\022\'\n\ntable_name\030\001 \002(\0132\023.hbase.pb.Ta" +
+      "bleName\0225\n\017column_families\030\002 \002(\0132\034.hbase" +
+      ".pb.ColumnFamilySchema\022\026\n\013nonce_group\030\003 " +
+      "\001(\004:\0010\022\020\n\005nonce\030\004 \001(\004:\0010\"\'\n\024ModifyColumn" +
+      "Response\022\017\n\007proc_id\030\001 \001(\004\"n\n\021MoveRegionR" +
+      "equest\022)\n\006region\030\001 \002(\0132\031.hbase.pb.Region" +
+      "Specifier\022.\n\020dest_server_name\030\002 \001(\0132\024.hb",
+      "ase.pb.ServerName\"\024\n\022MoveRegionResponse\"" +
+      "\222\001\n\035DispatchMergingRegionsRequest\022+\n\010reg" +
+      "ion_a\030\001 \002(\0132\031.hbase.pb.RegionSpecifier\022+" +
+      "\n\010region_b\030\002 \002(\0132\031.hbase.pb.RegionSpecif" +
+      "ier\022\027\n\010forcible\030\003 \001(\010:\005false\" \n\036Dispatch" +
+      "MergingRegionsResponse\"@\n\023AssignRegionRe" +
+      "quest\022)\n\006region\030\001 \002(\0132\031.hbase.pb.RegionS" +
+      "pecifier\"\026\n\024AssignRegionResponse\"X\n\025Unas" +
+      "signRegionRequest\022)\n\006region\030\001 \002(\0132\031.hbas" +
+      "e.pb.RegionSpecifier\022\024\n\005force\030\002 \001(\010:\005fal",
+      "se\"\030\n\026UnassignRegionResponse\"A\n\024OfflineR" +
+      "egionRequest\022)\n\006region\030\001 \002(\0132\031.hbase.pb." +
+      "RegionSpecifier\"\027\n\025OfflineRegionResponse" +
+      "\"\177\n\022CreateTableRequest\022+\n\014table_schema\030\001" +
+      " \002(\0132\025.hbase.pb.TableSchema\022\022\n\nsplit_key" +
+      "s\030\002 \003(\014\022\026\n\013nonce_group\030\003 \001(\004:\0010\022\020\n\005nonce" +
+      "\030\004 \001(\004:\0010\"&\n\023CreateTableResponse\022\017\n\007proc" +
+      "_id\030\001 \001(\004\"g\n\022DeleteTableRequest\022\'\n\ntable" +
+      "_name\030\001 \002(\0132\023.hbase.pb.TableName\022\026\n\013nonc" +
+      "e_group\030\002 \001(\004:\0010\022\020\n\005nonce\030\003 \001(\004:\0010\"&\n\023De",
+      "leteTableResponse\022\017\n\007proc_id\030\001 \001(\004\"\207\001\n\024T" +
+      "runcateTableRequest\022&\n\ttableName\030\001 \002(\0132\023" +
+      ".hbase.pb.TableName\022\035\n\016preserveSplits\030\002 " +
+      "\001(\010:\005false\022\026\n\013nonce_group\030\003 \001(\004:\0010\022\020\n\005no" +
+      "nce\030\004 \001(\004:\0010\"(\n\025TruncateTableResponse\022\017\n" +
+      "\007proc_id\030\001 \001(\004\"g\n\022EnableTableRequest\022\'\n\n" +
+      "table_name\030\001 \002(\0132\023.hbase.pb.TableName\022\026\n" +
+      "\013nonce_group\030\002 \001(\004:\0010\022\020\n\005nonce\030\003 \001(\004:\0010\"" +
+      "&\n\023EnableTableResponse\022\017\n\007proc_id\030\001 \001(\004\"" +
+      "h\n\023DisableTableRequest\022\'\n\ntable_name\030\001 \002",
       "(\0132\023.hbase.pb.TableName\022\026\n\013nonce_group\030\002" +
-      " \001(\004:\0010\022\020\n\005nonce\030\003 \001(\004:\0010\"&\n\023EnableTable" +
-      "Response\022\017\n\007proc_id\030\001 \001(\004\"h\n\023DisableTabl" +
-      "eRequest\022\'\n\ntable_name\030\001 \002(\0132\023.hbase.pb.",
-      "TableName\022\026\n\013nonce_group\030\002 \001(\004:\0010\022\020\n\005non" +
-      "ce\030\003 \001(\004:\0010\"\'\n\024DisableTableResponse\022\017\n\007p" +
-      "roc_id\030\001 \001(\004\"\224\001\n\022ModifyTableRequest\022\'\n\nt" +
-      "able_name\030\001 \002(\0132\023.hbase.pb.TableName\022+\n\014" +
-      "table_schema\030\002 \002(\0132\025.hbase.pb.TableSchem" +
-      "a\022\026\n\013nonce_group\030\003 \001(\004:\0010\022\020\n\005nonce\030\004 \001(\004" +
-      ":\0010\"&\n\023ModifyTableResponse\022\017\n\007proc_id\030\001 " +
-      "\001(\004\"~\n\026CreateNamespaceRequest\022:\n\023namespa" +
-      "ceDescriptor\030\001 \002(\0132\035.hbase.pb.NamespaceD" +
-      "escriptor\022\026\n\013nonce_group\030\002 \001(\004:\0010\022\020\n\005non",
-      "ce\030\003 \001(\004:\0010\"*\n\027CreateNamespaceResponse\022\017" +
-      "\n\007proc_id\030\001 \001(\004\"Y\n\026DeleteNamespaceReques" +
-      "t\022\025\n\rnamespaceName\030\001 \002(\t\022\026\n\013nonce_group\030" +
-      "\002 \001(\004:\0010\022\020\n\005nonce\030\003 \001(\004:\0010\"*\n\027DeleteName" +
-      "spaceResponse\022\017\n\007proc_id\030\001 \001(\004\"~\n\026Modify" +
-      "NamespaceRequest\022:\n\023namespaceDescriptor\030" +
-      "\001 \002(\0132\035.hbase.pb.NamespaceDescriptor\022\026\n\013" +
-      "nonce_group\030\002 \001(\004:\0010\022\020\n\005nonce\030\003 \001(\004:\0010\"*" +
-      "\n\027ModifyNamespaceResponse\022\017\n\007proc_id\030\001 \001" +
-      "(\004\"6\n\035GetNamespaceDescriptorRequest\022\025\n\rn",
-      "amespaceName\030\001 \002(\t\"\\\n\036GetNamespaceDescri" +
-      "ptorResponse\022:\n\023namespaceDescriptor\030\001 \002(" +
-      "\0132\035.hbase.pb.NamespaceDescriptor\"!\n\037List" +
-      "NamespaceDescriptorsRequest\"^\n ListNames" +
-      "paceDescriptorsResponse\022:\n\023namespaceDesc" +
-      "riptor\030\001 \003(\0132\035.hbase.pb.NamespaceDescrip" +
-      "tor\"?\n&ListTableDescriptorsByNamespaceRe" +
-      "quest\022\025\n\rna

<TRUNCATED>

[2/6] hbase git commit: HBASE-15411 Rewrite backup with Procedure V2 - phase 1

Posted by te...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/FullTableBackupProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/FullTableBackupProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/FullTableBackupProcedure.java
new file mode 100644
index 0000000..175f2bb
--- /dev/null
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/FullTableBackupProcedure.java
@@ -0,0 +1,745 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.backup.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileStatus;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hbase.HConstants;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.backup.BackupClientUtil;
+import org.apache.hadoop.hbase.backup.BackupRestoreFactory;
+import org.apache.hadoop.hbase.backup.BackupType;
+import org.apache.hadoop.hbase.backup.HBackupFileSystem;
+import org.apache.hadoop.hbase.backup.impl.BackupContext.BackupPhase;
+import org.apache.hadoop.hbase.backup.impl.BackupContext.BackupState;
+import org.apache.hadoop.hbase.backup.impl.BackupManifest.BackupImage;
+import org.apache.hadoop.hbase.backup.master.LogRollMasterProcedureManager;
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
+import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
+import org.apache.hadoop.hbase.master.procedure.MasterProcedureUtil;
+import org.apache.hadoop.hbase.master.procedure.TableProcedureInterface;
+import org.apache.hadoop.hbase.procedure.MasterProcedureManager;
+import org.apache.hadoop.hbase.procedure2.StateMachineProcedure;
+import org.apache.hadoop.hbase.protobuf.generated.BackupProtos;
+import org.apache.hadoop.hbase.protobuf.generated.BackupProtos.FullTableBackupState;
+import org.apache.hadoop.hbase.protobuf.generated.BackupProtos.ServerTimestamp;
+import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos;
+import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
+import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
+import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
+import org.apache.hadoop.hbase.util.FSUtils;
+
+@InterfaceAudience.Private
+public class FullTableBackupProcedure
+    extends StateMachineProcedure<MasterProcedureEnv, FullTableBackupState>
+    implements TableProcedureInterface {
+  private static final Log LOG = LogFactory.getLog(FullTableBackupProcedure.class);
+
+  private final AtomicBoolean aborted = new AtomicBoolean(false);
+  private Configuration conf;
+  private String backupId;
+  private List<TableName> tableList;
+  private String targetRootDir;
+  HashMap<String, Long> newTimestamps = null;
+
+  private BackupManager backupManager;
+  private BackupContext backupContext;
+
+  public FullTableBackupProcedure() {
+    // Required by the Procedure framework to create the procedure on replay
+  }
+
+  public FullTableBackupProcedure(final MasterProcedureEnv env,
+      final String backupId, List<TableName> tableList, String targetRootDir, final int workers,
+      final long bandwidth) throws IOException {
+    backupManager = new BackupManager(env.getMasterConfiguration());
+    this.backupId = backupId;
+    this.tableList = tableList;
+    this.targetRootDir = targetRootDir;
+    backupContext =
+        backupManager.createBackupContext(backupId, BackupType.FULL, tableList, targetRootDir);
+    if (tableList == null || tableList.isEmpty()) {
+      this.tableList = new ArrayList<>(backupContext.getTables());
+    }
+  }
+
+  @Override
+  public byte[] getResult() {
+    return backupId.getBytes();
+  }
+
+  /**
+   * Begin the overall backup.
+   * @param backupContext backup context
+   * @throws IOException exception
+   */
+  static void beginBackup(BackupManager backupManager, BackupContext backupContext)
+      throws IOException {
+    backupManager.setBackupContext(backupContext);
+    // set the start timestamp of the overall backup
+    long startTs = EnvironmentEdgeManager.currentTime();
+    backupContext.setStartTs(startTs);
+    // set overall backup status: ongoing
+    backupContext.setState(BackupState.RUNNING);
+    LOG.info("Backup " + backupContext.getBackupId() + " started at " + startTs + ".");
+
+    backupManager.updateBackupStatus(backupContext);
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("Backup session " + backupContext.getBackupId() + " has been started.");
+    }
+  }
+  
+  private static String getMessage(Exception e) {
+    String msg = e.getMessage();
+    if (msg == null || msg.equals("")) {
+      msg = e.getClass().getName();
+    }
+    return msg;
+  }
+
+  /**
+   * Delete HBase snapshot for backup.
+   * @param backupCtx backup context
+   * @throws Exception exception
+   */
+  private static void deleteSnapshot(final MasterProcedureEnv env,
+      BackupContext backupCtx, Configuration conf)
+      throws IOException {
+    LOG.debug("Trying to delete snapshot for full backup.");
+    for (String snapshotName : backupCtx.getSnapshotNames()) {
+      if (snapshotName == null) {
+        continue;
+      }
+      LOG.debug("Trying to delete snapshot: " + snapshotName);
+      HBaseProtos.SnapshotDescription.Builder builder =
+          HBaseProtos.SnapshotDescription.newBuilder();
+      builder.setName(snapshotName);
+      try {
+        env.getMasterServices().getSnapshotManager().deleteSnapshot(builder.build());
+      } catch (IOException ioe) {
+        LOG.debug("when deleting snapshot " + snapshotName, ioe);
+      }
+      LOG.debug("Deleting the snapshot " + snapshotName + " for backup "
+          + backupCtx.getBackupId() + " succeeded.");
+    }
+  }
+
+  /**
+   * Clean up directories with prefix "exportSnapshot-", which are generated when exporting
+   * snapshots.
+   * @throws IOException exception
+   */
+  private static void cleanupExportSnapshotLog(Configuration conf) throws IOException {
+    FileSystem fs = FSUtils.getCurrentFileSystem(conf);
+    Path stagingDir =
+        new Path(conf.get(BackupRestoreConstants.CONF_STAGING_ROOT, fs.getWorkingDirectory()
+          .toString()));
+    FileStatus[] files = FSUtils.listStatus(fs, stagingDir);
+    if (files == null) {
+      return;
+    }
+    for (FileStatus file : files) {
+      if (file.getPath().getName().startsWith("exportSnapshot-")) {
+        LOG.debug("Delete log files of exporting snapshot: " + file.getPath().getName());
+        if (FSUtils.delete(fs, file.getPath(), true) == false) {
+          LOG.warn("Can not delete " + file.getPath());
+        }
+      }
+    }
+  }
+
+  /**
+   * Clean up the uncompleted data at target directory if the ongoing backup has already entered the
+   * copy phase.
+   */
+  static void cleanupTargetDir(BackupContext backupContext, Configuration conf) {
+    try {
+      // clean up the uncompleted data at target directory if the ongoing backup has already entered
+      // the copy phase
+      LOG.debug("Trying to cleanup up target dir. Current backup phase: "
+          + backupContext.getPhase());
+      if (backupContext.getPhase().equals(BackupPhase.SNAPSHOTCOPY)
+          || backupContext.getPhase().equals(BackupPhase.INCREMENTAL_COPY)
+          || backupContext.getPhase().equals(BackupPhase.STORE_MANIFEST)) {
+        FileSystem outputFs =
+            FileSystem.get(new Path(backupContext.getTargetRootDir()).toUri(), conf);
+
+        // now treat one backup as a transaction, clean up data that has been partially copied at
+        // table level
+        for (TableName table : backupContext.getTables()) {
+          Path targetDirPath =
+              new Path(HBackupFileSystem.getTableBackupDir(backupContext.getTargetRootDir(),
+                backupContext.getBackupId(), table));
+          if (outputFs.delete(targetDirPath, true)) {
+            LOG.info("Cleaning up uncompleted backup data at " + targetDirPath.toString()
+              + " done.");
+          } else {
+            LOG.info("No data has been copied to " + targetDirPath.toString() + ".");
+          }
+
+          Path tableDir = targetDirPath.getParent();
+          FileStatus[] backups = FSUtils.listStatus(outputFs, tableDir);
+          if (backups == null || backups.length == 0) {
+            outputFs.delete(tableDir, true);
+            LOG.debug(tableDir.toString() + " is empty, remove it.");
+          }
+        }
+      }
+
+    } catch (IOException e1) {
+      LOG.error("Cleaning up uncompleted backup data of " + backupContext.getBackupId() + " at "
+          + backupContext.getTargetRootDir() + " failed due to " + e1.getMessage() + ".");
+    }
+  }
+
+  /**
+   * Fail the overall backup.
+   * @param backupContext backup context
+   * @param e exception
+   * @throws Exception exception
+   */
+  static void failBackup(final MasterProcedureEnv env, BackupContext backupContext,
+      BackupManager backupManager, Exception e,
+      String msg, BackupType type, Configuration conf) throws IOException {
+    LOG.error(msg + getMessage(e));
+    // If this is a cancel exception, then we've already cleaned.
+
+    if (backupContext.getState().equals(BackupState.CANCELLED)) {
+      return;
+    }
+
+    // set the failure timestamp of the overall backup
+    backupContext.setEndTs(EnvironmentEdgeManager.currentTime());
+
+    // set failure message
+    backupContext.setFailedMsg(e.getMessage());
+
+    // set overall backup status: failed
+    backupContext.setState(BackupState.FAILED);
+
+    // compose the backup failed data
+    String backupFailedData =
+        "BackupId=" + backupContext.getBackupId() + ",startts=" + backupContext.getStartTs()
+        + ",failedts=" + backupContext.getEndTs() + ",failedphase=" + backupContext.getPhase()
+        + ",failedmessage=" + backupContext.getFailedMsg();
+    LOG.error(backupFailedData);
+
+    backupManager.updateBackupStatus(backupContext);
+
+    // if full backup, then delete HBase snapshots if there already are snapshots taken
+    // and also clean up export snapshot log files if exist
+    if (type == BackupType.FULL) {
+      deleteSnapshot(env, backupContext, conf);
+      cleanupExportSnapshotLog(conf);
+    }
+
+    // clean up the uncompleted data at target directory if the ongoing backup has already entered
+    // the copy phase
+    // For incremental backup, DistCp logs will be cleaned with the targetDir.
+    cleanupTargetDir(backupContext, conf);
+
+    LOG.info("Backup " + backupContext.getBackupId() + " failed.");
+  }
+
+  /**
+   * Do snapshot copy.
+   * @param backupContext backup context
+   * @throws Exception exception
+   */
+  private void snapshotCopy(BackupContext backupContext) throws Exception {
+    LOG.info("Snapshot copy is starting.");
+
+    // set overall backup phase: snapshot_copy
+    backupContext.setPhase(BackupPhase.SNAPSHOTCOPY);
+
+    // avoid action if has been cancelled
+    if (backupContext.isCancelled()) {
+      return;
+    }
+
+    // call ExportSnapshot to copy files based on hbase snapshot for backup
+    // ExportSnapshot only support single snapshot export, need loop for multiple tables case
+    BackupCopyService copyService = BackupRestoreFactory.getBackupCopyService(conf);
+
+    // number of snapshots matches number of tables
+    float numOfSnapshots = backupContext.getSnapshotNames().size();
+
+    LOG.debug("There are " + (int) numOfSnapshots + " snapshots to be copied.");
+
+    for (TableName table : backupContext.getTables()) {
+      // Currently we simply set the sub copy tasks by counting the table snapshot number, we can
+      // calculate the real files' size for the percentage in the future.
+      // backupCopier.setSubTaskPercntgInWholeTask(1f / numOfSnapshots);
+      int res = 0;
+      String[] args = new String[4];
+      args[0] = "-snapshot";
+      args[1] = backupContext.getSnapshotName(table);
+      args[2] = "-copy-to";
+      args[3] = backupContext.getBackupStatus(table).getTargetDir();
+
+      LOG.debug("Copy snapshot " + args[1] + " to " + args[3]);
+      res = copyService.copy(backupContext, backupManager, conf, BackupCopyService.Type.FULL, args);
+      // if one snapshot export failed, do not continue for remained snapshots
+      if (res != 0) {
+        LOG.error("Exporting Snapshot " + args[1] + " failed with return code: " + res + ".");
+
+        throw new IOException("Failed of exporting snapshot " + args[1] + " to " + args[3]
+            + " with reason code " + res);
+      }
+
+      LOG.info("Snapshot copy " + args[1] + " finished.");
+    }
+  }
+  
+  /**
+   * Add manifest for the current backup. The manifest is stored
+   * within the table backup directory.
+   * @param backupContext The current backup context
+   * @throws IOException exception
+   * @throws BackupException exception
+   */
+  private static void addManifest(BackupContext backupContext, BackupManager backupManager,
+      BackupType type, Configuration conf) throws IOException, BackupException {
+    // set the overall backup phase : store manifest
+    backupContext.setPhase(BackupPhase.STORE_MANIFEST);
+
+    // avoid action if has been cancelled
+    if (backupContext.isCancelled()) {
+      return;
+    }
+
+    BackupManifest manifest;
+
+    // Since we have each table's backup in its own directory structure,
+    // we'll store its manifest with the table directory.
+    for (TableName table : backupContext.getTables()) {
+      manifest = new BackupManifest(backupContext, table);
+      ArrayList<BackupImage> ancestors = backupManager.getAncestors(backupContext, table);
+      for (BackupImage image : ancestors) {
+        manifest.addDependentImage(image);
+      }
+
+      if (type == BackupType.INCREMENTAL) {
+        // We'll store the log timestamps for this table only in its manifest.
+        HashMap<TableName, HashMap<String, Long>> tableTimestampMap =
+            new HashMap<TableName, HashMap<String, Long>>();
+        tableTimestampMap.put(table, backupContext.getIncrTimestampMap().get(table));
+        manifest.setIncrTimestampMap(tableTimestampMap);
+        ArrayList<BackupImage> ancestorss = backupManager.getAncestors(backupContext);
+        for (BackupImage image : ancestorss) {
+          manifest.addDependentImage(image);
+        }
+      }
+      // TODO
+      // manifest.setRelativeWALReferences(backupContext.getRelWALRefs());
+      manifest.store(conf);
+    }
+
+    // For incremental backup, we store a overall manifest in
+    // <backup-root-dir>/WALs/<backup-id>
+    // This is used when created the next incremental backup
+    if (type == BackupType.INCREMENTAL) {
+      manifest = new BackupManifest(backupContext);
+      // set the table region server start and end timestamps for incremental backup
+      manifest.setIncrTimestampMap(backupContext.getIncrTimestampMap());
+      ArrayList<BackupImage> ancestors = backupManager.getAncestors(backupContext);
+      for (BackupImage image : ancestors) {
+        manifest.addDependentImage(image);
+      }
+      // TODO
+      // manifest.setRelativeWALReferences(backupContext.getRelWALRefs());
+      manifest.store(conf);
+    }
+  }
+
+  /**
+   * Get backup request meta data dir as string.
+   * @param backupContext backup context
+   * @return meta data dir
+   */
+  private static String obtainBackupMetaDataStr(BackupContext backupContext) {
+    StringBuffer sb = new StringBuffer();
+    sb.append("type=" + backupContext.getType() + ",tablelist=");
+    for (TableName table : backupContext.getTables()) {
+      sb.append(table + ";");
+    }
+    if (sb.lastIndexOf(";") > 0) {
+      sb.delete(sb.lastIndexOf(";"), sb.lastIndexOf(";") + 1);
+    }
+    sb.append(",targetRootDir=" + backupContext.getTargetRootDir());
+
+    return sb.toString();
+  }
+
+  /**
+   * Clean up directories with prefix "_distcp_logs-", which are generated when DistCp copying
+   * hlogs.
+   * @throws IOException exception
+   */
+  private static void cleanupDistCpLog(BackupContext backupContext, Configuration conf)
+      throws IOException {
+    Path rootPath = new Path(backupContext.getHLogTargetDir()).getParent();
+    FileSystem fs = FileSystem.get(rootPath.toUri(), conf);
+    FileStatus[] files = FSUtils.listStatus(fs, rootPath);
+    if (files == null) {
+      return;
+    }
+    for (FileStatus file : files) {
+      if (file.getPath().getName().startsWith("_distcp_logs")) {
+        LOG.debug("Delete log files of DistCp: " + file.getPath().getName());
+        FSUtils.delete(fs, file.getPath(), true);
+      }
+    }
+  }
+
+  /**
+   * Complete the overall backup.
+   * @param backupContext backup context
+   * @throws Exception exception
+   */
+  static void completeBackup(final MasterProcedureEnv env, BackupContext backupContext,
+      BackupManager backupManager, BackupType type, Configuration conf) throws IOException {
+    // set the complete timestamp of the overall backup
+    backupContext.setEndTs(EnvironmentEdgeManager.currentTime());
+    // set overall backup status: complete
+    backupContext.setState(BackupState.COMPLETE);
+    // add and store the manifest for the backup
+    addManifest(backupContext, backupManager, type, conf);
+
+    // after major steps done and manifest persisted, do convert if needed for incremental backup
+    /* in-fly convert code here, provided by future jira */
+    LOG.debug("in-fly convert code here, provided by future jira");
+
+    // compose the backup complete data
+    String backupCompleteData =
+        obtainBackupMetaDataStr(backupContext) + ",startts=" + backupContext.getStartTs()
+        + ",completets=" + backupContext.getEndTs() + ",bytescopied="
+        + backupContext.getTotalBytesCopied();
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("Backup " + backupContext.getBackupId() + " finished: " + backupCompleteData);
+    }
+    backupManager.updateBackupStatus(backupContext);
+
+    // when full backup is done:
+    // - delete HBase snapshot
+    // - clean up directories with prefix "exportSnapshot-", which are generated when exporting
+    // snapshots
+    if (type == BackupType.FULL) {
+      deleteSnapshot(env, backupContext, conf);
+      cleanupExportSnapshotLog(conf);
+    } else if (type == BackupType.INCREMENTAL) {
+      cleanupDistCpLog(backupContext, conf);
+    }
+
+    LOG.info("Backup " + backupContext.getBackupId() + " completed.");
+  }
+
+  /**
+   * Wrap a SnapshotDescription for a target table.
+   * @param table table
+   * @return a SnapshotDescription especially for backup.
+   */
+  static SnapshotDescription wrapSnapshotDescription(TableName tableName, String snapshotName) {
+    // Mock a SnapshotDescription from backupContext to call SnapshotManager function,
+    // Name it in the format "snapshot_<timestamp>_<table>"
+    HBaseProtos.SnapshotDescription.Builder builder = HBaseProtos.SnapshotDescription.newBuilder();
+    builder.setTable(tableName.getNameAsString());
+    builder.setName(snapshotName);
+    HBaseProtos.SnapshotDescription backupSnapshot = builder.build();
+
+    LOG.debug("Wrapped a SnapshotDescription " + backupSnapshot.getName()
+      + " from backupContext to request snapshot for backup.");
+
+    return backupSnapshot;
+  }
+
+  @Override
+  protected Flow executeFromState(final MasterProcedureEnv env, final FullTableBackupState state)
+      throws InterruptedException {
+    if (conf == null) {
+      conf = env.getMasterConfiguration();
+    }
+    if (backupManager == null) {
+      try {
+        backupManager = new BackupManager(env.getMasterConfiguration());
+      } catch (IOException ioe) {
+        setFailure("full backup", ioe);
+        return Flow.NO_MORE_STATE;
+      }
+    }
+    if (LOG.isTraceEnabled()) {
+      LOG.trace(this + " execute state=" + state);
+    }
+    try {
+      switch (state) {
+        case PRE_SNAPSHOT_TABLE:
+          beginBackup(backupManager, backupContext);
+          String savedStartCode = null;
+          boolean firstBackup = false;
+          // do snapshot for full table backup
+
+          try {
+            savedStartCode = backupManager.readBackupStartCode();
+            firstBackup = savedStartCode == null || Long.parseLong(savedStartCode) == 0L;
+            if (firstBackup) {
+              // This is our first backup. Let's put some marker on ZK so that we can hold the logs
+              // while we do the backup.
+              backupManager.writeBackupStartCode(0L);
+            }
+            // We roll log here before we do the snapshot. It is possible there is duplicate data
+            // in the log that is already in the snapshot. But if we do it after the snapshot, we
+            // could have data loss.
+            // A better approach is to do the roll log on each RS in the same global procedure as
+            // the snapshot.
+            LOG.info("Execute roll log procedure for full backup ...");
+            MasterProcedureManager mpm = env.getMasterServices().getMasterProcedureManagerHost()
+                .getProcedureManager(LogRollMasterProcedureManager.ROLLLOG_PROCEDURE_SIGNATURE);
+            Map<String, String> props= new HashMap<String, String>();
+            long waitTime = MasterProcedureUtil.execProcedure(mpm,
+              LogRollMasterProcedureManager.ROLLLOG_PROCEDURE_SIGNATURE,
+              LogRollMasterProcedureManager.ROLLLOG_PROCEDURE_NAME, props);
+            MasterProcedureUtil.waitForProcedure(mpm,
+              LogRollMasterProcedureManager.ROLLLOG_PROCEDURE_SIGNATURE,
+              LogRollMasterProcedureManager.ROLLLOG_PROCEDURE_NAME, props, waitTime,
+              conf.getInt(HConstants.HBASE_CLIENT_RETRIES_NUMBER,
+                HConstants.DEFAULT_HBASE_CLIENT_RETRIES_NUMBER),
+              conf.getLong(HConstants.HBASE_CLIENT_PAUSE,
+                HConstants.DEFAULT_HBASE_CLIENT_PAUSE));
+
+            newTimestamps = backupManager.readRegionServerLastLogRollResult();
+            if (firstBackup) {
+              // Updates registered log files
+              // We record ALL old WAL files as registered, because
+              // this is a first full backup in the system and these
+              // files are not needed for next incremental backup
+              List<String> logFiles = BackupUtil.getWALFilesOlderThan(conf, newTimestamps);
+              backupManager.recordWALFiles(logFiles);
+            }
+          } catch (BackupException e) {
+            // fail the overall backup and return
+            failBackup(env, backupContext, backupManager, e, "Unexpected BackupException : ",
+              BackupType.FULL, conf);
+            return Flow.NO_MORE_STATE;
+          }
+          setNextState(FullTableBackupState.SNAPSHOT_TABLES);
+          break;
+        case SNAPSHOT_TABLES:
+          for (TableName tableName : tableList) {
+            String snapshotName = "snapshot_" + Long.toString(EnvironmentEdgeManager.currentTime())
+                + "_" + tableName.getNamespaceAsString() + "_" + tableName.getQualifierAsString();
+            HBaseProtos.SnapshotDescription backupSnapshot;
+
+            // wrap a SnapshotDescription for offline/online snapshot
+            backupSnapshot = wrapSnapshotDescription(tableName,snapshotName);
+            try {
+              env.getMasterServices().getSnapshotManager().deleteSnapshot(backupSnapshot);
+            } catch (IOException e) {
+              LOG.debug("Unable to delete " + snapshotName, e);
+            }
+            // Kick off snapshot for backup
+            try {
+              env.getMasterServices().getSnapshotManager().takeSnapshot(backupSnapshot);
+            } catch (IOException e) {
+              LOG.debug("Unable to take snapshot: " + snapshotName, e);
+            }
+            long waitTime = SnapshotDescriptionUtils.getMaxMasterTimeout(
+                env.getMasterConfiguration(),
+                backupSnapshot.getType(), SnapshotDescriptionUtils.DEFAULT_MAX_WAIT_TIME);
+            BackupUtil.waitForSnapshot(backupSnapshot, waitTime,
+              env.getMasterServices().getSnapshotManager(), env.getMasterConfiguration());
+            // set the snapshot name in BackupStatus of this table, only after snapshot success.
+            backupContext.setSnapshotName(tableName, backupSnapshot.getName());
+          }
+          setNextState(FullTableBackupState.SNAPSHOT_COPY);
+          break;
+        case SNAPSHOT_COPY:
+          // do snapshot copy
+          LOG.debug("snapshot copy for " + backupId);
+          try {
+            this.snapshotCopy(backupContext);
+          } catch (Exception e) {
+            // fail the overall backup and return
+            failBackup(env, backupContext, backupManager, e, "Unexpected BackupException : ",
+              BackupType.FULL, conf);
+            return Flow.NO_MORE_STATE;
+          }
+          // Updates incremental backup table set
+          backupManager.addIncrementalBackupTableSet(backupContext.getTables());
+          setNextState(FullTableBackupState.BACKUP_COMPLETE);
+          break;
+
+        case BACKUP_COMPLETE:
+          // set overall backup status: complete. Here we make sure to complete the backup.
+          // After this checkpoint, even if entering cancel process, will let the backup finished
+          backupContext.setState(BackupState.COMPLETE);
+          // The table list in backupContext is good for both full backup and incremental backup.
+          // For incremental backup, it contains the incremental backup table set.
+          backupManager.writeRegionServerLogTimestamp(backupContext.getTables(), newTimestamps);
+
+          HashMap<TableName, HashMap<String, Long>> newTableSetTimestampMap =
+              backupManager.readLogTimestampMap();
+
+          Long newStartCode =
+            BackupClientUtil.getMinValue(BackupUtil.getRSLogTimestampMins(newTableSetTimestampMap));
+          backupManager.writeBackupStartCode(newStartCode);
+
+          // backup complete
+          completeBackup(env, backupContext, backupManager, BackupType.FULL, conf);
+          return Flow.NO_MORE_STATE;
+
+        default:
+          throw new UnsupportedOperationException("unhandled state=" + state);
+      }
+    } catch (IOException e) {
+      LOG.error("Backup failed in " + state);
+      setFailure("snapshot-table", e);
+    }
+    return Flow.HAS_MORE_STATE;
+  }
+
+  @Override
+  protected void rollbackState(final MasterProcedureEnv env, final FullTableBackupState state)
+      throws IOException {
+    if (state != FullTableBackupState.PRE_SNAPSHOT_TABLE) {
+      deleteSnapshot(env, backupContext, conf);
+      cleanupExportSnapshotLog(conf);
+    }
+
+    // clean up the uncompleted data at target directory if the ongoing backup has already entered
+    // the copy phase
+    // For incremental backup, DistCp logs will be cleaned with the targetDir.
+    if (state == FullTableBackupState.SNAPSHOT_COPY) {
+      cleanupTargetDir(backupContext, conf);
+    }
+  }
+
+  @Override
+  protected FullTableBackupState getState(final int stateId) {
+    return FullTableBackupState.valueOf(stateId);
+  }
+
+  @Override
+  protected int getStateId(final FullTableBackupState state) {
+    return state.getNumber();
+  }
+
+  @Override
+  protected FullTableBackupState getInitialState() {
+    return FullTableBackupState.PRE_SNAPSHOT_TABLE;
+  }
+
+  @Override
+  protected void setNextState(final FullTableBackupState state) {
+    if (aborted.get()) {
+      setAbortFailure("backup-table", "abort requested");
+    } else {
+      super.setNextState(state);
+    }
+  }
+
+  @Override
+  public boolean abort(final MasterProcedureEnv env) {
+    aborted.set(true);
+    return true;
+  }
+
+  @Override
+  public void toStringClassDetails(StringBuilder sb) {
+    sb.append(getClass().getSimpleName());
+    sb.append(" (targetRootDir=");
+    sb.append(targetRootDir);
+    sb.append(")");
+  }
+
+  BackupProtos.BackupProcContext toBackupContext() {
+    BackupProtos.BackupProcContext.Builder ctxBuilder = BackupProtos.BackupProcContext.newBuilder();
+    ctxBuilder.setCtx(backupContext.toBackupContext());
+    if (newTimestamps != null && !newTimestamps.isEmpty()) {
+      BackupProtos.ServerTimestamp.Builder tsBuilder = ServerTimestamp.newBuilder();
+      for (Entry<String, Long> entry : newTimestamps.entrySet()) {
+        tsBuilder.clear().setServer(entry.getKey()).setTimestamp(entry.getValue());
+        ctxBuilder.addServerTimestamp(tsBuilder.build());
+      }
+    }
+    return ctxBuilder.build();
+  }
+
+  @Override
+  public void serializeStateData(final OutputStream stream) throws IOException {
+    super.serializeStateData(stream);
+
+    BackupProtos.BackupProcContext backupProcCtx = toBackupContext();
+    backupProcCtx.writeDelimitedTo(stream);
+  }
+
+  @Override
+  public void deserializeStateData(final InputStream stream) throws IOException {
+    super.deserializeStateData(stream);
+
+    BackupProtos.BackupProcContext proto =BackupProtos.BackupProcContext.parseDelimitedFrom(stream);
+    backupContext = BackupContext.fromProto(proto.getCtx());
+    backupId = backupContext.getBackupId();
+    targetRootDir = backupContext.getTargetRootDir();
+    tableList = backupContext.getTableNames();
+    List<ServerTimestamp> svrTimestamps = proto.getServerTimestampList();
+    if (svrTimestamps != null && !svrTimestamps.isEmpty()) {
+      newTimestamps = new HashMap<>();
+      for (ServerTimestamp ts : svrTimestamps) {
+        newTimestamps.put(ts.getServer(), ts.getTimestamp());
+      }
+    }
+  }
+
+  @Override
+  public TableName getTableName() {
+    return TableName.BACKUP_TABLE_NAME; 
+  }
+
+  @Override
+  public TableOperationType getTableOperationType() {
+    return TableOperationType.BACKUP;
+  }
+
+  @Override
+  protected boolean acquireLock(final MasterProcedureEnv env) {
+    if (env.waitInitialized(this)) {
+      return false;
+    }
+    return env.getProcedureQueue().tryAcquireTableExclusiveLock(this, TableName.BACKUP_TABLE_NAME);
+  }
+
+  @Override
+  protected void releaseLock(final MasterProcedureEnv env) {
+    env.getProcedureQueue().releaseTableExclusiveLock(this, TableName.BACKUP_TABLE_NAME);
+  }
+}

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/IncrementalTableBackupProcedure.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/IncrementalTableBackupProcedure.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/IncrementalTableBackupProcedure.java
new file mode 100644
index 0000000..8c12582
--- /dev/null
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/IncrementalTableBackupProcedure.java
@@ -0,0 +1,325 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hadoop.hbase.backup.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hbase.TableName;
+import org.apache.hadoop.hbase.backup.BackupClientUtil;
+import org.apache.hadoop.hbase.backup.BackupRestoreFactory;
+import org.apache.hadoop.hbase.backup.BackupType;
+import org.apache.hadoop.hbase.backup.impl.BackupContext.BackupPhase;
+import org.apache.hadoop.hbase.backup.impl.BackupContext.BackupState;
+import org.apache.hadoop.hbase.classification.InterfaceAudience;
+import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;
+import org.apache.hadoop.hbase.master.procedure.TableProcedureInterface;
+import org.apache.hadoop.hbase.procedure2.StateMachineProcedure;
+import org.apache.hadoop.hbase.protobuf.generated.BackupProtos;
+import org.apache.hadoop.hbase.protobuf.generated.BackupProtos.IncrementalTableBackupState;
+import org.apache.hadoop.hbase.protobuf.generated.BackupProtos.ServerTimestamp;
+
+@InterfaceAudience.Private
+public class IncrementalTableBackupProcedure
+    extends StateMachineProcedure<MasterProcedureEnv, IncrementalTableBackupState> 
+    implements TableProcedureInterface {
+  private static final Log LOG = LogFactory.getLog(IncrementalTableBackupProcedure.class);
+
+  private final AtomicBoolean aborted = new AtomicBoolean(false);
+  private Configuration conf;
+  private String backupId;
+  private List<TableName> tableList;
+  private String targetRootDir;
+  HashMap<String, Long> newTimestamps = null;
+
+  private BackupManager backupManager;
+  private BackupContext backupContext;
+
+  public IncrementalTableBackupProcedure() {
+    // Required by the Procedure framework to create the procedure on replay
+  }
+
+  public IncrementalTableBackupProcedure(final MasterProcedureEnv env,
+      final String backupId,
+      List<TableName> tableList, String targetRootDir, final int workers,
+      final long bandwidth) throws IOException {
+    backupManager = new BackupManager(env.getMasterConfiguration());
+    this.backupId = backupId;
+    this.tableList = tableList;
+    this.targetRootDir = targetRootDir;
+    backupContext = backupManager.createBackupContext(backupId, BackupType.INCREMENTAL, tableList,
+          targetRootDir);
+  }
+
+  @Override
+  public byte[] getResult() {
+    return backupId.getBytes();
+  }
+
+  private List<String> filterMissingFiles(List<String> incrBackupFileList) throws IOException {
+    FileSystem fs = FileSystem.get(conf);
+    List<String> list = new ArrayList<String>();
+    for(String file : incrBackupFileList){
+      if(fs.exists(new Path(file))){
+        list.add(file);
+      } else{
+        LOG.warn("Can't find file: "+file);
+      }
+    }
+    return list;
+  }
+
+  /**
+   * Do incremental copy.
+   * @param backupContext backup context
+   */
+  private void incrementalCopy(BackupContext backupContext) throws Exception {
+
+    LOG.info("Incremental copy is starting.");
+
+    // set overall backup phase: incremental_copy
+    backupContext.setPhase(BackupPhase.INCREMENTAL_COPY);
+
+    // avoid action if has been cancelled
+    if (backupContext.isCancelled()) {
+      return;
+    }
+
+    // get incremental backup file list and prepare parms for DistCp
+    List<String> incrBackupFileList = backupContext.getIncrBackupFileList();
+    // filter missing files out (they have been copied by previous backups)
+    incrBackupFileList = filterMissingFiles(incrBackupFileList);
+    String[] strArr = incrBackupFileList.toArray(new String[incrBackupFileList.size() + 1]);
+    strArr[strArr.length - 1] = backupContext.getHLogTargetDir();
+
+    BackupCopyService copyService = BackupRestoreFactory.getBackupCopyService(conf);
+    int res = copyService.copy(backupContext, backupManager, conf,
+      BackupCopyService.Type.INCREMENTAL, strArr);
+
+    if (res != 0) {
+      LOG.error("Copy incremental log files failed with return code: " + res + ".");
+      throw new IOException("Failed of Hadoop Distributed Copy from " + incrBackupFileList + " to "
+          + backupContext.getHLogTargetDir());
+    }
+    LOG.info("Incremental copy from " + incrBackupFileList + " to "
+        + backupContext.getHLogTargetDir() + " finished.");
+  }
+
+  @Override
+  protected Flow executeFromState(final MasterProcedureEnv env,
+      final IncrementalTableBackupState state)
+      throws InterruptedException {
+    if (conf == null) {
+      conf = env.getMasterConfiguration();
+    }
+    if (backupManager == null) {
+      try {
+        backupManager = new BackupManager(env.getMasterConfiguration());
+      } catch (IOException ioe) {
+        setFailure("incremental backup", ioe);
+      }
+    }
+    if (LOG.isTraceEnabled()) {
+      LOG.trace(this + " execute state=" + state);
+    }
+    try {
+      switch (state) {
+        case PREPARE_INCREMENTAL:
+          FullTableBackupProcedure.beginBackup(backupManager, backupContext);
+          LOG.debug("For incremental backup, current table set is "
+              + backupManager.getIncrementalBackupTableSet());
+          try {
+            IncrementalBackupManager incrBackupManager =new IncrementalBackupManager(backupManager);
+
+            newTimestamps = incrBackupManager.getIncrBackupLogFileList(backupContext);
+          } catch (Exception e) {
+            // fail the overall backup and return
+            FullTableBackupProcedure.failBackup(env, backupContext, backupManager, e,
+              "Unexpected Exception : ", BackupType.INCREMENTAL, conf);
+          }
+
+          setNextState(IncrementalTableBackupState.INCREMENTAL_COPY);
+          break;
+        case INCREMENTAL_COPY:
+          try {
+            // copy out the table and region info files for each table
+            BackupUtil.copyTableRegionInfo(backupContext, conf);
+            incrementalCopy(backupContext);
+            // Save list of WAL files copied
+            backupManager.recordWALFiles(backupContext.getIncrBackupFileList());
+          } catch (Exception e) {
+            // fail the overall backup and return
+            FullTableBackupProcedure.failBackup(env, backupContext, backupManager, e,
+              "Unexpected exception doing incremental copy : ", BackupType.INCREMENTAL, conf);
+          }
+          setNextState(IncrementalTableBackupState.INCR_BACKUP_COMPLETE);
+          break;
+        case INCR_BACKUP_COMPLETE:
+          // set overall backup status: complete. Here we make sure to complete the backup.
+          // After this checkpoint, even if entering cancel process, will let the backup finished
+          backupContext.setState(BackupState.COMPLETE);
+          // Set the previousTimestampMap which is before this current log roll to the manifest.
+          HashMap<TableName, HashMap<String, Long>> previousTimestampMap =
+              backupManager.readLogTimestampMap();
+          backupContext.setIncrTimestampMap(previousTimestampMap);
+
+          // The table list in backupContext is good for both full backup and incremental backup.
+          // For incremental backup, it contains the incremental backup table set.
+          backupManager.writeRegionServerLogTimestamp(backupContext.getTables(), newTimestamps);
+
+          HashMap<TableName, HashMap<String, Long>> newTableSetTimestampMap =
+              backupManager.readLogTimestampMap();
+
+          Long newStartCode = BackupClientUtil
+              .getMinValue(BackupUtil.getRSLogTimestampMins(newTableSetTimestampMap));
+          backupManager.writeBackupStartCode(newStartCode);
+          // backup complete
+          FullTableBackupProcedure.completeBackup(env, backupContext, backupManager,
+            BackupType.INCREMENTAL, conf);
+          return Flow.NO_MORE_STATE;
+
+        default:
+          throw new UnsupportedOperationException("unhandled state=" + state);
+      }
+    } catch (IOException e) {
+      setFailure("snapshot-table", e);
+    }
+    return Flow.HAS_MORE_STATE;
+  }
+
+  @Override
+  protected void rollbackState(final MasterProcedureEnv env,
+      final IncrementalTableBackupState state) throws IOException {
+    // clean up the uncompleted data at target directory if the ongoing backup has already entered
+    // the copy phase
+    // For incremental backup, DistCp logs will be cleaned with the targetDir.
+    FullTableBackupProcedure.cleanupTargetDir(backupContext, conf);
+  }
+
+  @Override
+  protected IncrementalTableBackupState getState(final int stateId) {
+    return IncrementalTableBackupState.valueOf(stateId);
+  }
+
+  @Override
+  protected int getStateId(final IncrementalTableBackupState state) {
+    return state.getNumber();
+  }
+
+  @Override
+  protected IncrementalTableBackupState getInitialState() {
+    return IncrementalTableBackupState.PREPARE_INCREMENTAL;
+  }
+
+  @Override
+  protected void setNextState(final IncrementalTableBackupState state) {
+    if (aborted.get()) {
+      setAbortFailure("snapshot-table", "abort requested");
+    } else {
+      super.setNextState(state);
+    }
+  }
+
+  @Override
+  public boolean abort(final MasterProcedureEnv env) {
+    aborted.set(true);
+    return true;
+  }
+
+  @Override
+  public void toStringClassDetails(StringBuilder sb) {
+    sb.append(getClass().getSimpleName());
+    sb.append(" (targetRootDir=");
+    sb.append(targetRootDir);
+    sb.append(")");
+  }
+
+  BackupProtos.BackupProcContext toBackupContext() {
+    BackupProtos.BackupProcContext.Builder ctxBuilder = BackupProtos.BackupProcContext.newBuilder();
+    ctxBuilder.setCtx(backupContext.toBackupContext());
+    if (newTimestamps != null && !newTimestamps.isEmpty()) {
+      BackupProtos.ServerTimestamp.Builder tsBuilder = ServerTimestamp.newBuilder();
+      for (Entry<String, Long> entry : newTimestamps.entrySet()) {
+        tsBuilder.clear().setServer(entry.getKey()).setTimestamp(entry.getValue());
+        ctxBuilder.addServerTimestamp(tsBuilder.build());
+      }
+    }
+    return ctxBuilder.build();
+  }
+
+  @Override
+  public void serializeStateData(final OutputStream stream) throws IOException {
+    super.serializeStateData(stream);
+
+    BackupProtos.BackupProcContext backupProcCtx = toBackupContext();
+    backupProcCtx.writeDelimitedTo(stream);
+  }
+
+  @Override
+  public void deserializeStateData(final InputStream stream) throws IOException {
+    super.deserializeStateData(stream);
+
+    BackupProtos.BackupProcContext proto =BackupProtos.BackupProcContext.parseDelimitedFrom(stream);
+    backupContext = BackupContext.fromProto(proto.getCtx());
+    backupId = backupContext.getBackupId();
+    targetRootDir = backupContext.getTargetRootDir();
+    tableList = backupContext.getTableNames();
+    List<ServerTimestamp> svrTimestamps = proto.getServerTimestampList();
+    if (svrTimestamps != null && !svrTimestamps.isEmpty()) {
+      newTimestamps = new HashMap<>();
+      for (ServerTimestamp ts : svrTimestamps) {
+        newTimestamps.put(ts.getServer(), ts.getTimestamp());
+      }
+    }
+  }
+
+  @Override
+  public TableName getTableName() {
+    return TableName.BACKUP_TABLE_NAME;
+  }
+
+  @Override
+  public TableOperationType getTableOperationType() {
+    return TableOperationType.BACKUP;
+  }
+
+  @Override
+  protected boolean acquireLock(final MasterProcedureEnv env) {
+    if (env.waitInitialized(this)) {
+      return false;
+    }
+    return env.getProcedureQueue().tryAcquireTableExclusiveLock(this, TableName.BACKUP_TABLE_NAME);
+  }
+
+  @Override
+  protected void releaseLock(final MasterProcedureEnv env) {
+    env.getProcedureQueue().releaseTableExclusiveLock(this, TableName.BACKUP_TABLE_NAME);
+  }
+}

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/RestoreClientImpl.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/RestoreClientImpl.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/RestoreClientImpl.java
index 6617565..c0c5220 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/RestoreClientImpl.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/RestoreClientImpl.java
@@ -286,8 +286,7 @@ public final class RestoreClientImpl implements RestoreClient {
     String backupId = image.getBackupId();
 
     Path rootPath = new Path(rootDir);
-    HBackupFileSystem hFS = new HBackupFileSystem(conf, rootPath, backupId);
-    RestoreUtil restoreTool = new RestoreUtil(conf, hFS);
+    RestoreUtil restoreTool = new RestoreUtil(conf, rootPath, backupId);
     BackupManifest manifest = HBackupFileSystem.getManifest(sTable, conf, rootPath, backupId);
 
     Path tableBackupPath = HBackupFileSystem.getTableBackupPath(rootPath, sTable, backupId);

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/RestoreUtil.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/RestoreUtil.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/RestoreUtil.java
index 3882e95..9139b6e 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/RestoreUtil.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/impl/RestoreUtil.java
@@ -18,15 +18,20 @@
 
 package org.apache.hadoop.hbase.backup.impl;
 
+import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.TreeMap;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileStatus;
 import org.apache.hadoop.fs.FileSystem;
+import org.apache.hadoop.fs.FileUtil;
 import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.backup.BackupRestoreFactory;
@@ -37,10 +42,17 @@ import org.apache.hadoop.hbase.client.Admin;
 import org.apache.hadoop.hbase.client.Connection;
 import org.apache.hadoop.hbase.client.ConnectionFactory;
 import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.io.HFileLink;
+import org.apache.hadoop.hbase.io.hfile.CacheConfig;
+import org.apache.hadoop.hbase.io.hfile.HFile;
 import org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles;
 import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.SnapshotDescription;
+import org.apache.hadoop.hbase.regionserver.HRegionFileSystem;
+import org.apache.hadoop.hbase.regionserver.HStore;
+import org.apache.hadoop.hbase.regionserver.StoreFileInfo;
 import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
 import org.apache.hadoop.hbase.snapshot.SnapshotManifest;
+import org.apache.hadoop.hbase.util.Bytes;
 
 /**
  * A collection for methods used by multiple classes to restore HBase tables.
@@ -51,22 +63,72 @@ public class RestoreUtil {
 
   public static final Log LOG = LogFactory.getLog(RestoreUtil.class);
 
-  protected Configuration conf = null;
+  private final String[] ignoreDirs = { "recovered.edits" };
 
-  protected HBackupFileSystem hBackupFS = null;
+  protected Configuration conf = null;
 
   protected Path backupRootPath;
 
   protected String backupId;
 
+  protected FileSystem fs;
+  private final String RESTORE_TMP_PATH = "/tmp";
+  private final Path restoreTmpPath;
+
   // store table name and snapshot dir mapping
   private final HashMap<TableName, Path> snapshotMap = new HashMap<>();
 
-  public RestoreUtil(Configuration conf, HBackupFileSystem hBackupFS) throws IOException {
+  public RestoreUtil(Configuration conf, final Path backupRootPath, final String backupId)
+      throws IOException {
     this.conf = conf;
-    this.hBackupFS = hBackupFS;
-    this.backupRootPath = hBackupFS.getBackupRootPath();
-    this.backupId = hBackupFS.getBackupId();
+    this.backupRootPath = backupRootPath;
+    this.backupId = backupId;
+    this.fs = backupRootPath.getFileSystem(conf);
+    this.restoreTmpPath = new Path(conf.get("hbase.fs.tmp.dir") != null?
+        conf.get("hbase.fs.tmp.dir"): RESTORE_TMP_PATH,
+      "restore");
+  }
+
+  /**
+   * return value represent path for:
+   * ".../user/biadmin/backup1/default/t1_dn/backup_1396650096738/archive/data/default/t1_dn"
+   * @param tabelName table name
+   * @return path to table archive
+   * @throws IOException exception
+   */
+  Path getTableArchivePath(TableName tableName)
+      throws IOException {
+    Path baseDir = new Path(HBackupFileSystem.getTableBackupPath(backupRootPath, tableName,
+      backupId), HConstants.HFILE_ARCHIVE_DIRECTORY);
+    Path dataDir = new Path(baseDir, HConstants.BASE_NAMESPACE_DIR);
+    Path archivePath = new Path(dataDir, tableName.getNamespaceAsString());
+    Path tableArchivePath =
+        new Path(archivePath, tableName.getQualifierAsString());
+    if (!fs.exists(tableArchivePath) || !fs.getFileStatus(tableArchivePath).isDirectory()) {
+      LOG.debug("Folder tableArchivePath: " + tableArchivePath.toString() + " does not exists");
+      tableArchivePath = null; // empty table has no archive
+    }
+    return tableArchivePath;
+  }
+
+  /**
+   * Gets region list
+   * @param tableName table name
+   * @return RegionList region list
+   * @throws FileNotFoundException exception
+   * @throws IOException exception
+   */
+  ArrayList<Path> getRegionList(TableName tableName)
+      throws FileNotFoundException, IOException {
+    Path tableArchivePath = this.getTableArchivePath(tableName);
+    ArrayList<Path> regionDirList = new ArrayList<Path>();
+    FileStatus[] children = fs.listStatus(tableArchivePath);
+    for (FileStatus childStatus : children) {
+      // here child refer to each region(Name)
+      Path child = childStatus.getPath();
+      regionDirList.add(child);
+    }
+    return regionDirList;
   }
 
   /**
@@ -78,7 +140,7 @@ public class RestoreUtil {
    * @param newTableNames : target tableNames(table names to be restored to)
    * @throws IOException exception
    */
-  public void incrementalRestoreTable(String logDir,
+  void incrementalRestoreTable(String logDir,
       TableName[] tableNames, TableName[] newTableNames) throws IOException {
 
     if (tableNames.length != newTableNames.length) {
@@ -103,11 +165,112 @@ public class RestoreUtil {
     }
   }
 
-  public void fullRestoreTable(Path tableBackupPath, TableName tableName, TableName newTableName,
+  void fullRestoreTable(Path tableBackupPath, TableName tableName, TableName newTableName,
       boolean converted) throws IOException {
     restoreTableAndCreate(tableName, newTableName, tableBackupPath, converted);
   }
 
+  /**
+   * return value represent path for:
+   * ".../user/biadmin/backup1/default/t1_dn/backup_1396650096738/.hbase-snapshot"
+   * @param backupRootPath backup root path
+   * @param tableName table name
+   * @param backupId backup Id
+   * @return path for snapshot
+   */
+  static Path getTableSnapshotPath(Path backupRootPath, TableName tableName,
+      String backupId) {
+    return new Path(HBackupFileSystem.getTableBackupPath(backupRootPath, tableName, backupId),
+      HConstants.SNAPSHOT_DIR_NAME);
+  }
+
+  /**
+   * return value represent path for:
+   * "..../default/t1_dn/backup_1396650096738/.hbase-snapshot/snapshot_1396650097621_default_t1_dn"
+   * this path contains .snapshotinfo, .tabledesc (0.96 and 0.98) this path contains .snapshotinfo,
+   * .data.manifest (trunk)
+   * @param tableName table name
+   * @return path to table info
+   * @throws FileNotFoundException exception
+   * @throws IOException exception
+   */
+  Path getTableInfoPath(TableName tableName)
+      throws FileNotFoundException, IOException {
+    Path tableSnapShotPath = getTableSnapshotPath(backupRootPath, tableName, backupId);
+    Path tableInfoPath = null;
+
+    // can't build the path directly as the timestamp values are different
+    FileStatus[] snapshots = fs.listStatus(tableSnapShotPath);
+    for (FileStatus snapshot : snapshots) {
+      tableInfoPath = snapshot.getPath();
+      // SnapshotManifest.DATA_MANIFEST_NAME = "data.manifest";
+      if (tableInfoPath.getName().endsWith("data.manifest")) {
+        break;
+      }
+    }
+    return tableInfoPath;
+  }
+
+  /**
+   * @param tableName is the table backed up
+   * @return {@link HTableDescriptor} saved in backup image of the table
+   */
+  HTableDescriptor getTableDesc(TableName tableName)
+      throws FileNotFoundException, IOException {
+    Path tableInfoPath = this.getTableInfoPath(tableName);
+    SnapshotDescription desc = SnapshotDescriptionUtils.readSnapshotInfo(fs, tableInfoPath);
+    SnapshotManifest manifest = SnapshotManifest.open(conf, fs, tableInfoPath, desc);
+    HTableDescriptor tableDescriptor = manifest.getTableDescriptor();
+    if (!tableDescriptor.getNameAsString().equals(tableName)) {
+      LOG.error("couldn't find Table Desc for table: " + tableName + " under tableInfoPath: "
+          + tableInfoPath.toString());
+      LOG.error("tableDescriptor.getNameAsString() = " + tableDescriptor.getNameAsString());
+    }
+    return tableDescriptor;
+  }
+
+  /**
+   * Duplicate the backup image if it's on local cluster
+   * @see HStore#bulkLoadHFile(String, long)
+   * @see HRegionFileSystem#bulkLoadStoreFile(String familyName, Path srcPath, long seqNum)
+   * @param tableArchivePath archive path
+   * @return the new tableArchivePath
+   * @throws IOException exception
+   */
+  Path checkLocalAndBackup(Path tableArchivePath) throws IOException {
+    // Move the file if it's on local cluster
+    boolean isCopyNeeded = false;
+
+    FileSystem srcFs = tableArchivePath.getFileSystem(conf);
+    FileSystem desFs = FileSystem.get(conf);
+    if (tableArchivePath.getName().startsWith("/")) {
+      isCopyNeeded = true;
+    } else {
+      // This should match what is done in @see HRegionFileSystem#bulkLoadStoreFile(String, Path,
+      // long)
+      if (srcFs.getUri().equals(desFs.getUri())) {
+        LOG.debug("cluster hold the backup image: " + srcFs.getUri() + "; local cluster node: "
+            + desFs.getUri());
+        isCopyNeeded = true;
+      }
+    }
+    if (isCopyNeeded) {
+      LOG.debug("File " + tableArchivePath + " on local cluster, back it up before restore");
+      if (desFs.exists(restoreTmpPath)) {
+        try {
+          desFs.delete(restoreTmpPath, true);
+        } catch (IOException e) {
+          LOG.debug("Failed to delete path: " + restoreTmpPath
+            + ", need to check whether restore target DFS cluster is healthy");
+        }
+      }
+      FileUtil.copy(srcFs, tableArchivePath, desFs, restoreTmpPath, false, conf);
+      LOG.debug("Copied to temporary path on local cluster: " + restoreTmpPath);
+      tableArchivePath = restoreTmpPath;
+    }
+    return tableArchivePath;
+  }
+
   private void restoreTableAndCreate(TableName tableName, TableName newTableName,
       Path tableBackupPath, boolean converted) throws IOException {
     if (newTableName == null || newTableName.equals("")) {
@@ -119,8 +282,7 @@ public class RestoreUtil {
     // get table descriptor first
     HTableDescriptor tableDescriptor = null;
 
-    Path tableSnapshotPath = HBackupFileSystem.getTableSnapshotPath(backupRootPath, tableName,
-      backupId);
+    Path tableSnapshotPath = getTableSnapshotPath(backupRootPath, tableName, backupId);
 
     if (fileSys.exists(tableSnapshotPath)) {
       // snapshot path exist means the backup path is in HDFS
@@ -130,11 +292,9 @@ public class RestoreUtil {
             SnapshotDescriptionUtils.readSnapshotInfo(fileSys, tableSnapshotPath);
         SnapshotManifest manifest = SnapshotManifest.open(conf, fileSys, tableSnapshotPath, desc);
         tableDescriptor = manifest.getTableDescriptor();
-
-
       } else {
-        tableDescriptor = hBackupFS.getTableDesc(tableName);
-        snapshotMap.put(tableName, hBackupFS.getTableInfoPath(tableName));
+        tableDescriptor = getTableDesc(tableName);
+        snapshotMap.put(tableName, getTableInfoPath(tableName));
       }
       if (tableDescriptor == null) {
         LOG.debug("Found no table descriptor in the snapshot dir, previous schema would be lost");
@@ -144,7 +304,7 @@ public class RestoreUtil {
       LOG.error("convert will be supported in a future jira");
     }
 
-    Path tableArchivePath = hBackupFS.getTableArchivePath(tableName);
+    Path tableArchivePath = getTableArchivePath(tableName);
     if (tableArchivePath == null) {
       if (tableDescriptor != null) {
         // find table descriptor but no archive dir means the table is empty, create table and exit
@@ -171,7 +331,7 @@ public class RestoreUtil {
       // record all region dirs:
       // load all files in dir
       try {
-        ArrayList<Path> regionPathList = hBackupFS.getRegionList(tableName);
+        ArrayList<Path> regionPathList = getRegionList(tableName);
 
         // should only try to create the table with all region informations, so we could pre-split
         // the regions in fine grain
@@ -180,13 +340,13 @@ public class RestoreUtil {
         if (tableArchivePath != null) {
           // start real restore through bulkload
           // if the backup target is on local cluster, special action needed
-          Path tempTableArchivePath = hBackupFS.checkLocalAndBackup(tableArchivePath);
+          Path tempTableArchivePath = checkLocalAndBackup(tableArchivePath);
           if (tempTableArchivePath.equals(tableArchivePath)) {
             if(LOG.isDebugEnabled()) {
               LOG.debug("TableArchivePath for bulkload using existPath: " + tableArchivePath);
             }
           } else {
-            regionPathList = hBackupFS.getRegionList(tempTableArchivePath); // point to the tempDir
+            regionPathList = getRegionList(tempTableArchivePath); // point to the tempDir
             if(LOG.isDebugEnabled()) {
               LOG.debug("TableArchivePath for bulkload using tempPath: " + tempTableArchivePath);
             }
@@ -211,7 +371,72 @@ public class RestoreUtil {
     }
   }
 
+  /**
+   * Gets region list
+   * @param tableArchivePath table archive path
+   * @return RegionList region list
+   * @throws FileNotFoundException exception
+   * @throws IOException exception
+   */
+  ArrayList<Path> getRegionList(Path tableArchivePath) throws FileNotFoundException,
+  IOException {
+    ArrayList<Path> regionDirList = new ArrayList<Path>();
+    FileStatus[] children = fs.listStatus(tableArchivePath);
+    for (FileStatus childStatus : children) {
+      // here child refer to each region(Name)
+      Path child = childStatus.getPath();
+      regionDirList.add(child);
+    }
+    return regionDirList;
+  }
 
+  /**
+   * Counts the number of files in all subdirectories of an HBase table, i.e. HFiles.
+   * @param regionPath Path to an HBase table directory
+   * @return the number of files all directories
+   * @throws IOException exception
+   */
+  int getNumberOfFilesInDir(Path regionPath) throws IOException {
+    int result = 0;
+
+    if (!fs.exists(regionPath) || !fs.getFileStatus(regionPath).isDirectory()) {
+      throw new IllegalStateException("Cannot restore hbase table because directory '"
+          + regionPath.toString() + "' is not a directory.");
+    }
+
+    FileStatus[] tableDirContent = fs.listStatus(regionPath);
+    for (FileStatus subDirStatus : tableDirContent) {
+      FileStatus[] colFamilies = fs.listStatus(subDirStatus.getPath());
+      for (FileStatus colFamilyStatus : colFamilies) {
+        FileStatus[] colFamilyContent = fs.listStatus(colFamilyStatus.getPath());
+        result += colFamilyContent.length;
+      }
+    }
+    return result;
+  }
+
+  /**
+   * Counts the number of files in all subdirectories of an HBase tables, i.e. HFiles. And finds the
+   * maximum number of files in one HBase table.
+   * @param tableArchivePath archive path
+   * @return the maximum number of files found in 1 HBase table
+   * @throws IOException exception
+   */
+  int getMaxNumberOfFilesInSubDir(Path tableArchivePath) throws IOException {
+    int result = 1;
+    ArrayList<Path> regionPathList = getRegionList(tableArchivePath);
+    // tableArchivePath = this.getTableArchivePath(tableName);
+
+    if (regionPathList == null || regionPathList.size() == 0) {
+      throw new IllegalStateException("Cannot restore hbase table because directory '"
+          + tableArchivePath + "' is not a directory.");
+    }
+
+    for (Path regionPath : regionPathList) {
+      result = Math.max(result, getNumberOfFilesInDir(regionPath));
+    }
+    return result;
+  }
 
   /**
    * Create a {@link LoadIncrementalHFiles} instance to be used to restore the HFiles of a full
@@ -228,8 +453,8 @@ public class RestoreUtil {
     Integer milliSecInMin = 60000;
     Integer previousMillis = this.conf.getInt("hbase.rpc.timeout", 0);
     Integer numberOfFilesInDir =
-        multipleTables ? hBackupFS.getMaxNumberOfFilesInSubDir(tableArchivePath) : hBackupFS
-            .getNumberOfFilesInDir(tableArchivePath);
+        multipleTables ? getMaxNumberOfFilesInSubDir(tableArchivePath) :
+            getNumberOfFilesInDir(tableArchivePath);
     Integer calculatedMillis = numberOfFilesInDir * milliSecInMin; // 1 minute per file
     Integer resultMillis = Math.max(calculatedMillis, previousMillis);
     if (resultMillis > previousMillis) {
@@ -249,6 +474,86 @@ public class RestoreUtil {
   }
 
   /**
+   * Calculate region boundaries and add all the column families to the table descriptor
+   * @param regionDirList region dir list
+   * @return a set of keys to store the boundaries
+   */
+  byte[][] generateBoundaryKeys(ArrayList<Path> regionDirList)
+      throws FileNotFoundException, IOException {
+    TreeMap<byte[], Integer> map = new TreeMap<byte[], Integer>(Bytes.BYTES_COMPARATOR);
+    // Build a set of keys to store the boundaries
+    byte[][] keys = null;
+    // calculate region boundaries and add all the column families to the table descriptor
+    for (Path regionDir : regionDirList) {
+      LOG.debug("Parsing region dir: " + regionDir);
+      Path hfofDir = regionDir;
+
+      if (!fs.exists(hfofDir)) {
+        LOG.warn("HFileOutputFormat dir " + hfofDir + " not found");
+      }
+
+      FileStatus[] familyDirStatuses = fs.listStatus(hfofDir);
+      if (familyDirStatuses == null) {
+        throw new IOException("No families found in " + hfofDir);
+      }
+
+      for (FileStatus stat : familyDirStatuses) {
+        if (!stat.isDirectory()) {
+          LOG.warn("Skipping non-directory " + stat.getPath());
+          continue;
+        }
+        boolean isIgnore = false;
+        String pathName = stat.getPath().getName();
+        for (String ignore : ignoreDirs) {
+          if (pathName.contains(ignore)) {
+            LOG.warn("Skipping non-family directory" + pathName);
+            isIgnore = true;
+            break;
+          }
+        }
+        if (isIgnore) {
+          continue;
+        }
+        Path familyDir = stat.getPath();
+        LOG.debug("Parsing family dir [" + familyDir.toString() + " in region [" + regionDir + "]");
+        // Skip _logs, etc
+        if (familyDir.getName().startsWith("_") || familyDir.getName().startsWith(".")) {
+          continue;
+        }
+
+        // start to parse hfile inside one family dir
+        Path[] hfiles = FileUtil.stat2Paths(fs.listStatus(familyDir));
+        for (Path hfile : hfiles) {
+          if (hfile.getName().startsWith("_") || hfile.getName().startsWith(".")
+              || StoreFileInfo.isReference(hfile.getName())
+              || HFileLink.isHFileLink(hfile.getName())) {
+            continue;
+          }
+          HFile.Reader reader = HFile.createReader(fs, hfile, new CacheConfig(conf), conf);
+          final byte[] first, last;
+          try {
+            reader.loadFileInfo();
+            first = reader.getFirstRowKey();
+            last = reader.getLastRowKey();
+            LOG.debug("Trying to figure out region boundaries hfile=" + hfile + " first="
+                + Bytes.toStringBinary(first) + " last=" + Bytes.toStringBinary(last));
+
+            // To eventually infer start key-end key boundaries
+            Integer value = map.containsKey(first) ? (Integer) map.get(first) : 0;
+            map.put(first, value + 1);
+            value = map.containsKey(last) ? (Integer) map.get(last) : 0;
+            map.put(last, value - 1);
+          } finally {
+            reader.close();
+          }
+        }
+      }
+    }
+    keys = LoadIncrementalHFiles.inferBoundaries(map);
+    return keys;
+  }
+
+  /**
    * Prepare the table for bulkload, most codes copied from
    * {@link LoadIncrementalHFiles#createTable(String, String)}
    * @param tableBackupPath path
@@ -278,7 +583,7 @@ public class RestoreUtil {
           return;
         }
 
-        byte[][] keys = hBackupFS.generateBoundaryKeys(regionDirList);
+        byte[][] keys = generateBoundaryKeys(regionDirList);
 
         // create table using table decriptor and region boundaries
         hbadmin.createTable(htd, keys);

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/mapreduce/MapReduceBackupCopyService.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/mapreduce/MapReduceBackupCopyService.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/mapreduce/MapReduceBackupCopyService.java
index 14235ce..fdd8272 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/mapreduce/MapReduceBackupCopyService.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/backup/mapreduce/MapReduceBackupCopyService.java
@@ -32,7 +32,6 @@ import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.backup.impl.BackupContext;
 import org.apache.hadoop.hbase.backup.impl.BackupCopyService;
-import org.apache.hadoop.hbase.backup.impl.BackupHandler;
 import org.apache.hadoop.hbase.backup.impl.BackupManager;
 import org.apache.hadoop.hbase.backup.impl.BackupUtil;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
@@ -42,6 +41,7 @@ import org.apache.hadoop.mapreduce.Job;
 import org.apache.hadoop.tools.DistCp;
 import org.apache.hadoop.tools.DistCpConstants;
 import org.apache.hadoop.tools.DistCpOptions;
+import org.apache.zookeeper.KeeperException.NoNodeException;
 /**
  * Copier for backup operation. Basically, there are 2 types of copy. One is copying from snapshot,
  * which bases on extending ExportSnapshot's function with copy progress reporting to ZooKeeper
@@ -115,6 +115,25 @@ public class MapReduceBackupCopyService implements BackupCopyService {
     }
   }
 
+  /**
+   * Update the ongoing back token znode with new progress.
+   * @param backupContext backup context
+   * 
+   * @param newProgress progress
+   * @param bytesCopied bytes copied
+   * @throws NoNodeException exception
+   */
+  static void updateProgress(BackupContext backupContext, BackupManager backupManager,
+      int newProgress, long bytesCopied) throws IOException {
+    // compose the new backup progress data, using fake number for now
+    String backupProgressData = newProgress + "%";
+
+    backupContext.setProgress(newProgress);
+    backupManager.updateBackupStatus(backupContext);
+    LOG.debug("Backup progress data \"" + backupProgressData
+      + "\" has been updated to hbase:backup for " + backupContext.getBackupId());
+  }
+
   // Extends DistCp for progress updating to hbase:backup
   // during backup. Using DistCpV2 (MAPREDUCE-2765).
   // Simply extend it and override execute() method to get the
@@ -203,7 +222,7 @@ public class MapReduceBackupCopyService implements BackupCopyService {
                 new BigDecimal(newProgress * 100).setScale(1, BigDecimal.ROUND_HALF_UP);
             String newProgressStr = progressData + "%";
             LOG.info("Progress: " + newProgressStr);
-            BackupHandler.updateProgress(backupContext, backupManager, progressData.intValue(),
+            updateProgress(backupContext, backupManager, progressData.intValue(),
               bytesCopied);
             LOG.debug("Backup progress data updated to hbase:backup: \"Progress: " + newProgressStr
               + ".\"");
@@ -225,7 +244,7 @@ public class MapReduceBackupCopyService implements BackupCopyService {
         progressDone = newProgress;
         bytesCopied += totalSrcLgth;
 
-        BackupHandler.updateProgress(backupContext, backupManager, progressData.intValue(),
+        updateProgress(backupContext, backupManager, progressData.intValue(),
           bytesCopied);
         LOG.debug("Backup progress data updated to hbase:backup: \"Progress: " + newProgressStr
           + " - " + bytesCopied + " bytes copied.\"");

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
index 5bba1ea..0d5ed1f 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/HMaster.java
@@ -49,6 +49,7 @@ import javax.servlet.http.HttpServletResponse;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.FileSystem;
 import org.apache.hadoop.fs.Path;
 import org.apache.hadoop.hbase.ClusterStatus;
 import org.apache.hadoop.hbase.CoordinatedStateException;
@@ -75,7 +76,14 @@ import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.TableNotDisabledException;
 import org.apache.hadoop.hbase.TableNotFoundException;
 import org.apache.hadoop.hbase.UnknownRegionException;
+import org.apache.hadoop.hbase.backup.BackupType;
+import org.apache.hadoop.hbase.backup.HBackupFileSystem;
 import org.apache.hadoop.hbase.backup.impl.BackupManager;
+import org.apache.hadoop.hbase.backup.impl.BackupRestoreConstants;
+import org.apache.hadoop.hbase.backup.impl.BackupSystemTable;
+import org.apache.hadoop.hbase.backup.impl.BackupSystemTableHelper;
+import org.apache.hadoop.hbase.backup.impl.FullTableBackupProcedure;
+import org.apache.hadoop.hbase.backup.impl.IncrementalTableBackupProcedure;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.client.Admin;
 import org.apache.hadoop.hbase.client.RegionReplicaUtil;
@@ -142,6 +150,7 @@ import org.apache.hadoop.hbase.util.Addressing;
 import org.apache.hadoop.hbase.util.Bytes;
 import org.apache.hadoop.hbase.util.CompressionTest;
 import org.apache.hadoop.hbase.util.EncryptionTest;
+import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
 import org.apache.hadoop.hbase.util.FSUtils;
 import org.apache.hadoop.hbase.util.HFileArchiveUtil;
 import org.apache.hadoop.hbase.util.HasThread;
@@ -167,6 +176,9 @@ import org.mortbay.jetty.nio.SelectChannelConnector;
 import org.mortbay.jetty.servlet.Context;
 
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.protobuf.Descriptors;
 import com.google.protobuf.Service;
@@ -2601,6 +2613,68 @@ public class HMaster extends HRegionServer implements MasterServices {
     return procInfoList;
   }
 
+  @Override
+  public Pair<Long, String> backupTables(final BackupType type,
+        List<TableName> tableList, final String targetRootDir, final int workers,
+        final long bandwidth) throws IOException {
+    long procId;
+    String backupId = BackupRestoreConstants.BACKUPID_PREFIX + EnvironmentEdgeManager.currentTime();
+    if (type == BackupType.INCREMENTAL) {
+      Set<TableName> incrTableSet =
+          BackupSystemTableHelper.getIncrementalBackupTableSet(clusterConnection);
+      if (incrTableSet.isEmpty()) {
+        LOG.warn("Incremental backup table set contains no table.\n"
+            + "Use 'backup create full' or 'backup stop' to \n "
+            + "change the tables covered by incremental backup.");
+        throw new DoNotRetryIOException("No table covered by incremental backup.");
+      }
+
+      LOG.info("Incremental backup for the following table set: " + incrTableSet);
+      tableList = Lists.newArrayList(incrTableSet);
+    }
+    if (tableList != null && !tableList.isEmpty()) {
+      for (TableName table : tableList) {
+        String targetTableBackupDir =
+            HBackupFileSystem.getTableBackupDir(targetRootDir, backupId, table);
+        Path targetTableBackupDirPath = new Path(targetTableBackupDir);
+        FileSystem outputFs = FileSystem.get(targetTableBackupDirPath.toUri(), conf);
+        if (outputFs.exists(targetTableBackupDirPath)) {
+          throw new DoNotRetryIOException("Target backup directory " + targetTableBackupDir
+            + " exists already.");
+        }
+      }
+      ArrayList<TableName> nonExistingTableList = null;
+      for (TableName tableName : tableList) {
+        if (!MetaTableAccessor.tableExists(getConnection(), tableName)) {
+          if (nonExistingTableList == null) {
+            nonExistingTableList = new ArrayList<>();
+          }
+          nonExistingTableList.add(tableName);
+        }
+      }
+      if (nonExistingTableList != null) {
+        if (type == BackupType.INCREMENTAL ) {
+          LOG.warn("Incremental backup table set contains non-exising table: "
+              + nonExistingTableList);
+        } else {
+          // Throw exception only in full mode - we try to backup non-existing table
+          throw new DoNotRetryIOException("Non-existing tables found in the table list: "
+              + nonExistingTableList);
+        }
+      }
+    }
+    if (type == BackupType.FULL) {
+      procId = this.procedureExecutor.submitProcedure(
+        new FullTableBackupProcedure(procedureExecutor.getEnvironment(), backupId,
+          tableList, targetRootDir, workers, bandwidth));
+    } else {
+      procId = this.procedureExecutor.submitProcedure(
+        new IncrementalTableBackupProcedure(procedureExecutor.getEnvironment(), backupId,
+          tableList, targetRootDir, workers, bandwidth));
+    }
+    return new Pair<>(procId, backupId);
+  }
+
   /**
    * Returns the list of table descriptors that match the specified request
    * @param namespace the namespace to query, or null if querying for all

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
index 8b036d9..e3004bb 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterRpcServices.java
@@ -40,6 +40,7 @@ import org.apache.hadoop.hbase.ServerLoad;
 import org.apache.hadoop.hbase.ServerName;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.UnknownRegionException;
+import org.apache.hadoop.hbase.backup.BackupType;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.client.Admin;
 import org.apache.hadoop.hbase.client.TableState;
@@ -1052,6 +1053,25 @@ public class MasterRpcServices extends RSRpcServices
   }
 
   @Override
+  public MasterProtos.BackupTablesResponse backupTables(
+      RpcController controller,
+      MasterProtos.BackupTablesRequest request)  throws ServiceException {
+    try {
+      BackupTablesResponse.Builder response = BackupTablesResponse.newBuilder();
+      List<TableName> tablesList = new ArrayList<>(request.getTablesList().size());
+      for (HBaseProtos.TableName table : request.getTablesList()) {
+        tablesList.add(ProtobufUtil.toTableName(table));
+      }
+      Pair<Long, String> pair = master.backupTables(
+        BackupType.valueOf(request.getType().name()), tablesList, request.getTargetRootDir(),
+        (int)request.getWorkers(), request.getBandwidth());
+      return response.setProcId(pair.getFirst()).setBackupId(pair.getSecond()).build();
+    } catch (IOException e) {
+      throw new ServiceException(e);
+    }
+  }
+
+  @Override
   public ListTableDescriptorsByNamespaceResponse listTableDescriptorsByNamespace(RpcController c,
       ListTableDescriptorsByNamespaceRequest request) throws ServiceException {
     try {

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java
index 867faed..3557bb4 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/MasterServices.java
@@ -20,6 +20,7 @@ package org.apache.hadoop.hbase.master;
 
 import java.io.IOException;
 import java.util.List;
+import java.util.concurrent.Future;
 
 import org.apache.hadoop.hbase.HColumnDescriptor;
 import org.apache.hadoop.hbase.HRegionInfo;
@@ -30,6 +31,7 @@ import org.apache.hadoop.hbase.TableDescriptors;
 import org.apache.hadoop.hbase.TableName;
 import org.apache.hadoop.hbase.TableNotDisabledException;
 import org.apache.hadoop.hbase.TableNotFoundException;
+import org.apache.hadoop.hbase.backup.BackupType;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.executor.ExecutorService;
 import org.apache.hadoop.hbase.master.normalizer.RegionNormalizer;
@@ -39,6 +41,7 @@ import org.apache.hadoop.hbase.procedure.MasterProcedureManagerHost;
 import org.apache.hadoop.hbase.procedure2.ProcedureExecutor;
 import org.apache.hadoop.hbase.quotas.MasterQuotaManager;
 import org.apache.hadoop.hbase.security.User;
+import org.apache.hadoop.hbase.util.Pair;
 
 import com.google.protobuf.Service;
 
@@ -179,6 +182,23 @@ public interface MasterServices extends Server {
       throws IOException;
 
   /**
+   * Full backup given list of tables
+   * @param type whether the backup is full or incremental
+   * @param tableList list of tables to backup
+   * @param targetRootDir root dir for saving the backup
+   * @param workers number of paralle workers. -1 - system defined
+   * @param bandwidth bandwidth per worker in MB per sec. -1 - unlimited
+   * @return pair of procedure Id and backupId
+   * @throws IOException
+   */
+  public Pair<Long, String> backupTables(
+      final BackupType type,
+      List<TableName> tableList,
+      final String targetRootDir,
+      final int workers,
+      final long bandwidth) throws IOException;
+
+  /**
    * Enable an existing table
    * @param tableName The table name
    * @param nonceGroup

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureUtil.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureUtil.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureUtil.java
index d7c0b92..e2409d4 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureUtil.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/MasterProcedureUtil.java
@@ -18,11 +18,22 @@
 
 package org.apache.hadoop.hbase.master.procedure;
 
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.util.Map;
+import java.util.Map.Entry;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.hadoop.hbase.classification.InterfaceAudience;
 import org.apache.hadoop.hbase.classification.InterfaceStability;
+import org.apache.hadoop.hbase.client.HBaseAdmin;
+import org.apache.hadoop.hbase.procedure.MasterProcedureManager;
+import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.NameStringPair;
+import org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.ProcedureDescription;
 import org.apache.hadoop.hbase.protobuf.generated.RPCProtos.UserInformation;
+import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;
+import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;
 import org.apache.hadoop.security.UserGroupInformation;
 
 @InterfaceAudience.Private
@@ -53,4 +64,62 @@ public final class MasterProcedureUtil {
     }
     return null;
   }
+
+  public static ProcedureDescription buildProcedure(String signature, String instance,
+      Map<String, String> props) {
+    ProcedureDescription.Builder builder = ProcedureDescription.newBuilder();
+    builder.setSignature(signature).setInstance(instance);
+    for (Entry<String, String> entry : props.entrySet()) {
+      NameStringPair pair = NameStringPair.newBuilder().setName(entry.getKey())
+          .setValue(entry.getValue()).build();
+      builder.addConfiguration(pair);
+    }
+    ProcedureDescription desc = builder.build();
+    return desc;
+  }
+
+  public static long execProcedure(MasterProcedureManager mpm, String signature, String instance,
+      Map<String, String> props) throws IOException {
+    if (mpm == null) {
+      throw new IOException("The procedure is not registered: " + signature);
+    }
+    ProcedureDescription desc = buildProcedure(signature, instance, props);
+    mpm.execProcedure(desc);
+
+    // send back the max amount of time the client should wait for the procedure
+    // to complete
+    long waitTime = SnapshotDescriptionUtils.DEFAULT_MAX_WAIT_TIME;
+    return waitTime;
+  }
+  
+  public static void waitForProcedure(MasterProcedureManager mpm, String signature, String instance,
+      Map<String, String> props, long max, int numRetries, long pause) throws IOException {
+    ProcedureDescription desc = buildProcedure(signature, instance, props);
+    long start = EnvironmentEdgeManager.currentTime();
+    long maxPauseTime = max / numRetries;
+    int tries = 0;
+    LOG.debug("Waiting a max of " + max + " ms for procedure '" +
+        signature + " : " + instance + "'' to complete. (max " + maxPauseTime + " ms per retry)");
+    boolean done = false;
+    while (tries == 0
+        || ((EnvironmentEdgeManager.currentTime() - start) < max && !done)) {
+      try {
+        // sleep a backoff <= pauseTime amount
+        long sleep = HBaseAdmin.getPauseTime(tries++, pause);
+        sleep = sleep > maxPauseTime ? maxPauseTime : sleep;
+        LOG.debug("(#" + tries + ") Sleeping: " + sleep +
+          "ms while waiting for procedure completion.");
+        Thread.sleep(sleep);
+      } catch (InterruptedException e) {
+        throw (InterruptedIOException) new InterruptedIOException("Interrupted").initCause(e);
+      }
+      LOG.debug("Getting current status of procedure from master...");
+      done = mpm.isProcedureDone(desc);
+    }
+    if (!done) {
+      throw new IOException("Procedure '" + signature + " : " + instance
+          + "' wasn't completed in expectedTime:" + max + " ms");
+    }
+
+  }
 }

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TableProcedureInterface.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TableProcedureInterface.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TableProcedureInterface.java
index cc088f3..56983a9 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TableProcedureInterface.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/master/procedure/TableProcedureInterface.java
@@ -30,7 +30,7 @@ import org.apache.hadoop.hbase.classification.InterfaceStability;
 @InterfaceStability.Evolving
 public interface TableProcedureInterface {
   public enum TableOperationType {
-    CREATE, DELETE, DISABLE, EDIT, ENABLE, READ,
+    CREATE, DELETE, DISABLE, EDIT, ENABLE, READ, BACKUP,
   };
 
   /**

http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupBase.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupBase.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupBase.java
index 84b7c78..1416523 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupBase.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestBackupBase.java
@@ -31,9 +31,10 @@ import org.apache.hadoop.hbase.HColumnDescriptor;
 import org.apache.hadoop.hbase.HConstants;
 import org.apache.hadoop.hbase.HTableDescriptor;
 import org.apache.hadoop.hbase.TableName;
-import org.apache.hadoop.hbase.backup.impl.BackupHandler.BackupState;
+import org.apache.hadoop.hbase.backup.impl.BackupContext.BackupState;
 import org.apache.hadoop.hbase.backup.impl.BackupContext;
 import org.apache.hadoop.hbase.backup.impl.BackupSystemTable;
+import org.apache.hadoop.hbase.backup.impl.BackupUtil;
 import org.apache.hadoop.hbase.backup.master.LogRollMasterProcedureManager;
 import org.apache.hadoop.hbase.backup.regionserver.LogRollRegionServerProcedureManager;
 import org.apache.hadoop.hbase.client.Connection;
@@ -47,6 +48,8 @@ import org.apache.hadoop.hbase.zookeeper.MiniZooKeeperCluster;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 
+import com.google.common.collect.Lists;
+
 /**
  * This class is only a base for other integration-level backup tests. Do not add tests here.
  * TestBackupSmallTests is where tests that don't require bring machines up/down should go All other
@@ -126,6 +129,32 @@ public class TestBackupBase {
     TEST_UTIL.shutdownMiniMapReduceCluster();
   }
 
+  protected String backupTables(BackupType type, List<TableName> tables, String path)
+      throws IOException {
+    Connection conn = null;
+    HBaseAdmin admin = null;
+    String backupId;
+    try {
+      conn = ConnectionFactory.createConnection(conf1);
+      admin = (HBaseAdmin) conn.getAdmin();
+      BackupRequest request = new BackupRequest();
+      request.setBackupType(type).setTableList(tables).setTargetRootDir(path);
+      backupId = admin.backupTables(request);
+    } finally {
+      if (admin != null) {
+        admin.close();
+      }
+      if (conn != null) {
+        conn.close();
+      }
+    }
+    return backupId;
+  }
+
+  protected String fullTableBackup(List<TableName> tables) throws IOException {
+    return backupTables(BackupType.FULL, tables, BACKUP_ROOT_DIR);
+  }
+
   protected static void loadTable(HTable table) throws Exception {
 
     Put p; // 100 + 1 row to t1_syncup
@@ -140,6 +169,7 @@ public class TestBackupBase {
 
     long tid = System.currentTimeMillis();
     table1 = TableName.valueOf("test-" + tid);
+    BackupSystemTable backupTable = new BackupSystemTable(TEST_UTIL.getConnection());
     HBaseAdmin ha = TEST_UTIL.getHBaseAdmin();
     HTableDescriptor desc = new HTableDescriptor(table1);
     HColumnDescriptor fam = new HColumnDescriptor(famName);
@@ -187,10 +217,6 @@ public class TestBackupBase {
     }
   }
 
-  protected BackupClient getBackupClient(){
-    return BackupRestoreFactory.getBackupClient(conf1);
-  }
-
   protected RestoreClient getRestoreClient()
   {
     return BackupRestoreFactory.getRestoreClient(conf1);


[5/6] hbase git commit: HBASE-15411 Rewrite backup with Procedure V2 - phase 1

Posted by te...@apache.org.
http://git-wip-us.apache.org/repos/asf/hbase/blob/b37cc760/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/BackupProtos.java
----------------------------------------------------------------------
diff --git a/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/BackupProtos.java b/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/BackupProtos.java
index 1a7a1ba..a1a1a78 100644
--- a/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/BackupProtos.java
+++ b/hbase-protocol/src/main/java/org/apache/hadoop/hbase/protobuf/generated/BackupProtos.java
@@ -9,6 +9,197 @@ public final class BackupProtos {
       com.google.protobuf.ExtensionRegistry registry) {
   }
   /**
+   * Protobuf enum {@code hbase.pb.FullTableBackupState}
+   */
+  public enum FullTableBackupState
+      implements com.google.protobuf.ProtocolMessageEnum {
+    /**
+     * <code>PRE_SNAPSHOT_TABLE = 1;</code>
+     */
+    PRE_SNAPSHOT_TABLE(0, 1),
+    /**
+     * <code>SNAPSHOT_TABLES = 2;</code>
+     */
+    SNAPSHOT_TABLES(1, 2),
+    /**
+     * <code>SNAPSHOT_COPY = 3;</code>
+     */
+    SNAPSHOT_COPY(2, 3),
+    /**
+     * <code>BACKUP_COMPLETE = 4;</code>
+     */
+    BACKUP_COMPLETE(3, 4),
+    ;
+
+    /**
+     * <code>PRE_SNAPSHOT_TABLE = 1;</code>
+     */
+    public static final int PRE_SNAPSHOT_TABLE_VALUE = 1;
+    /**
+     * <code>SNAPSHOT_TABLES = 2;</code>
+     */
+    public static final int SNAPSHOT_TABLES_VALUE = 2;
+    /**
+     * <code>SNAPSHOT_COPY = 3;</code>
+     */
+    public static final int SNAPSHOT_COPY_VALUE = 3;
+    /**
+     * <code>BACKUP_COMPLETE = 4;</code>
+     */
+    public static final int BACKUP_COMPLETE_VALUE = 4;
+
+
+    public final int getNumber() { return value; }
+
+    public static FullTableBackupState valueOf(int value) {
+      switch (value) {
+        case 1: return PRE_SNAPSHOT_TABLE;
+        case 2: return SNAPSHOT_TABLES;
+        case 3: return SNAPSHOT_COPY;
+        case 4: return BACKUP_COMPLETE;
+        default: return null;
+      }
+    }
+
+    public static com.google.protobuf.Internal.EnumLiteMap<FullTableBackupState>
+        internalGetValueMap() {
+      return internalValueMap;
+    }
+    private static com.google.protobuf.Internal.EnumLiteMap<FullTableBackupState>
+        internalValueMap =
+          new com.google.protobuf.Internal.EnumLiteMap<FullTableBackupState>() {
+            public FullTableBackupState findValueByNumber(int number) {
+              return FullTableBackupState.valueOf(number);
+            }
+          };
+
+    public final com.google.protobuf.Descriptors.EnumValueDescriptor
+        getValueDescriptor() {
+      return getDescriptor().getValues().get(index);
+    }
+    public final com.google.protobuf.Descriptors.EnumDescriptor
+        getDescriptorForType() {
+      return getDescriptor();
+    }
+    public static final com.google.protobuf.Descriptors.EnumDescriptor
+        getDescriptor() {
+      return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.getDescriptor().getEnumTypes().get(0);
+    }
+
+    private static final FullTableBackupState[] VALUES = values();
+
+    public static FullTableBackupState valueOf(
+        com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
+      if (desc.getType() != getDescriptor()) {
+        throw new java.lang.IllegalArgumentException(
+          "EnumValueDescriptor is not for this type.");
+      }
+      return VALUES[desc.getIndex()];
+    }
+
+    private final int index;
+    private final int value;
+
+    private FullTableBackupState(int index, int value) {
+      this.index = index;
+      this.value = value;
+    }
+
+    // @@protoc_insertion_point(enum_scope:hbase.pb.FullTableBackupState)
+  }
+
+  /**
+   * Protobuf enum {@code hbase.pb.IncrementalTableBackupState}
+   */
+  public enum IncrementalTableBackupState
+      implements com.google.protobuf.ProtocolMessageEnum {
+    /**
+     * <code>PREPARE_INCREMENTAL = 1;</code>
+     */
+    PREPARE_INCREMENTAL(0, 1),
+    /**
+     * <code>INCREMENTAL_COPY = 2;</code>
+     */
+    INCREMENTAL_COPY(1, 2),
+    /**
+     * <code>INCR_BACKUP_COMPLETE = 3;</code>
+     */
+    INCR_BACKUP_COMPLETE(2, 3),
+    ;
+
+    /**
+     * <code>PREPARE_INCREMENTAL = 1;</code>
+     */
+    public static final int PREPARE_INCREMENTAL_VALUE = 1;
+    /**
+     * <code>INCREMENTAL_COPY = 2;</code>
+     */
+    public static final int INCREMENTAL_COPY_VALUE = 2;
+    /**
+     * <code>INCR_BACKUP_COMPLETE = 3;</code>
+     */
+    public static final int INCR_BACKUP_COMPLETE_VALUE = 3;
+
+
+    public final int getNumber() { return value; }
+
+    public static IncrementalTableBackupState valueOf(int value) {
+      switch (value) {
+        case 1: return PREPARE_INCREMENTAL;
+        case 2: return INCREMENTAL_COPY;
+        case 3: return INCR_BACKUP_COMPLETE;
+        default: return null;
+      }
+    }
+
+    public static com.google.protobuf.Internal.EnumLiteMap<IncrementalTableBackupState>
+        internalGetValueMap() {
+      return internalValueMap;
+    }
+    private static com.google.protobuf.Internal.EnumLiteMap<IncrementalTableBackupState>
+        internalValueMap =
+          new com.google.protobuf.Internal.EnumLiteMap<IncrementalTableBackupState>() {
+            public IncrementalTableBackupState findValueByNumber(int number) {
+              return IncrementalTableBackupState.valueOf(number);
+            }
+          };
+
+    public final com.google.protobuf.Descriptors.EnumValueDescriptor
+        getValueDescriptor() {
+      return getDescriptor().getValues().get(index);
+    }
+    public final com.google.protobuf.Descriptors.EnumDescriptor
+        getDescriptorForType() {
+      return getDescriptor();
+    }
+    public static final com.google.protobuf.Descriptors.EnumDescriptor
+        getDescriptor() {
+      return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.getDescriptor().getEnumTypes().get(1);
+    }
+
+    private static final IncrementalTableBackupState[] VALUES = values();
+
+    public static IncrementalTableBackupState valueOf(
+        com.google.protobuf.Descriptors.EnumValueDescriptor desc) {
+      if (desc.getType() != getDescriptor()) {
+        throw new java.lang.IllegalArgumentException(
+          "EnumValueDescriptor is not for this type.");
+      }
+      return VALUES[desc.getIndex()];
+    }
+
+    private final int index;
+    private final int value;
+
+    private IncrementalTableBackupState(int index, int value) {
+      this.index = index;
+      this.value = value;
+    }
+
+    // @@protoc_insertion_point(enum_scope:hbase.pb.IncrementalTableBackupState)
+  }
+
+  /**
    * Protobuf enum {@code hbase.pb.BackupType}
    */
   public enum BackupType
@@ -65,7 +256,7 @@ public final class BackupProtos {
     }
     public static final com.google.protobuf.Descriptors.EnumDescriptor
         getDescriptor() {
-      return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.getDescriptor().getEnumTypes().get(0);
+      return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.getDescriptor().getEnumTypes().get(2);
     }
 
     private static final BackupType[] VALUES = values();
@@ -90,138 +281,57 @@ public final class BackupProtos {
     // @@protoc_insertion_point(enum_scope:hbase.pb.BackupType)
   }
 
-  public interface BackupImageOrBuilder
+  public interface SnapshotTableStateDataOrBuilder
       extends com.google.protobuf.MessageOrBuilder {
 
-    // required string backup_id = 1;
-    /**
-     * <code>required string backup_id = 1;</code>
-     */
-    boolean hasBackupId();
-    /**
-     * <code>required string backup_id = 1;</code>
-     */
-    java.lang.String getBackupId();
+    // required .hbase.pb.TableName table = 1;
     /**
-     * <code>required string backup_id = 1;</code>
+     * <code>required .hbase.pb.TableName table = 1;</code>
      */
-    com.google.protobuf.ByteString
-        getBackupIdBytes();
-
-    // required .hbase.pb.BackupType backup_type = 2;
+    boolean hasTable();
     /**
-     * <code>required .hbase.pb.BackupType backup_type = 2;</code>
+     * <code>required .hbase.pb.TableName table = 1;</code>
      */
-    boolean hasBackupType();
+    org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName getTable();
     /**
-     * <code>required .hbase.pb.BackupType backup_type = 2;</code>
+     * <code>required .hbase.pb.TableName table = 1;</code>
      */
-    org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType getBackupType();
+    org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder getTableOrBuilder();
 
-    // required string root_dir = 3;
+    // required string snapshotName = 2;
     /**
-     * <code>required string root_dir = 3;</code>
+     * <code>required string snapshotName = 2;</code>
      */
-    boolean hasRootDir();
+    boolean hasSnapshotName();
     /**
-     * <code>required string root_dir = 3;</code>
+     * <code>required string snapshotName = 2;</code>
      */
-    java.lang.String getRootDir();
+    java.lang.String getSnapshotName();
     /**
-     * <code>required string root_dir = 3;</code>
+     * <code>required string snapshotName = 2;</code>
      */
     com.google.protobuf.ByteString
-        getRootDirBytes();
-
-    // repeated .hbase.pb.TableName table_list = 4;
-    /**
-     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-     */
-    java.util.List<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName> 
-        getTableListList();
-    /**
-     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-     */
-    org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName getTableList(int index);
-    /**
-     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-     */
-    int getTableListCount();
-    /**
-     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-     */
-    java.util.List<? extends org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder> 
-        getTableListOrBuilderList();
-    /**
-     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-     */
-    org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder getTableListOrBuilder(
-        int index);
-
-    // required uint64 start_ts = 5;
-    /**
-     * <code>required uint64 start_ts = 5;</code>
-     */
-    boolean hasStartTs();
-    /**
-     * <code>required uint64 start_ts = 5;</code>
-     */
-    long getStartTs();
-
-    // required uint64 complete_ts = 6;
-    /**
-     * <code>required uint64 complete_ts = 6;</code>
-     */
-    boolean hasCompleteTs();
-    /**
-     * <code>required uint64 complete_ts = 6;</code>
-     */
-    long getCompleteTs();
-
-    // repeated .hbase.pb.BackupImage ancestors = 7;
-    /**
-     * <code>repeated .hbase.pb.BackupImage ancestors = 7;</code>
-     */
-    java.util.List<org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage> 
-        getAncestorsList();
-    /**
-     * <code>repeated .hbase.pb.BackupImage ancestors = 7;</code>
-     */
-    org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage getAncestors(int index);
-    /**
-     * <code>repeated .hbase.pb.BackupImage ancestors = 7;</code>
-     */
-    int getAncestorsCount();
-    /**
-     * <code>repeated .hbase.pb.BackupImage ancestors = 7;</code>
-     */
-    java.util.List<? extends org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImageOrBuilder> 
-        getAncestorsOrBuilderList();
-    /**
-     * <code>repeated .hbase.pb.BackupImage ancestors = 7;</code>
-     */
-    org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImageOrBuilder getAncestorsOrBuilder(
-        int index);
+        getSnapshotNameBytes();
   }
   /**
-   * Protobuf type {@code hbase.pb.BackupImage}
+   * Protobuf type {@code hbase.pb.SnapshotTableStateData}
    */
-  public static final class BackupImage extends
+  public static final class SnapshotTableStateData extends
       com.google.protobuf.GeneratedMessage
-      implements BackupImageOrBuilder {
-    // Use BackupImage.newBuilder() to construct.
-    private BackupImage(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      implements SnapshotTableStateDataOrBuilder {
+    // Use SnapshotTableStateData.newBuilder() to construct.
+    private SnapshotTableStateData(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
       super(builder);
       this.unknownFields = builder.getUnknownFields();
     }
-    private BackupImage(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+    private SnapshotTableStateData(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
 
-    private static final BackupImage defaultInstance;
-    public static BackupImage getDefaultInstance() {
+    private static final SnapshotTableStateData defaultInstance;
+    public static SnapshotTableStateData getDefaultInstance() {
       return defaultInstance;
     }
 
-    public BackupImage getDefaultInstanceForType() {
+    public SnapshotTableStateData getDefaultInstanceForType() {
       return defaultInstance;
     }
 
@@ -231,7 +341,7 @@ public final class BackupProtos {
         getUnknownFields() {
       return this.unknownFields;
     }
-    private BackupImage(
+    private SnapshotTableStateData(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
@@ -255,50 +365,21 @@ public final class BackupProtos {
               break;
             }
             case 10: {
+              org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder subBuilder = null;
+              if (((bitField0_ & 0x00000001) == 0x00000001)) {
+                subBuilder = table_.toBuilder();
+              }
+              table_ = input.readMessage(org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.PARSER, extensionRegistry);
+              if (subBuilder != null) {
+                subBuilder.mergeFrom(table_);
+                table_ = subBuilder.buildPartial();
+              }
               bitField0_ |= 0x00000001;
-              backupId_ = input.readBytes();
               break;
             }
-            case 16: {
-              int rawValue = input.readEnum();
-              org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType value = org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType.valueOf(rawValue);
-              if (value == null) {
-                unknownFields.mergeVarintField(2, rawValue);
-              } else {
-                bitField0_ |= 0x00000002;
-                backupType_ = value;
-              }
-              break;
-            }
-            case 26: {
-              bitField0_ |= 0x00000004;
-              rootDir_ = input.readBytes();
-              break;
-            }
-            case 34: {
-              if (!((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
-                tableList_ = new java.util.ArrayList<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName>();
-                mutable_bitField0_ |= 0x00000008;
-              }
-              tableList_.add(input.readMessage(org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.PARSER, extensionRegistry));
-              break;
-            }
-            case 40: {
-              bitField0_ |= 0x00000008;
-              startTs_ = input.readUInt64();
-              break;
-            }
-            case 48: {
-              bitField0_ |= 0x00000010;
-              completeTs_ = input.readUInt64();
-              break;
-            }
-            case 58: {
-              if (!((mutable_bitField0_ & 0x00000040) == 0x00000040)) {
-                ancestors_ = new java.util.ArrayList<org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage>();
-                mutable_bitField0_ |= 0x00000040;
-              }
-              ancestors_.add(input.readMessage(org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage.PARSER, extensionRegistry));
+            case 18: {
+              bitField0_ |= 0x00000002;
+              snapshotName_ = input.readBytes();
               break;
             }
           }
@@ -309,117 +390,74 @@ public final class BackupProtos {
         throw new com.google.protobuf.InvalidProtocolBufferException(
             e.getMessage()).setUnfinishedMessage(this);
       } finally {
-        if (((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
-          tableList_ = java.util.Collections.unmodifiableList(tableList_);
-        }
-        if (((mutable_bitField0_ & 0x00000040) == 0x00000040)) {
-          ancestors_ = java.util.Collections.unmodifiableList(ancestors_);
-        }
         this.unknownFields = unknownFields.build();
         makeExtensionsImmutable();
       }
     }
     public static final com.google.protobuf.Descriptors.Descriptor
         getDescriptor() {
-      return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.internal_static_hbase_pb_BackupImage_descriptor;
+      return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.internal_static_hbase_pb_SnapshotTableStateData_descriptor;
     }
 
     protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
         internalGetFieldAccessorTable() {
-      return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.internal_static_hbase_pb_BackupImage_fieldAccessorTable
+      return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.internal_static_hbase_pb_SnapshotTableStateData_fieldAccessorTable
           .ensureFieldAccessorsInitialized(
-              org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage.class, org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage.Builder.class);
+              org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData.class, org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData.Builder.class);
     }
 
-    public static com.google.protobuf.Parser<BackupImage> PARSER =
-        new com.google.protobuf.AbstractParser<BackupImage>() {
-      public BackupImage parsePartialFrom(
+    public static com.google.protobuf.Parser<SnapshotTableStateData> PARSER =
+        new com.google.protobuf.AbstractParser<SnapshotTableStateData>() {
+      public SnapshotTableStateData parsePartialFrom(
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws com.google.protobuf.InvalidProtocolBufferException {
-        return new BackupImage(input, extensionRegistry);
+        return new SnapshotTableStateData(input, extensionRegistry);
       }
     };
 
     @java.lang.Override
-    public com.google.protobuf.Parser<BackupImage> getParserForType() {
+    public com.google.protobuf.Parser<SnapshotTableStateData> getParserForType() {
       return PARSER;
     }
 
     private int bitField0_;
-    // required string backup_id = 1;
-    public static final int BACKUP_ID_FIELD_NUMBER = 1;
-    private java.lang.Object backupId_;
+    // required .hbase.pb.TableName table = 1;
+    public static final int TABLE_FIELD_NUMBER = 1;
+    private org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName table_;
     /**
-     * <code>required string backup_id = 1;</code>
+     * <code>required .hbase.pb.TableName table = 1;</code>
      */
-    public boolean hasBackupId() {
+    public boolean hasTable() {
       return ((bitField0_ & 0x00000001) == 0x00000001);
     }
     /**
-     * <code>required string backup_id = 1;</code>
+     * <code>required .hbase.pb.TableName table = 1;</code>
      */
-    public java.lang.String getBackupId() {
-      java.lang.Object ref = backupId_;
-      if (ref instanceof java.lang.String) {
-        return (java.lang.String) ref;
-      } else {
-        com.google.protobuf.ByteString bs = 
-            (com.google.protobuf.ByteString) ref;
-        java.lang.String s = bs.toStringUtf8();
-        if (bs.isValidUtf8()) {
-          backupId_ = s;
-        }
-        return s;
-      }
+    public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName getTable() {
+      return table_;
     }
     /**
-     * <code>required string backup_id = 1;</code>
+     * <code>required .hbase.pb.TableName table = 1;</code>
      */
-    public com.google.protobuf.ByteString
-        getBackupIdBytes() {
-      java.lang.Object ref = backupId_;
-      if (ref instanceof java.lang.String) {
-        com.google.protobuf.ByteString b = 
-            com.google.protobuf.ByteString.copyFromUtf8(
-                (java.lang.String) ref);
-        backupId_ = b;
-        return b;
-      } else {
-        return (com.google.protobuf.ByteString) ref;
-      }
+    public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder getTableOrBuilder() {
+      return table_;
     }
 
-    // required .hbase.pb.BackupType backup_type = 2;
-    public static final int BACKUP_TYPE_FIELD_NUMBER = 2;
-    private org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType backupType_;
+    // required string snapshotName = 2;
+    public static final int SNAPSHOTNAME_FIELD_NUMBER = 2;
+    private java.lang.Object snapshotName_;
     /**
-     * <code>required .hbase.pb.BackupType backup_type = 2;</code>
+     * <code>required string snapshotName = 2;</code>
      */
-    public boolean hasBackupType() {
+    public boolean hasSnapshotName() {
       return ((bitField0_ & 0x00000002) == 0x00000002);
     }
     /**
-     * <code>required .hbase.pb.BackupType backup_type = 2;</code>
-     */
-    public org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType getBackupType() {
-      return backupType_;
-    }
-
-    // required string root_dir = 3;
-    public static final int ROOT_DIR_FIELD_NUMBER = 3;
-    private java.lang.Object rootDir_;
-    /**
-     * <code>required string root_dir = 3;</code>
-     */
-    public boolean hasRootDir() {
-      return ((bitField0_ & 0x00000004) == 0x00000004);
-    }
-    /**
-     * <code>required string root_dir = 3;</code>
+     * <code>required string snapshotName = 2;</code>
      */
-    public java.lang.String getRootDir() {
-      java.lang.Object ref = rootDir_;
+    public java.lang.String getSnapshotName() {
+      java.lang.Object ref = snapshotName_;
       if (ref instanceof java.lang.String) {
         return (java.lang.String) ref;
       } else {
@@ -427,205 +465,61 @@ public final class BackupProtos {
             (com.google.protobuf.ByteString) ref;
         java.lang.String s = bs.toStringUtf8();
         if (bs.isValidUtf8()) {
-          rootDir_ = s;
+          snapshotName_ = s;
         }
         return s;
       }
     }
     /**
-     * <code>required string root_dir = 3;</code>
+     * <code>required string snapshotName = 2;</code>
      */
     public com.google.protobuf.ByteString
-        getRootDirBytes() {
-      java.lang.Object ref = rootDir_;
+        getSnapshotNameBytes() {
+      java.lang.Object ref = snapshotName_;
       if (ref instanceof java.lang.String) {
         com.google.protobuf.ByteString b = 
             com.google.protobuf.ByteString.copyFromUtf8(
                 (java.lang.String) ref);
-        rootDir_ = b;
+        snapshotName_ = b;
         return b;
       } else {
         return (com.google.protobuf.ByteString) ref;
       }
     }
 
-    // repeated .hbase.pb.TableName table_list = 4;
-    public static final int TABLE_LIST_FIELD_NUMBER = 4;
-    private java.util.List<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName> tableList_;
-    /**
-     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-     */
-    public java.util.List<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName> getTableListList() {
-      return tableList_;
-    }
-    /**
-     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-     */
-    public java.util.List<? extends org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder> 
-        getTableListOrBuilderList() {
-      return tableList_;
-    }
-    /**
-     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-     */
-    public int getTableListCount() {
-      return tableList_.size();
-    }
-    /**
-     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-     */
-    public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName getTableList(int index) {
-      return tableList_.get(index);
-    }
-    /**
-     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-     */
-    public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder getTableListOrBuilder(
-        int index) {
-      return tableList_.get(index);
-    }
-
-    // required uint64 start_ts = 5;
-    public static final int START_TS_FIELD_NUMBER = 5;
-    private long startTs_;
-    /**
-     * <code>required uint64 start_ts = 5;</code>
-     */
-    public boolean hasStartTs() {
-      return ((bitField0_ & 0x00000008) == 0x00000008);
-    }
-    /**
-     * <code>required uint64 start_ts = 5;</code>
-     */
-    public long getStartTs() {
-      return startTs_;
-    }
-
-    // required uint64 complete_ts = 6;
-    public static final int COMPLETE_TS_FIELD_NUMBER = 6;
-    private long completeTs_;
-    /**
-     * <code>required uint64 complete_ts = 6;</code>
-     */
-    public boolean hasCompleteTs() {
-      return ((bitField0_ & 0x00000010) == 0x00000010);
-    }
-    /**
-     * <code>required uint64 complete_ts = 6;</code>
-     */
-    public long getCompleteTs() {
-      return completeTs_;
-    }
-
-    // repeated .hbase.pb.BackupImage ancestors = 7;
-    public static final int ANCESTORS_FIELD_NUMBER = 7;
-    private java.util.List<org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage> ancestors_;
-    /**
-     * <code>repeated .hbase.pb.BackupImage ancestors = 7;</code>
-     */
-    public java.util.List<org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage> getAncestorsList() {
-      return ancestors_;
-    }
-    /**
-     * <code>repeated .hbase.pb.BackupImage ancestors = 7;</code>
-     */
-    public java.util.List<? extends org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImageOrBuilder> 
-        getAncestorsOrBuilderList() {
-      return ancestors_;
-    }
-    /**
-     * <code>repeated .hbase.pb.BackupImage ancestors = 7;</code>
-     */
-    public int getAncestorsCount() {
-      return ancestors_.size();
-    }
-    /**
-     * <code>repeated .hbase.pb.BackupImage ancestors = 7;</code>
-     */
-    public org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage getAncestors(int index) {
-      return ancestors_.get(index);
-    }
-    /**
-     * <code>repeated .hbase.pb.BackupImage ancestors = 7;</code>
-     */
-    public org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImageOrBuilder getAncestorsOrBuilder(
-        int index) {
-      return ancestors_.get(index);
-    }
-
     private void initFields() {
-      backupId_ = "";
-      backupType_ = org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType.FULL;
-      rootDir_ = "";
-      tableList_ = java.util.Collections.emptyList();
-      startTs_ = 0L;
-      completeTs_ = 0L;
-      ancestors_ = java.util.Collections.emptyList();
+      table_ = org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.getDefaultInstance();
+      snapshotName_ = "";
     }
     private byte memoizedIsInitialized = -1;
     public final boolean isInitialized() {
       byte isInitialized = memoizedIsInitialized;
       if (isInitialized != -1) return isInitialized == 1;
 
-      if (!hasBackupId()) {
+      if (!hasTable()) {
         memoizedIsInitialized = 0;
         return false;
       }
-      if (!hasBackupType()) {
+      if (!hasSnapshotName()) {
         memoizedIsInitialized = 0;
         return false;
       }
-      if (!hasRootDir()) {
+      if (!getTable().isInitialized()) {
         memoizedIsInitialized = 0;
         return false;
       }
-      if (!hasStartTs()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      if (!hasCompleteTs()) {
-        memoizedIsInitialized = 0;
-        return false;
-      }
-      for (int i = 0; i < getTableListCount(); i++) {
-        if (!getTableList(i).isInitialized()) {
-          memoizedIsInitialized = 0;
-          return false;
-        }
-      }
-      for (int i = 0; i < getAncestorsCount(); i++) {
-        if (!getAncestors(i).isInitialized()) {
-          memoizedIsInitialized = 0;
-          return false;
-        }
-      }
-      memoizedIsInitialized = 1;
-      return true;
-    }
-
-    public void writeTo(com.google.protobuf.CodedOutputStream output)
-                        throws java.io.IOException {
-      getSerializedSize();
-      if (((bitField0_ & 0x00000001) == 0x00000001)) {
-        output.writeBytes(1, getBackupIdBytes());
+      memoizedIsInitialized = 1;
+      return true;
+    }
+
+    public void writeTo(com.google.protobuf.CodedOutputStream output)
+                        throws java.io.IOException {
+      getSerializedSize();
+      if (((bitField0_ & 0x00000001) == 0x00000001)) {
+        output.writeMessage(1, table_);
       }
       if (((bitField0_ & 0x00000002) == 0x00000002)) {
-        output.writeEnum(2, backupType_.getNumber());
-      }
-      if (((bitField0_ & 0x00000004) == 0x00000004)) {
-        output.writeBytes(3, getRootDirBytes());
-      }
-      for (int i = 0; i < tableList_.size(); i++) {
-        output.writeMessage(4, tableList_.get(i));
-      }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        output.writeUInt64(5, startTs_);
-      }
-      if (((bitField0_ & 0x00000010) == 0x00000010)) {
-        output.writeUInt64(6, completeTs_);
-      }
-      for (int i = 0; i < ancestors_.size(); i++) {
-        output.writeMessage(7, ancestors_.get(i));
+        output.writeBytes(2, getSnapshotNameBytes());
       }
       getUnknownFields().writeTo(output);
     }
@@ -638,31 +532,11 @@ public final class BackupProtos {
       size = 0;
       if (((bitField0_ & 0x00000001) == 0x00000001)) {
         size += com.google.protobuf.CodedOutputStream
-          .computeBytesSize(1, getBackupIdBytes());
+          .computeMessageSize(1, table_);
       }
       if (((bitField0_ & 0x00000002) == 0x00000002)) {
         size += com.google.protobuf.CodedOutputStream
-          .computeEnumSize(2, backupType_.getNumber());
-      }
-      if (((bitField0_ & 0x00000004) == 0x00000004)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeBytesSize(3, getRootDirBytes());
-      }
-      for (int i = 0; i < tableList_.size(); i++) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(4, tableList_.get(i));
-      }
-      if (((bitField0_ & 0x00000008) == 0x00000008)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeUInt64Size(5, startTs_);
-      }
-      if (((bitField0_ & 0x00000010) == 0x00000010)) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeUInt64Size(6, completeTs_);
-      }
-      for (int i = 0; i < ancestors_.size(); i++) {
-        size += com.google.protobuf.CodedOutputStream
-          .computeMessageSize(7, ancestors_.get(i));
+          .computeBytesSize(2, getSnapshotNameBytes());
       }
       size += getUnknownFields().getSerializedSize();
       memoizedSerializedSize = size;
@@ -681,41 +555,22 @@ public final class BackupProtos {
       if (obj == this) {
        return true;
       }
-      if (!(obj instanceof org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage)) {
+      if (!(obj instanceof org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData)) {
         return super.equals(obj);
       }
-      org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage other = (org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage) obj;
+      org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData other = (org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData) obj;
 
       boolean result = true;
-      result = result && (hasBackupId() == other.hasBackupId());
-      if (hasBackupId()) {
-        result = result && getBackupId()
-            .equals(other.getBackupId());
-      }
-      result = result && (hasBackupType() == other.hasBackupType());
-      if (hasBackupType()) {
-        result = result &&
-            (getBackupType() == other.getBackupType());
-      }
-      result = result && (hasRootDir() == other.hasRootDir());
-      if (hasRootDir()) {
-        result = result && getRootDir()
-            .equals(other.getRootDir());
-      }
-      result = result && getTableListList()
-          .equals(other.getTableListList());
-      result = result && (hasStartTs() == other.hasStartTs());
-      if (hasStartTs()) {
-        result = result && (getStartTs()
-            == other.getStartTs());
+      result = result && (hasTable() == other.hasTable());
+      if (hasTable()) {
+        result = result && getTable()
+            .equals(other.getTable());
       }
-      result = result && (hasCompleteTs() == other.hasCompleteTs());
-      if (hasCompleteTs()) {
-        result = result && (getCompleteTs()
-            == other.getCompleteTs());
+      result = result && (hasSnapshotName() == other.hasSnapshotName());
+      if (hasSnapshotName()) {
+        result = result && getSnapshotName()
+            .equals(other.getSnapshotName());
       }
-      result = result && getAncestorsList()
-          .equals(other.getAncestorsList());
       result = result &&
           getUnknownFields().equals(other.getUnknownFields());
       return result;
@@ -729,86 +584,66 @@ public final class BackupProtos {
       }
       int hash = 41;
       hash = (19 * hash) + getDescriptorForType().hashCode();
-      if (hasBackupId()) {
-        hash = (37 * hash) + BACKUP_ID_FIELD_NUMBER;
-        hash = (53 * hash) + getBackupId().hashCode();
-      }
-      if (hasBackupType()) {
-        hash = (37 * hash) + BACKUP_TYPE_FIELD_NUMBER;
-        hash = (53 * hash) + hashEnum(getBackupType());
-      }
-      if (hasRootDir()) {
-        hash = (37 * hash) + ROOT_DIR_FIELD_NUMBER;
-        hash = (53 * hash) + getRootDir().hashCode();
-      }
-      if (getTableListCount() > 0) {
-        hash = (37 * hash) + TABLE_LIST_FIELD_NUMBER;
-        hash = (53 * hash) + getTableListList().hashCode();
-      }
-      if (hasStartTs()) {
-        hash = (37 * hash) + START_TS_FIELD_NUMBER;
-        hash = (53 * hash) + hashLong(getStartTs());
-      }
-      if (hasCompleteTs()) {
-        hash = (37 * hash) + COMPLETE_TS_FIELD_NUMBER;
-        hash = (53 * hash) + hashLong(getCompleteTs());
+      if (hasTable()) {
+        hash = (37 * hash) + TABLE_FIELD_NUMBER;
+        hash = (53 * hash) + getTable().hashCode();
       }
-      if (getAncestorsCount() > 0) {
-        hash = (37 * hash) + ANCESTORS_FIELD_NUMBER;
-        hash = (53 * hash) + getAncestorsList().hashCode();
+      if (hasSnapshotName()) {
+        hash = (37 * hash) + SNAPSHOTNAME_FIELD_NUMBER;
+        hash = (53 * hash) + getSnapshotName().hashCode();
       }
       hash = (29 * hash) + getUnknownFields().hashCode();
       memoizedHashCode = hash;
       return hash;
     }
 
-    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage parseFrom(
+    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData parseFrom(
         com.google.protobuf.ByteString data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage parseFrom(
+    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData parseFrom(
         com.google.protobuf.ByteString data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage parseFrom(byte[] data)
+    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData parseFrom(byte[] data)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data);
     }
-    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage parseFrom(
+    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData parseFrom(
         byte[] data,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws com.google.protobuf.InvalidProtocolBufferException {
       return PARSER.parseFrom(data, extensionRegistry);
     }
-    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage parseFrom(java.io.InputStream input)
+    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData parseFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage parseFrom(
+    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData parseFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseFrom(input, extensionRegistry);
     }
-    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage parseDelimitedFrom(java.io.InputStream input)
+    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData parseDelimitedFrom(java.io.InputStream input)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input);
     }
-    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage parseDelimitedFrom(
+    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData parseDelimitedFrom(
         java.io.InputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
       return PARSER.parseDelimitedFrom(input, extensionRegistry);
     }
-    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage parseFrom(
+    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData parseFrom(
         com.google.protobuf.CodedInputStream input)
         throws java.io.IOException {
       return PARSER.parseFrom(input);
     }
-    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage parseFrom(
+    public static org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData parseFrom(
         com.google.protobuf.CodedInputStream input,
         com.google.protobuf.ExtensionRegistryLite extensionRegistry)
         throws java.io.IOException {
@@ -817,7 +652,7 @@ public final class BackupProtos {
 
     public static Builder newBuilder() { return Builder.create(); }
     public Builder newBuilderForType() { return newBuilder(); }
-    public static Builder newBuilder(org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage prototype) {
+    public static Builder newBuilder(org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData prototype) {
       return newBuilder().mergeFrom(prototype);
     }
     public Builder toBuilder() { return newBuilder(this); }
@@ -829,24 +664,24 @@ public final class BackupProtos {
       return builder;
     }
     /**
-     * Protobuf type {@code hbase.pb.BackupImage}
+     * Protobuf type {@code hbase.pb.SnapshotTableStateData}
      */
     public static final class Builder extends
         com.google.protobuf.GeneratedMessage.Builder<Builder>
-       implements org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImageOrBuilder {
+       implements org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateDataOrBuilder {
       public static final com.google.protobuf.Descriptors.Descriptor
           getDescriptor() {
-        return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.internal_static_hbase_pb_BackupImage_descriptor;
+        return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.internal_static_hbase_pb_SnapshotTableStateData_descriptor;
       }
 
       protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
           internalGetFieldAccessorTable() {
-        return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.internal_static_hbase_pb_BackupImage_fieldAccessorTable
+        return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.internal_static_hbase_pb_SnapshotTableStateData_fieldAccessorTable
             .ensureFieldAccessorsInitialized(
-                org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage.class, org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage.Builder.class);
+                org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData.class, org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData.Builder.class);
       }
 
-      // Construct using org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage.newBuilder()
+      // Construct using org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData.newBuilder()
       private Builder() {
         maybeForceBuilderInitialization();
       }
@@ -858,8 +693,7 @@ public final class BackupProtos {
       }
       private void maybeForceBuilderInitialization() {
         if (com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders) {
-          getTableListFieldBuilder();
-          getAncestorsFieldBuilder();
+          getTableFieldBuilder();
         }
       }
       private static Builder create() {
@@ -868,28 +702,14 @@ public final class BackupProtos {
 
       public Builder clear() {
         super.clear();
-        backupId_ = "";
-        bitField0_ = (bitField0_ & ~0x00000001);
-        backupType_ = org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType.FULL;
-        bitField0_ = (bitField0_ & ~0x00000002);
-        rootDir_ = "";
-        bitField0_ = (bitField0_ & ~0x00000004);
-        if (tableListBuilder_ == null) {
-          tableList_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000008);
-        } else {
-          tableListBuilder_.clear();
-        }
-        startTs_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000010);
-        completeTs_ = 0L;
-        bitField0_ = (bitField0_ & ~0x00000020);
-        if (ancestorsBuilder_ == null) {
-          ancestors_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000040);
+        if (tableBuilder_ == null) {
+          table_ = org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.getDefaultInstance();
         } else {
-          ancestorsBuilder_.clear();
+          tableBuilder_.clear();
         }
+        bitField0_ = (bitField0_ & ~0x00000001);
+        snapshotName_ = "";
+        bitField0_ = (bitField0_ & ~0x00000002);
         return this;
       }
 
@@ -899,187 +719,78 @@ public final class BackupProtos {
 
       public com.google.protobuf.Descriptors.Descriptor
           getDescriptorForType() {
-        return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.internal_static_hbase_pb_BackupImage_descriptor;
+        return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.internal_static_hbase_pb_SnapshotTableStateData_descriptor;
       }
 
-      public org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage getDefaultInstanceForType() {
-        return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage.getDefaultInstance();
+      public org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData getDefaultInstanceForType() {
+        return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData.getDefaultInstance();
       }
 
-      public org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage build() {
-        org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage result = buildPartial();
+      public org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData build() {
+        org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData result = buildPartial();
         if (!result.isInitialized()) {
           throw newUninitializedMessageException(result);
         }
         return result;
       }
 
-      public org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage buildPartial() {
-        org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage result = new org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage(this);
+      public org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData buildPartial() {
+        org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData result = new org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData(this);
         int from_bitField0_ = bitField0_;
         int to_bitField0_ = 0;
         if (((from_bitField0_ & 0x00000001) == 0x00000001)) {
           to_bitField0_ |= 0x00000001;
         }
-        result.backupId_ = backupId_;
-        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
-          to_bitField0_ |= 0x00000002;
-        }
-        result.backupType_ = backupType_;
-        if (((from_bitField0_ & 0x00000004) == 0x00000004)) {
-          to_bitField0_ |= 0x00000004;
-        }
-        result.rootDir_ = rootDir_;
-        if (tableListBuilder_ == null) {
-          if (((bitField0_ & 0x00000008) == 0x00000008)) {
-            tableList_ = java.util.Collections.unmodifiableList(tableList_);
-            bitField0_ = (bitField0_ & ~0x00000008);
-          }
-          result.tableList_ = tableList_;
+        if (tableBuilder_ == null) {
+          result.table_ = table_;
         } else {
-          result.tableList_ = tableListBuilder_.build();
-        }
-        if (((from_bitField0_ & 0x00000010) == 0x00000010)) {
-          to_bitField0_ |= 0x00000008;
-        }
-        result.startTs_ = startTs_;
-        if (((from_bitField0_ & 0x00000020) == 0x00000020)) {
-          to_bitField0_ |= 0x00000010;
+          result.table_ = tableBuilder_.build();
         }
-        result.completeTs_ = completeTs_;
-        if (ancestorsBuilder_ == null) {
-          if (((bitField0_ & 0x00000040) == 0x00000040)) {
-            ancestors_ = java.util.Collections.unmodifiableList(ancestors_);
-            bitField0_ = (bitField0_ & ~0x00000040);
-          }
-          result.ancestors_ = ancestors_;
-        } else {
-          result.ancestors_ = ancestorsBuilder_.build();
+        if (((from_bitField0_ & 0x00000002) == 0x00000002)) {
+          to_bitField0_ |= 0x00000002;
         }
+        result.snapshotName_ = snapshotName_;
         result.bitField0_ = to_bitField0_;
         onBuilt();
         return result;
       }
 
       public Builder mergeFrom(com.google.protobuf.Message other) {
-        if (other instanceof org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage) {
-          return mergeFrom((org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage)other);
+        if (other instanceof org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData) {
+          return mergeFrom((org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData)other);
         } else {
           super.mergeFrom(other);
           return this;
         }
       }
 
-      public Builder mergeFrom(org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage other) {
-        if (other == org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage.getDefaultInstance()) return this;
-        if (other.hasBackupId()) {
-          bitField0_ |= 0x00000001;
-          backupId_ = other.backupId_;
+      public Builder mergeFrom(org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData other) {
+        if (other == org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData.getDefaultInstance()) return this;
+        if (other.hasTable()) {
+          mergeTable(other.getTable());
+        }
+        if (other.hasSnapshotName()) {
+          bitField0_ |= 0x00000002;
+          snapshotName_ = other.snapshotName_;
           onChanged();
         }
-        if (other.hasBackupType()) {
-          setBackupType(other.getBackupType());
+        this.mergeUnknownFields(other.getUnknownFields());
+        return this;
+      }
+
+      public final boolean isInitialized() {
+        if (!hasTable()) {
+          
+          return false;
         }
-        if (other.hasRootDir()) {
-          bitField0_ |= 0x00000004;
-          rootDir_ = other.rootDir_;
-          onChanged();
+        if (!hasSnapshotName()) {
+          
+          return false;
         }
-        if (tableListBuilder_ == null) {
-          if (!other.tableList_.isEmpty()) {
-            if (tableList_.isEmpty()) {
-              tableList_ = other.tableList_;
-              bitField0_ = (bitField0_ & ~0x00000008);
-            } else {
-              ensureTableListIsMutable();
-              tableList_.addAll(other.tableList_);
-            }
-            onChanged();
-          }
-        } else {
-          if (!other.tableList_.isEmpty()) {
-            if (tableListBuilder_.isEmpty()) {
-              tableListBuilder_.dispose();
-              tableListBuilder_ = null;
-              tableList_ = other.tableList_;
-              bitField0_ = (bitField0_ & ~0x00000008);
-              tableListBuilder_ = 
-                com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
-                   getTableListFieldBuilder() : null;
-            } else {
-              tableListBuilder_.addAllMessages(other.tableList_);
-            }
-          }
-        }
-        if (other.hasStartTs()) {
-          setStartTs(other.getStartTs());
-        }
-        if (other.hasCompleteTs()) {
-          setCompleteTs(other.getCompleteTs());
-        }
-        if (ancestorsBuilder_ == null) {
-          if (!other.ancestors_.isEmpty()) {
-            if (ancestors_.isEmpty()) {
-              ancestors_ = other.ancestors_;
-              bitField0_ = (bitField0_ & ~0x00000040);
-            } else {
-              ensureAncestorsIsMutable();
-              ancestors_.addAll(other.ancestors_);
-            }
-            onChanged();
-          }
-        } else {
-          if (!other.ancestors_.isEmpty()) {
-            if (ancestorsBuilder_.isEmpty()) {
-              ancestorsBuilder_.dispose();
-              ancestorsBuilder_ = null;
-              ancestors_ = other.ancestors_;
-              bitField0_ = (bitField0_ & ~0x00000040);
-              ancestorsBuilder_ = 
-                com.google.protobuf.GeneratedMessage.alwaysUseFieldBuilders ?
-                   getAncestorsFieldBuilder() : null;
-            } else {
-              ancestorsBuilder_.addAllMessages(other.ancestors_);
-            }
-          }
-        }
-        this.mergeUnknownFields(other.getUnknownFields());
-        return this;
-      }
-
-      public final boolean isInitialized() {
-        if (!hasBackupId()) {
-          
-          return false;
-        }
-        if (!hasBackupType()) {
-          
-          return false;
-        }
-        if (!hasRootDir()) {
-          
-          return false;
-        }
-        if (!hasStartTs()) {
-          
-          return false;
-        }
-        if (!hasCompleteTs()) {
+        if (!getTable().isInitialized()) {
           
           return false;
         }
-        for (int i = 0; i < getTableListCount(); i++) {
-          if (!getTableList(i).isInitialized()) {
-            
-            return false;
-          }
-        }
-        for (int i = 0; i < getAncestorsCount(); i++) {
-          if (!getAncestors(i).isInitialized()) {
-            
-            return false;
-          }
-        }
         return true;
       }
 
@@ -1087,11 +798,11 @@ public final class BackupProtos {
           com.google.protobuf.CodedInputStream input,
           com.google.protobuf.ExtensionRegistryLite extensionRegistry)
           throws java.io.IOException {
-        org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage parsedMessage = null;
+        org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData parsedMessage = null;
         try {
           parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
         } catch (com.google.protobuf.InvalidProtocolBufferException e) {
-          parsedMessage = (org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage) e.getUnfinishedMessage();
+          parsedMessage = (org.apache.hadoop.hbase.protobuf.generated.BackupProtos.SnapshotTableStateData) e.getUnfinishedMessage();
           throw e;
         } finally {
           if (parsedMessage != null) {
@@ -1102,436 +813,1650 @@ public final class BackupProtos {
       }
       private int bitField0_;
 
-      // required string backup_id = 1;
-      private java.lang.Object backupId_ = "";
+      // required .hbase.pb.TableName table = 1;
+      private org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName table_ = org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.getDefaultInstance();
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder> tableBuilder_;
       /**
-       * <code>required string backup_id = 1;</code>
+       * <code>required .hbase.pb.TableName table = 1;</code>
        */
-      public boolean hasBackupId() {
+      public boolean hasTable() {
         return ((bitField0_ & 0x00000001) == 0x00000001);
       }
       /**
-       * <code>required string backup_id = 1;</code>
+       * <code>required .hbase.pb.TableName table = 1;</code>
        */
-      public java.lang.String getBackupId() {
-        java.lang.Object ref = backupId_;
-        if (!(ref instanceof java.lang.String)) {
-          java.lang.String s = ((com.google.protobuf.ByteString) ref)
-              .toStringUtf8();
-          backupId_ = s;
-          return s;
+      public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName getTable() {
+        if (tableBuilder_ == null) {
+          return table_;
         } else {
-          return (java.lang.String) ref;
+          return tableBuilder_.getMessage();
         }
       }
       /**
-       * <code>required string backup_id = 1;</code>
+       * <code>required .hbase.pb.TableName table = 1;</code>
        */
-      public com.google.protobuf.ByteString
-          getBackupIdBytes() {
-        java.lang.Object ref = backupId_;
-        if (ref instanceof String) {
-          com.google.protobuf.ByteString b = 
-              com.google.protobuf.ByteString.copyFromUtf8(
-                  (java.lang.String) ref);
-          backupId_ = b;
-          return b;
+      public Builder setTable(org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName value) {
+        if (tableBuilder_ == null) {
+          if (value == null) {
+            throw new NullPointerException();
+          }
+          table_ = value;
+          onChanged();
         } else {
-          return (com.google.protobuf.ByteString) ref;
+          tableBuilder_.setMessage(value);
         }
-      }
-      /**
-       * <code>required string backup_id = 1;</code>
-       */
-      public Builder setBackupId(
-          java.lang.String value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000001;
-        backupId_ = value;
-        onChanged();
+        bitField0_ |= 0x00000001;
         return this;
       }
       /**
-       * <code>required string backup_id = 1;</code>
+       * <code>required .hbase.pb.TableName table = 1;</code>
        */
-      public Builder clearBackupId() {
-        bitField0_ = (bitField0_ & ~0x00000001);
-        backupId_ = getDefaultInstance().getBackupId();
-        onChanged();
+      public Builder setTable(
+          org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder builderForValue) {
+        if (tableBuilder_ == null) {
+          table_ = builderForValue.build();
+          onChanged();
+        } else {
+          tableBuilder_.setMessage(builderForValue.build());
+        }
+        bitField0_ |= 0x00000001;
         return this;
       }
       /**
-       * <code>required string backup_id = 1;</code>
+       * <code>required .hbase.pb.TableName table = 1;</code>
        */
-      public Builder setBackupIdBytes(
-          com.google.protobuf.ByteString value) {
-        if (value == null) {
-    throw new NullPointerException();
-  }
-  bitField0_ |= 0x00000001;
-        backupId_ = value;
-        onChanged();
+      public Builder mergeTable(org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName value) {
+        if (tableBuilder_ == null) {
+          if (((bitField0_ & 0x00000001) == 0x00000001) &&
+              table_ != org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.getDefaultInstance()) {
+            table_ =
+              org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.newBuilder(table_).mergeFrom(value).buildPartial();
+          } else {
+            table_ = value;
+          }
+          onChanged();
+        } else {
+          tableBuilder_.mergeFrom(value);
+        }
+        bitField0_ |= 0x00000001;
         return this;
       }
-
-      // required .hbase.pb.BackupType backup_type = 2;
-      private org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType backupType_ = org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType.FULL;
       /**
-       * <code>required .hbase.pb.BackupType backup_type = 2;</code>
+       * <code>required .hbase.pb.TableName table = 1;</code>
        */
-      public boolean hasBackupType() {
-        return ((bitField0_ & 0x00000002) == 0x00000002);
+      public Builder clearTable() {
+        if (tableBuilder_ == null) {
+          table_ = org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.getDefaultInstance();
+          onChanged();
+        } else {
+          tableBuilder_.clear();
+        }
+        bitField0_ = (bitField0_ & ~0x00000001);
+        return this;
       }
       /**
-       * <code>required .hbase.pb.BackupType backup_type = 2;</code>
+       * <code>required .hbase.pb.TableName table = 1;</code>
        */
-      public org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType getBackupType() {
-        return backupType_;
+      public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder getTableBuilder() {
+        bitField0_ |= 0x00000001;
+        onChanged();
+        return getTableFieldBuilder().getBuilder();
       }
       /**
-       * <code>required .hbase.pb.BackupType backup_type = 2;</code>
+       * <code>required .hbase.pb.TableName table = 1;</code>
        */
-      public Builder setBackupType(org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType value) {
-        if (value == null) {
-          throw new NullPointerException();
+      public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder getTableOrBuilder() {
+        if (tableBuilder_ != null) {
+          return tableBuilder_.getMessageOrBuilder();
+        } else {
+          return table_;
         }
-        bitField0_ |= 0x00000002;
-        backupType_ = value;
-        onChanged();
-        return this;
       }
       /**
-       * <code>required .hbase.pb.BackupType backup_type = 2;</code>
+       * <code>required .hbase.pb.TableName table = 1;</code>
        */
-      public Builder clearBackupType() {
-        bitField0_ = (bitField0_ & ~0x00000002);
-        backupType_ = org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType.FULL;
-        onChanged();
-        return this;
+      private com.google.protobuf.SingleFieldBuilder<
+          org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder> 
+          getTableFieldBuilder() {
+        if (tableBuilder_ == null) {
+          tableBuilder_ = new com.google.protobuf.SingleFieldBuilder<
+              org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder>(
+                  table_,
+                  getParentForChildren(),
+                  isClean());
+          table_ = null;
+        }
+        return tableBuilder_;
       }
 
-      // required string root_dir = 3;
-      private java.lang.Object rootDir_ = "";
+      // required string snapshotName = 2;
+      private java.lang.Object snapshotName_ = "";
       /**
-       * <code>required string root_dir = 3;</code>
+       * <code>required string snapshotName = 2;</code>
        */
-      public boolean hasRootDir() {
-        return ((bitField0_ & 0x00000004) == 0x00000004);
+      public boolean hasSnapshotName() {
+        return ((bitField0_ & 0x00000002) == 0x00000002);
       }
       /**
-       * <code>required string root_dir = 3;</code>
+       * <code>required string snapshotName = 2;</code>
        */
-      public java.lang.String getRootDir() {
-        java.lang.Object ref = rootDir_;
+      public java.lang.String getSnapshotName() {
+        java.lang.Object ref = snapshotName_;
         if (!(ref instanceof java.lang.String)) {
           java.lang.String s = ((com.google.protobuf.ByteString) ref)
               .toStringUtf8();
-          rootDir_ = s;
+          snapshotName_ = s;
           return s;
         } else {
           return (java.lang.String) ref;
         }
       }
       /**
-       * <code>required string root_dir = 3;</code>
+       * <code>required string snapshotName = 2;</code>
        */
       public com.google.protobuf.ByteString
-          getRootDirBytes() {
-        java.lang.Object ref = rootDir_;
+          getSnapshotNameBytes() {
+        java.lang.Object ref = snapshotName_;
         if (ref instanceof String) {
           com.google.protobuf.ByteString b = 
               com.google.protobuf.ByteString.copyFromUtf8(
                   (java.lang.String) ref);
-          rootDir_ = b;
+          snapshotName_ = b;
           return b;
         } else {
           return (com.google.protobuf.ByteString) ref;
         }
       }
       /**
-       * <code>required string root_dir = 3;</code>
+       * <code>required string snapshotName = 2;</code>
        */
-      public Builder setRootDir(
+      public Builder setSnapshotName(
           java.lang.String value) {
         if (value == null) {
     throw new NullPointerException();
   }
-  bitField0_ |= 0x00000004;
-        rootDir_ = value;
+  bitField0_ |= 0x00000002;
+        snapshotName_ = value;
         onChanged();
         return this;
       }
       /**
-       * <code>required string root_dir = 3;</code>
+       * <code>required string snapshotName = 2;</code>
        */
-      public Builder clearRootDir() {
-        bitField0_ = (bitField0_ & ~0x00000004);
-        rootDir_ = getDefaultInstance().getRootDir();
+      public Builder clearSnapshotName() {
+        bitField0_ = (bitField0_ & ~0x00000002);
+        snapshotName_ = getDefaultInstance().getSnapshotName();
         onChanged();
         return this;
       }
       /**
-       * <code>required string root_dir = 3;</code>
+       * <code>required string snapshotName = 2;</code>
        */
-      public Builder setRootDirBytes(
+      public Builder setSnapshotNameBytes(
           com.google.protobuf.ByteString value) {
         if (value == null) {
     throw new NullPointerException();
   }
-  bitField0_ |= 0x00000004;
-        rootDir_ = value;
+  bitField0_ |= 0x00000002;
+        snapshotName_ = value;
         onChanged();
         return this;
       }
 
-      // repeated .hbase.pb.TableName table_list = 4;
-      private java.util.List<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName> tableList_ =
-        java.util.Collections.emptyList();
-      private void ensureTableListIsMutable() {
-        if (!((bitField0_ & 0x00000008) == 0x00000008)) {
-          tableList_ = new java.util.ArrayList<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName>(tableList_);
-          bitField0_ |= 0x00000008;
-         }
-      }
+      // @@protoc_insertion_point(builder_scope:hbase.pb.SnapshotTableStateData)
+    }
 
-      private com.google.protobuf.RepeatedFieldBuilder<
-          org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder> tableListBuilder_;
+    static {
+      defaultInstance = new SnapshotTableStateData(true);
+      defaultInstance.initFields();
+    }
 
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public java.util.List<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName> getTableListList() {
-        if (tableListBuilder_ == null) {
-          return java.util.Collections.unmodifiableList(tableList_);
-        } else {
-          return tableListBuilder_.getMessageList();
-        }
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public int getTableListCount() {
-        if (tableListBuilder_ == null) {
-          return tableList_.size();
-        } else {
-          return tableListBuilder_.getCount();
-        }
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName getTableList(int index) {
-        if (tableListBuilder_ == null) {
-          return tableList_.get(index);
-        } else {
-          return tableListBuilder_.getMessage(index);
-        }
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public Builder setTableList(
-          int index, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName value) {
-        if (tableListBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureTableListIsMutable();
-          tableList_.set(index, value);
-          onChanged();
-        } else {
-          tableListBuilder_.setMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public Builder setTableList(
-          int index, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder builderForValue) {
-        if (tableListBuilder_ == null) {
-          ensureTableListIsMutable();
-          tableList_.set(index, builderForValue.build());
-          onChanged();
-        } else {
-          tableListBuilder_.setMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public Builder addTableList(org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName value) {
-        if (tableListBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureTableListIsMutable();
-          tableList_.add(value);
-          onChanged();
-        } else {
-          tableListBuilder_.addMessage(value);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public Builder addTableList(
-          int index, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName value) {
-        if (tableListBuilder_ == null) {
-          if (value == null) {
-            throw new NullPointerException();
-          }
-          ensureTableListIsMutable();
-          tableList_.add(index, value);
-          onChanged();
-        } else {
-          tableListBuilder_.addMessage(index, value);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public Builder addTableList(
-          org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder builderForValue) {
-        if (tableListBuilder_ == null) {
-          ensureTableListIsMutable();
-          tableList_.add(builderForValue.build());
-          onChanged();
-        } else {
-          tableListBuilder_.addMessage(builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public Builder addTableList(
-          int index, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder builderForValue) {
-        if (tableListBuilder_ == null) {
-          ensureTableListIsMutable();
-          tableList_.add(index, builderForValue.build());
-          onChanged();
-        } else {
-          tableListBuilder_.addMessage(index, builderForValue.build());
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public Builder addAllTableList(
-          java.lang.Iterable<? extends org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName> values) {
-        if (tableListBuilder_ == null) {
-          ensureTableListIsMutable();
-          super.addAll(values, tableList_);
-          onChanged();
-        } else {
-          tableListBuilder_.addAllMessages(values);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public Builder clearTableList() {
-        if (tableListBuilder_ == null) {
-          tableList_ = java.util.Collections.emptyList();
-          bitField0_ = (bitField0_ & ~0x00000008);
-          onChanged();
-        } else {
-          tableListBuilder_.clear();
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public Builder removeTableList(int index) {
-        if (tableListBuilder_ == null) {
-          ensureTableListIsMutable();
-          tableList_.remove(index);
-          onChanged();
-        } else {
-          tableListBuilder_.remove(index);
-        }
-        return this;
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder getTableListBuilder(
-          int index) {
-        return getTableListFieldBuilder().getBuilder(index);
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder getTableListOrBuilder(
-          int index) {
-        if (tableListBuilder_ == null) {
-          return tableList_.get(index);  } else {
-          return tableListBuilder_.getMessageOrBuilder(index);
-        }
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public java.util.List<? extends org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder> 
-           getTableListOrBuilderList() {
-        if (tableListBuilder_ != null) {
-          return tableListBuilder_.getMessageOrBuilderList();
-        } else {
-          return java.util.Collections.unmodifiableList(tableList_);
-        }
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder addTableListBuilder() {
-        return getTableListFieldBuilder().addBuilder(
-            org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.getDefaultInstance());
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder addTableListBuilder(
-          int index) {
-        return getTableListFieldBuilder().addBuilder(
-            index, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.getDefaultInstance());
-      }
-      /**
-       * <code>repeated .hbase.pb.TableName table_list = 4;</code>
-       */
-      public java.util.List<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder> 
-           getTableListBuilderList() {
-        return getTableListFieldBuilder().getBuilderList();
-      }
-      private com.google.protobuf.RepeatedFieldBuilder<
-          org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder> 
-          getTableListFieldBuilder() {
-        if (tableListBuilder_ == null) {
-          tableListBuilder_ = new com.google.protobuf.RepeatedFieldBuilder<
-              org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.Builder, org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder>(
-                  tableList_,
-                  ((bitField0_ & 0x00000008) == 0x00000008),
-                  getParentForChildren(),
-                  isClean());
-          tableList_ = null;
-        }
-        return tableListBuilder_;
-      }
+    // @@protoc_insertion_point(class_scope:hbase.pb.SnapshotTableStateData)
+  }
 
-      // required uint64 start_ts = 5;
-      private long startTs_ ;
-      /**
-       * <code>required uint64 start_ts = 5;</code>
-       */
-      public boolean hasStartTs() {
+  public interface BackupImageOrBuilder
+      extends com.google.protobuf.MessageOrBuilder {
+
+    // required string backup_id = 1;
+    /**
+     * <code>required string backup_id = 1;</code>
+     */
+    boolean hasBackupId();
+    /**
+     * <code>required string backup_id = 1;</code>
+     */
+    java.lang.String getBackupId();
+    /**
+     * <code>required string backup_id = 1;</code>
+     */
+    com.google.protobuf.ByteString
+        getBackupIdBytes();
+
+    // required .hbase.pb.BackupType backup_type = 2;
+    /**
+     * <code>required .hbase.pb.BackupType backup_type = 2;</code>
+     */
+    boolean hasBackupType();
+    /**
+     * <code>required .hbase.pb.BackupType backup_type = 2;</code>
+     */
+    org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType getBackupType();
+
+    // required string root_dir = 3;
+    /**
+     * <code>required string root_dir = 3;</code>
+     */
+    boolean hasRootDir();
+    /**
+     * <code>required string root_dir = 3;</code>
+     */
+    java.lang.String getRootDir();
+    /**
+     * <code>required string root_dir = 3;</code>
+     */
+    com.google.protobuf.ByteString
+        getRootDirBytes();
+
+    // repeated .hbase.pb.TableName table_list = 4;
+    /**
+     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
+     */
+    java.util.List<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName> 
+        getTableListList();
+    /**
+     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
+     */
+    org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName getTableList(int index);
+    /**
+     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
+     */
+    int getTableListCount();
+    /**
+     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
+     */
+    java.util.List<? extends org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder> 
+        getTableListOrBuilderList();
+    /**
+     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
+     */
+    org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder getTableListOrBuilder(
+        int index);
+
+    // required uint64 start_ts = 5;
+    /**
+     * <code>required uint64 start_ts = 5;</code>
+     */
+    boolean hasStartTs();
+    /**
+     * <code>required uint64 start_ts = 5;</code>
+     */
+    long getStartTs();
+
+    // required uint64 complete_ts = 6;
+    /**
+     * <code>required uint64 complete_ts = 6;</code>
+     */
+    boolean hasCompleteTs();
+    /**
+     * <code>required uint64 complete_ts = 6;</code>
+     */
+    long getCompleteTs();
+
+    // repeated .hbase.pb.BackupImage ancestors = 7;
+    /**
+     * <code>repeated .hbase.pb.BackupImage ancestors = 7;</code>
+     */
+    java.util.List<org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage> 
+        getAncestorsList();
+    /**
+     * <code>repeated .hbase.pb.BackupImage ancestors = 7;</code>
+     */
+    org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage getAncestors(int index);
+    /**
+     * <code>repeated .hbase.pb.BackupImage ancestors = 7;</code>
+     */
+    int getAncestorsCount();
+    /**
+     * <code>repeated .hbase.pb.BackupImage ancestors = 7;</code>
+     */
+    java.util.List<? extends org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImageOrBuilder> 
+        getAncestorsOrBuilderList();
+    /**
+     * <code>repeated .hbase.pb.BackupImage ancestors = 7;</code>
+     */
+    org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImageOrBuilder getAncestorsOrBuilder(
+        int index);
+  }
+  /**
+   * Protobuf type {@code hbase.pb.BackupImage}
+   */
+  public static final class BackupImage extends
+      com.google.protobuf.GeneratedMessage
+      implements BackupImageOrBuilder {
+    // Use BackupImage.newBuilder() to construct.
+    private BackupImage(com.google.protobuf.GeneratedMessage.Builder<?> builder) {
+      super(builder);
+      this.unknownFields = builder.getUnknownFields();
+    }
+    private BackupImage(boolean noInit) { this.unknownFields = com.google.protobuf.UnknownFieldSet.getDefaultInstance(); }
+
+    private static final BackupImage defaultInstance;
+    public static BackupImage getDefaultInstance() {
+      return defaultInstance;
+    }
+
+    public BackupImage getDefaultInstanceForType() {
+      return defaultInstance;
+    }
+
+    private final com.google.protobuf.UnknownFieldSet unknownFields;
+    @java.lang.Override
+    public final com.google.protobuf.UnknownFieldSet
+        getUnknownFields() {
+      return this.unknownFields;
+    }
+    private BackupImage(
+        com.google.protobuf.CodedInputStream input,
+        com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+        throws com.google.protobuf.InvalidProtocolBufferException {
+      initFields();
+      int mutable_bitField0_ = 0;
+      com.google.protobuf.UnknownFieldSet.Builder unknownFields =
+          com.google.protobuf.UnknownFieldSet.newBuilder();
+      try {
+        boolean done = false;
+        while (!done) {
+          int tag = input.readTag();
+          switch (tag) {
+            case 0:
+              done = true;
+              break;
+            default: {
+              if (!parseUnknownField(input, unknownFields,
+                                     extensionRegistry, tag)) {
+                done = true;
+              }
+              break;
+            }
+            case 10: {
+              bitField0_ |= 0x00000001;
+              backupId_ = input.readBytes();
+              break;
+            }
+            case 16: {
+              int rawValue = input.readEnum();
+              org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType value = org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType.valueOf(rawValue);
+              if (value == null) {
+                unknownFields.mergeVarintField(2, rawValue);
+              } else {
+                bitField0_ |= 0x00000002;
+                backupType_ = value;
+              }
+              break;
+            }
+            case 26: {
+              bitField0_ |= 0x00000004;
+              rootDir_ = input.readBytes();
+              break;
+            }
+            case 34: {
+              if (!((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
+                tableList_ = new java.util.ArrayList<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName>();
+                mutable_bitField0_ |= 0x00000008;
+              }
+              tableList_.add(input.readMessage(org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName.PARSER, extensionRegistry));
+              break;
+            }
+            case 40: {
+              bitField0_ |= 0x00000008;
+              startTs_ = input.readUInt64();
+              break;
+            }
+            case 48: {
+              bitField0_ |= 0x00000010;
+              completeTs_ = input.readUInt64();
+              break;
+            }
+            case 58: {
+              if (!((mutable_bitField0_ & 0x00000040) == 0x00000040)) {
+                ancestors_ = new java.util.ArrayList<org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage>();
+                mutable_bitField0_ |= 0x00000040;
+              }
+              ancestors_.add(input.readMessage(org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage.PARSER, extensionRegistry));
+              break;
+            }
+          }
+        }
+      } catch (com.google.protobuf.InvalidProtocolBufferException e) {
+        throw e.setUnfinishedMessage(this);
+      } catch (java.io.IOException e) {
+        throw new com.google.protobuf.InvalidProtocolBufferException(
+            e.getMessage()).setUnfinishedMessage(this);
+      } finally {
+        if (((mutable_bitField0_ & 0x00000008) == 0x00000008)) {
+          tableList_ = java.util.Collections.unmodifiableList(tableList_);
+        }
+        if (((mutable_bitField0_ & 0x00000040) == 0x00000040)) {
+          ancestors_ = java.util.Collections.unmodifiableList(ancestors_);
+        }
+        this.unknownFields = unknownFields.build();
+        makeExtensionsImmutable();
+      }
+    }
+    public static final com.google.protobuf.Descriptors.Descriptor
+        getDescriptor() {
+      return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.internal_static_hbase_pb_BackupImage_descriptor;
+    }
+
+    protected com.google.protobuf.GeneratedMessage.FieldAccessorTable
+        internalGetFieldAccessorTable() {
+      return org.apache.hadoop.hbase.protobuf.generated.BackupProtos.internal_static_hbase_pb_BackupImage_fieldAccessorTable
+          .ensureFieldAccessorsInitialized(
+              org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage.class, org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupImage.Builder.class);
+    }
+
+    public static com.google.protobuf.Parser<BackupImage> PARSER =
+        new com.google.protobuf.AbstractParser<BackupImage>() {
+      public BackupImage parsePartialFrom(
+          com.google.protobuf.CodedInputStream input,
+          com.google.protobuf.ExtensionRegistryLite extensionRegistry)
+          throws com.google.protobuf.InvalidProtocolBufferException {
+        return new BackupImage(input, extensionRegistry);
+      }
+    };
+
+    @java.lang.Override
+    public com.google.protobuf.Parser<BackupImage> getParserForType() {
+      return PARSER;
+    }
+
+    private int bitField0_;
+    // required string backup_id = 1;
+    public static final int BACKUP_ID_FIELD_NUMBER = 1;
+    private java.lang.Object backupId_;
+    /**
+     * <code>required string backup_id = 1;</code>
+     */
+    public boolean hasBackupId() {
+      return ((bitField0_ & 0x00000001) == 0x00000001);
+    }
+    /**
+     * <code>required string backup_id = 1;</code>
+     */
+    public java.lang.String getBackupId() {
+      java.lang.Object ref = backupId_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          backupId_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>required string backup_id = 1;</code>
+     */
+    public com.google.protobuf.ByteString
+        getBackupIdBytes() {
+      java.lang.Object ref = backupId_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        backupId_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    // required .hbase.pb.BackupType backup_type = 2;
+    public static final int BACKUP_TYPE_FIELD_NUMBER = 2;
+    private org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType backupType_;
+    /**
+     * <code>required .hbase.pb.BackupType backup_type = 2;</code>
+     */
+    public boolean hasBackupType() {
+      return ((bitField0_ & 0x00000002) == 0x00000002);
+    }
+    /**
+     * <code>required .hbase.pb.BackupType backup_type = 2;</code>
+     */
+    public org.apache.hadoop.hbase.protobuf.generated.BackupProtos.BackupType getBackupType() {
+      return backupType_;
+    }
+
+    // required string root_dir = 3;
+    public static final int ROOT_DIR_FIELD_NUMBER = 3;
+    private java.lang.Object rootDir_;
+    /**
+     * <code>required string root_dir = 3;</code>
+     */
+    public boolean hasRootDir() {
+      return ((bitField0_ & 0x00000004) == 0x00000004);
+    }
+    /**
+     * <code>required string root_dir = 3;</code>
+     */
+    public java.lang.String getRootDir() {
+      java.lang.Object ref = rootDir_;
+      if (ref instanceof java.lang.String) {
+        return (java.lang.String) ref;
+      } else {
+        com.google.protobuf.ByteString bs = 
+            (com.google.protobuf.ByteString) ref;
+        java.lang.String s = bs.toStringUtf8();
+        if (bs.isValidUtf8()) {
+          rootDir_ = s;
+        }
+        return s;
+      }
+    }
+    /**
+     * <code>required string root_dir = 3;</code>
+     */
+    public com.google.protobuf.ByteString
+        getRootDirBytes() {
+      java.lang.Object ref = rootDir_;
+      if (ref instanceof java.lang.String) {
+        com.google.protobuf.ByteString b = 
+            com.google.protobuf.ByteString.copyFromUtf8(
+                (java.lang.String) ref);
+        rootDir_ = b;
+        return b;
+      } else {
+        return (com.google.protobuf.ByteString) ref;
+      }
+    }
+
+    // repeated .hbase.pb.TableName table_list = 4;
+    public static final int TABLE_LIST_FIELD_NUMBER = 4;
+    private java.util.List<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName> tableList_;
+    /**
+     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
+     */
+    public java.util.List<org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName> getTableListList() {
+      return tableList_;
+    }
+    /**
+     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
+     */
+    public java.util.List<? extends org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableNameOrBuilder> 
+        getTableListOrBuilderList() {
+      return tableList_;
+    }
+    /**
+     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
+     */
+    public int getTableListCount() {
+      return tableList_.size();
+    }
+    /**
+     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
+     */
+    public org.apache.hadoop.hbase.protobuf.generated.HBaseProtos.TableName getTableList(int index) {
+      return tableList_.get(index);
+    }
+    /**
+     * <code>repeated .hbase.pb.TableName table_list = 4;</code>
+     */


<TRUNCATED>