From b05a34fec6ed8411daa998d127d1105851b4f81d Mon Sep 17 00:00:00 2001 From: Vladimir Rodionov Date: Tue, 19 Feb 2019 16:18:33 -0800 Subject: [PATCH] HBASE-21936: Disable split/merge of a table during snapshot --- .../org/apache/hadoop/hbase/client/Admin.java | 11 ++- .../hadoop/hbase/client/HBaseAdmin.java | 83 ++++++++++++++----- 2 files changed, 70 insertions(+), 24 deletions(-) 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 deaea8c29c..bf1aed2646 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 @@ -1882,6 +1882,8 @@ public interface Admin extends Abortable, Closeable { * org.apache.hadoop.hbase.snapshot.SnapshotCreationException} indicating the duplicate naming. * Snapshot names follow the same naming constraints as tables in HBase. See {@link * org.apache.hadoop.hbase.TableName#isLegalFullyQualifiedTableName(byte[])}. + * The system disables merges and splits for a table during the operation, when operation is + * complete the merge/split settings are restored. * * @param snapshotName name of the snapshot to be created * @param tableName name of the table for which snapshot is created @@ -1897,7 +1899,8 @@ public interface Admin extends Abortable, Closeable { * based on the name of the snapshot. Attempts to take a snapshot with the same name (even * different type or with different parameters) will fail with a {@link SnapshotCreationException} * indicating the duplicate naming. Snapshot names follow the same naming constraints as tables in - * HBase. + * HBase. The system disables merges and splits for a table during the operation, when operation is + * complete the merge/split settings are restored. * * @param snapshotName name of the snapshot to be created * @param tableName name of the table for which snapshot is created @@ -1914,7 +1917,8 @@ public interface Admin extends Abortable, Closeable { * different parameters) will fail with a {@link SnapshotCreationException} indicating the * duplicate naming. Snapshot names follow the same naming constraints as tables in HBase. See * {@link org.apache.hadoop.hbase.TableName#isLegalFullyQualifiedTableName(byte[])}. - * + * The system disables merges and splits for a table during the operation, when operation is + * complete the merge/split settings are restored. * @param snapshotName name to give the snapshot on the filesystem. Must be unique from all other * snapshots stored on the cluster * @param tableName name of the table to snapshot @@ -1940,7 +1944,8 @@ public interface Admin extends Abortable, Closeable { * use {@link #snapshot(String, org.apache.hadoop.hbase.TableName)} or * {@link #snapshot(byte[], org.apache.hadoop.hbase.TableName)} unless you are sure about the type * of snapshot that you want to take. - * + * The system disables merges and splits for a table during the operation, when operation is + * complete the merge/split settings are restored. * @param snapshot snapshot to take * @throws IOException or we lose contact with the master. * @throws SnapshotCreationException if snapshot failed to be taken 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 769ddd7962..739821eb73 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 @@ -2586,6 +2586,7 @@ public class HBaseAdmin implements Admin { snapshot(new SnapshotDescription(snapshotName, tableName, type)); } + @SuppressWarnings("deprecation") @Override public void snapshot(SnapshotDescription snapshotDesc) throws IOException, SnapshotCreationException, IllegalArgumentException { @@ -2603,30 +2604,70 @@ public class HBaseAdmin implements Admin { 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.getDone())) { - try { - // sleep a backoff <= pauseTime amount - long sleep = getPauseTime(tries++); - 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); + + boolean splitSet = false; + boolean mergeSet = false; + HTableDescriptor desc = (HTableDescriptor)getDescriptor(snapshotDesc.getTableName()); + + try { + + if (desc.isSplitEnabled()) { + desc.setSplitEnabled(false); + LOG.debug("Disabling splits for table {}", desc.getTableName()); + splitSet = true; } - LOG.debug("Getting current status of snapshot from master..."); - done = executeCallable(new MasterCallable(getConnection(), - getRpcControllerFactory()) { - @Override - protected IsSnapshotDoneResponse rpcCall() throws Exception { - return master.isSnapshotDone(getRpcController(), request); + if (desc.isMergeEnabled()) { + desc.setMergeEnabled(false); + LOG.debug("Disabling merges for table {}", desc.getTableName()); + mergeSet = true; + } + if ( splitSet || mergeSet ) { + modifyTable(desc); + LOG.debug("Modification for table {} is complete" , desc.getTableName()); + + } + + while (tries == 0 + || ((EnvironmentEdgeManager.currentTime() - start) < max && !done.getDone())) { + try { + // sleep a backoff <= pauseTime amount + long sleep = getPauseTime(tries++); + 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); } - }); - } - if (!done.getDone()) { - throw new SnapshotCreationException("Snapshot '" + snapshot.getName() + LOG.debug("Getting current status of snapshot from master..."); + done = executeCallable(new MasterCallable(getConnection(), + getRpcControllerFactory()) { + @Override + protected IsSnapshotDoneResponse rpcCall() throws Exception { + return master.isSnapshotDone(getRpcController(), request); + } + }); + } + if (!done.getDone()) { + throw new SnapshotCreationException("Snapshot '" + snapshot.getName() + "' wasn't completed in expectedTime:" + max + " ms", snapshotDesc); + } + } finally { + boolean modify = splitSet || mergeSet; + + if (splitSet) { + desc.setSplitEnabled(true); + LOG.debug("Enabling splits for table {}", desc.getTableName()); + + } + if (mergeSet) { + desc.setMergeEnabled(true); + LOG.debug("Enabling merges for table {}", desc.getTableName()); + } + if (modify) { + modifyTable(desc); + LOG.debug("Restored split/merge settings for table {}" , desc.getTableName()); + } } } -- 2.17.2 (Apple Git-113)