diff --git hbase-client/src/main/java/org/apache/hadoop/hbase/backup/BackupRequest.java hbase-client/src/main/java/org/apache/hadoop/hbase/backup/BackupRequest.java index bbf421c..8832223 100644 --- hbase-client/src/main/java/org/apache/hadoop/hbase/backup/BackupRequest.java +++ hbase-client/src/main/java/org/apache/hadoop/hbase/backup/BackupRequest.java @@ -36,6 +36,7 @@ public final class BackupRequest { private String targetRootDir; private int workers = -1; private long bandwidth = -1L; + private boolean safeMode = true; public BackupRequest() { } @@ -79,4 +80,12 @@ public final class BackupRequest { public long getBandwidth() { return this.bandwidth; } + + public boolean isSafeMode() { + return safeMode; + } + + public void setSafeMode(boolean safeMode) { + this.safeMode = safeMode; + } } diff --git hbase-client/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupCommands.java hbase-client/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupCommands.java index 8a4d48a..49ea761 100644 --- hbase-client/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupCommands.java +++ hbase-client/src/main/java/org/apache/hadoop/hbase/backup/impl/BackupCommands.java @@ -192,6 +192,7 @@ public final class BackupCommands { } int bandwidth = cmdline.hasOption('b') ? Integer.parseInt(cmdline.getOptionValue('b')) : -1; int workers = cmdline.hasOption('w') ? Integer.parseInt(cmdline.getOptionValue('w')) : -1; + boolean safeMode = cmdline.hasOption("unsafe")? false: true; try (Connection conn = ConnectionFactory.createConnection(getConf()); Admin admin = conn.getAdmin(); @@ -199,7 +200,7 @@ public final class BackupCommands { BackupRequest request = new BackupRequest(); request.setBackupType(BackupType.valueOf(args[1].toUpperCase())) .setTableList(tables != null?Lists.newArrayList(BackupClientUtil.parseTableNames(tables)): null) - .setTargetRootDir(args[2]).setWorkers(workers).setBandwidth(bandwidth); + .setTargetRootDir(args[2]).setWorkers(workers).setBandwidth(bandwidth).setSafeMode(safeMode); String backupId = backupAdmin.backupTables(request); System.out.println("Backup session "+ backupId+" finished. Status: SUCCESS"); } catch (IOException e) { diff --git hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java index 8ba26ba..51f8f8d 100644 --- hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java +++ hbase-client/src/main/java/org/apache/hadoop/hbase/client/HBaseAdmin.java @@ -62,6 +62,7 @@ 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.BackupType; import org.apache.hadoop.hbase.backup.util.BackupClientUtil; import org.apache.hadoop.hbase.classification.InterfaceAudience; import org.apache.hadoop.hbase.classification.InterfaceStability; @@ -1588,11 +1589,42 @@ public class HBaseAdmin implements Admin { return new TableBackupFuture(this, TableName.BACKUP_TABLE_NAME, response); } - String backupTables(final BackupRequest userRequest) throws IOException { - return get( - backupTablesAsync(userRequest), - backupWaitTimeout, - TimeUnit.SECONDS); + String backupTables(final BackupRequest userRequest) throws IOException { + boolean[] currentSettings = null; + boolean balancer = false; + String backupId = null; + + boolean isFullBackup = userRequest.getBackupType() == BackupType.FULL; + if (isFullBackup && userRequest.isSafeMode()) { + currentSettings = setSplitOrMergeEnabled(false, true, MasterSwitchType.SPLIT, + MasterSwitchType.MERGE); + LOG.debug("Table splits and merges was disabled"); + + balancer = isBalancerEnabled(); + if (balancer) { + setBalancerRunning(false, true); + LOG.debug("Auto-balancing was turned off"); + } + } + try{ + backupId = get( + backupTablesAsync(userRequest), + backupWaitTimeout, + TimeUnit.SECONDS); + } finally { + if (isFullBackup && userRequest.isSafeMode()) { + LOG.debug("Set SPLIT_ENABLED to "+ currentSettings[0]); + setSplitOrMergeEnabled(currentSettings[0], true, MasterSwitchType.SPLIT); + LOG.debug("Set MERGE_ENABLED to "+ currentSettings[1]); + setSplitOrMergeEnabled(currentSettings[1], true, MasterSwitchType.MERGE); + LOG.debug("Table splits and merges was restored"); + if (balancer) { + setBalancerRunning(true, true); + LOG.debug("Auto-balancing was enabled"); + } + } + } + return backupId; } public static class TableBackupFuture extends TableFuture { diff --git hbase-server/src/main/java/org/apache/hadoop/hbase/backup/BackupDriver.java hbase-server/src/main/java/org/apache/hadoop/hbase/backup/BackupDriver.java index 8eb2ff8..163d33b 100644 --- hbase-server/src/main/java/org/apache/hadoop/hbase/backup/BackupDriver.java +++ hbase-server/src/main/java/org/apache/hadoop/hbase/backup/BackupDriver.java @@ -57,6 +57,8 @@ public class BackupDriver extends AbstractHBaseTool { addOptWithArg("n", "History length"); addOptWithArg("set", "Backup set name"); addOptWithArg("path", "Backup destination root directory path"); + addOptNoArg("unsafe", + "Region splits, merges and region balancer are not disabled during full backup"); // disable irrelevant loggers to avoid it mess up command output diff --git hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestFullBackup.java hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestFullBackup.java index e9aa478..0576be5 100644 --- hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestFullBackup.java +++ hbase-server/src/test/java/org/apache/hadoop/hbase/backup/TestFullBackup.java @@ -19,20 +19,16 @@ package org.apache.hadoop.hbase.backup; import static org.junit.Assert.assertTrue; -import java.util.ArrayList; import java.util.List; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.apache.hadoop.hbase.TableName; import org.apache.hadoop.hbase.backup.impl.BackupSystemTable; import org.apache.hadoop.hbase.testclassification.LargeTests; import org.apache.hadoop.util.ToolRunner; import org.junit.Test; import org.junit.experimental.categories.Category; -import com.google.common.collect.Lists; - @Category(LargeTests.class) public class TestFullBackup extends TestBackupBase { @@ -60,6 +56,28 @@ public class TestFullBackup extends TestBackupBase { } @Test + public void testFullBackupMultipleCommandUnsafe() throws Exception { + LOG.info("test full backup on a multiple tables with data (unsafe): command-line"); + try(BackupSystemTable table = new BackupSystemTable(TEST_UTIL.getConnection())) { + int before = table.getBackupHistory().size(); + String[] args = new String[]{"create", "full", BACKUP_ROOT_DIR, + table1.getNameAsString() +","+ table2.getNameAsString(), "-unsafe" }; + // Run backup + int ret = ToolRunner.run(conf1, new BackupDriver(), args); + assertTrue(ret == 0); + List backups = table.getBackupHistory(); + int after = table.getBackupHistory().size(); + assertTrue(after == before +1); + for(BackupInfo data : backups){ + String backupId = data.getBackupId(); + assertTrue(checkSucceeded(backupId)); + } + } + LOG.info("backup (unsafe) complete"); + } + + + @Test public void testFullBackupAllCommand() throws Exception { LOG.info("create full backup image on all tables: command-line"); try(BackupSystemTable table = new BackupSystemTable(TEST_UTIL.getConnection())) {