You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by gi...@apache.org on 2026/06/25 00:07:57 UTC
(hbase-site) branch asf-site updated: Published site at e309dec11f1f984fa2978037e2c200e11c70a3c3.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/hbase-site.git
The following commit(s) were added to refs/heads/asf-site by this push:
new d29036a4102 Published site at e309dec11f1f984fa2978037e2c200e11c70a3c3.
d29036a4102 is described below
commit d29036a41023dbf76565ff746a0936603c430e34
Author: HBase <de...@hbase.apache.org>
AuthorDate: Thu Jun 25 00:03:46 2026 +0000
Published site at e309dec11f1f984fa2978037e2c200e11c70a3c3.
---
apidocs/index-all.html | 36 +-
apidocs/member-search-index.js | 2 +-
.../replication/ReplicationEndpoint.Context.html | 9 +-
.../ReplicationEndpoint.ReplicateContext.html | 9 +-
.../hbase/replication/ReplicationEndpoint.html | 9 +-
.../hbase/snapshot/SnapshotInfo.SnapshotStats.html | 1461 +++---
.../apache/hadoop/hbase/snapshot/SnapshotInfo.html | 1461 +++---
books/apache-hbase-reference-guide-dark-mode.pdf | Bin 38919224 -> 38919228 bytes
books/apache-hbase-reference-guide.pdf | Bin 38809487 -> 38809487 bytes
checkstyle-aggregate.html | 16 +-
dependency-convergence.html | 2 +-
dependency-info.html | 2 +-
dependency-management.html | 2 +-
devapidocs/constant-values.html | 29 +
devapidocs/index-all.html | 36 +
devapidocs/member-search-index.js | 2 +-
.../hbase/replication/BaseReplicationEndpoint.html | 2 +-
.../replication/HBaseReplicationEndpoint.html | 2 +-
.../hbase/replication/ReplicationEndpoint.html | 76 +-
.../VerifyWALEntriesReplicationEndpoint.html | 2 +-
.../HBaseInterClusterReplicationEndpoint.html | 2 +-
.../regionserver/RecoveredReplicationSource.html | 2 +-
.../RecoveredReplicationSourceShipper.html | 2 +-
.../regionserver/ReplicationSource.html | 75 +-
.../regionserver/ReplicationSourceShipper.html | 281 +-
.../class-use/ReplicationSourceShipper.html | 8 +-
.../regionserver/class-use/WALEntryBatch.html | 9 +-
.../visibility/VisibilityReplicationEndpoint.html | 3 +
.../hbase/snapshot/SnapshotInfo.Options.html | 18 +-
.../SnapshotInfo.SnapshotStats.FileInfo.html | 20 +-
.../hbase/snapshot/SnapshotInfo.SnapshotStats.html | 78 +-
.../apache/hadoop/hbase/snapshot/SnapshotInfo.html | 121 +-
.../apache/hadoop/hbase/wal/class-use/WALEdit.html | 2 +-
.../replication/ReplicationEndpoint.Context.html | 9 +-
.../ReplicationEndpoint.ReplicateContext.html | 9 +-
.../hbase/replication/ReplicationEndpoint.html | 9 +-
.../regionserver/ReplicationSource.html | 14 +-
.../ReplicationSourceShipper.WorkerState.html | 671 +--
.../regionserver/ReplicationSourceShipper.html | 671 +--
.../hbase/snapshot/SnapshotInfo.Options.html | 1461 +++---
.../SnapshotInfo.SnapshotStats.FileInfo.html | 1461 +++---
.../hbase/snapshot/SnapshotInfo.SnapshotStats.html | 1461 +++---
.../apache/hadoop/hbase/snapshot/SnapshotInfo.html | 1461 +++---
hbase-website/dependency-convergence.html | 2 +-
hbase-website/dependency-info.html | 2 +-
hbase-website/dependency-management.html | 2 +-
hbase-website/index.html | 2 +-
hbase-website/issue-management.html | 2 +-
hbase-website/licenses.html | 2 +-
hbase-website/mailing-lists.html | 2 +-
hbase-website/plugin-management.html | 2 +-
hbase-website/plugins.html | 2 +-
hbase-website/project-info.html | 2 +-
hbase-website/scm.html | 2 +-
hbase-website/summary.html | 2 +-
hbase-website/team.html | 2 +-
issue-management.html | 2 +-
licenses.html | 2 +-
mailing-lists.html | 2 +-
plugin-management.html | 2 +-
plugins.html | 2 +-
project-info.html | 2 +-
project-reports.html | 2 +-
scm.html | 2 +-
summary.html | 2 +-
team.html | 2 +-
testapidocs/allclasses-index.html | 5089 +++++++++----------
testapidocs/index-all.html | 53 +-
testapidocs/member-search-index.js | 2 +-
.../class-use/HBaseParameterizedTestTemplate.html | 84 +-
.../hadoop/hbase/class-use/HBaseTestingUtil.html | 19 +-
...lientAfterSplittingRegionWithLinksTestBase.html | 90 +
.../class-use/CloneSnapshotFromClientTestBase.html | 26 +-
...hotFromClientAfterSplittingRegionWithLinks.html | 62 +
...hotFromClientAfterSplittingRegionWithLinks.html | 62 +
.../hadoop/hbase/client/package-summary.html | 815 ++--
.../apache/hadoop/hbase/client/package-tree.html | 6 +
.../apache/hadoop/hbase/client/package-use.html | 137 +-
testapidocs/overview-tree.html | 6 +
...shotFromClientAfterSplittingRegionTestBase.html | 214 +-
...lientAfterSplittingRegionWithLinksTestBase.html | 298 ++
.../client/CloneSnapshotFromClientTestBase.html | 135 +-
.../hbase/client/TestClientScannerTimeouts.html | 848 ++--
...hotFromClientAfterSplittingRegionWithLinks.html | 119 +
...hotFromClientAfterSplittingRegionWithLinks.html | 148 +
...oadReplication.BulkReplicationTestObserver.html | 648 +--
.../hbase/replication/TestBulkLoadReplication.html | 648 +--
testapidocs/type-search-index.js | 2 +-
testdevapidocs/allclasses-index.html | 5099 ++++++++++----------
testdevapidocs/constant-values.html | 17 +
testdevapidocs/index-all.html | 345 +-
testdevapidocs/member-search-index.js | 2 +-
.../class-use/HBaseParameterizedTestTemplate.html | 84 +-
.../hadoop/hbase/class-use/HBaseTestingUtil.html | 25 +-
...shotFromClientAfterSplittingRegionTestBase.html | 6 +-
...lientAfterSplittingRegionWithLinksTestBase.html | 446 ++
...hotFromClientCloneLinksAfterDeleteTestBase.html | 2 +-
.../CloneSnapshotFromClientErrorTestBase.html | 2 +-
.../CloneSnapshotFromClientNormalTestBase.html | 2 +-
.../client/CloneSnapshotFromClientTestBase.html | 69 +-
...annerTimeouts.RSRpcServicesWithScanTimeout.html | 69 +-
...cannerTimeouts.RegionServerWithScanTimeout.html | 6 +-
.../hbase/client/TestClientScannerTimeouts.html | 80 +-
...loneSnapshotFromClientAfterSplittingRegion.html | 2 +-
...otFromClientAfterSplittingRegionWithLinks.html} | 30 +-
...oneSnapshotFromClientCloneLinksAfterDelete.html | 2 +-
.../TestCloneSnapshotFromClientCustomSFT.html | 2 +-
.../client/TestCloneSnapshotFromClientError.html | 2 +-
.../client/TestCloneSnapshotFromClientNormal.html | 2 +-
...loneSnapshotFromClientAfterSplittingRegion.html | 2 +-
...otFromClientAfterSplittingRegionWithLinks.html} | 75 +-
...oneSnapshotFromClientCloneLinksAfterDelete.html | 2 +-
.../TestMobCloneSnapshotFromClientError.html | 2 +-
.../TestMobCloneSnapshotFromClientNormal.html | 2 +-
...lientAfterSplittingRegionWithLinksTestBase.html | 90 +
.../class-use/CloneSnapshotFromClientTestBase.html | 26 +-
...hotFromClientAfterSplittingRegionWithLinks.html | 62 +
...hotFromClientAfterSplittingRegionWithLinks.html | 62 +
.../hadoop/hbase/client/package-summary.html | 891 ++--
.../apache/hadoop/hbase/client/package-tree.html | 6 +
.../apache/hadoop/hbase/client/package-use.html | 161 +-
.../replication/DummyReplicationEndpoint.html | 2 +-
...ase.InterClusterReplicationEndpointForTest.html | 2 +-
...ndpointTestBase.ReplicationEndpointForTest.html | 2 +-
...TestBase.ReplicationEndpointReturningFalse.html | 2 +-
...Base.ReplicationEndpointWithWALEntryFilter.html | 2 +-
...estBase.SleepingReplicationEndpointForTest.html | 2 +-
...plicationTestBase.LocalReplicationEndpoint.html | 2 +-
...oadReplication.BulkReplicationTestObserver.html | 10 +-
.../hbase/replication/TestBulkLoadReplication.html | 103 +-
...tionEndpoint.DummyHBaseReplicationEndpoint.html | 2 +-
...TestNamespaceReplicationWithBulkLoadedData.html | 4 +-
...cationEndpoint.NonHBaseReplicationEndpoint.html | 3 +
...ionBaseNoBeforeAll.ReplicationEndpointTest.html | 2 +-
...fyCellsReplicationEndpoint.EndpointForTest.html | 2 +-
...ReplicationSource.LocalReplicationEndpoint.html | 2 +-
...stReplicationSource.BadReplicationEndpoint.html | 2 +-
...icationSource.DoNothingReplicationEndpoint.html | 2 +-
...eplicationSource.FaultyReplicationEndpoint.html | 2 +-
...ReplicationSource.FlakyReplicationEndpoint.html | 2 +-
...onSourceManager.ReplicationEndpointForTest.html | 2 +-
.../TestReplicationSourceShipperRestart.html | 419 ++
...FailureInjectingReplicationEndpointForTest.html | 2 +-
.../TestReplicator.ReplicationEndpointForTest.html | 2 +-
...TestSerialReplicationEndpoint.TestEndpoint.html | 2 +-
.../TestReplicationSourceShipperRestart.html | 62 +
.../replication/regionserver/package-summary.html | 62 +-
.../replication/regionserver/package-tree.html | 1 +
...ation.VisibilityReplicationEndPointForTest.html | 3 +
testdevapidocs/overview-tree.html | 7 +
...shotFromClientAfterSplittingRegionTestBase.html | 214 +-
...lientAfterSplittingRegionWithLinksTestBase.html | 298 ++
.../client/CloneSnapshotFromClientTestBase.html | 135 +-
...annerTimeouts.RSRpcServicesWithScanTimeout.html | 848 ++--
...cannerTimeouts.RegionServerWithScanTimeout.html | 848 ++--
.../hbase/client/TestClientScannerTimeouts.html | 848 ++--
...hotFromClientAfterSplittingRegionWithLinks.html | 119 +
...hotFromClientAfterSplittingRegionWithLinks.html | 148 +
...oadReplication.BulkReplicationTestObserver.html | 648 +--
.../hbase/replication/TestBulkLoadReplication.html | 648 +--
.../TestReplicationSourceShipperRestart.html | 405 ++
testdevapidocs/type-search-index.js | 2 +-
162 files changed, 19067 insertions(+), 15044 deletions(-)
diff --git a/apidocs/index-all.html b/apidocs/index-all.html
index e0d33341bf3..665430b866d 100644
--- a/apidocs/index-all.html
+++ b/apidocs/index-all.html
@@ -1517,9 +1517,9 @@ loadScripts(document, 'script');</script>
<dd> </dd>
<dt>affixShutdownHook(Thread, int) - Static method in class org.apache.hadoop.hbase.util.ShutdownHookManager</dt>
<dd> </dd>
-<dt>afterDecodingKeyValue(DataInputStream, ByteBuffer, HFileBlockDefaultDecodingContext) - Method in class org.apache.hadoop.hbase.io.encoding.DiffKeyDeltaEncoder</dt>
+<dt>afterDecodingKeyValue(DataInputStream, ByteBuffer, HFileBlockDefaultDecodingContext) - Method in class org.apache.hadoop.hbase.io.encoding.PrefixKeyDeltaEncoder</dt>
<dd> </dd>
-<dt>afterEncodingKeyValue(ExtendedCell, DataOutputStream, HFileBlockDefaultEncodingContext) - Method in class org.apache.hadoop.hbase.io.encoding.DiffKeyDeltaEncoder</dt>
+<dt>afterEncodingKeyValue(ExtendedCell, DataOutputStream, HFileBlockDefaultEncodingContext) - Method in class org.apache.hadoop.hbase.io.encoding.PrefixKeyDeltaEncoder</dt>
<dd>
<div class="block">Returns unencoded size added</div>
</dd>
@@ -3260,6 +3260,10 @@ loadScripts(document, 'script');</script>
</dd>
<dt>beforeMutate(long, Mutation) - Method in class org.apache.hadoop.hbase.util.LoadTestDataGeneratorWithTags</dt>
<dd> </dd>
+<dt>beforePersistingReplicationOffset() - Method in interface org.apache.hadoop.hbase.replication.ReplicationEndpoint</dt>
+<dd>
+<div class="block">Hook invoked before persisting replication offsets.</div>
+</dd>
<dt>beforeShipped() - Method in class org.apache.hadoop.hbase.io.encoding.EncodingState</dt>
<dd> </dd>
<dt>beforeShipped() - Method in class org.apache.hadoop.hbase.io.hfile.CompoundBloomFilterWriter</dt>
@@ -5258,7 +5262,7 @@ loadScripts(document, 'script');</script>
<dd> </dd>
<dt>call(O) - Method in class org.apache.hadoop.hbase.coprocessor.CoprocessorHost.ObserverOperationWithResult</dt>
<dd> </dd>
-<dt>call(AbstractRpcBasedConnectionRegistry.Callable<T>, Predicate<T>, String) - Method in class org.apache.hadoop.hbase.client.RpcConnectionRegistry</dt>
+<dt>call(AbstractRpcBasedConnectionRegistry.Callable<T>, Predicate<T>, String) - Method in class org.apache.hadoop.hbase.client.MasterRegistry</dt>
<dd> </dd>
<dt>call(HBaseRpcController, AdminProtos.AdminService.Interface) - Method in interface org.apache.hadoop.hbase.client.AsyncAdminRequestRetryingCaller.Callable</dt>
<dd> </dd>
@@ -7380,7 +7384,7 @@ loadScripts(document, 'script');</script>
</dd>
<dt>close() - Method in class org.apache.hadoop.hbase.chaos.ChaosAgent</dt>
<dd> </dd>
-<dt>close() - Method in class org.apache.hadoop.hbase.client.RpcConnectionRegistry</dt>
+<dt>close() - Method in class org.apache.hadoop.hbase.client.MasterRegistry</dt>
<dd> </dd>
<dt>close() - Method in interface org.apache.hadoop.hbase.client.Admin</dt>
<dd> </dd>
@@ -8785,11 +8789,11 @@ loadScripts(document, 'script');</script>
<dd>
<div class="block">Compares the family and qualifier part of the cell</div>
</dd>
-<dt>compareCommonFamilyPrefix(Cell, Cell, int) - Static method in class org.apache.hadoop.hbase.io.encoding.DiffKeyDeltaEncoder</dt>
+<dt>compareCommonFamilyPrefix(Cell, Cell, int) - Static method in class org.apache.hadoop.hbase.io.encoding.PrefixKeyDeltaEncoder</dt>
<dd> </dd>
-<dt>compareCommonQualifierPrefix(Cell, Cell, int) - Static method in class org.apache.hadoop.hbase.io.encoding.DiffKeyDeltaEncoder</dt>
+<dt>compareCommonQualifierPrefix(Cell, Cell, int) - Static method in class org.apache.hadoop.hbase.io.encoding.PrefixKeyDeltaEncoder</dt>
<dd> </dd>
-<dt>compareCommonRowPrefix(Cell, Cell, int) - Static method in class org.apache.hadoop.hbase.io.encoding.DiffKeyDeltaEncoder</dt>
+<dt>compareCommonRowPrefix(Cell, Cell, int) - Static method in class org.apache.hadoop.hbase.io.encoding.PrefixKeyDeltaEncoder</dt>
<dd>
<div class="block">common prefixes</div>
</dd>
@@ -13398,7 +13402,7 @@ loadScripts(document, 'script');</script>
<dd>
<div class="block">Decode an <code>int8</code> value.</div>
</dd>
-<dt>decodeKeyValues(DataInputStream, HFileBlockDecodingContext) - Method in class org.apache.hadoop.hbase.io.encoding.DiffKeyDeltaEncoder</dt>
+<dt>decodeKeyValues(DataInputStream, HFileBlockDecodingContext) - Method in class org.apache.hadoop.hbase.io.encoding.PrefixKeyDeltaEncoder</dt>
<dd> </dd>
<dt>decodeKeyValues(DataInputStream, HFileBlockDecodingContext) - Method in interface org.apache.hadoop.hbase.io.encoding.DataBlockEncoder</dt>
<dd>
@@ -16357,7 +16361,7 @@ loadScripts(document, 'script');</script>
<dd>
<div class="block">Separator used to demarcate the encodedName in a region name in the new format.</div>
</dd>
-<dt>encode(ExtendedCell, HFileBlockEncodingContext, DataOutputStream) - Method in class org.apache.hadoop.hbase.io.encoding.DiffKeyDeltaEncoder</dt>
+<dt>encode(ExtendedCell, HFileBlockEncodingContext, DataOutputStream) - Method in class org.apache.hadoop.hbase.io.encoding.PrefixKeyDeltaEncoder</dt>
<dd> </dd>
<dt>encode(ExtendedCell, HFileBlockEncodingContext, DataOutputStream) - Method in interface org.apache.hadoop.hbase.io.encoding.DataBlockEncoder</dt>
<dd>
@@ -16771,7 +16775,7 @@ loadScripts(document, 'script');</script>
</dd>
<dt>END_TIME_KEY - Static variable in class org.apache.hadoop.hbase.mapreduce.WALInputFormat</dt>
<dd> </dd>
-<dt>endBlockEncoding(HFileBlockEncodingContext, DataOutputStream, byte[]) - Method in class org.apache.hadoop.hbase.io.encoding.DiffKeyDeltaEncoder</dt>
+<dt>endBlockEncoding(HFileBlockEncodingContext, DataOutputStream, byte[]) - Method in class org.apache.hadoop.hbase.io.encoding.PrefixKeyDeltaEncoder</dt>
<dd> </dd>
<dt>endBlockEncoding(HFileBlockEncodingContext, DataOutputStream, byte[]) - Method in interface org.apache.hadoop.hbase.io.encoding.DataBlockEncoder</dt>
<dd>
@@ -16887,7 +16891,7 @@ loadScripts(document, 'script');</script>
<div class="deprecation-block"><span class="deprecated-label">Deprecated.</span></div>
<div class="block">Make sure that at least the specified number of region servers are running</div>
</dd>
-<dt>ensureSpace(ByteBuffer, int) - Static method in class org.apache.hadoop.hbase.io.encoding.DiffKeyDeltaEncoder</dt>
+<dt>ensureSpace(ByteBuffer, int) - Static method in class org.apache.hadoop.hbase.io.encoding.PrefixKeyDeltaEncoder</dt>
<dd>
<div class="block">Asserts that there is at least the given amount of unfilled space remaining in the given
buffer.</div>
@@ -20578,7 +20582,7 @@ loadScripts(document, 'script');</script>
<dd> </dd>
<dt>getActiveLogFiles() - Static method in class org.apache.hadoop.hbase.logging.Log4jUtils</dt>
<dd> </dd>
-<dt>getActiveMaster() - Method in class org.apache.hadoop.hbase.client.RpcConnectionRegistry</dt>
+<dt>getActiveMaster() - Method in class org.apache.hadoop.hbase.client.MasterRegistry</dt>
<dd> </dd>
<dt>getActiveMaster() - Method in interface org.apache.hadoop.hbase.client.ConnectionRegistry</dt>
<dd>
@@ -22426,7 +22430,7 @@ loadScripts(document, 'script');</script>
<dd>
<div class="block">Returns the cluster definition</div>
</dd>
-<dt>getClusterId() - Method in class org.apache.hadoop.hbase.client.RpcConnectionRegistry</dt>
+<dt>getClusterId() - Method in class org.apache.hadoop.hbase.client.MasterRegistry</dt>
<dd> </dd>
<dt>getClusterId() - Method in interface org.apache.hadoop.hbase.client.Connection</dt>
<dd>
@@ -27940,7 +27944,7 @@ loadScripts(document, 'script');</script>
</dd>
<dt>getMetaRegionLocationCache() - Method in class org.apache.hadoop.hbase.HBaseServerBase</dt>
<dd> </dd>
-<dt>getMetaRegionLocations() - Method in class org.apache.hadoop.hbase.client.RpcConnectionRegistry</dt>
+<dt>getMetaRegionLocations() - Method in class org.apache.hadoop.hbase.client.MasterRegistry</dt>
<dd> </dd>
<dt>getMetaRegionLocations() - Method in interface org.apache.hadoop.hbase.client.ConnectionRegistry</dt>
<dd>
@@ -38640,7 +38644,7 @@ loadScripts(document, 'script');</script>
<dd> </dd>
<dt>HEDGED_READS_DESC - Static variable in interface org.apache.hadoop.hbase.regionserver.MetricsRegionServerSource</dt>
<dd> </dd>
-<dt>HEDGED_REQS_FANOUT_DEFAULT - Static variable in class org.apache.hadoop.hbase.client.RpcConnectionRegistry</dt>
+<dt>HEDGED_REQS_FANOUT_DEFAULT - Static variable in class org.apache.hadoop.hbase.client.MasterRegistry</dt>
<dd>
<div class="block">Default value for the fan out of hedged requests.</div>
</dd>
@@ -69416,7 +69420,7 @@ service.</div>
</dd>
<dt>START_TIME_KEY - Static variable in class org.apache.hadoop.hbase.mapreduce.WALInputFormat</dt>
<dd> </dd>
-<dt>startBlockEncoding(HFileBlockEncodingContext, DataOutputStream) - Method in class org.apache.hadoop.hbase.io.encoding.DiffKeyDeltaEncoder</dt>
+<dt>startBlockEncoding(HFileBlockEncodingContext, DataOutputStream) - Method in class org.apache.hadoop.hbase.io.encoding.PrefixKeyDeltaEncoder</dt>
<dd> </dd>
<dt>startBlockEncoding(HFileBlockEncodingContext, DataOutputStream) - Method in class org.apache.hadoop.hbase.io.encoding.CopyKeyDataBlockEncoder</dt>
<dd> </dd>
diff --git a/apidocs/member-search-index.js b/apidocs/member-search-index.js
index 520422e2f60..21ab281ac8e 100644
--- a/apidocs/member-search-index.js
+++ b/apidocs/member-search-index.js
@@ -1 +1 @@
-memberSearchIndex = [{"p":"org.apache.hadoop.hbase.filter","c":"ParseConstants","l":"A"},{"p":"org.apache.hadoop.hbase.master","c":"RegionState.State","l":"ABNORMALLY_CLOSED"},{"p":"org.apache.hadoop.hbase.coprocessor","c":"CoprocessorHost","l":"ABORT_ON_ERROR_KEY"},{"p":"org.apache.hadoop.hdfs","c":"DummyDFSOutputStream","l":"abort()"},{"p":"org.apache.hadoop.hbase","c":"Abortable","l":"abort(String)","u":"abort(java.lang.String)"},{"p":"org.apache.hadoop.hbase","c":"Abortable","l":"abo [...]
\ No newline at end of file
+memberSearchIndex = [{"p":"org.apache.hadoop.hbase.filter","c":"ParseConstants","l":"A"},{"p":"org.apache.hadoop.hbase.master","c":"RegionState.State","l":"ABNORMALLY_CLOSED"},{"p":"org.apache.hadoop.hbase.coprocessor","c":"CoprocessorHost","l":"ABORT_ON_ERROR_KEY"},{"p":"org.apache.hadoop.hdfs","c":"DummyDFSOutputStream","l":"abort()"},{"p":"org.apache.hadoop.hbase","c":"Abortable","l":"abort(String)","u":"abort(java.lang.String)"},{"p":"org.apache.hadoop.hbase","c":"Abortable","l":"abo [...]
\ No newline at end of file
diff --git a/apidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.Context.html b/apidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.Context.html
index 4cc0b718ec2..ea6d1c4fbdd 100644
--- a/apidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.Context.html
+++ b/apidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.Context.html
@@ -296,7 +296,14 @@
<span class="source-line-no">283</span><span id="line-283"> * @throws IllegalStateException if this service's state isn't FAILED.</span>
<span class="source-line-no">284</span><span id="line-284"> */</span>
<span class="source-line-no">285</span><span id="line-285"> Throwable failureCause();</span>
-<span class="source-line-no">286</span><span id="line-286">}</span>
+<span class="source-line-no">286</span><span id="line-286"></span>
+<span class="source-line-no">287</span><span id="line-287"> /**</span>
+<span class="source-line-no">288</span><span id="line-288"> * Hook invoked before persisting replication offsets. Eg: Buffered endpoints can flush/close WALs</span>
+<span class="source-line-no">289</span><span id="line-289"> * here.</span>
+<span class="source-line-no">290</span><span id="line-290"> */</span>
+<span class="source-line-no">291</span><span id="line-291"> default void beforePersistingReplicationOffset() throws IOException {</span>
+<span class="source-line-no">292</span><span id="line-292"> }</span>
+<span class="source-line-no">293</span><span id="line-293">}</span>
diff --git a/apidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.ReplicateContext.html b/apidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.ReplicateContext.html
index e2835872952..c1ce59df9ef 100644
--- a/apidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.ReplicateContext.html
+++ b/apidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.ReplicateContext.html
@@ -296,7 +296,14 @@
<span class="source-line-no">283</span><span id="line-283"> * @throws IllegalStateException if this service's state isn't FAILED.</span>
<span class="source-line-no">284</span><span id="line-284"> */</span>
<span class="source-line-no">285</span><span id="line-285"> Throwable failureCause();</span>
-<span class="source-line-no">286</span><span id="line-286">}</span>
+<span class="source-line-no">286</span><span id="line-286"></span>
+<span class="source-line-no">287</span><span id="line-287"> /**</span>
+<span class="source-line-no">288</span><span id="line-288"> * Hook invoked before persisting replication offsets. Eg: Buffered endpoints can flush/close WALs</span>
+<span class="source-line-no">289</span><span id="line-289"> * here.</span>
+<span class="source-line-no">290</span><span id="line-290"> */</span>
+<span class="source-line-no">291</span><span id="line-291"> default void beforePersistingReplicationOffset() throws IOException {</span>
+<span class="source-line-no">292</span><span id="line-292"> }</span>
+<span class="source-line-no">293</span><span id="line-293">}</span>
diff --git a/apidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.html b/apidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.html
index 962ebe7fc25..35301e30ed6 100644
--- a/apidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.html
+++ b/apidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.html
@@ -296,7 +296,14 @@
<span class="source-line-no">283</span><span id="line-283"> * @throws IllegalStateException if this service's state isn't FAILED.</span>
<span class="source-line-no">284</span><span id="line-284"> */</span>
<span class="source-line-no">285</span><span id="line-285"> Throwable failureCause();</span>
-<span class="source-line-no">286</span><span id="line-286">}</span>
+<span class="source-line-no">286</span><span id="line-286"></span>
+<span class="source-line-no">287</span><span id="line-287"> /**</span>
+<span class="source-line-no">288</span><span id="line-288"> * Hook invoked before persisting replication offsets. Eg: Buffered endpoints can flush/close WALs</span>
+<span class="source-line-no">289</span><span id="line-289"> * here.</span>
+<span class="source-line-no">290</span><span id="line-290"> */</span>
+<span class="source-line-no">291</span><span id="line-291"> default void beforePersistingReplicationOffset() throws IOException {</span>
+<span class="source-line-no">292</span><span id="line-292"> }</span>
+<span class="source-line-no">293</span><span id="line-293">}</span>
diff --git a/apidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html b/apidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html
index e8578d2d279..5999aee5723 100644
--- a/apidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html
+++ b/apidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html
@@ -30,731 +30,752 @@
<span class="source-line-no">017</span><span id="line-17"> */</span>
<span class="source-line-no">018</span><span id="line-18">package org.apache.hadoop.hbase.snapshot;</span>
<span class="source-line-no">019</span><span id="line-19"></span>
-<span class="source-line-no">020</span><span id="line-20">import java.io.FileNotFoundException;</span>
-<span class="source-line-no">021</span><span id="line-21">import java.io.IOException;</span>
-<span class="source-line-no">022</span><span id="line-22">import java.net.URI;</span>
-<span class="source-line-no">023</span><span id="line-23">import java.text.SimpleDateFormat;</span>
-<span class="source-line-no">024</span><span id="line-24">import java.util.ArrayList;</span>
-<span class="source-line-no">025</span><span id="line-25">import java.util.Collections;</span>
-<span class="source-line-no">026</span><span id="line-26">import java.util.Date;</span>
-<span class="source-line-no">027</span><span id="line-27">import java.util.List;</span>
-<span class="source-line-no">028</span><span id="line-28">import java.util.Map;</span>
-<span class="source-line-no">029</span><span id="line-29">import java.util.Properties;</span>
-<span class="source-line-no">030</span><span id="line-30">import java.util.concurrent.ConcurrentHashMap;</span>
-<span class="source-line-no">031</span><span id="line-31">import java.util.concurrent.ExecutorService;</span>
-<span class="source-line-no">032</span><span id="line-32">import java.util.concurrent.atomic.AtomicInteger;</span>
-<span class="source-line-no">033</span><span id="line-33">import java.util.concurrent.atomic.AtomicLong;</span>
-<span class="source-line-no">034</span><span id="line-34">import org.apache.hadoop.conf.Configuration;</span>
-<span class="source-line-no">035</span><span id="line-35">import org.apache.hadoop.fs.FileStatus;</span>
-<span class="source-line-no">036</span><span id="line-36">import org.apache.hadoop.fs.FileSystem;</span>
-<span class="source-line-no">037</span><span id="line-37">import org.apache.hadoop.fs.Path;</span>
-<span class="source-line-no">038</span><span id="line-38">import org.apache.hadoop.hbase.TableName;</span>
-<span class="source-line-no">039</span><span id="line-39">import org.apache.hadoop.hbase.client.RegionInfo;</span>
-<span class="source-line-no">040</span><span id="line-40">import org.apache.hadoop.hbase.client.SnapshotDescription;</span>
-<span class="source-line-no">041</span><span id="line-41">import org.apache.hadoop.hbase.io.HFileLink;</span>
-<span class="source-line-no">042</span><span id="line-42">import org.apache.hadoop.hbase.io.WALLink;</span>
-<span class="source-line-no">043</span><span id="line-43">import org.apache.hadoop.hbase.util.AbstractHBaseTool;</span>
-<span class="source-line-no">044</span><span id="line-44">import org.apache.hadoop.hbase.util.CommonFSUtils;</span>
-<span class="source-line-no">045</span><span id="line-45">import org.apache.hadoop.hbase.util.Strings;</span>
-<span class="source-line-no">046</span><span id="line-46">import org.apache.yetus.audience.InterfaceAudience;</span>
-<span class="source-line-no">047</span><span id="line-47">import org.slf4j.Logger;</span>
-<span class="source-line-no">048</span><span id="line-48">import org.slf4j.LoggerFactory;</span>
-<span class="source-line-no">049</span><span id="line-49"></span>
-<span class="source-line-no">050</span><span id="line-50">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;</span>
-<span class="source-line-no">051</span><span id="line-51">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLineParser;</span>
-<span class="source-line-no">052</span><span id="line-52">import org.apache.hbase.thirdparty.org.apache.commons.cli.DefaultParser;</span>
-<span class="source-line-no">053</span><span id="line-53">import org.apache.hbase.thirdparty.org.apache.commons.cli.Option;</span>
-<span class="source-line-no">054</span><span id="line-54">import org.apache.hbase.thirdparty.org.apache.commons.cli.Options;</span>
-<span class="source-line-no">055</span><span id="line-55">import org.apache.hbase.thirdparty.org.apache.commons.cli.ParseException;</span>
-<span class="source-line-no">056</span><span id="line-56"></span>
-<span class="source-line-no">057</span><span id="line-57">import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;</span>
-<span class="source-line-no">058</span><span id="line-58">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos;</span>
-<span class="source-line-no">059</span><span id="line-59">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;</span>
-<span class="source-line-no">060</span><span id="line-60"></span>
-<span class="source-line-no">061</span><span id="line-61">/**</span>
-<span class="source-line-no">062</span><span id="line-62"> * Tool for dumping snapshot information.</span>
-<span class="source-line-no">063</span><span id="line-63"> * <ol></span>
-<span class="source-line-no">064</span><span id="line-64"> * <li>Table Descriptor</span>
-<span class="source-line-no">065</span><span id="line-65"> * <li>Snapshot creation time, type, format version, ...</span>
-<span class="source-line-no">066</span><span id="line-66"> * <li>List of hfiles and wals</span>
-<span class="source-line-no">067</span><span id="line-67"> * <li>Stats about hfiles and logs sizes, percentage of shared with the source table, ...</span>
-<span class="source-line-no">068</span><span id="line-68"> * </ol></span>
-<span class="source-line-no">069</span><span id="line-69"> */</span>
-<span class="source-line-no">070</span><span id="line-70">@InterfaceAudience.Public</span>
-<span class="source-line-no">071</span><span id="line-71">public final class SnapshotInfo extends AbstractHBaseTool {</span>
-<span class="source-line-no">072</span><span id="line-72"> private static final Logger LOG = LoggerFactory.getLogger(SnapshotInfo.class);</span>
-<span class="source-line-no">073</span><span id="line-73"></span>
-<span class="source-line-no">074</span><span id="line-74"> static final class Options {</span>
-<span class="source-line-no">075</span><span id="line-75"> static final Option SNAPSHOT =</span>
-<span class="source-line-no">076</span><span id="line-76"> new Option(null, "snapshot", true, "The name of the snapshot to be detailed.");</span>
-<span class="source-line-no">077</span><span id="line-77"> static final Option REMOTE_DIR =</span>
-<span class="source-line-no">078</span><span id="line-78"> new Option(null, "remote-dir", true, "A custom root directory where snapshots are stored. "</span>
-<span class="source-line-no">079</span><span id="line-79"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">080</span><span id="line-80"> static final Option LIST_SNAPSHOTS =</span>
-<span class="source-line-no">081</span><span id="line-81"> new Option(null, "list-snapshots", false, "List all the available snapshots and exit.");</span>
-<span class="source-line-no">082</span><span id="line-82"> static final Option FILES =</span>
-<span class="source-line-no">083</span><span id="line-83"> new Option(null, "files", false, "The list of files retained by the specified snapshot. "</span>
-<span class="source-line-no">084</span><span id="line-84"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">085</span><span id="line-85"> static final Option STATS =</span>
-<span class="source-line-no">086</span><span id="line-86"> new Option(null, "stats", false, "Additional information about the specified snapshot. "</span>
-<span class="source-line-no">087</span><span id="line-87"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">088</span><span id="line-88"> static final Option SCHEMA = new Option(null, "schema", false,</span>
-<span class="source-line-no">089</span><span id="line-89"> "Show the descriptor of the table for the specified snapshot. "</span>
+<span class="source-line-no">020</span><span id="line-20">import static org.apache.hadoop.hbase.HConstants.DEFAULT_SNAPSHOT_TTL;</span>
+<span class="source-line-no">021</span><span id="line-21"></span>
+<span class="source-line-no">022</span><span id="line-22">import java.io.FileNotFoundException;</span>
+<span class="source-line-no">023</span><span id="line-23">import java.io.IOException;</span>
+<span class="source-line-no">024</span><span id="line-24">import java.net.URI;</span>
+<span class="source-line-no">025</span><span id="line-25">import java.text.SimpleDateFormat;</span>
+<span class="source-line-no">026</span><span id="line-26">import java.util.ArrayList;</span>
+<span class="source-line-no">027</span><span id="line-27">import java.util.Collections;</span>
+<span class="source-line-no">028</span><span id="line-28">import java.util.Date;</span>
+<span class="source-line-no">029</span><span id="line-29">import java.util.List;</span>
+<span class="source-line-no">030</span><span id="line-30">import java.util.Map;</span>
+<span class="source-line-no">031</span><span id="line-31">import java.util.Properties;</span>
+<span class="source-line-no">032</span><span id="line-32">import java.util.concurrent.ConcurrentHashMap;</span>
+<span class="source-line-no">033</span><span id="line-33">import java.util.concurrent.ExecutorService;</span>
+<span class="source-line-no">034</span><span id="line-34">import java.util.concurrent.atomic.AtomicInteger;</span>
+<span class="source-line-no">035</span><span id="line-35">import java.util.concurrent.atomic.AtomicLong;</span>
+<span class="source-line-no">036</span><span id="line-36">import org.apache.hadoop.conf.Configuration;</span>
+<span class="source-line-no">037</span><span id="line-37">import org.apache.hadoop.fs.FileStatus;</span>
+<span class="source-line-no">038</span><span id="line-38">import org.apache.hadoop.fs.FileSystem;</span>
+<span class="source-line-no">039</span><span id="line-39">import org.apache.hadoop.fs.Path;</span>
+<span class="source-line-no">040</span><span id="line-40">import org.apache.hadoop.hbase.TableName;</span>
+<span class="source-line-no">041</span><span id="line-41">import org.apache.hadoop.hbase.client.RegionInfo;</span>
+<span class="source-line-no">042</span><span id="line-42">import org.apache.hadoop.hbase.client.SnapshotDescription;</span>
+<span class="source-line-no">043</span><span id="line-43">import org.apache.hadoop.hbase.io.HFileLink;</span>
+<span class="source-line-no">044</span><span id="line-44">import org.apache.hadoop.hbase.io.WALLink;</span>
+<span class="source-line-no">045</span><span id="line-45">import org.apache.hadoop.hbase.util.AbstractHBaseTool;</span>
+<span class="source-line-no">046</span><span id="line-46">import org.apache.hadoop.hbase.util.CommonFSUtils;</span>
+<span class="source-line-no">047</span><span id="line-47">import org.apache.hadoop.hbase.util.Strings;</span>
+<span class="source-line-no">048</span><span id="line-48">import org.apache.yetus.audience.InterfaceAudience;</span>
+<span class="source-line-no">049</span><span id="line-49">import org.slf4j.Logger;</span>
+<span class="source-line-no">050</span><span id="line-50">import org.slf4j.LoggerFactory;</span>
+<span class="source-line-no">051</span><span id="line-51"></span>
+<span class="source-line-no">052</span><span id="line-52">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;</span>
+<span class="source-line-no">053</span><span id="line-53">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLineParser;</span>
+<span class="source-line-no">054</span><span id="line-54">import org.apache.hbase.thirdparty.org.apache.commons.cli.DefaultParser;</span>
+<span class="source-line-no">055</span><span id="line-55">import org.apache.hbase.thirdparty.org.apache.commons.cli.Option;</span>
+<span class="source-line-no">056</span><span id="line-56">import org.apache.hbase.thirdparty.org.apache.commons.cli.Options;</span>
+<span class="source-line-no">057</span><span id="line-57">import org.apache.hbase.thirdparty.org.apache.commons.cli.ParseException;</span>
+<span class="source-line-no">058</span><span id="line-58"></span>
+<span class="source-line-no">059</span><span id="line-59">import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;</span>
+<span class="source-line-no">060</span><span id="line-60">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos;</span>
+<span class="source-line-no">061</span><span id="line-61">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;</span>
+<span class="source-line-no">062</span><span id="line-62"></span>
+<span class="source-line-no">063</span><span id="line-63">/**</span>
+<span class="source-line-no">064</span><span id="line-64"> * Tool for dumping snapshot information.</span>
+<span class="source-line-no">065</span><span id="line-65"> * <ol></span>
+<span class="source-line-no">066</span><span id="line-66"> * <li>Table Descriptor</span>
+<span class="source-line-no">067</span><span id="line-67"> * <li>Snapshot creation time, type, format version, ...</span>
+<span class="source-line-no">068</span><span id="line-68"> * <li>List of hfiles and wals</span>
+<span class="source-line-no">069</span><span id="line-69"> * <li>Stats about hfiles and logs sizes, percentage of shared with the source table, ...</span>
+<span class="source-line-no">070</span><span id="line-70"> * </ol></span>
+<span class="source-line-no">071</span><span id="line-71"> */</span>
+<span class="source-line-no">072</span><span id="line-72">@InterfaceAudience.Public</span>
+<span class="source-line-no">073</span><span id="line-73">public final class SnapshotInfo extends AbstractHBaseTool {</span>
+<span class="source-line-no">074</span><span id="line-74"> private static final Logger LOG = LoggerFactory.getLogger(SnapshotInfo.class);</span>
+<span class="source-line-no">075</span><span id="line-75"></span>
+<span class="source-line-no">076</span><span id="line-76"> private static final String EXPIRED_LABEL = "Yes";</span>
+<span class="source-line-no">077</span><span id="line-77"> private static final String NOT_EXPIRED_LABEL = "No";</span>
+<span class="source-line-no">078</span><span id="line-78"> private static final String TTL_FOREVER = "FOREVER";</span>
+<span class="source-line-no">079</span><span id="line-79"></span>
+<span class="source-line-no">080</span><span id="line-80"> static final class Options {</span>
+<span class="source-line-no">081</span><span id="line-81"> static final Option SNAPSHOT =</span>
+<span class="source-line-no">082</span><span id="line-82"> new Option(null, "snapshot", true, "The name of the snapshot to be detailed.");</span>
+<span class="source-line-no">083</span><span id="line-83"> static final Option REMOTE_DIR =</span>
+<span class="source-line-no">084</span><span id="line-84"> new Option(null, "remote-dir", true, "A custom root directory where snapshots are stored. "</span>
+<span class="source-line-no">085</span><span id="line-85"> + "Use it together with the --snapshot option.");</span>
+<span class="source-line-no">086</span><span id="line-86"> static final Option LIST_SNAPSHOTS =</span>
+<span class="source-line-no">087</span><span id="line-87"> new Option(null, "list-snapshots", false, "List all the available snapshots and exit.");</span>
+<span class="source-line-no">088</span><span id="line-88"> static final Option FILES =</span>
+<span class="source-line-no">089</span><span id="line-89"> new Option(null, "files", false, "The list of files retained by the specified snapshot. "</span>
<span class="source-line-no">090</span><span id="line-90"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">091</span><span id="line-91"> static final Option SIZE_IN_BYTES =</span>
-<span class="source-line-no">092</span><span id="line-92"> new Option(null, "size-in-bytes", false, "Print the size of the files in bytes. "</span>
-<span class="source-line-no">093</span><span id="line-93"> + "Use it together with the --snapshot and --files options.");</span>
-<span class="source-line-no">094</span><span id="line-94"> }</span>
-<span class="source-line-no">095</span><span id="line-95"></span>
-<span class="source-line-no">096</span><span id="line-96"> /**</span>
-<span class="source-line-no">097</span><span id="line-97"> * Statistics about the snapshot</span>
-<span class="source-line-no">098</span><span id="line-98"> * <ol></span>
-<span class="source-line-no">099</span><span id="line-99"> * <li>How many store files and logs are in the archive</span>
-<span class="source-line-no">100</span><span id="line-100"> * <li>How many store files and logs are shared with the table</span>
-<span class="source-line-no">101</span><span id="line-101"> * <li>Total store files and logs size and shared amount</span>
-<span class="source-line-no">102</span><span id="line-102"> * </ol></span>
-<span class="source-line-no">103</span><span id="line-103"> */</span>
-<span class="source-line-no">104</span><span id="line-104"> public static class SnapshotStats {</span>
-<span class="source-line-no">105</span><span id="line-105"> /** Information about the file referenced by the snapshot */</span>
-<span class="source-line-no">106</span><span id="line-106"> static class FileInfo {</span>
-<span class="source-line-no">107</span><span id="line-107"> private final boolean corrupted;</span>
-<span class="source-line-no">108</span><span id="line-108"> private final boolean inArchive;</span>
-<span class="source-line-no">109</span><span id="line-109"> private final long size;</span>
-<span class="source-line-no">110</span><span id="line-110"></span>
-<span class="source-line-no">111</span><span id="line-111"> FileInfo(final boolean inArchive, final long size, final boolean corrupted) {</span>
-<span class="source-line-no">112</span><span id="line-112"> this.corrupted = corrupted;</span>
-<span class="source-line-no">113</span><span id="line-113"> this.inArchive = inArchive;</span>
-<span class="source-line-no">114</span><span id="line-114"> this.size = size;</span>
-<span class="source-line-no">115</span><span id="line-115"> }</span>
+<span class="source-line-no">091</span><span id="line-91"> static final Option STATS =</span>
+<span class="source-line-no">092</span><span id="line-92"> new Option(null, "stats", false, "Additional information about the specified snapshot. "</span>
+<span class="source-line-no">093</span><span id="line-93"> + "Use it together with the --snapshot option.");</span>
+<span class="source-line-no">094</span><span id="line-94"> static final Option SCHEMA = new Option(null, "schema", false,</span>
+<span class="source-line-no">095</span><span id="line-95"> "Show the descriptor of the table for the specified snapshot. "</span>
+<span class="source-line-no">096</span><span id="line-96"> + "Use it together with the --snapshot option.");</span>
+<span class="source-line-no">097</span><span id="line-97"> static final Option SIZE_IN_BYTES =</span>
+<span class="source-line-no">098</span><span id="line-98"> new Option(null, "size-in-bytes", false, "Print the size of the files in bytes. "</span>
+<span class="source-line-no">099</span><span id="line-99"> + "Use it together with the --snapshot and --files options.");</span>
+<span class="source-line-no">100</span><span id="line-100"> }</span>
+<span class="source-line-no">101</span><span id="line-101"></span>
+<span class="source-line-no">102</span><span id="line-102"> /**</span>
+<span class="source-line-no">103</span><span id="line-103"> * Statistics about the snapshot</span>
+<span class="source-line-no">104</span><span id="line-104"> * <ol></span>
+<span class="source-line-no">105</span><span id="line-105"> * <li>How many store files and logs are in the archive</span>
+<span class="source-line-no">106</span><span id="line-106"> * <li>How many store files and logs are shared with the table</span>
+<span class="source-line-no">107</span><span id="line-107"> * <li>Total store files and logs size and shared amount</span>
+<span class="source-line-no">108</span><span id="line-108"> * </ol></span>
+<span class="source-line-no">109</span><span id="line-109"> */</span>
+<span class="source-line-no">110</span><span id="line-110"> public static class SnapshotStats {</span>
+<span class="source-line-no">111</span><span id="line-111"> /** Information about the file referenced by the snapshot */</span>
+<span class="source-line-no">112</span><span id="line-112"> static class FileInfo {</span>
+<span class="source-line-no">113</span><span id="line-113"> private final boolean corrupted;</span>
+<span class="source-line-no">114</span><span id="line-114"> private final boolean inArchive;</span>
+<span class="source-line-no">115</span><span id="line-115"> private final long size;</span>
<span class="source-line-no">116</span><span id="line-116"></span>
-<span class="source-line-no">117</span><span id="line-117"> /** Returns true if the file is in the archive */</span>
-<span class="source-line-no">118</span><span id="line-118"> public boolean inArchive() {</span>
-<span class="source-line-no">119</span><span id="line-119"> return this.inArchive;</span>
-<span class="source-line-no">120</span><span id="line-120"> }</span>
-<span class="source-line-no">121</span><span id="line-121"></span>
-<span class="source-line-no">122</span><span id="line-122"> /** Returns true if the file is corrupted */</span>
-<span class="source-line-no">123</span><span id="line-123"> public boolean isCorrupted() {</span>
-<span class="source-line-no">124</span><span id="line-124"> return this.corrupted;</span>
-<span class="source-line-no">125</span><span id="line-125"> }</span>
-<span class="source-line-no">126</span><span id="line-126"></span>
-<span class="source-line-no">127</span><span id="line-127"> /** Returns true if the file is missing */</span>
-<span class="source-line-no">128</span><span id="line-128"> public boolean isMissing() {</span>
-<span class="source-line-no">129</span><span id="line-129"> return this.size < 0;</span>
-<span class="source-line-no">130</span><span id="line-130"> }</span>
-<span class="source-line-no">131</span><span id="line-131"></span>
-<span class="source-line-no">132</span><span id="line-132"> /** Returns the file size */</span>
-<span class="source-line-no">133</span><span id="line-133"> public long getSize() {</span>
-<span class="source-line-no">134</span><span id="line-134"> return this.size;</span>
-<span class="source-line-no">135</span><span id="line-135"> }</span>
-<span class="source-line-no">136</span><span id="line-136"></span>
-<span class="source-line-no">137</span><span id="line-137"> String getStateToString() {</span>
-<span class="source-line-no">138</span><span id="line-138"> if (isCorrupted()) return "CORRUPTED";</span>
-<span class="source-line-no">139</span><span id="line-139"> if (isMissing()) return "NOT FOUND";</span>
-<span class="source-line-no">140</span><span id="line-140"> if (inArchive()) return "archive";</span>
-<span class="source-line-no">141</span><span id="line-141"> return null;</span>
-<span class="source-line-no">142</span><span id="line-142"> }</span>
-<span class="source-line-no">143</span><span id="line-143"> }</span>
-<span class="source-line-no">144</span><span id="line-144"></span>
-<span class="source-line-no">145</span><span id="line-145"> private AtomicInteger hfilesArchiveCount = new AtomicInteger();</span>
-<span class="source-line-no">146</span><span id="line-146"> private AtomicInteger hfilesCorrupted = new AtomicInteger();</span>
-<span class="source-line-no">147</span><span id="line-147"> private AtomicInteger hfilesMissing = new AtomicInteger();</span>
-<span class="source-line-no">148</span><span id="line-148"> private AtomicInteger hfilesCount = new AtomicInteger();</span>
-<span class="source-line-no">149</span><span id="line-149"> private AtomicInteger hfilesMobCount = new AtomicInteger();</span>
-<span class="source-line-no">150</span><span id="line-150"> private AtomicInteger logsMissing = new AtomicInteger();</span>
-<span class="source-line-no">151</span><span id="line-151"> private AtomicInteger logsCount = new AtomicInteger();</span>
-<span class="source-line-no">152</span><span id="line-152"> private AtomicLong hfilesArchiveSize = new AtomicLong();</span>
-<span class="source-line-no">153</span><span id="line-153"> private AtomicLong hfilesSize = new AtomicLong();</span>
-<span class="source-line-no">154</span><span id="line-154"> private AtomicLong hfilesMobSize = new AtomicLong();</span>
-<span class="source-line-no">155</span><span id="line-155"> private AtomicLong nonSharedHfilesArchiveSize = new AtomicLong();</span>
-<span class="source-line-no">156</span><span id="line-156"> private AtomicLong logSize = new AtomicLong();</span>
-<span class="source-line-no">157</span><span id="line-157"></span>
-<span class="source-line-no">158</span><span id="line-158"> private final SnapshotProtos.SnapshotDescription snapshot;</span>
-<span class="source-line-no">159</span><span id="line-159"> private final TableName snapshotTable;</span>
-<span class="source-line-no">160</span><span id="line-160"> private final Configuration conf;</span>
-<span class="source-line-no">161</span><span id="line-161"> private final FileSystem fs;</span>
-<span class="source-line-no">162</span><span id="line-162"></span>
-<span class="source-line-no">163</span><span id="line-163"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
-<span class="source-line-no">164</span><span id="line-164"> final SnapshotDescription snapshot) {</span>
-<span class="source-line-no">165</span><span id="line-165"> this.snapshot = ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
-<span class="source-line-no">166</span><span id="line-166"> this.snapshotTable = snapshot.getTableName();</span>
-<span class="source-line-no">167</span><span id="line-167"> this.conf = conf;</span>
-<span class="source-line-no">168</span><span id="line-168"> this.fs = fs;</span>
-<span class="source-line-no">169</span><span id="line-169"> }</span>
-<span class="source-line-no">170</span><span id="line-170"></span>
-<span class="source-line-no">171</span><span id="line-171"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
-<span class="source-line-no">172</span><span id="line-172"> final SnapshotProtos.SnapshotDescription snapshot) {</span>
-<span class="source-line-no">173</span><span id="line-173"> this.snapshot = snapshot;</span>
-<span class="source-line-no">174</span><span id="line-174"> this.snapshotTable = TableName.valueOf(snapshot.getTable());</span>
-<span class="source-line-no">175</span><span id="line-175"> this.conf = conf;</span>
-<span class="source-line-no">176</span><span id="line-176"> this.fs = fs;</span>
-<span class="source-line-no">177</span><span id="line-177"> }</span>
-<span class="source-line-no">178</span><span id="line-178"></span>
-<span class="source-line-no">179</span><span id="line-179"> /** Returns the snapshot descriptor */</span>
-<span class="source-line-no">180</span><span id="line-180"> public SnapshotDescription getSnapshotDescription() {</span>
-<span class="source-line-no">181</span><span id="line-181"> return ProtobufUtil.createSnapshotDesc(this.snapshot);</span>
-<span class="source-line-no">182</span><span id="line-182"> }</span>
-<span class="source-line-no">183</span><span id="line-183"></span>
-<span class="source-line-no">184</span><span id="line-184"> /** Returns true if the snapshot is corrupted */</span>
-<span class="source-line-no">185</span><span id="line-185"> public boolean isSnapshotCorrupted() {</span>
-<span class="source-line-no">186</span><span id="line-186"> return hfilesMissing.get() > 0 || logsMissing.get() > 0 || hfilesCorrupted.get() > 0;</span>
-<span class="source-line-no">187</span><span id="line-187"> }</span>
-<span class="source-line-no">188</span><span id="line-188"></span>
-<span class="source-line-no">189</span><span id="line-189"> /** Returns the number of available store files */</span>
-<span class="source-line-no">190</span><span id="line-190"> public int getStoreFilesCount() {</span>
-<span class="source-line-no">191</span><span id="line-191"> return hfilesCount.get() + hfilesArchiveCount.get() + hfilesMobCount.get();</span>
-<span class="source-line-no">192</span><span id="line-192"> }</span>
-<span class="source-line-no">193</span><span id="line-193"></span>
-<span class="source-line-no">194</span><span id="line-194"> /** Returns the number of available store files in the archive */</span>
-<span class="source-line-no">195</span><span id="line-195"> public int getArchivedStoreFilesCount() {</span>
-<span class="source-line-no">196</span><span id="line-196"> return hfilesArchiveCount.get();</span>
-<span class="source-line-no">197</span><span id="line-197"> }</span>
-<span class="source-line-no">198</span><span id="line-198"></span>
-<span class="source-line-no">199</span><span id="line-199"> /** Returns the number of available store files in the mob dir */</span>
-<span class="source-line-no">200</span><span id="line-200"> public int getMobStoreFilesCount() {</span>
-<span class="source-line-no">201</span><span id="line-201"> return hfilesMobCount.get();</span>
-<span class="source-line-no">202</span><span id="line-202"> }</span>
-<span class="source-line-no">203</span><span id="line-203"></span>
-<span class="source-line-no">204</span><span id="line-204"> /** Returns the number of available log files */</span>
-<span class="source-line-no">205</span><span id="line-205"> public int getLogsCount() {</span>
-<span class="source-line-no">206</span><span id="line-206"> return logsCount.get();</span>
-<span class="source-line-no">207</span><span id="line-207"> }</span>
-<span class="source-line-no">208</span><span id="line-208"></span>
-<span class="source-line-no">209</span><span id="line-209"> /** Returns the number of missing store files */</span>
-<span class="source-line-no">210</span><span id="line-210"> public int getMissingStoreFilesCount() {</span>
-<span class="source-line-no">211</span><span id="line-211"> return hfilesMissing.get();</span>
-<span class="source-line-no">212</span><span id="line-212"> }</span>
-<span class="source-line-no">213</span><span id="line-213"></span>
-<span class="source-line-no">214</span><span id="line-214"> /** Returns the number of corrupted store files */</span>
-<span class="source-line-no">215</span><span id="line-215"> public int getCorruptedStoreFilesCount() {</span>
-<span class="source-line-no">216</span><span id="line-216"> return hfilesCorrupted.get();</span>
-<span class="source-line-no">217</span><span id="line-217"> }</span>
-<span class="source-line-no">218</span><span id="line-218"></span>
-<span class="source-line-no">219</span><span id="line-219"> /** Returns the number of missing log files */</span>
-<span class="source-line-no">220</span><span id="line-220"> public int getMissingLogsCount() {</span>
-<span class="source-line-no">221</span><span id="line-221"> return logsMissing.get();</span>
-<span class="source-line-no">222</span><span id="line-222"> }</span>
-<span class="source-line-no">223</span><span id="line-223"></span>
-<span class="source-line-no">224</span><span id="line-224"> /** Returns the total size of the store files referenced by the snapshot */</span>
-<span class="source-line-no">225</span><span id="line-225"> public long getStoreFilesSize() {</span>
-<span class="source-line-no">226</span><span id="line-226"> return hfilesSize.get() + hfilesArchiveSize.get() + hfilesMobSize.get();</span>
-<span class="source-line-no">227</span><span id="line-227"> }</span>
-<span class="source-line-no">228</span><span id="line-228"></span>
-<span class="source-line-no">229</span><span id="line-229"> /** Returns the total size of the store files shared */</span>
-<span class="source-line-no">230</span><span id="line-230"> public long getSharedStoreFilesSize() {</span>
-<span class="source-line-no">231</span><span id="line-231"> return hfilesSize.get();</span>
-<span class="source-line-no">232</span><span id="line-232"> }</span>
-<span class="source-line-no">233</span><span id="line-233"></span>
-<span class="source-line-no">234</span><span id="line-234"> /** Returns the total size of the store files in the archive */</span>
-<span class="source-line-no">235</span><span id="line-235"> public long getArchivedStoreFileSize() {</span>
-<span class="source-line-no">236</span><span id="line-236"> return hfilesArchiveSize.get();</span>
-<span class="source-line-no">237</span><span id="line-237"> }</span>
-<span class="source-line-no">238</span><span id="line-238"></span>
-<span class="source-line-no">239</span><span id="line-239"> /** Returns the total size of the store files in the mob store */</span>
-<span class="source-line-no">240</span><span id="line-240"> public long getMobStoreFilesSize() {</span>
-<span class="source-line-no">241</span><span id="line-241"> return hfilesMobSize.get();</span>
-<span class="source-line-no">242</span><span id="line-242"> }</span>
-<span class="source-line-no">243</span><span id="line-243"></span>
-<span class="source-line-no">244</span><span id="line-244"> /**</span>
-<span class="source-line-no">245</span><span id="line-245"> * @return the total size of the store files in the archive which is not shared with other</span>
-<span class="source-line-no">246</span><span id="line-246"> * snapshots and tables This is only calculated when</span>
-<span class="source-line-no">247</span><span id="line-247"> * {@link #getSnapshotStats(Configuration, SnapshotProtos.SnapshotDescription, Map)} is</span>
-<span class="source-line-no">248</span><span id="line-248"> * called with a non-null Map</span>
-<span class="source-line-no">249</span><span id="line-249"> */</span>
-<span class="source-line-no">250</span><span id="line-250"> public long getNonSharedArchivedStoreFilesSize() {</span>
-<span class="source-line-no">251</span><span id="line-251"> return nonSharedHfilesArchiveSize.get();</span>
-<span class="source-line-no">252</span><span id="line-252"> }</span>
-<span class="source-line-no">253</span><span id="line-253"></span>
-<span class="source-line-no">254</span><span id="line-254"> /** Returns the percentage of the shared store files */</span>
-<span class="source-line-no">255</span><span id="line-255"> public float getSharedStoreFilePercentage() {</span>
-<span class="source-line-no">256</span><span id="line-256"> return getStoreFilesSize() == 0</span>
-<span class="source-line-no">257</span><span id="line-257"> ? 0</span>
-<span class="source-line-no">258</span><span id="line-258"> : ((float) hfilesSize.get() / (getStoreFilesSize())) * 100;</span>
-<span class="source-line-no">259</span><span id="line-259"> }</span>
-<span class="source-line-no">260</span><span id="line-260"></span>
-<span class="source-line-no">261</span><span id="line-261"> /** Returns the percentage of the mob store files */</span>
-<span class="source-line-no">262</span><span id="line-262"> public float getMobStoreFilePercentage() {</span>
-<span class="source-line-no">263</span><span id="line-263"> return getStoreFilesSize() == 0</span>
-<span class="source-line-no">264</span><span id="line-264"> ? 0</span>
-<span class="source-line-no">265</span><span id="line-265"> : ((float) hfilesMobSize.get() / (getStoreFilesSize())) * 100;</span>
-<span class="source-line-no">266</span><span id="line-266"> }</span>
-<span class="source-line-no">267</span><span id="line-267"></span>
-<span class="source-line-no">268</span><span id="line-268"> /** Returns the total log size */</span>
-<span class="source-line-no">269</span><span id="line-269"> public long getLogsSize() {</span>
-<span class="source-line-no">270</span><span id="line-270"> return logSize.get();</span>
-<span class="source-line-no">271</span><span id="line-271"> }</span>
-<span class="source-line-no">272</span><span id="line-272"></span>
-<span class="source-line-no">273</span><span id="line-273"> /**</span>
-<span class="source-line-no">274</span><span id="line-274"> * Check if for a give file in archive, if there are other snapshots/tables still reference it.</span>
-<span class="source-line-no">275</span><span id="line-275"> * @param filePath file path in archive</span>
-<span class="source-line-no">276</span><span id="line-276"> * @param snapshotFilesMap a map for store files in snapshots about how many snapshots refer to</span>
-<span class="source-line-no">277</span><span id="line-277"> * it.</span>
-<span class="source-line-no">278</span><span id="line-278"> * @return true or false</span>
-<span class="source-line-no">279</span><span id="line-279"> */</span>
-<span class="source-line-no">280</span><span id="line-280"> private boolean isArchivedFileStillReferenced(final Path filePath,</span>
-<span class="source-line-no">281</span><span id="line-281"> final Map<Path, Integer> snapshotFilesMap) {</span>
-<span class="source-line-no">282</span><span id="line-282"></span>
-<span class="source-line-no">283</span><span id="line-283"> Integer c = snapshotFilesMap.get(filePath);</span>
-<span class="source-line-no">284</span><span id="line-284"></span>
-<span class="source-line-no">285</span><span id="line-285"> // Check if there are other snapshots or table from clone_snapshot() (via back-reference)</span>
-<span class="source-line-no">286</span><span id="line-286"> // still reference to it.</span>
-<span class="source-line-no">287</span><span id="line-287"> if ((c != null) && (c == 1)) {</span>
-<span class="source-line-no">288</span><span id="line-288"> Path parentDir = filePath.getParent();</span>
-<span class="source-line-no">289</span><span id="line-289"> Path backRefDir = HFileLink.getBackReferencesDir(parentDir, filePath.getName());</span>
-<span class="source-line-no">290</span><span id="line-290"> try {</span>
-<span class="source-line-no">291</span><span id="line-291"> if (CommonFSUtils.listStatus(fs, backRefDir) == null) {</span>
-<span class="source-line-no">292</span><span id="line-292"> return false;</span>
-<span class="source-line-no">293</span><span id="line-293"> }</span>
-<span class="source-line-no">294</span><span id="line-294"> } catch (IOException e) {</span>
-<span class="source-line-no">295</span><span id="line-295"> // For the purpose of this function, IOException is ignored and treated as</span>
-<span class="source-line-no">296</span><span id="line-296"> // the file is still being referenced.</span>
-<span class="source-line-no">297</span><span id="line-297"> }</span>
-<span class="source-line-no">298</span><span id="line-298"> }</span>
-<span class="source-line-no">299</span><span id="line-299"> return true;</span>
-<span class="source-line-no">300</span><span id="line-300"> }</span>
-<span class="source-line-no">301</span><span id="line-301"></span>
-<span class="source-line-no">302</span><span id="line-302"> /**</span>
-<span class="source-line-no">303</span><span id="line-303"> * Add the specified store file to the stats</span>
-<span class="source-line-no">304</span><span id="line-304"> * @param region region encoded Name</span>
-<span class="source-line-no">305</span><span id="line-305"> * @param family family name</span>
-<span class="source-line-no">306</span><span id="line-306"> * @param storeFile store file name</span>
-<span class="source-line-no">307</span><span id="line-307"> * @param filesMap store files map for all snapshots, it may be null</span>
-<span class="source-line-no">308</span><span id="line-308"> * @return the store file information</span>
-<span class="source-line-no">309</span><span id="line-309"> */</span>
-<span class="source-line-no">310</span><span id="line-310"> FileInfo addStoreFile(final RegionInfo region, final String family,</span>
-<span class="source-line-no">311</span><span id="line-311"> final SnapshotRegionManifest.StoreFile storeFile, final Map<Path, Integer> filesMap)</span>
-<span class="source-line-no">312</span><span id="line-312"> throws IOException {</span>
-<span class="source-line-no">313</span><span id="line-313"> HFileLink link =</span>
-<span class="source-line-no">314</span><span id="line-314"> HFileLink.build(conf, snapshotTable, region.getEncodedName(), family, storeFile.getName());</span>
-<span class="source-line-no">315</span><span id="line-315"> boolean isCorrupted = false;</span>
-<span class="source-line-no">316</span><span id="line-316"> boolean inArchive = false;</span>
-<span class="source-line-no">317</span><span id="line-317"> long size = -1;</span>
-<span class="source-line-no">318</span><span id="line-318"> try {</span>
-<span class="source-line-no">319</span><span id="line-319"> if (fs.exists(link.getArchivePath())) {</span>
-<span class="source-line-no">320</span><span id="line-320"> inArchive = true;</span>
-<span class="source-line-no">321</span><span id="line-321"> size = fs.getFileStatus(link.getArchivePath()).getLen();</span>
-<span class="source-line-no">322</span><span id="line-322"> hfilesArchiveSize.addAndGet(size);</span>
-<span class="source-line-no">323</span><span id="line-323"> hfilesArchiveCount.incrementAndGet();</span>
-<span class="source-line-no">324</span><span id="line-324"></span>
-<span class="source-line-no">325</span><span id="line-325"> // If store file is not shared with other snapshots and tables,</span>
-<span class="source-line-no">326</span><span id="line-326"> // increase nonSharedHfilesArchiveSize</span>
-<span class="source-line-no">327</span><span id="line-327"> if (</span>
-<span class="source-line-no">328</span><span id="line-328"> (filesMap != null) && !isArchivedFileStillReferenced(link.getArchivePath(), filesMap)</span>
-<span class="source-line-no">329</span><span id="line-329"> ) {</span>
-<span class="source-line-no">330</span><span id="line-330"> nonSharedHfilesArchiveSize.addAndGet(size);</span>
-<span class="source-line-no">331</span><span id="line-331"> }</span>
-<span class="source-line-no">332</span><span id="line-332"> } else if (fs.exists(link.getMobPath())) {</span>
-<span class="source-line-no">333</span><span id="line-333"> inArchive = true;</span>
-<span class="source-line-no">334</span><span id="line-334"> size = fs.getFileStatus(link.getMobPath()).getLen();</span>
-<span class="source-line-no">335</span><span id="line-335"> hfilesMobSize.addAndGet(size);</span>
-<span class="source-line-no">336</span><span id="line-336"> hfilesMobCount.incrementAndGet();</span>
-<span class="source-line-no">337</span><span id="line-337"> } else {</span>
-<span class="source-line-no">338</span><span id="line-338"> size = link.getFileStatus(fs).getLen();</span>
-<span class="source-line-no">339</span><span id="line-339"> hfilesSize.addAndGet(size);</span>
-<span class="source-line-no">340</span><span id="line-340"> hfilesCount.incrementAndGet();</span>
-<span class="source-line-no">341</span><span id="line-341"> }</span>
-<span class="source-line-no">342</span><span id="line-342"> isCorrupted = (storeFile.hasFileSize() && storeFile.getFileSize() != size);</span>
-<span class="source-line-no">343</span><span id="line-343"> if (isCorrupted) hfilesCorrupted.incrementAndGet();</span>
-<span class="source-line-no">344</span><span id="line-344"> } catch (FileNotFoundException e) {</span>
-<span class="source-line-no">345</span><span id="line-345"> hfilesMissing.incrementAndGet();</span>
-<span class="source-line-no">346</span><span id="line-346"> }</span>
-<span class="source-line-no">347</span><span id="line-347"> return new FileInfo(inArchive, size, isCorrupted);</span>
-<span class="source-line-no">348</span><span id="line-348"> }</span>
-<span class="source-line-no">349</span><span id="line-349"></span>
-<span class="source-line-no">350</span><span id="line-350"> /**</span>
-<span class="source-line-no">351</span><span id="line-351"> * Add the specified log file to the stats</span>
-<span class="source-line-no">352</span><span id="line-352"> * @param server server name</span>
-<span class="source-line-no">353</span><span id="line-353"> * @param logfile log file name</span>
-<span class="source-line-no">354</span><span id="line-354"> * @return the log information</span>
-<span class="source-line-no">355</span><span id="line-355"> */</span>
-<span class="source-line-no">356</span><span id="line-356"> FileInfo addLogFile(final String server, final String logfile) throws IOException {</span>
-<span class="source-line-no">357</span><span id="line-357"> WALLink logLink = new WALLink(conf, server, logfile);</span>
-<span class="source-line-no">358</span><span id="line-358"> long size = -1;</span>
-<span class="source-line-no">359</span><span id="line-359"> try {</span>
-<span class="source-line-no">360</span><span id="line-360"> size = logLink.getFileStatus(fs).getLen();</span>
-<span class="source-line-no">361</span><span id="line-361"> logSize.addAndGet(size);</span>
-<span class="source-line-no">362</span><span id="line-362"> logsCount.incrementAndGet();</span>
-<span class="source-line-no">363</span><span id="line-363"> } catch (FileNotFoundException e) {</span>
-<span class="source-line-no">364</span><span id="line-364"> logsMissing.incrementAndGet();</span>
-<span class="source-line-no">365</span><span id="line-365"> }</span>
-<span class="source-line-no">366</span><span id="line-366"> return new FileInfo(false, size, false);</span>
-<span class="source-line-no">367</span><span id="line-367"> }</span>
-<span class="source-line-no">368</span><span id="line-368"> }</span>
-<span class="source-line-no">369</span><span id="line-369"></span>
-<span class="source-line-no">370</span><span id="line-370"> private FileSystem fs;</span>
-<span class="source-line-no">371</span><span id="line-371"> private Path rootDir;</span>
-<span class="source-line-no">372</span><span id="line-372"></span>
-<span class="source-line-no">373</span><span id="line-373"> private SnapshotManifest snapshotManifest;</span>
-<span class="source-line-no">374</span><span id="line-374"></span>
-<span class="source-line-no">375</span><span id="line-375"> private boolean listSnapshots = false;</span>
-<span class="source-line-no">376</span><span id="line-376"> private String snapshotName;</span>
-<span class="source-line-no">377</span><span id="line-377"> private Path remoteDir;</span>
-<span class="source-line-no">378</span><span id="line-378"> private boolean showSchema = false;</span>
-<span class="source-line-no">379</span><span id="line-379"> private boolean showFiles = false;</span>
-<span class="source-line-no">380</span><span id="line-380"> private boolean showStats = false;</span>
-<span class="source-line-no">381</span><span id="line-381"> private boolean printSizeInBytes = false;</span>
-<span class="source-line-no">382</span><span id="line-382"></span>
-<span class="source-line-no">383</span><span id="line-383"> @Override</span>
-<span class="source-line-no">384</span><span id="line-384"> public int doWork() throws IOException, InterruptedException {</span>
-<span class="source-line-no">385</span><span id="line-385"> if (remoteDir != null) {</span>
-<span class="source-line-no">386</span><span id="line-386"> URI defaultFs = remoteDir.getFileSystem(conf).getUri();</span>
-<span class="source-line-no">387</span><span id="line-387"> CommonFSUtils.setFsDefault(conf, new Path(defaultFs));</span>
-<span class="source-line-no">388</span><span id="line-388"> CommonFSUtils.setRootDir(conf, remoteDir);</span>
-<span class="source-line-no">389</span><span id="line-389"> }</span>
-<span class="source-line-no">390</span><span id="line-390"></span>
-<span class="source-line-no">391</span><span id="line-391"> // List Available Snapshots</span>
-<span class="source-line-no">392</span><span id="line-392"> if (listSnapshots) {</span>
-<span class="source-line-no">393</span><span id="line-393"> SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");</span>
-<span class="source-line-no">394</span><span id="line-394"> System.out.printf("%-20s | %-20s | %-20s | %s%n", "SNAPSHOT", "CREATION TIME", "TTL IN SEC",</span>
-<span class="source-line-no">395</span><span id="line-395"> "TABLE NAME");</span>
-<span class="source-line-no">396</span><span id="line-396"> for (SnapshotDescription desc : getSnapshotList(conf)) {</span>
-<span class="source-line-no">397</span><span id="line-397"> System.out.printf("%-20s | %20s | %20s | %s%n", desc.getName(),</span>
-<span class="source-line-no">398</span><span id="line-398"> df.format(new Date(desc.getCreationTime())), desc.getTtl(), desc.getTableNameAsString());</span>
-<span class="source-line-no">399</span><span id="line-399"> }</span>
-<span class="source-line-no">400</span><span id="line-400"> return 0;</span>
-<span class="source-line-no">401</span><span id="line-401"> }</span>
-<span class="source-line-no">402</span><span id="line-402"></span>
-<span class="source-line-no">403</span><span id="line-403"> rootDir = CommonFSUtils.getRootDir(conf);</span>
-<span class="source-line-no">404</span><span id="line-404"> fs = FileSystem.get(rootDir.toUri(), conf);</span>
-<span class="source-line-no">405</span><span id="line-405"> LOG.debug("fs=" + fs.getUri().toString() + " root=" + rootDir);</span>
-<span class="source-line-no">406</span><span id="line-406"></span>
-<span class="source-line-no">407</span><span id="line-407"> // Load snapshot information</span>
-<span class="source-line-no">408</span><span id="line-408"> if (!loadSnapshotInfo(snapshotName)) {</span>
-<span class="source-line-no">409</span><span id="line-409"> System.err.println("Snapshot '" + snapshotName + "' not found!");</span>
-<span class="source-line-no">410</span><span id="line-410"> return 1;</span>
-<span class="source-line-no">411</span><span id="line-411"> }</span>
-<span class="source-line-no">412</span><span id="line-412"></span>
-<span class="source-line-no">413</span><span id="line-413"> printInfo();</span>
-<span class="source-line-no">414</span><span id="line-414"> if (showSchema) {</span>
-<span class="source-line-no">415</span><span id="line-415"> printSchema();</span>
-<span class="source-line-no">416</span><span id="line-416"> }</span>
-<span class="source-line-no">417</span><span id="line-417"> printFiles(showFiles, showStats);</span>
-<span class="source-line-no">418</span><span id="line-418"></span>
-<span class="source-line-no">419</span><span id="line-419"> return 0;</span>
-<span class="source-line-no">420</span><span id="line-420"> }</span>
-<span class="source-line-no">421</span><span id="line-421"></span>
-<span class="source-line-no">422</span><span id="line-422"> /**</span>
-<span class="source-line-no">423</span><span id="line-423"> * Load snapshot info and table descriptor for the specified snapshot</span>
-<span class="source-line-no">424</span><span id="line-424"> * @param snapshotName name of the snapshot to load</span>
-<span class="source-line-no">425</span><span id="line-425"> * @return false if snapshot is not found</span>
-<span class="source-line-no">426</span><span id="line-426"> */</span>
-<span class="source-line-no">427</span><span id="line-427"> private boolean loadSnapshotInfo(final String snapshotName) throws IOException {</span>
-<span class="source-line-no">428</span><span id="line-428"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);</span>
-<span class="source-line-no">429</span><span id="line-429"> if (!fs.exists(snapshotDir)) {</span>
-<span class="source-line-no">430</span><span id="line-430"> LOG.warn("Snapshot '" + snapshotName + "' not found in: " + snapshotDir);</span>
-<span class="source-line-no">431</span><span id="line-431"> return false;</span>
-<span class="source-line-no">432</span><span id="line-432"> }</span>
-<span class="source-line-no">433</span><span id="line-433"></span>
-<span class="source-line-no">434</span><span id="line-434"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">435</span><span id="line-435"> SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);</span>
-<span class="source-line-no">436</span><span id="line-436"> snapshotManifest = SnapshotManifest.open(getConf(), fs, snapshotDir, snapshotDesc);</span>
-<span class="source-line-no">437</span><span id="line-437"> return true;</span>
-<span class="source-line-no">438</span><span id="line-438"> }</span>
-<span class="source-line-no">439</span><span id="line-439"></span>
-<span class="source-line-no">440</span><span id="line-440"> /**</span>
-<span class="source-line-no">441</span><span id="line-441"> * Dump the {@link SnapshotDescription}</span>
-<span class="source-line-no">442</span><span id="line-442"> */</span>
-<span class="source-line-no">443</span><span id="line-443"> private void printInfo() {</span>
-<span class="source-line-no">444</span><span id="line-444"> SnapshotProtos.SnapshotDescription snapshotDesc = snapshotManifest.getSnapshotDescription();</span>
-<span class="source-line-no">445</span><span id="line-445"> SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");</span>
-<span class="source-line-no">446</span><span id="line-446"> System.out.println("Snapshot Info");</span>
-<span class="source-line-no">447</span><span id="line-447"> System.out.println("----------------------------------------");</span>
-<span class="source-line-no">448</span><span id="line-448"> System.out.println(" Name: " + snapshotDesc.getName());</span>
-<span class="source-line-no">449</span><span id="line-449"> System.out.println(" Type: " + snapshotDesc.getType());</span>
-<span class="source-line-no">450</span><span id="line-450"> System.out.println(" Table: " + snapshotDesc.getTable());</span>
-<span class="source-line-no">451</span><span id="line-451"> System.out.println(" Format: " + snapshotDesc.getVersion());</span>
-<span class="source-line-no">452</span><span id="line-452"> System.out.println("Created: " + df.format(new Date(snapshotDesc.getCreationTime())));</span>
-<span class="source-line-no">453</span><span id="line-453"> System.out.println(" Ttl: " + snapshotDesc.getTtl());</span>
-<span class="source-line-no">454</span><span id="line-454"> System.out.println(" Owner: " + snapshotDesc.getOwner());</span>
-<span class="source-line-no">455</span><span id="line-455"> System.out.println();</span>
-<span class="source-line-no">456</span><span id="line-456"> }</span>
-<span class="source-line-no">457</span><span id="line-457"></span>
-<span class="source-line-no">458</span><span id="line-458"> /**</span>
-<span class="source-line-no">459</span><span id="line-459"> * Dump the {@link org.apache.hadoop.hbase.client.TableDescriptor}</span>
-<span class="source-line-no">460</span><span id="line-460"> */</span>
-<span class="source-line-no">461</span><span id="line-461"> private void printSchema() {</span>
-<span class="source-line-no">462</span><span id="line-462"> System.out.println("Table Descriptor");</span>
-<span class="source-line-no">463</span><span id="line-463"> System.out.println("----------------------------------------");</span>
-<span class="source-line-no">464</span><span id="line-464"> System.out.println(snapshotManifest.getTableDescriptor().toString());</span>
-<span class="source-line-no">465</span><span id="line-465"> System.out.println();</span>
-<span class="source-line-no">466</span><span id="line-466"> }</span>
-<span class="source-line-no">467</span><span id="line-467"></span>
-<span class="source-line-no">468</span><span id="line-468"> /**</span>
-<span class="source-line-no">469</span><span id="line-469"> * Collect the hfiles and logs statistics of the snapshot and dump the file list if requested and</span>
-<span class="source-line-no">470</span><span id="line-470"> * the collected information.</span>
-<span class="source-line-no">471</span><span id="line-471"> */</span>
-<span class="source-line-no">472</span><span id="line-472"> private void printFiles(final boolean showFiles, final boolean showStats) throws IOException {</span>
-<span class="source-line-no">473</span><span id="line-473"> if (showFiles) {</span>
-<span class="source-line-no">474</span><span id="line-474"> System.out.println("Snapshot Files");</span>
-<span class="source-line-no">475</span><span id="line-475"> System.out.println("----------------------------------------");</span>
-<span class="source-line-no">476</span><span id="line-476"> }</span>
-<span class="source-line-no">477</span><span id="line-477"></span>
-<span class="source-line-no">478</span><span id="line-478"> // Collect information about hfiles and logs in the snapshot</span>
-<span class="source-line-no">479</span><span id="line-479"> final SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">480</span><span id="line-480"> snapshotManifest.getSnapshotDescription();</span>
-<span class="source-line-no">481</span><span id="line-481"> final String table = snapshotDesc.getTable();</span>
-<span class="source-line-no">482</span><span id="line-482"> final SnapshotDescription desc = ProtobufUtil.createSnapshotDesc(snapshotDesc);</span>
-<span class="source-line-no">483</span><span id="line-483"> final SnapshotStats stats = new SnapshotStats(this.getConf(), this.fs, desc);</span>
-<span class="source-line-no">484</span><span id="line-484"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(getConf(), fs, snapshotManifest,</span>
-<span class="source-line-no">485</span><span id="line-485"> "SnapshotInfo", new SnapshotReferenceUtil.SnapshotVisitor() {</span>
-<span class="source-line-no">486</span><span id="line-486"> @Override</span>
-<span class="source-line-no">487</span><span id="line-487"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
-<span class="source-line-no">488</span><span id="line-488"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
-<span class="source-line-no">489</span><span id="line-489"> if (storeFile.hasReference()) return;</span>
-<span class="source-line-no">490</span><span id="line-490"></span>
-<span class="source-line-no">491</span><span id="line-491"> SnapshotStats.FileInfo info = stats.addStoreFile(regionInfo, family, storeFile, null);</span>
-<span class="source-line-no">492</span><span id="line-492"> if (showFiles) {</span>
-<span class="source-line-no">493</span><span id="line-493"> String state = info.getStateToString();</span>
-<span class="source-line-no">494</span><span id="line-494"> System.out.printf("%8s %s/%s/%s/%s %s%n",</span>
-<span class="source-line-no">495</span><span id="line-495"> (info.isMissing() ? "-" : fileSizeToString(info.getSize())), table,</span>
-<span class="source-line-no">496</span><span id="line-496"> regionInfo.getEncodedName(), family, storeFile.getName(),</span>
-<span class="source-line-no">497</span><span id="line-497"> state == null ? "" : "(" + state + ")");</span>
-<span class="source-line-no">498</span><span id="line-498"> }</span>
-<span class="source-line-no">499</span><span id="line-499"> }</span>
-<span class="source-line-no">500</span><span id="line-500"> });</span>
-<span class="source-line-no">501</span><span id="line-501"></span>
-<span class="source-line-no">502</span><span id="line-502"> // Dump the stats</span>
-<span class="source-line-no">503</span><span id="line-503"> System.out.println();</span>
-<span class="source-line-no">504</span><span id="line-504"> if (stats.isSnapshotCorrupted()) {</span>
-<span class="source-line-no">505</span><span id="line-505"> System.out.println("**************************************************************");</span>
-<span class="source-line-no">506</span><span id="line-506"> System.out.printf("BAD SNAPSHOT: %d hfile(s) and %d log(s) missing.%n",</span>
-<span class="source-line-no">507</span><span id="line-507"> stats.getMissingStoreFilesCount(), stats.getMissingLogsCount());</span>
-<span class="source-line-no">508</span><span id="line-508"> System.out.printf(" %d hfile(s) corrupted.%n",</span>
-<span class="source-line-no">509</span><span id="line-509"> stats.getCorruptedStoreFilesCount());</span>
-<span class="source-line-no">510</span><span id="line-510"> System.out.println("**************************************************************");</span>
-<span class="source-line-no">511</span><span id="line-511"> }</span>
-<span class="source-line-no">512</span><span id="line-512"></span>
-<span class="source-line-no">513</span><span id="line-513"> if (showStats) {</span>
-<span class="source-line-no">514</span><span id="line-514"> System.out.printf(</span>
-<span class="source-line-no">515</span><span id="line-515"> "%d HFiles (%d in archive, %d in mob storage), total size %s "</span>
-<span class="source-line-no">516</span><span id="line-516"> + "(%.2f%% %s shared with the source table, %.2f%% %s in mob dir)%n",</span>
-<span class="source-line-no">517</span><span id="line-517"> stats.getStoreFilesCount(), stats.getArchivedStoreFilesCount(),</span>
-<span class="source-line-no">518</span><span id="line-518"> stats.getMobStoreFilesCount(), fileSizeToString(stats.getStoreFilesSize()),</span>
-<span class="source-line-no">519</span><span id="line-519"> stats.getSharedStoreFilePercentage(), fileSizeToString(stats.getSharedStoreFilesSize()),</span>
-<span class="source-line-no">520</span><span id="line-520"> stats.getMobStoreFilePercentage(), fileSizeToString(stats.getMobStoreFilesSize()));</span>
-<span class="source-line-no">521</span><span id="line-521"> System.out.printf("%d Logs, total size %s%n", stats.getLogsCount(),</span>
-<span class="source-line-no">522</span><span id="line-522"> fileSizeToString(stats.getLogsSize()));</span>
-<span class="source-line-no">523</span><span id="line-523"> System.out.println();</span>
-<span class="source-line-no">524</span><span id="line-524"> }</span>
-<span class="source-line-no">525</span><span id="line-525"> }</span>
-<span class="source-line-no">526</span><span id="line-526"></span>
-<span class="source-line-no">527</span><span id="line-527"> private String fileSizeToString(long size) {</span>
-<span class="source-line-no">528</span><span id="line-528"> return printSizeInBytes ? Long.toString(size) : Strings.humanReadableInt(size);</span>
-<span class="source-line-no">529</span><span id="line-529"> }</span>
-<span class="source-line-no">530</span><span id="line-530"></span>
-<span class="source-line-no">531</span><span id="line-531"> @Override</span>
-<span class="source-line-no">532</span><span id="line-532"> protected void addOptions() {</span>
-<span class="source-line-no">533</span><span id="line-533"> addOption(Options.SNAPSHOT);</span>
-<span class="source-line-no">534</span><span id="line-534"> addOption(Options.REMOTE_DIR);</span>
-<span class="source-line-no">535</span><span id="line-535"> addOption(Options.LIST_SNAPSHOTS);</span>
-<span class="source-line-no">536</span><span id="line-536"> addOption(Options.FILES);</span>
-<span class="source-line-no">537</span><span id="line-537"> addOption(Options.STATS);</span>
-<span class="source-line-no">538</span><span id="line-538"> addOption(Options.SCHEMA);</span>
-<span class="source-line-no">539</span><span id="line-539"> addOption(Options.SIZE_IN_BYTES);</span>
-<span class="source-line-no">540</span><span id="line-540"> }</span>
-<span class="source-line-no">541</span><span id="line-541"></span>
-<span class="source-line-no">542</span><span id="line-542"> @Override</span>
-<span class="source-line-no">543</span><span id="line-543"> protected CommandLineParser newParser() {</span>
-<span class="source-line-no">544</span><span id="line-544"> // Commons-CLI lacks the capability to handle combinations of options, so we do it ourselves</span>
-<span class="source-line-no">545</span><span id="line-545"> // Validate in parse() to get helpful error messages instead of exploding in processOptions()</span>
-<span class="source-line-no">546</span><span id="line-546"> return new DefaultParser() {</span>
-<span class="source-line-no">547</span><span id="line-547"> @Override</span>
-<span class="source-line-no">548</span><span id="line-548"> public CommandLine parse(org.apache.hbase.thirdparty.org.apache.commons.cli.Options opts,</span>
-<span class="source-line-no">549</span><span id="line-549"> String[] args, Properties props, boolean stop) throws ParseException {</span>
-<span class="source-line-no">550</span><span id="line-550"> CommandLine cl = super.parse(opts, args, props, stop);</span>
-<span class="source-line-no">551</span><span id="line-551"> if (!cmd.hasOption(Options.LIST_SNAPSHOTS) && !cmd.hasOption(Options.SNAPSHOT)) {</span>
-<span class="source-line-no">552</span><span id="line-552"> throw new ParseException("Missing required snapshot option!");</span>
-<span class="source-line-no">553</span><span id="line-553"> }</span>
-<span class="source-line-no">554</span><span id="line-554"> return cl;</span>
-<span class="source-line-no">555</span><span id="line-555"> }</span>
-<span class="source-line-no">556</span><span id="line-556"> };</span>
-<span class="source-line-no">557</span><span id="line-557"> }</span>
-<span class="source-line-no">558</span><span id="line-558"></span>
-<span class="source-line-no">559</span><span id="line-559"> @Override</span>
-<span class="source-line-no">560</span><span id="line-560"> protected void processOptions(CommandLine cmd) {</span>
-<span class="source-line-no">561</span><span id="line-561"> snapshotName = cmd.getOptionValue(Options.SNAPSHOT.getLongOpt());</span>
-<span class="source-line-no">562</span><span id="line-562"> showFiles = cmd.hasOption(Options.FILES.getLongOpt());</span>
-<span class="source-line-no">563</span><span id="line-563"> showStats =</span>
-<span class="source-line-no">564</span><span id="line-564"> cmd.hasOption(Options.FILES.getLongOpt()) || cmd.hasOption(Options.STATS.getLongOpt());</span>
-<span class="source-line-no">565</span><span id="line-565"> showSchema = cmd.hasOption(Options.SCHEMA.getLongOpt());</span>
-<span class="source-line-no">566</span><span id="line-566"> listSnapshots = cmd.hasOption(Options.LIST_SNAPSHOTS.getLongOpt());</span>
-<span class="source-line-no">567</span><span id="line-567"> printSizeInBytes = cmd.hasOption(Options.SIZE_IN_BYTES.getLongOpt());</span>
-<span class="source-line-no">568</span><span id="line-568"> if (cmd.hasOption(Options.REMOTE_DIR.getLongOpt())) {</span>
-<span class="source-line-no">569</span><span id="line-569"> remoteDir = new Path(cmd.getOptionValue(Options.REMOTE_DIR.getLongOpt()));</span>
-<span class="source-line-no">570</span><span id="line-570"> }</span>
-<span class="source-line-no">571</span><span id="line-571"> }</span>
-<span class="source-line-no">572</span><span id="line-572"></span>
-<span class="source-line-no">573</span><span id="line-573"> @Override</span>
-<span class="source-line-no">574</span><span id="line-574"> protected void printUsage() {</span>
-<span class="source-line-no">575</span><span id="line-575"> printUsage("hbase snapshot info [options]", "Options:", "");</span>
-<span class="source-line-no">576</span><span id="line-576"> System.err.println("Examples:");</span>
-<span class="source-line-no">577</span><span id="line-577"> System.err.println(" hbase snapshot info --snapshot MySnapshot --files");</span>
+<span class="source-line-no">117</span><span id="line-117"> FileInfo(final boolean inArchive, final long size, final boolean corrupted) {</span>
+<span class="source-line-no">118</span><span id="line-118"> this.corrupted = corrupted;</span>
+<span class="source-line-no">119</span><span id="line-119"> this.inArchive = inArchive;</span>
+<span class="source-line-no">120</span><span id="line-120"> this.size = size;</span>
+<span class="source-line-no">121</span><span id="line-121"> }</span>
+<span class="source-line-no">122</span><span id="line-122"></span>
+<span class="source-line-no">123</span><span id="line-123"> /** Returns true if the file is in the archive */</span>
+<span class="source-line-no">124</span><span id="line-124"> public boolean inArchive() {</span>
+<span class="source-line-no">125</span><span id="line-125"> return this.inArchive;</span>
+<span class="source-line-no">126</span><span id="line-126"> }</span>
+<span class="source-line-no">127</span><span id="line-127"></span>
+<span class="source-line-no">128</span><span id="line-128"> /** Returns true if the file is corrupted */</span>
+<span class="source-line-no">129</span><span id="line-129"> public boolean isCorrupted() {</span>
+<span class="source-line-no">130</span><span id="line-130"> return this.corrupted;</span>
+<span class="source-line-no">131</span><span id="line-131"> }</span>
+<span class="source-line-no">132</span><span id="line-132"></span>
+<span class="source-line-no">133</span><span id="line-133"> /** Returns true if the file is missing */</span>
+<span class="source-line-no">134</span><span id="line-134"> public boolean isMissing() {</span>
+<span class="source-line-no">135</span><span id="line-135"> return this.size < 0;</span>
+<span class="source-line-no">136</span><span id="line-136"> }</span>
+<span class="source-line-no">137</span><span id="line-137"></span>
+<span class="source-line-no">138</span><span id="line-138"> /** Returns the file size */</span>
+<span class="source-line-no">139</span><span id="line-139"> public long getSize() {</span>
+<span class="source-line-no">140</span><span id="line-140"> return this.size;</span>
+<span class="source-line-no">141</span><span id="line-141"> }</span>
+<span class="source-line-no">142</span><span id="line-142"></span>
+<span class="source-line-no">143</span><span id="line-143"> String getStateToString() {</span>
+<span class="source-line-no">144</span><span id="line-144"> if (isCorrupted()) return "CORRUPTED";</span>
+<span class="source-line-no">145</span><span id="line-145"> if (isMissing()) return "NOT FOUND";</span>
+<span class="source-line-no">146</span><span id="line-146"> if (inArchive()) return "archive";</span>
+<span class="source-line-no">147</span><span id="line-147"> return null;</span>
+<span class="source-line-no">148</span><span id="line-148"> }</span>
+<span class="source-line-no">149</span><span id="line-149"> }</span>
+<span class="source-line-no">150</span><span id="line-150"></span>
+<span class="source-line-no">151</span><span id="line-151"> private AtomicInteger hfilesArchiveCount = new AtomicInteger();</span>
+<span class="source-line-no">152</span><span id="line-152"> private AtomicInteger hfilesCorrupted = new AtomicInteger();</span>
+<span class="source-line-no">153</span><span id="line-153"> private AtomicInteger hfilesMissing = new AtomicInteger();</span>
+<span class="source-line-no">154</span><span id="line-154"> private AtomicInteger hfilesCount = new AtomicInteger();</span>
+<span class="source-line-no">155</span><span id="line-155"> private AtomicInteger hfilesMobCount = new AtomicInteger();</span>
+<span class="source-line-no">156</span><span id="line-156"> private AtomicInteger logsMissing = new AtomicInteger();</span>
+<span class="source-line-no">157</span><span id="line-157"> private AtomicInteger logsCount = new AtomicInteger();</span>
+<span class="source-line-no">158</span><span id="line-158"> private AtomicLong hfilesArchiveSize = new AtomicLong();</span>
+<span class="source-line-no">159</span><span id="line-159"> private AtomicLong hfilesSize = new AtomicLong();</span>
+<span class="source-line-no">160</span><span id="line-160"> private AtomicLong hfilesMobSize = new AtomicLong();</span>
+<span class="source-line-no">161</span><span id="line-161"> private AtomicLong nonSharedHfilesArchiveSize = new AtomicLong();</span>
+<span class="source-line-no">162</span><span id="line-162"> private AtomicLong logSize = new AtomicLong();</span>
+<span class="source-line-no">163</span><span id="line-163"></span>
+<span class="source-line-no">164</span><span id="line-164"> private final SnapshotProtos.SnapshotDescription snapshot;</span>
+<span class="source-line-no">165</span><span id="line-165"> private final TableName snapshotTable;</span>
+<span class="source-line-no">166</span><span id="line-166"> private final Configuration conf;</span>
+<span class="source-line-no">167</span><span id="line-167"> private final FileSystem fs;</span>
+<span class="source-line-no">168</span><span id="line-168"></span>
+<span class="source-line-no">169</span><span id="line-169"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
+<span class="source-line-no">170</span><span id="line-170"> final SnapshotDescription snapshot) {</span>
+<span class="source-line-no">171</span><span id="line-171"> this.snapshot = ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
+<span class="source-line-no">172</span><span id="line-172"> this.snapshotTable = snapshot.getTableName();</span>
+<span class="source-line-no">173</span><span id="line-173"> this.conf = conf;</span>
+<span class="source-line-no">174</span><span id="line-174"> this.fs = fs;</span>
+<span class="source-line-no">175</span><span id="line-175"> }</span>
+<span class="source-line-no">176</span><span id="line-176"></span>
+<span class="source-line-no">177</span><span id="line-177"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
+<span class="source-line-no">178</span><span id="line-178"> final SnapshotProtos.SnapshotDescription snapshot) {</span>
+<span class="source-line-no">179</span><span id="line-179"> this.snapshot = snapshot;</span>
+<span class="source-line-no">180</span><span id="line-180"> this.snapshotTable = TableName.valueOf(snapshot.getTable());</span>
+<span class="source-line-no">181</span><span id="line-181"> this.conf = conf;</span>
+<span class="source-line-no">182</span><span id="line-182"> this.fs = fs;</span>
+<span class="source-line-no">183</span><span id="line-183"> }</span>
+<span class="source-line-no">184</span><span id="line-184"></span>
+<span class="source-line-no">185</span><span id="line-185"> /** Returns the snapshot descriptor */</span>
+<span class="source-line-no">186</span><span id="line-186"> public SnapshotDescription getSnapshotDescription() {</span>
+<span class="source-line-no">187</span><span id="line-187"> return ProtobufUtil.createSnapshotDesc(this.snapshot);</span>
+<span class="source-line-no">188</span><span id="line-188"> }</span>
+<span class="source-line-no">189</span><span id="line-189"></span>
+<span class="source-line-no">190</span><span id="line-190"> /** Returns true if the snapshot is corrupted */</span>
+<span class="source-line-no">191</span><span id="line-191"> public boolean isSnapshotCorrupted() {</span>
+<span class="source-line-no">192</span><span id="line-192"> return hfilesMissing.get() > 0 || logsMissing.get() > 0 || hfilesCorrupted.get() > 0;</span>
+<span class="source-line-no">193</span><span id="line-193"> }</span>
+<span class="source-line-no">194</span><span id="line-194"></span>
+<span class="source-line-no">195</span><span id="line-195"> /** Returns the number of available store files */</span>
+<span class="source-line-no">196</span><span id="line-196"> public int getStoreFilesCount() {</span>
+<span class="source-line-no">197</span><span id="line-197"> return hfilesCount.get() + hfilesArchiveCount.get() + hfilesMobCount.get();</span>
+<span class="source-line-no">198</span><span id="line-198"> }</span>
+<span class="source-line-no">199</span><span id="line-199"></span>
+<span class="source-line-no">200</span><span id="line-200"> /** Returns the number of available store files in the archive */</span>
+<span class="source-line-no">201</span><span id="line-201"> public int getArchivedStoreFilesCount() {</span>
+<span class="source-line-no">202</span><span id="line-202"> return hfilesArchiveCount.get();</span>
+<span class="source-line-no">203</span><span id="line-203"> }</span>
+<span class="source-line-no">204</span><span id="line-204"></span>
+<span class="source-line-no">205</span><span id="line-205"> /** Returns the number of available store files in the mob dir */</span>
+<span class="source-line-no">206</span><span id="line-206"> public int getMobStoreFilesCount() {</span>
+<span class="source-line-no">207</span><span id="line-207"> return hfilesMobCount.get();</span>
+<span class="source-line-no">208</span><span id="line-208"> }</span>
+<span class="source-line-no">209</span><span id="line-209"></span>
+<span class="source-line-no">210</span><span id="line-210"> /** Returns the number of available log files */</span>
+<span class="source-line-no">211</span><span id="line-211"> public int getLogsCount() {</span>
+<span class="source-line-no">212</span><span id="line-212"> return logsCount.get();</span>
+<span class="source-line-no">213</span><span id="line-213"> }</span>
+<span class="source-line-no">214</span><span id="line-214"></span>
+<span class="source-line-no">215</span><span id="line-215"> /** Returns the number of missing store files */</span>
+<span class="source-line-no">216</span><span id="line-216"> public int getMissingStoreFilesCount() {</span>
+<span class="source-line-no">217</span><span id="line-217"> return hfilesMissing.get();</span>
+<span class="source-line-no">218</span><span id="line-218"> }</span>
+<span class="source-line-no">219</span><span id="line-219"></span>
+<span class="source-line-no">220</span><span id="line-220"> /** Returns the number of corrupted store files */</span>
+<span class="source-line-no">221</span><span id="line-221"> public int getCorruptedStoreFilesCount() {</span>
+<span class="source-line-no">222</span><span id="line-222"> return hfilesCorrupted.get();</span>
+<span class="source-line-no">223</span><span id="line-223"> }</span>
+<span class="source-line-no">224</span><span id="line-224"></span>
+<span class="source-line-no">225</span><span id="line-225"> /** Returns the number of missing log files */</span>
+<span class="source-line-no">226</span><span id="line-226"> public int getMissingLogsCount() {</span>
+<span class="source-line-no">227</span><span id="line-227"> return logsMissing.get();</span>
+<span class="source-line-no">228</span><span id="line-228"> }</span>
+<span class="source-line-no">229</span><span id="line-229"></span>
+<span class="source-line-no">230</span><span id="line-230"> /** Returns the total size of the store files referenced by the snapshot */</span>
+<span class="source-line-no">231</span><span id="line-231"> public long getStoreFilesSize() {</span>
+<span class="source-line-no">232</span><span id="line-232"> return hfilesSize.get() + hfilesArchiveSize.get() + hfilesMobSize.get();</span>
+<span class="source-line-no">233</span><span id="line-233"> }</span>
+<span class="source-line-no">234</span><span id="line-234"></span>
+<span class="source-line-no">235</span><span id="line-235"> /** Returns the total size of the store files shared */</span>
+<span class="source-line-no">236</span><span id="line-236"> public long getSharedStoreFilesSize() {</span>
+<span class="source-line-no">237</span><span id="line-237"> return hfilesSize.get();</span>
+<span class="source-line-no">238</span><span id="line-238"> }</span>
+<span class="source-line-no">239</span><span id="line-239"></span>
+<span class="source-line-no">240</span><span id="line-240"> /** Returns the total size of the store files in the archive */</span>
+<span class="source-line-no">241</span><span id="line-241"> public long getArchivedStoreFileSize() {</span>
+<span class="source-line-no">242</span><span id="line-242"> return hfilesArchiveSize.get();</span>
+<span class="source-line-no">243</span><span id="line-243"> }</span>
+<span class="source-line-no">244</span><span id="line-244"></span>
+<span class="source-line-no">245</span><span id="line-245"> /** Returns the total size of the store files in the mob store */</span>
+<span class="source-line-no">246</span><span id="line-246"> public long getMobStoreFilesSize() {</span>
+<span class="source-line-no">247</span><span id="line-247"> return hfilesMobSize.get();</span>
+<span class="source-line-no">248</span><span id="line-248"> }</span>
+<span class="source-line-no">249</span><span id="line-249"></span>
+<span class="source-line-no">250</span><span id="line-250"> /**</span>
+<span class="source-line-no">251</span><span id="line-251"> * @return the total size of the store files in the archive which is not shared with other</span>
+<span class="source-line-no">252</span><span id="line-252"> * snapshots and tables This is only calculated when</span>
+<span class="source-line-no">253</span><span id="line-253"> * {@link #getSnapshotStats(Configuration, SnapshotProtos.SnapshotDescription, Map)} is</span>
+<span class="source-line-no">254</span><span id="line-254"> * called with a non-null Map</span>
+<span class="source-line-no">255</span><span id="line-255"> */</span>
+<span class="source-line-no">256</span><span id="line-256"> public long getNonSharedArchivedStoreFilesSize() {</span>
+<span class="source-line-no">257</span><span id="line-257"> return nonSharedHfilesArchiveSize.get();</span>
+<span class="source-line-no">258</span><span id="line-258"> }</span>
+<span class="source-line-no">259</span><span id="line-259"></span>
+<span class="source-line-no">260</span><span id="line-260"> /** Returns the percentage of the shared store files */</span>
+<span class="source-line-no">261</span><span id="line-261"> public float getSharedStoreFilePercentage() {</span>
+<span class="source-line-no">262</span><span id="line-262"> return getStoreFilesSize() == 0</span>
+<span class="source-line-no">263</span><span id="line-263"> ? 0</span>
+<span class="source-line-no">264</span><span id="line-264"> : ((float) hfilesSize.get() / (getStoreFilesSize())) * 100;</span>
+<span class="source-line-no">265</span><span id="line-265"> }</span>
+<span class="source-line-no">266</span><span id="line-266"></span>
+<span class="source-line-no">267</span><span id="line-267"> /** Returns the percentage of the mob store files */</span>
+<span class="source-line-no">268</span><span id="line-268"> public float getMobStoreFilePercentage() {</span>
+<span class="source-line-no">269</span><span id="line-269"> return getStoreFilesSize() == 0</span>
+<span class="source-line-no">270</span><span id="line-270"> ? 0</span>
+<span class="source-line-no">271</span><span id="line-271"> : ((float) hfilesMobSize.get() / (getStoreFilesSize())) * 100;</span>
+<span class="source-line-no">272</span><span id="line-272"> }</span>
+<span class="source-line-no">273</span><span id="line-273"></span>
+<span class="source-line-no">274</span><span id="line-274"> /** Returns the total log size */</span>
+<span class="source-line-no">275</span><span id="line-275"> public long getLogsSize() {</span>
+<span class="source-line-no">276</span><span id="line-276"> return logSize.get();</span>
+<span class="source-line-no">277</span><span id="line-277"> }</span>
+<span class="source-line-no">278</span><span id="line-278"></span>
+<span class="source-line-no">279</span><span id="line-279"> /**</span>
+<span class="source-line-no">280</span><span id="line-280"> * Check if for a give file in archive, if there are other snapshots/tables still reference it.</span>
+<span class="source-line-no">281</span><span id="line-281"> * @param filePath file path in archive</span>
+<span class="source-line-no">282</span><span id="line-282"> * @param snapshotFilesMap a map for store files in snapshots about how many snapshots refer to</span>
+<span class="source-line-no">283</span><span id="line-283"> * it.</span>
+<span class="source-line-no">284</span><span id="line-284"> * @return true or false</span>
+<span class="source-line-no">285</span><span id="line-285"> */</span>
+<span class="source-line-no">286</span><span id="line-286"> private boolean isArchivedFileStillReferenced(final Path filePath,</span>
+<span class="source-line-no">287</span><span id="line-287"> final Map<Path, Integer> snapshotFilesMap) {</span>
+<span class="source-line-no">288</span><span id="line-288"></span>
+<span class="source-line-no">289</span><span id="line-289"> Integer c = snapshotFilesMap.get(filePath);</span>
+<span class="source-line-no">290</span><span id="line-290"></span>
+<span class="source-line-no">291</span><span id="line-291"> // Check if there are other snapshots or table from clone_snapshot() (via back-reference)</span>
+<span class="source-line-no">292</span><span id="line-292"> // still reference to it.</span>
+<span class="source-line-no">293</span><span id="line-293"> if ((c != null) && (c == 1)) {</span>
+<span class="source-line-no">294</span><span id="line-294"> Path parentDir = filePath.getParent();</span>
+<span class="source-line-no">295</span><span id="line-295"> Path backRefDir = HFileLink.getBackReferencesDir(parentDir, filePath.getName());</span>
+<span class="source-line-no">296</span><span id="line-296"> try {</span>
+<span class="source-line-no">297</span><span id="line-297"> if (CommonFSUtils.listStatus(fs, backRefDir) == null) {</span>
+<span class="source-line-no">298</span><span id="line-298"> return false;</span>
+<span class="source-line-no">299</span><span id="line-299"> }</span>
+<span class="source-line-no">300</span><span id="line-300"> } catch (IOException e) {</span>
+<span class="source-line-no">301</span><span id="line-301"> // For the purpose of this function, IOException is ignored and treated as</span>
+<span class="source-line-no">302</span><span id="line-302"> // the file is still being referenced.</span>
+<span class="source-line-no">303</span><span id="line-303"> }</span>
+<span class="source-line-no">304</span><span id="line-304"> }</span>
+<span class="source-line-no">305</span><span id="line-305"> return true;</span>
+<span class="source-line-no">306</span><span id="line-306"> }</span>
+<span class="source-line-no">307</span><span id="line-307"></span>
+<span class="source-line-no">308</span><span id="line-308"> /**</span>
+<span class="source-line-no">309</span><span id="line-309"> * Add the specified store file to the stats</span>
+<span class="source-line-no">310</span><span id="line-310"> * @param region region encoded Name</span>
+<span class="source-line-no">311</span><span id="line-311"> * @param family family name</span>
+<span class="source-line-no">312</span><span id="line-312"> * @param storeFile store file name</span>
+<span class="source-line-no">313</span><span id="line-313"> * @param filesMap store files map for all snapshots, it may be null</span>
+<span class="source-line-no">314</span><span id="line-314"> * @return the store file information</span>
+<span class="source-line-no">315</span><span id="line-315"> */</span>
+<span class="source-line-no">316</span><span id="line-316"> FileInfo addStoreFile(final RegionInfo region, final String family,</span>
+<span class="source-line-no">317</span><span id="line-317"> final SnapshotRegionManifest.StoreFile storeFile, final Map<Path, Integer> filesMap)</span>
+<span class="source-line-no">318</span><span id="line-318"> throws IOException {</span>
+<span class="source-line-no">319</span><span id="line-319"> HFileLink link =</span>
+<span class="source-line-no">320</span><span id="line-320"> HFileLink.build(conf, snapshotTable, region.getEncodedName(), family, storeFile.getName());</span>
+<span class="source-line-no">321</span><span id="line-321"> boolean isCorrupted = false;</span>
+<span class="source-line-no">322</span><span id="line-322"> boolean inArchive = false;</span>
+<span class="source-line-no">323</span><span id="line-323"> long size = -1;</span>
+<span class="source-line-no">324</span><span id="line-324"> try {</span>
+<span class="source-line-no">325</span><span id="line-325"> if (fs.exists(link.getArchivePath())) {</span>
+<span class="source-line-no">326</span><span id="line-326"> inArchive = true;</span>
+<span class="source-line-no">327</span><span id="line-327"> size = fs.getFileStatus(link.getArchivePath()).getLen();</span>
+<span class="source-line-no">328</span><span id="line-328"> hfilesArchiveSize.addAndGet(size);</span>
+<span class="source-line-no">329</span><span id="line-329"> hfilesArchiveCount.incrementAndGet();</span>
+<span class="source-line-no">330</span><span id="line-330"></span>
+<span class="source-line-no">331</span><span id="line-331"> // If store file is not shared with other snapshots and tables,</span>
+<span class="source-line-no">332</span><span id="line-332"> // increase nonSharedHfilesArchiveSize</span>
+<span class="source-line-no">333</span><span id="line-333"> if (</span>
+<span class="source-line-no">334</span><span id="line-334"> (filesMap != null) && !isArchivedFileStillReferenced(link.getArchivePath(), filesMap)</span>
+<span class="source-line-no">335</span><span id="line-335"> ) {</span>
+<span class="source-line-no">336</span><span id="line-336"> nonSharedHfilesArchiveSize.addAndGet(size);</span>
+<span class="source-line-no">337</span><span id="line-337"> }</span>
+<span class="source-line-no">338</span><span id="line-338"> } else if (fs.exists(link.getMobPath())) {</span>
+<span class="source-line-no">339</span><span id="line-339"> inArchive = true;</span>
+<span class="source-line-no">340</span><span id="line-340"> size = fs.getFileStatus(link.getMobPath()).getLen();</span>
+<span class="source-line-no">341</span><span id="line-341"> hfilesMobSize.addAndGet(size);</span>
+<span class="source-line-no">342</span><span id="line-342"> hfilesMobCount.incrementAndGet();</span>
+<span class="source-line-no">343</span><span id="line-343"> } else {</span>
+<span class="source-line-no">344</span><span id="line-344"> size = link.getFileStatus(fs).getLen();</span>
+<span class="source-line-no">345</span><span id="line-345"> hfilesSize.addAndGet(size);</span>
+<span class="source-line-no">346</span><span id="line-346"> hfilesCount.incrementAndGet();</span>
+<span class="source-line-no">347</span><span id="line-347"> }</span>
+<span class="source-line-no">348</span><span id="line-348"> isCorrupted = (storeFile.hasFileSize() && storeFile.getFileSize() != size);</span>
+<span class="source-line-no">349</span><span id="line-349"> if (isCorrupted) hfilesCorrupted.incrementAndGet();</span>
+<span class="source-line-no">350</span><span id="line-350"> } catch (FileNotFoundException e) {</span>
+<span class="source-line-no">351</span><span id="line-351"> hfilesMissing.incrementAndGet();</span>
+<span class="source-line-no">352</span><span id="line-352"> }</span>
+<span class="source-line-no">353</span><span id="line-353"> return new FileInfo(inArchive, size, isCorrupted);</span>
+<span class="source-line-no">354</span><span id="line-354"> }</span>
+<span class="source-line-no">355</span><span id="line-355"></span>
+<span class="source-line-no">356</span><span id="line-356"> /**</span>
+<span class="source-line-no">357</span><span id="line-357"> * Add the specified log file to the stats</span>
+<span class="source-line-no">358</span><span id="line-358"> * @param server server name</span>
+<span class="source-line-no">359</span><span id="line-359"> * @param logfile log file name</span>
+<span class="source-line-no">360</span><span id="line-360"> * @return the log information</span>
+<span class="source-line-no">361</span><span id="line-361"> */</span>
+<span class="source-line-no">362</span><span id="line-362"> FileInfo addLogFile(final String server, final String logfile) throws IOException {</span>
+<span class="source-line-no">363</span><span id="line-363"> WALLink logLink = new WALLink(conf, server, logfile);</span>
+<span class="source-line-no">364</span><span id="line-364"> long size = -1;</span>
+<span class="source-line-no">365</span><span id="line-365"> try {</span>
+<span class="source-line-no">366</span><span id="line-366"> size = logLink.getFileStatus(fs).getLen();</span>
+<span class="source-line-no">367</span><span id="line-367"> logSize.addAndGet(size);</span>
+<span class="source-line-no">368</span><span id="line-368"> logsCount.incrementAndGet();</span>
+<span class="source-line-no">369</span><span id="line-369"> } catch (FileNotFoundException e) {</span>
+<span class="source-line-no">370</span><span id="line-370"> logsMissing.incrementAndGet();</span>
+<span class="source-line-no">371</span><span id="line-371"> }</span>
+<span class="source-line-no">372</span><span id="line-372"> return new FileInfo(false, size, false);</span>
+<span class="source-line-no">373</span><span id="line-373"> }</span>
+<span class="source-line-no">374</span><span id="line-374"> }</span>
+<span class="source-line-no">375</span><span id="line-375"></span>
+<span class="source-line-no">376</span><span id="line-376"> private FileSystem fs;</span>
+<span class="source-line-no">377</span><span id="line-377"> private Path rootDir;</span>
+<span class="source-line-no">378</span><span id="line-378"></span>
+<span class="source-line-no">379</span><span id="line-379"> private SnapshotManifest snapshotManifest;</span>
+<span class="source-line-no">380</span><span id="line-380"></span>
+<span class="source-line-no">381</span><span id="line-381"> private boolean listSnapshots = false;</span>
+<span class="source-line-no">382</span><span id="line-382"> private String snapshotName;</span>
+<span class="source-line-no">383</span><span id="line-383"> private Path remoteDir;</span>
+<span class="source-line-no">384</span><span id="line-384"> private boolean showSchema = false;</span>
+<span class="source-line-no">385</span><span id="line-385"> private boolean showFiles = false;</span>
+<span class="source-line-no">386</span><span id="line-386"> private boolean showStats = false;</span>
+<span class="source-line-no">387</span><span id="line-387"> private boolean printSizeInBytes = false;</span>
+<span class="source-line-no">388</span><span id="line-388"></span>
+<span class="source-line-no">389</span><span id="line-389"> @Override</span>
+<span class="source-line-no">390</span><span id="line-390"> public int doWork() throws IOException, InterruptedException {</span>
+<span class="source-line-no">391</span><span id="line-391"> if (remoteDir != null) {</span>
+<span class="source-line-no">392</span><span id="line-392"> URI defaultFs = remoteDir.getFileSystem(conf).getUri();</span>
+<span class="source-line-no">393</span><span id="line-393"> CommonFSUtils.setFsDefault(conf, new Path(defaultFs));</span>
+<span class="source-line-no">394</span><span id="line-394"> CommonFSUtils.setRootDir(conf, remoteDir);</span>
+<span class="source-line-no">395</span><span id="line-395"> }</span>
+<span class="source-line-no">396</span><span id="line-396"></span>
+<span class="source-line-no">397</span><span id="line-397"> // List Available Snapshots</span>
+<span class="source-line-no">398</span><span id="line-398"> if (listSnapshots) {</span>
+<span class="source-line-no">399</span><span id="line-399"> SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");</span>
+<span class="source-line-no">400</span><span id="line-400"> List<SnapshotDescription> snapshotDescriptions = getSnapshotList(conf);</span>
+<span class="source-line-no">401</span><span id="line-401"> System.out.printf("%-20s | %-20s | %-20s | %-20s | %s%n", "SNAPSHOT", "CREATION TIME",</span>
+<span class="source-line-no">402</span><span id="line-402"> "TTL(Sec)", "EXPIRED", "TABLE NAME");</span>
+<span class="source-line-no">403</span><span id="line-403"> long currentTime = System.currentTimeMillis();</span>
+<span class="source-line-no">404</span><span id="line-404"> for (SnapshotDescription desc : snapshotDescriptions) {</span>
+<span class="source-line-no">405</span><span id="line-405"> String ttlInfo =</span>
+<span class="source-line-no">406</span><span id="line-406"> desc.getTtl() == DEFAULT_SNAPSHOT_TTL ? TTL_FOREVER : String.valueOf(desc.getTtl());</span>
+<span class="source-line-no">407</span><span id="line-407"> String expired = SnapshotDescriptionUtils.isExpiredSnapshot(desc.getTtl(),</span>
+<span class="source-line-no">408</span><span id="line-408"> desc.getCreationTime(), currentTime) ? EXPIRED_LABEL : NOT_EXPIRED_LABEL;</span>
+<span class="source-line-no">409</span><span id="line-409"> System.out.printf("%-20s | %20s | %20s | %20s | %s%n", desc.getName(),</span>
+<span class="source-line-no">410</span><span id="line-410"> df.format(new Date(desc.getCreationTime())), ttlInfo, expired,</span>
+<span class="source-line-no">411</span><span id="line-411"> desc.getTableNameAsString());</span>
+<span class="source-line-no">412</span><span id="line-412"> }</span>
+<span class="source-line-no">413</span><span id="line-413"> return 0;</span>
+<span class="source-line-no">414</span><span id="line-414"> }</span>
+<span class="source-line-no">415</span><span id="line-415"></span>
+<span class="source-line-no">416</span><span id="line-416"> rootDir = CommonFSUtils.getRootDir(conf);</span>
+<span class="source-line-no">417</span><span id="line-417"> fs = FileSystem.get(rootDir.toUri(), conf);</span>
+<span class="source-line-no">418</span><span id="line-418"> LOG.debug("fs=" + fs.getUri().toString() + " root=" + rootDir);</span>
+<span class="source-line-no">419</span><span id="line-419"></span>
+<span class="source-line-no">420</span><span id="line-420"> // Load snapshot information</span>
+<span class="source-line-no">421</span><span id="line-421"> if (!loadSnapshotInfo(snapshotName)) {</span>
+<span class="source-line-no">422</span><span id="line-422"> System.err.println("Snapshot '" + snapshotName + "' not found!");</span>
+<span class="source-line-no">423</span><span id="line-423"> return 1;</span>
+<span class="source-line-no">424</span><span id="line-424"> }</span>
+<span class="source-line-no">425</span><span id="line-425"></span>
+<span class="source-line-no">426</span><span id="line-426"> printInfo();</span>
+<span class="source-line-no">427</span><span id="line-427"> if (showSchema) {</span>
+<span class="source-line-no">428</span><span id="line-428"> printSchema();</span>
+<span class="source-line-no">429</span><span id="line-429"> }</span>
+<span class="source-line-no">430</span><span id="line-430"> printFiles(showFiles, showStats);</span>
+<span class="source-line-no">431</span><span id="line-431"></span>
+<span class="source-line-no">432</span><span id="line-432"> return 0;</span>
+<span class="source-line-no">433</span><span id="line-433"> }</span>
+<span class="source-line-no">434</span><span id="line-434"></span>
+<span class="source-line-no">435</span><span id="line-435"> /**</span>
+<span class="source-line-no">436</span><span id="line-436"> * Load snapshot info and table descriptor for the specified snapshot</span>
+<span class="source-line-no">437</span><span id="line-437"> * @param snapshotName name of the snapshot to load</span>
+<span class="source-line-no">438</span><span id="line-438"> * @return false if snapshot is not found</span>
+<span class="source-line-no">439</span><span id="line-439"> */</span>
+<span class="source-line-no">440</span><span id="line-440"> private boolean loadSnapshotInfo(final String snapshotName) throws IOException {</span>
+<span class="source-line-no">441</span><span id="line-441"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);</span>
+<span class="source-line-no">442</span><span id="line-442"> if (!fs.exists(snapshotDir)) {</span>
+<span class="source-line-no">443</span><span id="line-443"> LOG.warn("Snapshot '" + snapshotName + "' not found in: " + snapshotDir);</span>
+<span class="source-line-no">444</span><span id="line-444"> return false;</span>
+<span class="source-line-no">445</span><span id="line-445"> }</span>
+<span class="source-line-no">446</span><span id="line-446"></span>
+<span class="source-line-no">447</span><span id="line-447"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">448</span><span id="line-448"> SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);</span>
+<span class="source-line-no">449</span><span id="line-449"> snapshotManifest = SnapshotManifest.open(getConf(), fs, snapshotDir, snapshotDesc);</span>
+<span class="source-line-no">450</span><span id="line-450"> return true;</span>
+<span class="source-line-no">451</span><span id="line-451"> }</span>
+<span class="source-line-no">452</span><span id="line-452"></span>
+<span class="source-line-no">453</span><span id="line-453"> /**</span>
+<span class="source-line-no">454</span><span id="line-454"> * Dump the {@link SnapshotDescription}</span>
+<span class="source-line-no">455</span><span id="line-455"> */</span>
+<span class="source-line-no">456</span><span id="line-456"> private void printInfo() {</span>
+<span class="source-line-no">457</span><span id="line-457"> SnapshotProtos.SnapshotDescription snapshotDesc = snapshotManifest.getSnapshotDescription();</span>
+<span class="source-line-no">458</span><span id="line-458"> SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");</span>
+<span class="source-line-no">459</span><span id="line-459"> String ttlInfo = snapshotDesc.getTtl() == DEFAULT_SNAPSHOT_TTL</span>
+<span class="source-line-no">460</span><span id="line-460"> ? TTL_FOREVER</span>
+<span class="source-line-no">461</span><span id="line-461"> : String.valueOf(snapshotDesc.getTtl());</span>
+<span class="source-line-no">462</span><span id="line-462"> String expired = SnapshotDescriptionUtils.isExpiredSnapshot(snapshotDesc.getTtl(),</span>
+<span class="source-line-no">463</span><span id="line-463"> snapshotDesc.getCreationTime(), System.currentTimeMillis())</span>
+<span class="source-line-no">464</span><span id="line-464"> ? EXPIRED_LABEL</span>
+<span class="source-line-no">465</span><span id="line-465"> : NOT_EXPIRED_LABEL;</span>
+<span class="source-line-no">466</span><span id="line-466"> System.out.println("Snapshot Info");</span>
+<span class="source-line-no">467</span><span id="line-467"> System.out.println("-----------------------------------------");</span>
+<span class="source-line-no">468</span><span id="line-468"> System.out.println(" Name: " + snapshotDesc.getName());</span>
+<span class="source-line-no">469</span><span id="line-469"> System.out.println(" Type: " + snapshotDesc.getType());</span>
+<span class="source-line-no">470</span><span id="line-470"> System.out.println(" Table: " + snapshotDesc.getTable());</span>
+<span class="source-line-no">471</span><span id="line-471"> System.out.println(" Format: " + snapshotDesc.getVersion());</span>
+<span class="source-line-no">472</span><span id="line-472"> System.out.println(" Created: " + df.format(new Date(snapshotDesc.getCreationTime())));</span>
+<span class="source-line-no">473</span><span id="line-473"> System.out.println("Ttl(Sec): " + ttlInfo);</span>
+<span class="source-line-no">474</span><span id="line-474"> System.out.println(" Expired: " + expired);</span>
+<span class="source-line-no">475</span><span id="line-475"> System.out.println(" Owner: " + snapshotDesc.getOwner());</span>
+<span class="source-line-no">476</span><span id="line-476"> System.out.println();</span>
+<span class="source-line-no">477</span><span id="line-477"> }</span>
+<span class="source-line-no">478</span><span id="line-478"></span>
+<span class="source-line-no">479</span><span id="line-479"> /**</span>
+<span class="source-line-no">480</span><span id="line-480"> * Dump the {@link org.apache.hadoop.hbase.client.TableDescriptor}</span>
+<span class="source-line-no">481</span><span id="line-481"> */</span>
+<span class="source-line-no">482</span><span id="line-482"> private void printSchema() {</span>
+<span class="source-line-no">483</span><span id="line-483"> System.out.println("Table Descriptor");</span>
+<span class="source-line-no">484</span><span id="line-484"> System.out.println("----------------------------------------");</span>
+<span class="source-line-no">485</span><span id="line-485"> System.out.println(snapshotManifest.getTableDescriptor().toString());</span>
+<span class="source-line-no">486</span><span id="line-486"> System.out.println();</span>
+<span class="source-line-no">487</span><span id="line-487"> }</span>
+<span class="source-line-no">488</span><span id="line-488"></span>
+<span class="source-line-no">489</span><span id="line-489"> /**</span>
+<span class="source-line-no">490</span><span id="line-490"> * Collect the hfiles and logs statistics of the snapshot and dump the file list if requested and</span>
+<span class="source-line-no">491</span><span id="line-491"> * the collected information.</span>
+<span class="source-line-no">492</span><span id="line-492"> */</span>
+<span class="source-line-no">493</span><span id="line-493"> private void printFiles(final boolean showFiles, final boolean showStats) throws IOException {</span>
+<span class="source-line-no">494</span><span id="line-494"> if (showFiles) {</span>
+<span class="source-line-no">495</span><span id="line-495"> System.out.println("Snapshot Files");</span>
+<span class="source-line-no">496</span><span id="line-496"> System.out.println("----------------------------------------");</span>
+<span class="source-line-no">497</span><span id="line-497"> }</span>
+<span class="source-line-no">498</span><span id="line-498"></span>
+<span class="source-line-no">499</span><span id="line-499"> // Collect information about hfiles and logs in the snapshot</span>
+<span class="source-line-no">500</span><span id="line-500"> final SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">501</span><span id="line-501"> snapshotManifest.getSnapshotDescription();</span>
+<span class="source-line-no">502</span><span id="line-502"> final String table = snapshotDesc.getTable();</span>
+<span class="source-line-no">503</span><span id="line-503"> final SnapshotDescription desc = ProtobufUtil.createSnapshotDesc(snapshotDesc);</span>
+<span class="source-line-no">504</span><span id="line-504"> final SnapshotStats stats = new SnapshotStats(this.getConf(), this.fs, desc);</span>
+<span class="source-line-no">505</span><span id="line-505"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(getConf(), fs, snapshotManifest,</span>
+<span class="source-line-no">506</span><span id="line-506"> "SnapshotInfo", new SnapshotReferenceUtil.SnapshotVisitor() {</span>
+<span class="source-line-no">507</span><span id="line-507"> @Override</span>
+<span class="source-line-no">508</span><span id="line-508"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
+<span class="source-line-no">509</span><span id="line-509"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
+<span class="source-line-no">510</span><span id="line-510"> if (storeFile.hasReference()) return;</span>
+<span class="source-line-no">511</span><span id="line-511"></span>
+<span class="source-line-no">512</span><span id="line-512"> SnapshotStats.FileInfo info = stats.addStoreFile(regionInfo, family, storeFile, null);</span>
+<span class="source-line-no">513</span><span id="line-513"> if (showFiles) {</span>
+<span class="source-line-no">514</span><span id="line-514"> String state = info.getStateToString();</span>
+<span class="source-line-no">515</span><span id="line-515"> System.out.printf("%8s %s/%s/%s/%s %s%n",</span>
+<span class="source-line-no">516</span><span id="line-516"> (info.isMissing() ? "-" : fileSizeToString(info.getSize())), table,</span>
+<span class="source-line-no">517</span><span id="line-517"> regionInfo.getEncodedName(), family, storeFile.getName(),</span>
+<span class="source-line-no">518</span><span id="line-518"> state == null ? "" : "(" + state + ")");</span>
+<span class="source-line-no">519</span><span id="line-519"> }</span>
+<span class="source-line-no">520</span><span id="line-520"> }</span>
+<span class="source-line-no">521</span><span id="line-521"> });</span>
+<span class="source-line-no">522</span><span id="line-522"></span>
+<span class="source-line-no">523</span><span id="line-523"> // Dump the stats</span>
+<span class="source-line-no">524</span><span id="line-524"> System.out.println();</span>
+<span class="source-line-no">525</span><span id="line-525"> if (stats.isSnapshotCorrupted()) {</span>
+<span class="source-line-no">526</span><span id="line-526"> System.out.println("**************************************************************");</span>
+<span class="source-line-no">527</span><span id="line-527"> System.out.printf("BAD SNAPSHOT: %d hfile(s) and %d log(s) missing.%n",</span>
+<span class="source-line-no">528</span><span id="line-528"> stats.getMissingStoreFilesCount(), stats.getMissingLogsCount());</span>
+<span class="source-line-no">529</span><span id="line-529"> System.out.printf(" %d hfile(s) corrupted.%n",</span>
+<span class="source-line-no">530</span><span id="line-530"> stats.getCorruptedStoreFilesCount());</span>
+<span class="source-line-no">531</span><span id="line-531"> System.out.println("**************************************************************");</span>
+<span class="source-line-no">532</span><span id="line-532"> }</span>
+<span class="source-line-no">533</span><span id="line-533"></span>
+<span class="source-line-no">534</span><span id="line-534"> if (showStats) {</span>
+<span class="source-line-no">535</span><span id="line-535"> System.out.printf(</span>
+<span class="source-line-no">536</span><span id="line-536"> "%d HFiles (%d in archive, %d in mob storage), total size %s "</span>
+<span class="source-line-no">537</span><span id="line-537"> + "(%.2f%% %s shared with the source table, %.2f%% %s in mob dir)%n",</span>
+<span class="source-line-no">538</span><span id="line-538"> stats.getStoreFilesCount(), stats.getArchivedStoreFilesCount(),</span>
+<span class="source-line-no">539</span><span id="line-539"> stats.getMobStoreFilesCount(), fileSizeToString(stats.getStoreFilesSize()),</span>
+<span class="source-line-no">540</span><span id="line-540"> stats.getSharedStoreFilePercentage(), fileSizeToString(stats.getSharedStoreFilesSize()),</span>
+<span class="source-line-no">541</span><span id="line-541"> stats.getMobStoreFilePercentage(), fileSizeToString(stats.getMobStoreFilesSize()));</span>
+<span class="source-line-no">542</span><span id="line-542"> System.out.printf("%d Logs, total size %s%n", stats.getLogsCount(),</span>
+<span class="source-line-no">543</span><span id="line-543"> fileSizeToString(stats.getLogsSize()));</span>
+<span class="source-line-no">544</span><span id="line-544"> System.out.println();</span>
+<span class="source-line-no">545</span><span id="line-545"> }</span>
+<span class="source-line-no">546</span><span id="line-546"> }</span>
+<span class="source-line-no">547</span><span id="line-547"></span>
+<span class="source-line-no">548</span><span id="line-548"> private String fileSizeToString(long size) {</span>
+<span class="source-line-no">549</span><span id="line-549"> return printSizeInBytes ? Long.toString(size) : Strings.humanReadableInt(size);</span>
+<span class="source-line-no">550</span><span id="line-550"> }</span>
+<span class="source-line-no">551</span><span id="line-551"></span>
+<span class="source-line-no">552</span><span id="line-552"> @Override</span>
+<span class="source-line-no">553</span><span id="line-553"> protected void addOptions() {</span>
+<span class="source-line-no">554</span><span id="line-554"> addOption(Options.SNAPSHOT);</span>
+<span class="source-line-no">555</span><span id="line-555"> addOption(Options.REMOTE_DIR);</span>
+<span class="source-line-no">556</span><span id="line-556"> addOption(Options.LIST_SNAPSHOTS);</span>
+<span class="source-line-no">557</span><span id="line-557"> addOption(Options.FILES);</span>
+<span class="source-line-no">558</span><span id="line-558"> addOption(Options.STATS);</span>
+<span class="source-line-no">559</span><span id="line-559"> addOption(Options.SCHEMA);</span>
+<span class="source-line-no">560</span><span id="line-560"> addOption(Options.SIZE_IN_BYTES);</span>
+<span class="source-line-no">561</span><span id="line-561"> }</span>
+<span class="source-line-no">562</span><span id="line-562"></span>
+<span class="source-line-no">563</span><span id="line-563"> @Override</span>
+<span class="source-line-no">564</span><span id="line-564"> protected CommandLineParser newParser() {</span>
+<span class="source-line-no">565</span><span id="line-565"> // Commons-CLI lacks the capability to handle combinations of options, so we do it ourselves</span>
+<span class="source-line-no">566</span><span id="line-566"> // Validate in parse() to get helpful error messages instead of exploding in processOptions()</span>
+<span class="source-line-no">567</span><span id="line-567"> return new DefaultParser() {</span>
+<span class="source-line-no">568</span><span id="line-568"> @Override</span>
+<span class="source-line-no">569</span><span id="line-569"> public CommandLine parse(org.apache.hbase.thirdparty.org.apache.commons.cli.Options opts,</span>
+<span class="source-line-no">570</span><span id="line-570"> String[] args, Properties props, boolean stop) throws ParseException {</span>
+<span class="source-line-no">571</span><span id="line-571"> CommandLine cl = super.parse(opts, args, props, stop);</span>
+<span class="source-line-no">572</span><span id="line-572"> if (!cmd.hasOption(Options.LIST_SNAPSHOTS) && !cmd.hasOption(Options.SNAPSHOT)) {</span>
+<span class="source-line-no">573</span><span id="line-573"> throw new ParseException("Missing required snapshot option!");</span>
+<span class="source-line-no">574</span><span id="line-574"> }</span>
+<span class="source-line-no">575</span><span id="line-575"> return cl;</span>
+<span class="source-line-no">576</span><span id="line-576"> }</span>
+<span class="source-line-no">577</span><span id="line-577"> };</span>
<span class="source-line-no">578</span><span id="line-578"> }</span>
<span class="source-line-no">579</span><span id="line-579"></span>
-<span class="source-line-no">580</span><span id="line-580"> /**</span>
-<span class="source-line-no">581</span><span id="line-581"> * Returns the snapshot stats</span>
-<span class="source-line-no">582</span><span id="line-582"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">583</span><span id="line-583"> * @param snapshot {@link SnapshotDescription} to get stats from</span>
-<span class="source-line-no">584</span><span id="line-584"> * @return the snapshot stats</span>
-<span class="source-line-no">585</span><span id="line-585"> */</span>
-<span class="source-line-no">586</span><span id="line-586"> public static SnapshotStats getSnapshotStats(final Configuration conf,</span>
-<span class="source-line-no">587</span><span id="line-587"> final SnapshotDescription snapshot) throws IOException {</span>
-<span class="source-line-no">588</span><span id="line-588"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">589</span><span id="line-589"> ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
-<span class="source-line-no">590</span><span id="line-590"> return getSnapshotStats(conf, snapshotDesc, null);</span>
-<span class="source-line-no">591</span><span id="line-591"> }</span>
-<span class="source-line-no">592</span><span id="line-592"></span>
-<span class="source-line-no">593</span><span id="line-593"> /**</span>
-<span class="source-line-no">594</span><span id="line-594"> * Returns the snapshot stats</span>
-<span class="source-line-no">595</span><span id="line-595"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">596</span><span id="line-596"> * @param snapshotDesc HBaseProtos.SnapshotDescription to get stats from</span>
-<span class="source-line-no">597</span><span id="line-597"> * @param filesMap {@link Map} store files map for all snapshots, it may be null</span>
-<span class="source-line-no">598</span><span id="line-598"> * @return the snapshot stats</span>
-<span class="source-line-no">599</span><span id="line-599"> */</span>
-<span class="source-line-no">600</span><span id="line-600"> public static SnapshotStats getSnapshotStats(final Configuration conf,</span>
-<span class="source-line-no">601</span><span id="line-601"> final SnapshotProtos.SnapshotDescription snapshotDesc, final Map<Path, Integer> filesMap)</span>
-<span class="source-line-no">602</span><span id="line-602"> throws IOException {</span>
-<span class="source-line-no">603</span><span id="line-603"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
-<span class="source-line-no">604</span><span id="line-604"> FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
-<span class="source-line-no">605</span><span id="line-605"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotDesc, rootDir);</span>
-<span class="source-line-no">606</span><span id="line-606"> SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);</span>
-<span class="source-line-no">607</span><span id="line-607"> final SnapshotStats stats = new SnapshotStats(conf, fs, snapshotDesc);</span>
-<span class="source-line-no">608</span><span id="line-608"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(conf, fs, manifest,</span>
-<span class="source-line-no">609</span><span id="line-609"> "SnapshotsStatsAggregation", new SnapshotReferenceUtil.SnapshotVisitor() {</span>
-<span class="source-line-no">610</span><span id="line-610"> @Override</span>
-<span class="source-line-no">611</span><span id="line-611"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
-<span class="source-line-no">612</span><span id="line-612"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
-<span class="source-line-no">613</span><span id="line-613"> if (!storeFile.hasReference()) {</span>
-<span class="source-line-no">614</span><span id="line-614"> stats.addStoreFile(regionInfo, family, storeFile, filesMap);</span>
-<span class="source-line-no">615</span><span id="line-615"> }</span>
-<span class="source-line-no">616</span><span id="line-616"> }</span>
-<span class="source-line-no">617</span><span id="line-617"> });</span>
-<span class="source-line-no">618</span><span id="line-618"> return stats;</span>
-<span class="source-line-no">619</span><span id="line-619"> }</span>
-<span class="source-line-no">620</span><span id="line-620"></span>
-<span class="source-line-no">621</span><span id="line-621"> /**</span>
-<span class="source-line-no">622</span><span id="line-622"> * Returns the list of available snapshots in the specified location</span>
-<span class="source-line-no">623</span><span id="line-623"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">624</span><span id="line-624"> * @return the list of snapshots</span>
-<span class="source-line-no">625</span><span id="line-625"> */</span>
-<span class="source-line-no">626</span><span id="line-626"> public static List<SnapshotDescription> getSnapshotList(final Configuration conf)</span>
-<span class="source-line-no">627</span><span id="line-627"> throws IOException {</span>
-<span class="source-line-no">628</span><span id="line-628"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
-<span class="source-line-no">629</span><span id="line-629"> FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
-<span class="source-line-no">630</span><span id="line-630"> Path snapshotDir = SnapshotDescriptionUtils.getSnapshotsDir(rootDir);</span>
-<span class="source-line-no">631</span><span id="line-631"> FileStatus[] snapshots = CommonFSUtils.listStatus(fs, snapshotDir,</span>
-<span class="source-line-no">632</span><span id="line-632"> new SnapshotDescriptionUtils.CompletedSnaphotDirectoriesFilter(fs));</span>
-<span class="source-line-no">633</span><span id="line-633"> if (snapshots == null) {</span>
-<span class="source-line-no">634</span><span id="line-634"> return Collections.emptyList();</span>
-<span class="source-line-no">635</span><span id="line-635"> }</span>
-<span class="source-line-no">636</span><span id="line-636"> List<SnapshotDescription> snapshotLists = new ArrayList<>(snapshots.length);</span>
-<span class="source-line-no">637</span><span id="line-637"> for (FileStatus snapshotDirStat : snapshots) {</span>
-<span class="source-line-no">638</span><span id="line-638"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">639</span><span id="line-639"> SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDirStat.getPath());</span>
-<span class="source-line-no">640</span><span id="line-640"> snapshotLists.add(ProtobufUtil.createSnapshotDesc(snapshotDesc));</span>
-<span class="source-line-no">641</span><span id="line-641"> }</span>
-<span class="source-line-no">642</span><span id="line-642"> return snapshotLists;</span>
-<span class="source-line-no">643</span><span id="line-643"> }</span>
-<span class="source-line-no">644</span><span id="line-644"></span>
-<span class="source-line-no">645</span><span id="line-645"> /**</span>
-<span class="source-line-no">646</span><span id="line-646"> * Gets the store files map for snapshot</span>
-<span class="source-line-no">647</span><span id="line-647"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">648</span><span id="line-648"> * @param snapshot {@link SnapshotDescription} to get stats from</span>
-<span class="source-line-no">649</span><span id="line-649"> * @param exec the {@link ExecutorService} to use</span>
-<span class="source-line-no">650</span><span id="line-650"> * @param filesMap {@link Map} the map to put the mapping entries</span>
-<span class="source-line-no">651</span><span id="line-651"> * @param uniqueHFilesArchiveSize {@link AtomicLong} the accumulated store file size in archive</span>
-<span class="source-line-no">652</span><span id="line-652"> * @param uniqueHFilesSize {@link AtomicLong} the accumulated store file size shared</span>
-<span class="source-line-no">653</span><span id="line-653"> * @param uniqueHFilesMobSize {@link AtomicLong} the accumulated mob store file size shared</span>
-<span class="source-line-no">654</span><span id="line-654"> */</span>
-<span class="source-line-no">655</span><span id="line-655"> private static void getSnapshotFilesMap(final Configuration conf,</span>
-<span class="source-line-no">656</span><span id="line-656"> final SnapshotDescription snapshot, final ExecutorService exec,</span>
-<span class="source-line-no">657</span><span id="line-657"> final ConcurrentHashMap<Path, Integer> filesMap, final AtomicLong uniqueHFilesArchiveSize,</span>
-<span class="source-line-no">658</span><span id="line-658"> final AtomicLong uniqueHFilesSize, final AtomicLong uniqueHFilesMobSize) throws IOException {</span>
-<span class="source-line-no">659</span><span id="line-659"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">660</span><span id="line-660"> ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
-<span class="source-line-no">661</span><span id="line-661"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
-<span class="source-line-no">662</span><span id="line-662"> final FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
-<span class="source-line-no">663</span><span id="line-663"></span>
-<span class="source-line-no">664</span><span id="line-664"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotDesc, rootDir);</span>
-<span class="source-line-no">665</span><span id="line-665"> SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);</span>
-<span class="source-line-no">666</span><span id="line-666"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(conf, fs, manifest, exec,</span>
-<span class="source-line-no">667</span><span id="line-667"> new SnapshotReferenceUtil.SnapshotVisitor() {</span>
-<span class="source-line-no">668</span><span id="line-668"> @Override</span>
-<span class="source-line-no">669</span><span id="line-669"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
-<span class="source-line-no">670</span><span id="line-670"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
-<span class="source-line-no">671</span><span id="line-671"> if (!storeFile.hasReference()) {</span>
-<span class="source-line-no">672</span><span id="line-672"> HFileLink link = HFileLink.build(conf, snapshot.getTableName(),</span>
-<span class="source-line-no">673</span><span id="line-673"> regionInfo.getEncodedName(), family, storeFile.getName());</span>
-<span class="source-line-no">674</span><span id="line-674"> long size;</span>
-<span class="source-line-no">675</span><span id="line-675"> Integer count;</span>
-<span class="source-line-no">676</span><span id="line-676"> Path p;</span>
-<span class="source-line-no">677</span><span id="line-677"> AtomicLong al;</span>
-<span class="source-line-no">678</span><span id="line-678"> int c = 0;</span>
-<span class="source-line-no">679</span><span id="line-679"></span>
-<span class="source-line-no">680</span><span id="line-680"> if (fs.exists(link.getArchivePath())) {</span>
-<span class="source-line-no">681</span><span id="line-681"> p = link.getArchivePath();</span>
-<span class="source-line-no">682</span><span id="line-682"> al = uniqueHFilesArchiveSize;</span>
-<span class="source-line-no">683</span><span id="line-683"> size = fs.getFileStatus(p).getLen();</span>
-<span class="source-line-no">684</span><span id="line-684"> } else if (fs.exists(link.getMobPath())) {</span>
-<span class="source-line-no">685</span><span id="line-685"> p = link.getMobPath();</span>
-<span class="source-line-no">686</span><span id="line-686"> al = uniqueHFilesMobSize;</span>
-<span class="source-line-no">687</span><span id="line-687"> size = fs.getFileStatus(p).getLen();</span>
-<span class="source-line-no">688</span><span id="line-688"> } else {</span>
-<span class="source-line-no">689</span><span id="line-689"> p = link.getOriginPath();</span>
-<span class="source-line-no">690</span><span id="line-690"> al = uniqueHFilesSize;</span>
-<span class="source-line-no">691</span><span id="line-691"> size = link.getFileStatus(fs).getLen();</span>
-<span class="source-line-no">692</span><span id="line-692"> }</span>
-<span class="source-line-no">693</span><span id="line-693"></span>
-<span class="source-line-no">694</span><span id="line-694"> // If it has been counted, do not double count</span>
-<span class="source-line-no">695</span><span id="line-695"> count = filesMap.get(p);</span>
-<span class="source-line-no">696</span><span id="line-696"> if (count != null) {</span>
-<span class="source-line-no">697</span><span id="line-697"> c = count.intValue();</span>
-<span class="source-line-no">698</span><span id="line-698"> } else {</span>
-<span class="source-line-no">699</span><span id="line-699"> al.addAndGet(size);</span>
-<span class="source-line-no">700</span><span id="line-700"> }</span>
-<span class="source-line-no">701</span><span id="line-701"></span>
-<span class="source-line-no">702</span><span id="line-702"> filesMap.put(p, ++c);</span>
-<span class="source-line-no">703</span><span id="line-703"> }</span>
-<span class="source-line-no">704</span><span id="line-704"> }</span>
-<span class="source-line-no">705</span><span id="line-705"> });</span>
-<span class="source-line-no">706</span><span id="line-706"> }</span>
-<span class="source-line-no">707</span><span id="line-707"></span>
-<span class="source-line-no">708</span><span id="line-708"> /**</span>
-<span class="source-line-no">709</span><span id="line-709"> * Returns the map of store files based on path for all snapshots</span>
-<span class="source-line-no">710</span><span id="line-710"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">711</span><span id="line-711"> * @param uniqueHFilesArchiveSize pass out the size for store files in archive</span>
-<span class="source-line-no">712</span><span id="line-712"> * @param uniqueHFilesSize pass out the size for store files shared</span>
-<span class="source-line-no">713</span><span id="line-713"> * @param uniqueHFilesMobSize pass out the size for mob store files shared</span>
-<span class="source-line-no">714</span><span id="line-714"> * @return the map of store files</span>
-<span class="source-line-no">715</span><span id="line-715"> */</span>
-<span class="source-line-no">716</span><span id="line-716"> public static Map<Path, Integer> getSnapshotsFilesMap(final Configuration conf,</span>
-<span class="source-line-no">717</span><span id="line-717"> AtomicLong uniqueHFilesArchiveSize, AtomicLong uniqueHFilesSize, AtomicLong uniqueHFilesMobSize)</span>
-<span class="source-line-no">718</span><span id="line-718"> throws IOException {</span>
-<span class="source-line-no">719</span><span id="line-719"> List<SnapshotDescription> snapshotList = getSnapshotList(conf);</span>
-<span class="source-line-no">720</span><span id="line-720"></span>
-<span class="source-line-no">721</span><span id="line-721"> if (snapshotList.isEmpty()) {</span>
-<span class="source-line-no">722</span><span id="line-722"> return Collections.emptyMap();</span>
-<span class="source-line-no">723</span><span id="line-723"> }</span>
-<span class="source-line-no">724</span><span id="line-724"></span>
-<span class="source-line-no">725</span><span id="line-725"> ConcurrentHashMap<Path, Integer> fileMap = new ConcurrentHashMap<>();</span>
-<span class="source-line-no">726</span><span id="line-726"></span>
-<span class="source-line-no">727</span><span id="line-727"> ExecutorService exec = SnapshotManifest.createExecutor(conf, "SnapshotsFilesMapping");</span>
+<span class="source-line-no">580</span><span id="line-580"> @Override</span>
+<span class="source-line-no">581</span><span id="line-581"> protected void processOptions(CommandLine cmd) {</span>
+<span class="source-line-no">582</span><span id="line-582"> snapshotName = cmd.getOptionValue(Options.SNAPSHOT.getLongOpt());</span>
+<span class="source-line-no">583</span><span id="line-583"> showFiles = cmd.hasOption(Options.FILES.getLongOpt());</span>
+<span class="source-line-no">584</span><span id="line-584"> showStats =</span>
+<span class="source-line-no">585</span><span id="line-585"> cmd.hasOption(Options.FILES.getLongOpt()) || cmd.hasOption(Options.STATS.getLongOpt());</span>
+<span class="source-line-no">586</span><span id="line-586"> showSchema = cmd.hasOption(Options.SCHEMA.getLongOpt());</span>
+<span class="source-line-no">587</span><span id="line-587"> listSnapshots = cmd.hasOption(Options.LIST_SNAPSHOTS.getLongOpt());</span>
+<span class="source-line-no">588</span><span id="line-588"> printSizeInBytes = cmd.hasOption(Options.SIZE_IN_BYTES.getLongOpt());</span>
+<span class="source-line-no">589</span><span id="line-589"> if (cmd.hasOption(Options.REMOTE_DIR.getLongOpt())) {</span>
+<span class="source-line-no">590</span><span id="line-590"> remoteDir = new Path(cmd.getOptionValue(Options.REMOTE_DIR.getLongOpt()));</span>
+<span class="source-line-no">591</span><span id="line-591"> }</span>
+<span class="source-line-no">592</span><span id="line-592"> }</span>
+<span class="source-line-no">593</span><span id="line-593"></span>
+<span class="source-line-no">594</span><span id="line-594"> @Override</span>
+<span class="source-line-no">595</span><span id="line-595"> protected void printUsage() {</span>
+<span class="source-line-no">596</span><span id="line-596"> printUsage("hbase snapshot info [options]", "Options:", "");</span>
+<span class="source-line-no">597</span><span id="line-597"> System.err.println("Examples:");</span>
+<span class="source-line-no">598</span><span id="line-598"> System.err.println(" hbase snapshot info --snapshot MySnapshot --files");</span>
+<span class="source-line-no">599</span><span id="line-599"> }</span>
+<span class="source-line-no">600</span><span id="line-600"></span>
+<span class="source-line-no">601</span><span id="line-601"> /**</span>
+<span class="source-line-no">602</span><span id="line-602"> * Returns the snapshot stats</span>
+<span class="source-line-no">603</span><span id="line-603"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">604</span><span id="line-604"> * @param snapshot {@link SnapshotDescription} to get stats from</span>
+<span class="source-line-no">605</span><span id="line-605"> * @return the snapshot stats</span>
+<span class="source-line-no">606</span><span id="line-606"> */</span>
+<span class="source-line-no">607</span><span id="line-607"> public static SnapshotStats getSnapshotStats(final Configuration conf,</span>
+<span class="source-line-no">608</span><span id="line-608"> final SnapshotDescription snapshot) throws IOException {</span>
+<span class="source-line-no">609</span><span id="line-609"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">610</span><span id="line-610"> ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
+<span class="source-line-no">611</span><span id="line-611"> return getSnapshotStats(conf, snapshotDesc, null);</span>
+<span class="source-line-no">612</span><span id="line-612"> }</span>
+<span class="source-line-no">613</span><span id="line-613"></span>
+<span class="source-line-no">614</span><span id="line-614"> /**</span>
+<span class="source-line-no">615</span><span id="line-615"> * Returns the snapshot stats</span>
+<span class="source-line-no">616</span><span id="line-616"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">617</span><span id="line-617"> * @param snapshotDesc HBaseProtos.SnapshotDescription to get stats from</span>
+<span class="source-line-no">618</span><span id="line-618"> * @param filesMap {@link Map} store files map for all snapshots, it may be null</span>
+<span class="source-line-no">619</span><span id="line-619"> * @return the snapshot stats</span>
+<span class="source-line-no">620</span><span id="line-620"> */</span>
+<span class="source-line-no">621</span><span id="line-621"> public static SnapshotStats getSnapshotStats(final Configuration conf,</span>
+<span class="source-line-no">622</span><span id="line-622"> final SnapshotProtos.SnapshotDescription snapshotDesc, final Map<Path, Integer> filesMap)</span>
+<span class="source-line-no">623</span><span id="line-623"> throws IOException {</span>
+<span class="source-line-no">624</span><span id="line-624"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
+<span class="source-line-no">625</span><span id="line-625"> FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
+<span class="source-line-no">626</span><span id="line-626"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotDesc, rootDir);</span>
+<span class="source-line-no">627</span><span id="line-627"> SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);</span>
+<span class="source-line-no">628</span><span id="line-628"> final SnapshotStats stats = new SnapshotStats(conf, fs, snapshotDesc);</span>
+<span class="source-line-no">629</span><span id="line-629"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(conf, fs, manifest,</span>
+<span class="source-line-no">630</span><span id="line-630"> "SnapshotsStatsAggregation", new SnapshotReferenceUtil.SnapshotVisitor() {</span>
+<span class="source-line-no">631</span><span id="line-631"> @Override</span>
+<span class="source-line-no">632</span><span id="line-632"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
+<span class="source-line-no">633</span><span id="line-633"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
+<span class="source-line-no">634</span><span id="line-634"> if (!storeFile.hasReference()) {</span>
+<span class="source-line-no">635</span><span id="line-635"> stats.addStoreFile(regionInfo, family, storeFile, filesMap);</span>
+<span class="source-line-no">636</span><span id="line-636"> }</span>
+<span class="source-line-no">637</span><span id="line-637"> }</span>
+<span class="source-line-no">638</span><span id="line-638"> });</span>
+<span class="source-line-no">639</span><span id="line-639"> return stats;</span>
+<span class="source-line-no">640</span><span id="line-640"> }</span>
+<span class="source-line-no">641</span><span id="line-641"></span>
+<span class="source-line-no">642</span><span id="line-642"> /**</span>
+<span class="source-line-no">643</span><span id="line-643"> * Returns the list of available snapshots in the specified location</span>
+<span class="source-line-no">644</span><span id="line-644"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">645</span><span id="line-645"> * @return the list of snapshots</span>
+<span class="source-line-no">646</span><span id="line-646"> */</span>
+<span class="source-line-no">647</span><span id="line-647"> public static List<SnapshotDescription> getSnapshotList(final Configuration conf)</span>
+<span class="source-line-no">648</span><span id="line-648"> throws IOException {</span>
+<span class="source-line-no">649</span><span id="line-649"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
+<span class="source-line-no">650</span><span id="line-650"> FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
+<span class="source-line-no">651</span><span id="line-651"> Path snapshotDir = SnapshotDescriptionUtils.getSnapshotsDir(rootDir);</span>
+<span class="source-line-no">652</span><span id="line-652"> FileStatus[] snapshots = CommonFSUtils.listStatus(fs, snapshotDir,</span>
+<span class="source-line-no">653</span><span id="line-653"> new SnapshotDescriptionUtils.CompletedSnaphotDirectoriesFilter(fs));</span>
+<span class="source-line-no">654</span><span id="line-654"> if (snapshots == null) {</span>
+<span class="source-line-no">655</span><span id="line-655"> return Collections.emptyList();</span>
+<span class="source-line-no">656</span><span id="line-656"> }</span>
+<span class="source-line-no">657</span><span id="line-657"> List<SnapshotDescription> snapshotLists = new ArrayList<>(snapshots.length);</span>
+<span class="source-line-no">658</span><span id="line-658"> for (FileStatus snapshotDirStat : snapshots) {</span>
+<span class="source-line-no">659</span><span id="line-659"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">660</span><span id="line-660"> SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDirStat.getPath());</span>
+<span class="source-line-no">661</span><span id="line-661"> snapshotLists.add(ProtobufUtil.createSnapshotDesc(snapshotDesc));</span>
+<span class="source-line-no">662</span><span id="line-662"> }</span>
+<span class="source-line-no">663</span><span id="line-663"> return snapshotLists;</span>
+<span class="source-line-no">664</span><span id="line-664"> }</span>
+<span class="source-line-no">665</span><span id="line-665"></span>
+<span class="source-line-no">666</span><span id="line-666"> /**</span>
+<span class="source-line-no">667</span><span id="line-667"> * Gets the store files map for snapshot</span>
+<span class="source-line-no">668</span><span id="line-668"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">669</span><span id="line-669"> * @param snapshot {@link SnapshotDescription} to get stats from</span>
+<span class="source-line-no">670</span><span id="line-670"> * @param exec the {@link ExecutorService} to use</span>
+<span class="source-line-no">671</span><span id="line-671"> * @param filesMap {@link Map} the map to put the mapping entries</span>
+<span class="source-line-no">672</span><span id="line-672"> * @param uniqueHFilesArchiveSize {@link AtomicLong} the accumulated store file size in archive</span>
+<span class="source-line-no">673</span><span id="line-673"> * @param uniqueHFilesSize {@link AtomicLong} the accumulated store file size shared</span>
+<span class="source-line-no">674</span><span id="line-674"> * @param uniqueHFilesMobSize {@link AtomicLong} the accumulated mob store file size shared</span>
+<span class="source-line-no">675</span><span id="line-675"> */</span>
+<span class="source-line-no">676</span><span id="line-676"> private static void getSnapshotFilesMap(final Configuration conf,</span>
+<span class="source-line-no">677</span><span id="line-677"> final SnapshotDescription snapshot, final ExecutorService exec,</span>
+<span class="source-line-no">678</span><span id="line-678"> final ConcurrentHashMap<Path, Integer> filesMap, final AtomicLong uniqueHFilesArchiveSize,</span>
+<span class="source-line-no">679</span><span id="line-679"> final AtomicLong uniqueHFilesSize, final AtomicLong uniqueHFilesMobSize) throws IOException {</span>
+<span class="source-line-no">680</span><span id="line-680"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">681</span><span id="line-681"> ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
+<span class="source-line-no">682</span><span id="line-682"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
+<span class="source-line-no">683</span><span id="line-683"> final FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
+<span class="source-line-no">684</span><span id="line-684"></span>
+<span class="source-line-no">685</span><span id="line-685"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotDesc, rootDir);</span>
+<span class="source-line-no">686</span><span id="line-686"> SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);</span>
+<span class="source-line-no">687</span><span id="line-687"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(conf, fs, manifest, exec,</span>
+<span class="source-line-no">688</span><span id="line-688"> new SnapshotReferenceUtil.SnapshotVisitor() {</span>
+<span class="source-line-no">689</span><span id="line-689"> @Override</span>
+<span class="source-line-no">690</span><span id="line-690"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
+<span class="source-line-no">691</span><span id="line-691"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
+<span class="source-line-no">692</span><span id="line-692"> if (!storeFile.hasReference()) {</span>
+<span class="source-line-no">693</span><span id="line-693"> HFileLink link = HFileLink.build(conf, snapshot.getTableName(),</span>
+<span class="source-line-no">694</span><span id="line-694"> regionInfo.getEncodedName(), family, storeFile.getName());</span>
+<span class="source-line-no">695</span><span id="line-695"> long size;</span>
+<span class="source-line-no">696</span><span id="line-696"> Integer count;</span>
+<span class="source-line-no">697</span><span id="line-697"> Path p;</span>
+<span class="source-line-no">698</span><span id="line-698"> AtomicLong al;</span>
+<span class="source-line-no">699</span><span id="line-699"> int c = 0;</span>
+<span class="source-line-no">700</span><span id="line-700"></span>
+<span class="source-line-no">701</span><span id="line-701"> if (fs.exists(link.getArchivePath())) {</span>
+<span class="source-line-no">702</span><span id="line-702"> p = link.getArchivePath();</span>
+<span class="source-line-no">703</span><span id="line-703"> al = uniqueHFilesArchiveSize;</span>
+<span class="source-line-no">704</span><span id="line-704"> size = fs.getFileStatus(p).getLen();</span>
+<span class="source-line-no">705</span><span id="line-705"> } else if (fs.exists(link.getMobPath())) {</span>
+<span class="source-line-no">706</span><span id="line-706"> p = link.getMobPath();</span>
+<span class="source-line-no">707</span><span id="line-707"> al = uniqueHFilesMobSize;</span>
+<span class="source-line-no">708</span><span id="line-708"> size = fs.getFileStatus(p).getLen();</span>
+<span class="source-line-no">709</span><span id="line-709"> } else {</span>
+<span class="source-line-no">710</span><span id="line-710"> p = link.getOriginPath();</span>
+<span class="source-line-no">711</span><span id="line-711"> al = uniqueHFilesSize;</span>
+<span class="source-line-no">712</span><span id="line-712"> size = link.getFileStatus(fs).getLen();</span>
+<span class="source-line-no">713</span><span id="line-713"> }</span>
+<span class="source-line-no">714</span><span id="line-714"></span>
+<span class="source-line-no">715</span><span id="line-715"> // If it has been counted, do not double count</span>
+<span class="source-line-no">716</span><span id="line-716"> count = filesMap.get(p);</span>
+<span class="source-line-no">717</span><span id="line-717"> if (count != null) {</span>
+<span class="source-line-no">718</span><span id="line-718"> c = count.intValue();</span>
+<span class="source-line-no">719</span><span id="line-719"> } else {</span>
+<span class="source-line-no">720</span><span id="line-720"> al.addAndGet(size);</span>
+<span class="source-line-no">721</span><span id="line-721"> }</span>
+<span class="source-line-no">722</span><span id="line-722"></span>
+<span class="source-line-no">723</span><span id="line-723"> filesMap.put(p, ++c);</span>
+<span class="source-line-no">724</span><span id="line-724"> }</span>
+<span class="source-line-no">725</span><span id="line-725"> }</span>
+<span class="source-line-no">726</span><span id="line-726"> });</span>
+<span class="source-line-no">727</span><span id="line-727"> }</span>
<span class="source-line-no">728</span><span id="line-728"></span>
-<span class="source-line-no">729</span><span id="line-729"> try {</span>
-<span class="source-line-no">730</span><span id="line-730"> for (final SnapshotDescription snapshot : snapshotList) {</span>
-<span class="source-line-no">731</span><span id="line-731"> getSnapshotFilesMap(conf, snapshot, exec, fileMap, uniqueHFilesArchiveSize,</span>
-<span class="source-line-no">732</span><span id="line-732"> uniqueHFilesSize, uniqueHFilesMobSize);</span>
-<span class="source-line-no">733</span><span id="line-733"> }</span>
-<span class="source-line-no">734</span><span id="line-734"> } finally {</span>
-<span class="source-line-no">735</span><span id="line-735"> exec.shutdown();</span>
-<span class="source-line-no">736</span><span id="line-736"> }</span>
-<span class="source-line-no">737</span><span id="line-737"></span>
-<span class="source-line-no">738</span><span id="line-738"> return fileMap;</span>
-<span class="source-line-no">739</span><span id="line-739"> }</span>
-<span class="source-line-no">740</span><span id="line-740"></span>
-<span class="source-line-no">741</span><span id="line-741"> public static void main(String[] args) {</span>
-<span class="source-line-no">742</span><span id="line-742"> new SnapshotInfo().doStaticMain(args);</span>
-<span class="source-line-no">743</span><span id="line-743"> }</span>
-<span class="source-line-no">744</span><span id="line-744">}</span>
+<span class="source-line-no">729</span><span id="line-729"> /**</span>
+<span class="source-line-no">730</span><span id="line-730"> * Returns the map of store files based on path for all snapshots</span>
+<span class="source-line-no">731</span><span id="line-731"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">732</span><span id="line-732"> * @param uniqueHFilesArchiveSize pass out the size for store files in archive</span>
+<span class="source-line-no">733</span><span id="line-733"> * @param uniqueHFilesSize pass out the size for store files shared</span>
+<span class="source-line-no">734</span><span id="line-734"> * @param uniqueHFilesMobSize pass out the size for mob store files shared</span>
+<span class="source-line-no">735</span><span id="line-735"> * @return the map of store files</span>
+<span class="source-line-no">736</span><span id="line-736"> */</span>
+<span class="source-line-no">737</span><span id="line-737"> public static Map<Path, Integer> getSnapshotsFilesMap(final Configuration conf,</span>
+<span class="source-line-no">738</span><span id="line-738"> AtomicLong uniqueHFilesArchiveSize, AtomicLong uniqueHFilesSize, AtomicLong uniqueHFilesMobSize)</span>
+<span class="source-line-no">739</span><span id="line-739"> throws IOException {</span>
+<span class="source-line-no">740</span><span id="line-740"> List<SnapshotDescription> snapshotList = getSnapshotList(conf);</span>
+<span class="source-line-no">741</span><span id="line-741"></span>
+<span class="source-line-no">742</span><span id="line-742"> if (snapshotList.isEmpty()) {</span>
+<span class="source-line-no">743</span><span id="line-743"> return Collections.emptyMap();</span>
+<span class="source-line-no">744</span><span id="line-744"> }</span>
+<span class="source-line-no">745</span><span id="line-745"></span>
+<span class="source-line-no">746</span><span id="line-746"> ConcurrentHashMap<Path, Integer> fileMap = new ConcurrentHashMap<>();</span>
+<span class="source-line-no">747</span><span id="line-747"></span>
+<span class="source-line-no">748</span><span id="line-748"> ExecutorService exec = SnapshotManifest.createExecutor(conf, "SnapshotsFilesMapping");</span>
+<span class="source-line-no">749</span><span id="line-749"></span>
+<span class="source-line-no">750</span><span id="line-750"> try {</span>
+<span class="source-line-no">751</span><span id="line-751"> for (final SnapshotDescription snapshot : snapshotList) {</span>
+<span class="source-line-no">752</span><span id="line-752"> getSnapshotFilesMap(conf, snapshot, exec, fileMap, uniqueHFilesArchiveSize,</span>
+<span class="source-line-no">753</span><span id="line-753"> uniqueHFilesSize, uniqueHFilesMobSize);</span>
+<span class="source-line-no">754</span><span id="line-754"> }</span>
+<span class="source-line-no">755</span><span id="line-755"> } finally {</span>
+<span class="source-line-no">756</span><span id="line-756"> exec.shutdown();</span>
+<span class="source-line-no">757</span><span id="line-757"> }</span>
+<span class="source-line-no">758</span><span id="line-758"></span>
+<span class="source-line-no">759</span><span id="line-759"> return fileMap;</span>
+<span class="source-line-no">760</span><span id="line-760"> }</span>
+<span class="source-line-no">761</span><span id="line-761"></span>
+<span class="source-line-no">762</span><span id="line-762"> public static void main(String[] args) {</span>
+<span class="source-line-no">763</span><span id="line-763"> new SnapshotInfo().doStaticMain(args);</span>
+<span class="source-line-no">764</span><span id="line-764"> }</span>
+<span class="source-line-no">765</span><span id="line-765">}</span>
diff --git a/apidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html b/apidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html
index fc0d7530f5e..a89ff1c0013 100644
--- a/apidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html
+++ b/apidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html
@@ -30,731 +30,752 @@
<span class="source-line-no">017</span><span id="line-17"> */</span>
<span class="source-line-no">018</span><span id="line-18">package org.apache.hadoop.hbase.snapshot;</span>
<span class="source-line-no">019</span><span id="line-19"></span>
-<span class="source-line-no">020</span><span id="line-20">import java.io.FileNotFoundException;</span>
-<span class="source-line-no">021</span><span id="line-21">import java.io.IOException;</span>
-<span class="source-line-no">022</span><span id="line-22">import java.net.URI;</span>
-<span class="source-line-no">023</span><span id="line-23">import java.text.SimpleDateFormat;</span>
-<span class="source-line-no">024</span><span id="line-24">import java.util.ArrayList;</span>
-<span class="source-line-no">025</span><span id="line-25">import java.util.Collections;</span>
-<span class="source-line-no">026</span><span id="line-26">import java.util.Date;</span>
-<span class="source-line-no">027</span><span id="line-27">import java.util.List;</span>
-<span class="source-line-no">028</span><span id="line-28">import java.util.Map;</span>
-<span class="source-line-no">029</span><span id="line-29">import java.util.Properties;</span>
-<span class="source-line-no">030</span><span id="line-30">import java.util.concurrent.ConcurrentHashMap;</span>
-<span class="source-line-no">031</span><span id="line-31">import java.util.concurrent.ExecutorService;</span>
-<span class="source-line-no">032</span><span id="line-32">import java.util.concurrent.atomic.AtomicInteger;</span>
-<span class="source-line-no">033</span><span id="line-33">import java.util.concurrent.atomic.AtomicLong;</span>
-<span class="source-line-no">034</span><span id="line-34">import org.apache.hadoop.conf.Configuration;</span>
-<span class="source-line-no">035</span><span id="line-35">import org.apache.hadoop.fs.FileStatus;</span>
-<span class="source-line-no">036</span><span id="line-36">import org.apache.hadoop.fs.FileSystem;</span>
-<span class="source-line-no">037</span><span id="line-37">import org.apache.hadoop.fs.Path;</span>
-<span class="source-line-no">038</span><span id="line-38">import org.apache.hadoop.hbase.TableName;</span>
-<span class="source-line-no">039</span><span id="line-39">import org.apache.hadoop.hbase.client.RegionInfo;</span>
-<span class="source-line-no">040</span><span id="line-40">import org.apache.hadoop.hbase.client.SnapshotDescription;</span>
-<span class="source-line-no">041</span><span id="line-41">import org.apache.hadoop.hbase.io.HFileLink;</span>
-<span class="source-line-no">042</span><span id="line-42">import org.apache.hadoop.hbase.io.WALLink;</span>
-<span class="source-line-no">043</span><span id="line-43">import org.apache.hadoop.hbase.util.AbstractHBaseTool;</span>
-<span class="source-line-no">044</span><span id="line-44">import org.apache.hadoop.hbase.util.CommonFSUtils;</span>
-<span class="source-line-no">045</span><span id="line-45">import org.apache.hadoop.hbase.util.Strings;</span>
-<span class="source-line-no">046</span><span id="line-46">import org.apache.yetus.audience.InterfaceAudience;</span>
-<span class="source-line-no">047</span><span id="line-47">import org.slf4j.Logger;</span>
-<span class="source-line-no">048</span><span id="line-48">import org.slf4j.LoggerFactory;</span>
-<span class="source-line-no">049</span><span id="line-49"></span>
-<span class="source-line-no">050</span><span id="line-50">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;</span>
-<span class="source-line-no">051</span><span id="line-51">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLineParser;</span>
-<span class="source-line-no">052</span><span id="line-52">import org.apache.hbase.thirdparty.org.apache.commons.cli.DefaultParser;</span>
-<span class="source-line-no">053</span><span id="line-53">import org.apache.hbase.thirdparty.org.apache.commons.cli.Option;</span>
-<span class="source-line-no">054</span><span id="line-54">import org.apache.hbase.thirdparty.org.apache.commons.cli.Options;</span>
-<span class="source-line-no">055</span><span id="line-55">import org.apache.hbase.thirdparty.org.apache.commons.cli.ParseException;</span>
-<span class="source-line-no">056</span><span id="line-56"></span>
-<span class="source-line-no">057</span><span id="line-57">import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;</span>
-<span class="source-line-no">058</span><span id="line-58">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos;</span>
-<span class="source-line-no">059</span><span id="line-59">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;</span>
-<span class="source-line-no">060</span><span id="line-60"></span>
-<span class="source-line-no">061</span><span id="line-61">/**</span>
-<span class="source-line-no">062</span><span id="line-62"> * Tool for dumping snapshot information.</span>
-<span class="source-line-no">063</span><span id="line-63"> * <ol></span>
-<span class="source-line-no">064</span><span id="line-64"> * <li>Table Descriptor</span>
-<span class="source-line-no">065</span><span id="line-65"> * <li>Snapshot creation time, type, format version, ...</span>
-<span class="source-line-no">066</span><span id="line-66"> * <li>List of hfiles and wals</span>
-<span class="source-line-no">067</span><span id="line-67"> * <li>Stats about hfiles and logs sizes, percentage of shared with the source table, ...</span>
-<span class="source-line-no">068</span><span id="line-68"> * </ol></span>
-<span class="source-line-no">069</span><span id="line-69"> */</span>
-<span class="source-line-no">070</span><span id="line-70">@InterfaceAudience.Public</span>
-<span class="source-line-no">071</span><span id="line-71">public final class SnapshotInfo extends AbstractHBaseTool {</span>
-<span class="source-line-no">072</span><span id="line-72"> private static final Logger LOG = LoggerFactory.getLogger(SnapshotInfo.class);</span>
-<span class="source-line-no">073</span><span id="line-73"></span>
-<span class="source-line-no">074</span><span id="line-74"> static final class Options {</span>
-<span class="source-line-no">075</span><span id="line-75"> static final Option SNAPSHOT =</span>
-<span class="source-line-no">076</span><span id="line-76"> new Option(null, "snapshot", true, "The name of the snapshot to be detailed.");</span>
-<span class="source-line-no">077</span><span id="line-77"> static final Option REMOTE_DIR =</span>
-<span class="source-line-no">078</span><span id="line-78"> new Option(null, "remote-dir", true, "A custom root directory where snapshots are stored. "</span>
-<span class="source-line-no">079</span><span id="line-79"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">080</span><span id="line-80"> static final Option LIST_SNAPSHOTS =</span>
-<span class="source-line-no">081</span><span id="line-81"> new Option(null, "list-snapshots", false, "List all the available snapshots and exit.");</span>
-<span class="source-line-no">082</span><span id="line-82"> static final Option FILES =</span>
-<span class="source-line-no">083</span><span id="line-83"> new Option(null, "files", false, "The list of files retained by the specified snapshot. "</span>
-<span class="source-line-no">084</span><span id="line-84"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">085</span><span id="line-85"> static final Option STATS =</span>
-<span class="source-line-no">086</span><span id="line-86"> new Option(null, "stats", false, "Additional information about the specified snapshot. "</span>
-<span class="source-line-no">087</span><span id="line-87"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">088</span><span id="line-88"> static final Option SCHEMA = new Option(null, "schema", false,</span>
-<span class="source-line-no">089</span><span id="line-89"> "Show the descriptor of the table for the specified snapshot. "</span>
+<span class="source-line-no">020</span><span id="line-20">import static org.apache.hadoop.hbase.HConstants.DEFAULT_SNAPSHOT_TTL;</span>
+<span class="source-line-no">021</span><span id="line-21"></span>
+<span class="source-line-no">022</span><span id="line-22">import java.io.FileNotFoundException;</span>
+<span class="source-line-no">023</span><span id="line-23">import java.io.IOException;</span>
+<span class="source-line-no">024</span><span id="line-24">import java.net.URI;</span>
+<span class="source-line-no">025</span><span id="line-25">import java.text.SimpleDateFormat;</span>
+<span class="source-line-no">026</span><span id="line-26">import java.util.ArrayList;</span>
+<span class="source-line-no">027</span><span id="line-27">import java.util.Collections;</span>
+<span class="source-line-no">028</span><span id="line-28">import java.util.Date;</span>
+<span class="source-line-no">029</span><span id="line-29">import java.util.List;</span>
+<span class="source-line-no">030</span><span id="line-30">import java.util.Map;</span>
+<span class="source-line-no">031</span><span id="line-31">import java.util.Properties;</span>
+<span class="source-line-no">032</span><span id="line-32">import java.util.concurrent.ConcurrentHashMap;</span>
+<span class="source-line-no">033</span><span id="line-33">import java.util.concurrent.ExecutorService;</span>
+<span class="source-line-no">034</span><span id="line-34">import java.util.concurrent.atomic.AtomicInteger;</span>
+<span class="source-line-no">035</span><span id="line-35">import java.util.concurrent.atomic.AtomicLong;</span>
+<span class="source-line-no">036</span><span id="line-36">import org.apache.hadoop.conf.Configuration;</span>
+<span class="source-line-no">037</span><span id="line-37">import org.apache.hadoop.fs.FileStatus;</span>
+<span class="source-line-no">038</span><span id="line-38">import org.apache.hadoop.fs.FileSystem;</span>
+<span class="source-line-no">039</span><span id="line-39">import org.apache.hadoop.fs.Path;</span>
+<span class="source-line-no">040</span><span id="line-40">import org.apache.hadoop.hbase.TableName;</span>
+<span class="source-line-no">041</span><span id="line-41">import org.apache.hadoop.hbase.client.RegionInfo;</span>
+<span class="source-line-no">042</span><span id="line-42">import org.apache.hadoop.hbase.client.SnapshotDescription;</span>
+<span class="source-line-no">043</span><span id="line-43">import org.apache.hadoop.hbase.io.HFileLink;</span>
+<span class="source-line-no">044</span><span id="line-44">import org.apache.hadoop.hbase.io.WALLink;</span>
+<span class="source-line-no">045</span><span id="line-45">import org.apache.hadoop.hbase.util.AbstractHBaseTool;</span>
+<span class="source-line-no">046</span><span id="line-46">import org.apache.hadoop.hbase.util.CommonFSUtils;</span>
+<span class="source-line-no">047</span><span id="line-47">import org.apache.hadoop.hbase.util.Strings;</span>
+<span class="source-line-no">048</span><span id="line-48">import org.apache.yetus.audience.InterfaceAudience;</span>
+<span class="source-line-no">049</span><span id="line-49">import org.slf4j.Logger;</span>
+<span class="source-line-no">050</span><span id="line-50">import org.slf4j.LoggerFactory;</span>
+<span class="source-line-no">051</span><span id="line-51"></span>
+<span class="source-line-no">052</span><span id="line-52">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;</span>
+<span class="source-line-no">053</span><span id="line-53">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLineParser;</span>
+<span class="source-line-no">054</span><span id="line-54">import org.apache.hbase.thirdparty.org.apache.commons.cli.DefaultParser;</span>
+<span class="source-line-no">055</span><span id="line-55">import org.apache.hbase.thirdparty.org.apache.commons.cli.Option;</span>
+<span class="source-line-no">056</span><span id="line-56">import org.apache.hbase.thirdparty.org.apache.commons.cli.Options;</span>
+<span class="source-line-no">057</span><span id="line-57">import org.apache.hbase.thirdparty.org.apache.commons.cli.ParseException;</span>
+<span class="source-line-no">058</span><span id="line-58"></span>
+<span class="source-line-no">059</span><span id="line-59">import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;</span>
+<span class="source-line-no">060</span><span id="line-60">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos;</span>
+<span class="source-line-no">061</span><span id="line-61">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;</span>
+<span class="source-line-no">062</span><span id="line-62"></span>
+<span class="source-line-no">063</span><span id="line-63">/**</span>
+<span class="source-line-no">064</span><span id="line-64"> * Tool for dumping snapshot information.</span>
+<span class="source-line-no">065</span><span id="line-65"> * <ol></span>
+<span class="source-line-no">066</span><span id="line-66"> * <li>Table Descriptor</span>
+<span class="source-line-no">067</span><span id="line-67"> * <li>Snapshot creation time, type, format version, ...</span>
+<span class="source-line-no">068</span><span id="line-68"> * <li>List of hfiles and wals</span>
+<span class="source-line-no">069</span><span id="line-69"> * <li>Stats about hfiles and logs sizes, percentage of shared with the source table, ...</span>
+<span class="source-line-no">070</span><span id="line-70"> * </ol></span>
+<span class="source-line-no">071</span><span id="line-71"> */</span>
+<span class="source-line-no">072</span><span id="line-72">@InterfaceAudience.Public</span>
+<span class="source-line-no">073</span><span id="line-73">public final class SnapshotInfo extends AbstractHBaseTool {</span>
+<span class="source-line-no">074</span><span id="line-74"> private static final Logger LOG = LoggerFactory.getLogger(SnapshotInfo.class);</span>
+<span class="source-line-no">075</span><span id="line-75"></span>
+<span class="source-line-no">076</span><span id="line-76"> private static final String EXPIRED_LABEL = "Yes";</span>
+<span class="source-line-no">077</span><span id="line-77"> private static final String NOT_EXPIRED_LABEL = "No";</span>
+<span class="source-line-no">078</span><span id="line-78"> private static final String TTL_FOREVER = "FOREVER";</span>
+<span class="source-line-no">079</span><span id="line-79"></span>
+<span class="source-line-no">080</span><span id="line-80"> static final class Options {</span>
+<span class="source-line-no">081</span><span id="line-81"> static final Option SNAPSHOT =</span>
+<span class="source-line-no">082</span><span id="line-82"> new Option(null, "snapshot", true, "The name of the snapshot to be detailed.");</span>
+<span class="source-line-no">083</span><span id="line-83"> static final Option REMOTE_DIR =</span>
+<span class="source-line-no">084</span><span id="line-84"> new Option(null, "remote-dir", true, "A custom root directory where snapshots are stored. "</span>
+<span class="source-line-no">085</span><span id="line-85"> + "Use it together with the --snapshot option.");</span>
+<span class="source-line-no">086</span><span id="line-86"> static final Option LIST_SNAPSHOTS =</span>
+<span class="source-line-no">087</span><span id="line-87"> new Option(null, "list-snapshots", false, "List all the available snapshots and exit.");</span>
+<span class="source-line-no">088</span><span id="line-88"> static final Option FILES =</span>
+<span class="source-line-no">089</span><span id="line-89"> new Option(null, "files", false, "The list of files retained by the specified snapshot. "</span>
<span class="source-line-no">090</span><span id="line-90"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">091</span><span id="line-91"> static final Option SIZE_IN_BYTES =</span>
-<span class="source-line-no">092</span><span id="line-92"> new Option(null, "size-in-bytes", false, "Print the size of the files in bytes. "</span>
-<span class="source-line-no">093</span><span id="line-93"> + "Use it together with the --snapshot and --files options.");</span>
-<span class="source-line-no">094</span><span id="line-94"> }</span>
-<span class="source-line-no">095</span><span id="line-95"></span>
-<span class="source-line-no">096</span><span id="line-96"> /**</span>
-<span class="source-line-no">097</span><span id="line-97"> * Statistics about the snapshot</span>
-<span class="source-line-no">098</span><span id="line-98"> * <ol></span>
-<span class="source-line-no">099</span><span id="line-99"> * <li>How many store files and logs are in the archive</span>
-<span class="source-line-no">100</span><span id="line-100"> * <li>How many store files and logs are shared with the table</span>
-<span class="source-line-no">101</span><span id="line-101"> * <li>Total store files and logs size and shared amount</span>
-<span class="source-line-no">102</span><span id="line-102"> * </ol></span>
-<span class="source-line-no">103</span><span id="line-103"> */</span>
-<span class="source-line-no">104</span><span id="line-104"> public static class SnapshotStats {</span>
-<span class="source-line-no">105</span><span id="line-105"> /** Information about the file referenced by the snapshot */</span>
-<span class="source-line-no">106</span><span id="line-106"> static class FileInfo {</span>
-<span class="source-line-no">107</span><span id="line-107"> private final boolean corrupted;</span>
-<span class="source-line-no">108</span><span id="line-108"> private final boolean inArchive;</span>
-<span class="source-line-no">109</span><span id="line-109"> private final long size;</span>
-<span class="source-line-no">110</span><span id="line-110"></span>
-<span class="source-line-no">111</span><span id="line-111"> FileInfo(final boolean inArchive, final long size, final boolean corrupted) {</span>
-<span class="source-line-no">112</span><span id="line-112"> this.corrupted = corrupted;</span>
-<span class="source-line-no">113</span><span id="line-113"> this.inArchive = inArchive;</span>
-<span class="source-line-no">114</span><span id="line-114"> this.size = size;</span>
-<span class="source-line-no">115</span><span id="line-115"> }</span>
+<span class="source-line-no">091</span><span id="line-91"> static final Option STATS =</span>
+<span class="source-line-no">092</span><span id="line-92"> new Option(null, "stats", false, "Additional information about the specified snapshot. "</span>
+<span class="source-line-no">093</span><span id="line-93"> + "Use it together with the --snapshot option.");</span>
+<span class="source-line-no">094</span><span id="line-94"> static final Option SCHEMA = new Option(null, "schema", false,</span>
+<span class="source-line-no">095</span><span id="line-95"> "Show the descriptor of the table for the specified snapshot. "</span>
+<span class="source-line-no">096</span><span id="line-96"> + "Use it together with the --snapshot option.");</span>
+<span class="source-line-no">097</span><span id="line-97"> static final Option SIZE_IN_BYTES =</span>
+<span class="source-line-no">098</span><span id="line-98"> new Option(null, "size-in-bytes", false, "Print the size of the files in bytes. "</span>
+<span class="source-line-no">099</span><span id="line-99"> + "Use it together with the --snapshot and --files options.");</span>
+<span class="source-line-no">100</span><span id="line-100"> }</span>
+<span class="source-line-no">101</span><span id="line-101"></span>
+<span class="source-line-no">102</span><span id="line-102"> /**</span>
+<span class="source-line-no">103</span><span id="line-103"> * Statistics about the snapshot</span>
+<span class="source-line-no">104</span><span id="line-104"> * <ol></span>
+<span class="source-line-no">105</span><span id="line-105"> * <li>How many store files and logs are in the archive</span>
+<span class="source-line-no">106</span><span id="line-106"> * <li>How many store files and logs are shared with the table</span>
+<span class="source-line-no">107</span><span id="line-107"> * <li>Total store files and logs size and shared amount</span>
+<span class="source-line-no">108</span><span id="line-108"> * </ol></span>
+<span class="source-line-no">109</span><span id="line-109"> */</span>
+<span class="source-line-no">110</span><span id="line-110"> public static class SnapshotStats {</span>
+<span class="source-line-no">111</span><span id="line-111"> /** Information about the file referenced by the snapshot */</span>
+<span class="source-line-no">112</span><span id="line-112"> static class FileInfo {</span>
+<span class="source-line-no">113</span><span id="line-113"> private final boolean corrupted;</span>
+<span class="source-line-no">114</span><span id="line-114"> private final boolean inArchive;</span>
+<span class="source-line-no">115</span><span id="line-115"> private final long size;</span>
<span class="source-line-no">116</span><span id="line-116"></span>
-<span class="source-line-no">117</span><span id="line-117"> /** Returns true if the file is in the archive */</span>
-<span class="source-line-no">118</span><span id="line-118"> public boolean inArchive() {</span>
-<span class="source-line-no">119</span><span id="line-119"> return this.inArchive;</span>
-<span class="source-line-no">120</span><span id="line-120"> }</span>
-<span class="source-line-no">121</span><span id="line-121"></span>
-<span class="source-line-no">122</span><span id="line-122"> /** Returns true if the file is corrupted */</span>
-<span class="source-line-no">123</span><span id="line-123"> public boolean isCorrupted() {</span>
-<span class="source-line-no">124</span><span id="line-124"> return this.corrupted;</span>
-<span class="source-line-no">125</span><span id="line-125"> }</span>
-<span class="source-line-no">126</span><span id="line-126"></span>
-<span class="source-line-no">127</span><span id="line-127"> /** Returns true if the file is missing */</span>
-<span class="source-line-no">128</span><span id="line-128"> public boolean isMissing() {</span>
-<span class="source-line-no">129</span><span id="line-129"> return this.size < 0;</span>
-<span class="source-line-no">130</span><span id="line-130"> }</span>
-<span class="source-line-no">131</span><span id="line-131"></span>
-<span class="source-line-no">132</span><span id="line-132"> /** Returns the file size */</span>
-<span class="source-line-no">133</span><span id="line-133"> public long getSize() {</span>
-<span class="source-line-no">134</span><span id="line-134"> return this.size;</span>
-<span class="source-line-no">135</span><span id="line-135"> }</span>
-<span class="source-line-no">136</span><span id="line-136"></span>
-<span class="source-line-no">137</span><span id="line-137"> String getStateToString() {</span>
-<span class="source-line-no">138</span><span id="line-138"> if (isCorrupted()) return "CORRUPTED";</span>
-<span class="source-line-no">139</span><span id="line-139"> if (isMissing()) return "NOT FOUND";</span>
-<span class="source-line-no">140</span><span id="line-140"> if (inArchive()) return "archive";</span>
-<span class="source-line-no">141</span><span id="line-141"> return null;</span>
-<span class="source-line-no">142</span><span id="line-142"> }</span>
-<span class="source-line-no">143</span><span id="line-143"> }</span>
-<span class="source-line-no">144</span><span id="line-144"></span>
-<span class="source-line-no">145</span><span id="line-145"> private AtomicInteger hfilesArchiveCount = new AtomicInteger();</span>
-<span class="source-line-no">146</span><span id="line-146"> private AtomicInteger hfilesCorrupted = new AtomicInteger();</span>
-<span class="source-line-no">147</span><span id="line-147"> private AtomicInteger hfilesMissing = new AtomicInteger();</span>
-<span class="source-line-no">148</span><span id="line-148"> private AtomicInteger hfilesCount = new AtomicInteger();</span>
-<span class="source-line-no">149</span><span id="line-149"> private AtomicInteger hfilesMobCount = new AtomicInteger();</span>
-<span class="source-line-no">150</span><span id="line-150"> private AtomicInteger logsMissing = new AtomicInteger();</span>
-<span class="source-line-no">151</span><span id="line-151"> private AtomicInteger logsCount = new AtomicInteger();</span>
-<span class="source-line-no">152</span><span id="line-152"> private AtomicLong hfilesArchiveSize = new AtomicLong();</span>
-<span class="source-line-no">153</span><span id="line-153"> private AtomicLong hfilesSize = new AtomicLong();</span>
-<span class="source-line-no">154</span><span id="line-154"> private AtomicLong hfilesMobSize = new AtomicLong();</span>
-<span class="source-line-no">155</span><span id="line-155"> private AtomicLong nonSharedHfilesArchiveSize = new AtomicLong();</span>
-<span class="source-line-no">156</span><span id="line-156"> private AtomicLong logSize = new AtomicLong();</span>
-<span class="source-line-no">157</span><span id="line-157"></span>
-<span class="source-line-no">158</span><span id="line-158"> private final SnapshotProtos.SnapshotDescription snapshot;</span>
-<span class="source-line-no">159</span><span id="line-159"> private final TableName snapshotTable;</span>
-<span class="source-line-no">160</span><span id="line-160"> private final Configuration conf;</span>
-<span class="source-line-no">161</span><span id="line-161"> private final FileSystem fs;</span>
-<span class="source-line-no">162</span><span id="line-162"></span>
-<span class="source-line-no">163</span><span id="line-163"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
-<span class="source-line-no">164</span><span id="line-164"> final SnapshotDescription snapshot) {</span>
-<span class="source-line-no">165</span><span id="line-165"> this.snapshot = ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
-<span class="source-line-no">166</span><span id="line-166"> this.snapshotTable = snapshot.getTableName();</span>
-<span class="source-line-no">167</span><span id="line-167"> this.conf = conf;</span>
-<span class="source-line-no">168</span><span id="line-168"> this.fs = fs;</span>
-<span class="source-line-no">169</span><span id="line-169"> }</span>
-<span class="source-line-no">170</span><span id="line-170"></span>
-<span class="source-line-no">171</span><span id="line-171"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
-<span class="source-line-no">172</span><span id="line-172"> final SnapshotProtos.SnapshotDescription snapshot) {</span>
-<span class="source-line-no">173</span><span id="line-173"> this.snapshot = snapshot;</span>
-<span class="source-line-no">174</span><span id="line-174"> this.snapshotTable = TableName.valueOf(snapshot.getTable());</span>
-<span class="source-line-no">175</span><span id="line-175"> this.conf = conf;</span>
-<span class="source-line-no">176</span><span id="line-176"> this.fs = fs;</span>
-<span class="source-line-no">177</span><span id="line-177"> }</span>
-<span class="source-line-no">178</span><span id="line-178"></span>
-<span class="source-line-no">179</span><span id="line-179"> /** Returns the snapshot descriptor */</span>
-<span class="source-line-no">180</span><span id="line-180"> public SnapshotDescription getSnapshotDescription() {</span>
-<span class="source-line-no">181</span><span id="line-181"> return ProtobufUtil.createSnapshotDesc(this.snapshot);</span>
-<span class="source-line-no">182</span><span id="line-182"> }</span>
-<span class="source-line-no">183</span><span id="line-183"></span>
-<span class="source-line-no">184</span><span id="line-184"> /** Returns true if the snapshot is corrupted */</span>
-<span class="source-line-no">185</span><span id="line-185"> public boolean isSnapshotCorrupted() {</span>
-<span class="source-line-no">186</span><span id="line-186"> return hfilesMissing.get() > 0 || logsMissing.get() > 0 || hfilesCorrupted.get() > 0;</span>
-<span class="source-line-no">187</span><span id="line-187"> }</span>
-<span class="source-line-no">188</span><span id="line-188"></span>
-<span class="source-line-no">189</span><span id="line-189"> /** Returns the number of available store files */</span>
-<span class="source-line-no">190</span><span id="line-190"> public int getStoreFilesCount() {</span>
-<span class="source-line-no">191</span><span id="line-191"> return hfilesCount.get() + hfilesArchiveCount.get() + hfilesMobCount.get();</span>
-<span class="source-line-no">192</span><span id="line-192"> }</span>
-<span class="source-line-no">193</span><span id="line-193"></span>
-<span class="source-line-no">194</span><span id="line-194"> /** Returns the number of available store files in the archive */</span>
-<span class="source-line-no">195</span><span id="line-195"> public int getArchivedStoreFilesCount() {</span>
-<span class="source-line-no">196</span><span id="line-196"> return hfilesArchiveCount.get();</span>
-<span class="source-line-no">197</span><span id="line-197"> }</span>
-<span class="source-line-no">198</span><span id="line-198"></span>
-<span class="source-line-no">199</span><span id="line-199"> /** Returns the number of available store files in the mob dir */</span>
-<span class="source-line-no">200</span><span id="line-200"> public int getMobStoreFilesCount() {</span>
-<span class="source-line-no">201</span><span id="line-201"> return hfilesMobCount.get();</span>
-<span class="source-line-no">202</span><span id="line-202"> }</span>
-<span class="source-line-no">203</span><span id="line-203"></span>
-<span class="source-line-no">204</span><span id="line-204"> /** Returns the number of available log files */</span>
-<span class="source-line-no">205</span><span id="line-205"> public int getLogsCount() {</span>
-<span class="source-line-no">206</span><span id="line-206"> return logsCount.get();</span>
-<span class="source-line-no">207</span><span id="line-207"> }</span>
-<span class="source-line-no">208</span><span id="line-208"></span>
-<span class="source-line-no">209</span><span id="line-209"> /** Returns the number of missing store files */</span>
-<span class="source-line-no">210</span><span id="line-210"> public int getMissingStoreFilesCount() {</span>
-<span class="source-line-no">211</span><span id="line-211"> return hfilesMissing.get();</span>
-<span class="source-line-no">212</span><span id="line-212"> }</span>
-<span class="source-line-no">213</span><span id="line-213"></span>
-<span class="source-line-no">214</span><span id="line-214"> /** Returns the number of corrupted store files */</span>
-<span class="source-line-no">215</span><span id="line-215"> public int getCorruptedStoreFilesCount() {</span>
-<span class="source-line-no">216</span><span id="line-216"> return hfilesCorrupted.get();</span>
-<span class="source-line-no">217</span><span id="line-217"> }</span>
-<span class="source-line-no">218</span><span id="line-218"></span>
-<span class="source-line-no">219</span><span id="line-219"> /** Returns the number of missing log files */</span>
-<span class="source-line-no">220</span><span id="line-220"> public int getMissingLogsCount() {</span>
-<span class="source-line-no">221</span><span id="line-221"> return logsMissing.get();</span>
-<span class="source-line-no">222</span><span id="line-222"> }</span>
-<span class="source-line-no">223</span><span id="line-223"></span>
-<span class="source-line-no">224</span><span id="line-224"> /** Returns the total size of the store files referenced by the snapshot */</span>
-<span class="source-line-no">225</span><span id="line-225"> public long getStoreFilesSize() {</span>
-<span class="source-line-no">226</span><span id="line-226"> return hfilesSize.get() + hfilesArchiveSize.get() + hfilesMobSize.get();</span>
-<span class="source-line-no">227</span><span id="line-227"> }</span>
-<span class="source-line-no">228</span><span id="line-228"></span>
-<span class="source-line-no">229</span><span id="line-229"> /** Returns the total size of the store files shared */</span>
-<span class="source-line-no">230</span><span id="line-230"> public long getSharedStoreFilesSize() {</span>
-<span class="source-line-no">231</span><span id="line-231"> return hfilesSize.get();</span>
-<span class="source-line-no">232</span><span id="line-232"> }</span>
-<span class="source-line-no">233</span><span id="line-233"></span>
-<span class="source-line-no">234</span><span id="line-234"> /** Returns the total size of the store files in the archive */</span>
-<span class="source-line-no">235</span><span id="line-235"> public long getArchivedStoreFileSize() {</span>
-<span class="source-line-no">236</span><span id="line-236"> return hfilesArchiveSize.get();</span>
-<span class="source-line-no">237</span><span id="line-237"> }</span>
-<span class="source-line-no">238</span><span id="line-238"></span>
-<span class="source-line-no">239</span><span id="line-239"> /** Returns the total size of the store files in the mob store */</span>
-<span class="source-line-no">240</span><span id="line-240"> public long getMobStoreFilesSize() {</span>
-<span class="source-line-no">241</span><span id="line-241"> return hfilesMobSize.get();</span>
-<span class="source-line-no">242</span><span id="line-242"> }</span>
-<span class="source-line-no">243</span><span id="line-243"></span>
-<span class="source-line-no">244</span><span id="line-244"> /**</span>
-<span class="source-line-no">245</span><span id="line-245"> * @return the total size of the store files in the archive which is not shared with other</span>
-<span class="source-line-no">246</span><span id="line-246"> * snapshots and tables This is only calculated when</span>
-<span class="source-line-no">247</span><span id="line-247"> * {@link #getSnapshotStats(Configuration, SnapshotProtos.SnapshotDescription, Map)} is</span>
-<span class="source-line-no">248</span><span id="line-248"> * called with a non-null Map</span>
-<span class="source-line-no">249</span><span id="line-249"> */</span>
-<span class="source-line-no">250</span><span id="line-250"> public long getNonSharedArchivedStoreFilesSize() {</span>
-<span class="source-line-no">251</span><span id="line-251"> return nonSharedHfilesArchiveSize.get();</span>
-<span class="source-line-no">252</span><span id="line-252"> }</span>
-<span class="source-line-no">253</span><span id="line-253"></span>
-<span class="source-line-no">254</span><span id="line-254"> /** Returns the percentage of the shared store files */</span>
-<span class="source-line-no">255</span><span id="line-255"> public float getSharedStoreFilePercentage() {</span>
-<span class="source-line-no">256</span><span id="line-256"> return getStoreFilesSize() == 0</span>
-<span class="source-line-no">257</span><span id="line-257"> ? 0</span>
-<span class="source-line-no">258</span><span id="line-258"> : ((float) hfilesSize.get() / (getStoreFilesSize())) * 100;</span>
-<span class="source-line-no">259</span><span id="line-259"> }</span>
-<span class="source-line-no">260</span><span id="line-260"></span>
-<span class="source-line-no">261</span><span id="line-261"> /** Returns the percentage of the mob store files */</span>
-<span class="source-line-no">262</span><span id="line-262"> public float getMobStoreFilePercentage() {</span>
-<span class="source-line-no">263</span><span id="line-263"> return getStoreFilesSize() == 0</span>
-<span class="source-line-no">264</span><span id="line-264"> ? 0</span>
-<span class="source-line-no">265</span><span id="line-265"> : ((float) hfilesMobSize.get() / (getStoreFilesSize())) * 100;</span>
-<span class="source-line-no">266</span><span id="line-266"> }</span>
-<span class="source-line-no">267</span><span id="line-267"></span>
-<span class="source-line-no">268</span><span id="line-268"> /** Returns the total log size */</span>
-<span class="source-line-no">269</span><span id="line-269"> public long getLogsSize() {</span>
-<span class="source-line-no">270</span><span id="line-270"> return logSize.get();</span>
-<span class="source-line-no">271</span><span id="line-271"> }</span>
-<span class="source-line-no">272</span><span id="line-272"></span>
-<span class="source-line-no">273</span><span id="line-273"> /**</span>
-<span class="source-line-no">274</span><span id="line-274"> * Check if for a give file in archive, if there are other snapshots/tables still reference it.</span>
-<span class="source-line-no">275</span><span id="line-275"> * @param filePath file path in archive</span>
-<span class="source-line-no">276</span><span id="line-276"> * @param snapshotFilesMap a map for store files in snapshots about how many snapshots refer to</span>
-<span class="source-line-no">277</span><span id="line-277"> * it.</span>
-<span class="source-line-no">278</span><span id="line-278"> * @return true or false</span>
-<span class="source-line-no">279</span><span id="line-279"> */</span>
-<span class="source-line-no">280</span><span id="line-280"> private boolean isArchivedFileStillReferenced(final Path filePath,</span>
-<span class="source-line-no">281</span><span id="line-281"> final Map<Path, Integer> snapshotFilesMap) {</span>
-<span class="source-line-no">282</span><span id="line-282"></span>
-<span class="source-line-no">283</span><span id="line-283"> Integer c = snapshotFilesMap.get(filePath);</span>
-<span class="source-line-no">284</span><span id="line-284"></span>
-<span class="source-line-no">285</span><span id="line-285"> // Check if there are other snapshots or table from clone_snapshot() (via back-reference)</span>
-<span class="source-line-no">286</span><span id="line-286"> // still reference to it.</span>
-<span class="source-line-no">287</span><span id="line-287"> if ((c != null) && (c == 1)) {</span>
-<span class="source-line-no">288</span><span id="line-288"> Path parentDir = filePath.getParent();</span>
-<span class="source-line-no">289</span><span id="line-289"> Path backRefDir = HFileLink.getBackReferencesDir(parentDir, filePath.getName());</span>
-<span class="source-line-no">290</span><span id="line-290"> try {</span>
-<span class="source-line-no">291</span><span id="line-291"> if (CommonFSUtils.listStatus(fs, backRefDir) == null) {</span>
-<span class="source-line-no">292</span><span id="line-292"> return false;</span>
-<span class="source-line-no">293</span><span id="line-293"> }</span>
-<span class="source-line-no">294</span><span id="line-294"> } catch (IOException e) {</span>
-<span class="source-line-no">295</span><span id="line-295"> // For the purpose of this function, IOException is ignored and treated as</span>
-<span class="source-line-no">296</span><span id="line-296"> // the file is still being referenced.</span>
-<span class="source-line-no">297</span><span id="line-297"> }</span>
-<span class="source-line-no">298</span><span id="line-298"> }</span>
-<span class="source-line-no">299</span><span id="line-299"> return true;</span>
-<span class="source-line-no">300</span><span id="line-300"> }</span>
-<span class="source-line-no">301</span><span id="line-301"></span>
-<span class="source-line-no">302</span><span id="line-302"> /**</span>
-<span class="source-line-no">303</span><span id="line-303"> * Add the specified store file to the stats</span>
-<span class="source-line-no">304</span><span id="line-304"> * @param region region encoded Name</span>
-<span class="source-line-no">305</span><span id="line-305"> * @param family family name</span>
-<span class="source-line-no">306</span><span id="line-306"> * @param storeFile store file name</span>
-<span class="source-line-no">307</span><span id="line-307"> * @param filesMap store files map for all snapshots, it may be null</span>
-<span class="source-line-no">308</span><span id="line-308"> * @return the store file information</span>
-<span class="source-line-no">309</span><span id="line-309"> */</span>
-<span class="source-line-no">310</span><span id="line-310"> FileInfo addStoreFile(final RegionInfo region, final String family,</span>
-<span class="source-line-no">311</span><span id="line-311"> final SnapshotRegionManifest.StoreFile storeFile, final Map<Path, Integer> filesMap)</span>
-<span class="source-line-no">312</span><span id="line-312"> throws IOException {</span>
-<span class="source-line-no">313</span><span id="line-313"> HFileLink link =</span>
-<span class="source-line-no">314</span><span id="line-314"> HFileLink.build(conf, snapshotTable, region.getEncodedName(), family, storeFile.getName());</span>
-<span class="source-line-no">315</span><span id="line-315"> boolean isCorrupted = false;</span>
-<span class="source-line-no">316</span><span id="line-316"> boolean inArchive = false;</span>
-<span class="source-line-no">317</span><span id="line-317"> long size = -1;</span>
-<span class="source-line-no">318</span><span id="line-318"> try {</span>
-<span class="source-line-no">319</span><span id="line-319"> if (fs.exists(link.getArchivePath())) {</span>
-<span class="source-line-no">320</span><span id="line-320"> inArchive = true;</span>
-<span class="source-line-no">321</span><span id="line-321"> size = fs.getFileStatus(link.getArchivePath()).getLen();</span>
-<span class="source-line-no">322</span><span id="line-322"> hfilesArchiveSize.addAndGet(size);</span>
-<span class="source-line-no">323</span><span id="line-323"> hfilesArchiveCount.incrementAndGet();</span>
-<span class="source-line-no">324</span><span id="line-324"></span>
-<span class="source-line-no">325</span><span id="line-325"> // If store file is not shared with other snapshots and tables,</span>
-<span class="source-line-no">326</span><span id="line-326"> // increase nonSharedHfilesArchiveSize</span>
-<span class="source-line-no">327</span><span id="line-327"> if (</span>
-<span class="source-line-no">328</span><span id="line-328"> (filesMap != null) && !isArchivedFileStillReferenced(link.getArchivePath(), filesMap)</span>
-<span class="source-line-no">329</span><span id="line-329"> ) {</span>
-<span class="source-line-no">330</span><span id="line-330"> nonSharedHfilesArchiveSize.addAndGet(size);</span>
-<span class="source-line-no">331</span><span id="line-331"> }</span>
-<span class="source-line-no">332</span><span id="line-332"> } else if (fs.exists(link.getMobPath())) {</span>
-<span class="source-line-no">333</span><span id="line-333"> inArchive = true;</span>
-<span class="source-line-no">334</span><span id="line-334"> size = fs.getFileStatus(link.getMobPath()).getLen();</span>
-<span class="source-line-no">335</span><span id="line-335"> hfilesMobSize.addAndGet(size);</span>
-<span class="source-line-no">336</span><span id="line-336"> hfilesMobCount.incrementAndGet();</span>
-<span class="source-line-no">337</span><span id="line-337"> } else {</span>
-<span class="source-line-no">338</span><span id="line-338"> size = link.getFileStatus(fs).getLen();</span>
-<span class="source-line-no">339</span><span id="line-339"> hfilesSize.addAndGet(size);</span>
-<span class="source-line-no">340</span><span id="line-340"> hfilesCount.incrementAndGet();</span>
-<span class="source-line-no">341</span><span id="line-341"> }</span>
-<span class="source-line-no">342</span><span id="line-342"> isCorrupted = (storeFile.hasFileSize() && storeFile.getFileSize() != size);</span>
-<span class="source-line-no">343</span><span id="line-343"> if (isCorrupted) hfilesCorrupted.incrementAndGet();</span>
-<span class="source-line-no">344</span><span id="line-344"> } catch (FileNotFoundException e) {</span>
-<span class="source-line-no">345</span><span id="line-345"> hfilesMissing.incrementAndGet();</span>
-<span class="source-line-no">346</span><span id="line-346"> }</span>
-<span class="source-line-no">347</span><span id="line-347"> return new FileInfo(inArchive, size, isCorrupted);</span>
-<span class="source-line-no">348</span><span id="line-348"> }</span>
-<span class="source-line-no">349</span><span id="line-349"></span>
-<span class="source-line-no">350</span><span id="line-350"> /**</span>
-<span class="source-line-no">351</span><span id="line-351"> * Add the specified log file to the stats</span>
-<span class="source-line-no">352</span><span id="line-352"> * @param server server name</span>
-<span class="source-line-no">353</span><span id="line-353"> * @param logfile log file name</span>
-<span class="source-line-no">354</span><span id="line-354"> * @return the log information</span>
-<span class="source-line-no">355</span><span id="line-355"> */</span>
-<span class="source-line-no">356</span><span id="line-356"> FileInfo addLogFile(final String server, final String logfile) throws IOException {</span>
-<span class="source-line-no">357</span><span id="line-357"> WALLink logLink = new WALLink(conf, server, logfile);</span>
-<span class="source-line-no">358</span><span id="line-358"> long size = -1;</span>
-<span class="source-line-no">359</span><span id="line-359"> try {</span>
-<span class="source-line-no">360</span><span id="line-360"> size = logLink.getFileStatus(fs).getLen();</span>
-<span class="source-line-no">361</span><span id="line-361"> logSize.addAndGet(size);</span>
-<span class="source-line-no">362</span><span id="line-362"> logsCount.incrementAndGet();</span>
-<span class="source-line-no">363</span><span id="line-363"> } catch (FileNotFoundException e) {</span>
-<span class="source-line-no">364</span><span id="line-364"> logsMissing.incrementAndGet();</span>
-<span class="source-line-no">365</span><span id="line-365"> }</span>
-<span class="source-line-no">366</span><span id="line-366"> return new FileInfo(false, size, false);</span>
-<span class="source-line-no">367</span><span id="line-367"> }</span>
-<span class="source-line-no">368</span><span id="line-368"> }</span>
-<span class="source-line-no">369</span><span id="line-369"></span>
-<span class="source-line-no">370</span><span id="line-370"> private FileSystem fs;</span>
-<span class="source-line-no">371</span><span id="line-371"> private Path rootDir;</span>
-<span class="source-line-no">372</span><span id="line-372"></span>
-<span class="source-line-no">373</span><span id="line-373"> private SnapshotManifest snapshotManifest;</span>
-<span class="source-line-no">374</span><span id="line-374"></span>
-<span class="source-line-no">375</span><span id="line-375"> private boolean listSnapshots = false;</span>
-<span class="source-line-no">376</span><span id="line-376"> private String snapshotName;</span>
-<span class="source-line-no">377</span><span id="line-377"> private Path remoteDir;</span>
-<span class="source-line-no">378</span><span id="line-378"> private boolean showSchema = false;</span>
-<span class="source-line-no">379</span><span id="line-379"> private boolean showFiles = false;</span>
-<span class="source-line-no">380</span><span id="line-380"> private boolean showStats = false;</span>
-<span class="source-line-no">381</span><span id="line-381"> private boolean printSizeInBytes = false;</span>
-<span class="source-line-no">382</span><span id="line-382"></span>
-<span class="source-line-no">383</span><span id="line-383"> @Override</span>
-<span class="source-line-no">384</span><span id="line-384"> public int doWork() throws IOException, InterruptedException {</span>
-<span class="source-line-no">385</span><span id="line-385"> if (remoteDir != null) {</span>
-<span class="source-line-no">386</span><span id="line-386"> URI defaultFs = remoteDir.getFileSystem(conf).getUri();</span>
-<span class="source-line-no">387</span><span id="line-387"> CommonFSUtils.setFsDefault(conf, new Path(defaultFs));</span>
-<span class="source-line-no">388</span><span id="line-388"> CommonFSUtils.setRootDir(conf, remoteDir);</span>
-<span class="source-line-no">389</span><span id="line-389"> }</span>
-<span class="source-line-no">390</span><span id="line-390"></span>
-<span class="source-line-no">391</span><span id="line-391"> // List Available Snapshots</span>
-<span class="source-line-no">392</span><span id="line-392"> if (listSnapshots) {</span>
-<span class="source-line-no">393</span><span id="line-393"> SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");</span>
-<span class="source-line-no">394</span><span id="line-394"> System.out.printf("%-20s | %-20s | %-20s | %s%n", "SNAPSHOT", "CREATION TIME", "TTL IN SEC",</span>
-<span class="source-line-no">395</span><span id="line-395"> "TABLE NAME");</span>
-<span class="source-line-no">396</span><span id="line-396"> for (SnapshotDescription desc : getSnapshotList(conf)) {</span>
-<span class="source-line-no">397</span><span id="line-397"> System.out.printf("%-20s | %20s | %20s | %s%n", desc.getName(),</span>
-<span class="source-line-no">398</span><span id="line-398"> df.format(new Date(desc.getCreationTime())), desc.getTtl(), desc.getTableNameAsString());</span>
-<span class="source-line-no">399</span><span id="line-399"> }</span>
-<span class="source-line-no">400</span><span id="line-400"> return 0;</span>
-<span class="source-line-no">401</span><span id="line-401"> }</span>
-<span class="source-line-no">402</span><span id="line-402"></span>
-<span class="source-line-no">403</span><span id="line-403"> rootDir = CommonFSUtils.getRootDir(conf);</span>
-<span class="source-line-no">404</span><span id="line-404"> fs = FileSystem.get(rootDir.toUri(), conf);</span>
-<span class="source-line-no">405</span><span id="line-405"> LOG.debug("fs=" + fs.getUri().toString() + " root=" + rootDir);</span>
-<span class="source-line-no">406</span><span id="line-406"></span>
-<span class="source-line-no">407</span><span id="line-407"> // Load snapshot information</span>
-<span class="source-line-no">408</span><span id="line-408"> if (!loadSnapshotInfo(snapshotName)) {</span>
-<span class="source-line-no">409</span><span id="line-409"> System.err.println("Snapshot '" + snapshotName + "' not found!");</span>
-<span class="source-line-no">410</span><span id="line-410"> return 1;</span>
-<span class="source-line-no">411</span><span id="line-411"> }</span>
-<span class="source-line-no">412</span><span id="line-412"></span>
-<span class="source-line-no">413</span><span id="line-413"> printInfo();</span>
-<span class="source-line-no">414</span><span id="line-414"> if (showSchema) {</span>
-<span class="source-line-no">415</span><span id="line-415"> printSchema();</span>
-<span class="source-line-no">416</span><span id="line-416"> }</span>
-<span class="source-line-no">417</span><span id="line-417"> printFiles(showFiles, showStats);</span>
-<span class="source-line-no">418</span><span id="line-418"></span>
-<span class="source-line-no">419</span><span id="line-419"> return 0;</span>
-<span class="source-line-no">420</span><span id="line-420"> }</span>
-<span class="source-line-no">421</span><span id="line-421"></span>
-<span class="source-line-no">422</span><span id="line-422"> /**</span>
-<span class="source-line-no">423</span><span id="line-423"> * Load snapshot info and table descriptor for the specified snapshot</span>
-<span class="source-line-no">424</span><span id="line-424"> * @param snapshotName name of the snapshot to load</span>
-<span class="source-line-no">425</span><span id="line-425"> * @return false if snapshot is not found</span>
-<span class="source-line-no">426</span><span id="line-426"> */</span>
-<span class="source-line-no">427</span><span id="line-427"> private boolean loadSnapshotInfo(final String snapshotName) throws IOException {</span>
-<span class="source-line-no">428</span><span id="line-428"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);</span>
-<span class="source-line-no">429</span><span id="line-429"> if (!fs.exists(snapshotDir)) {</span>
-<span class="source-line-no">430</span><span id="line-430"> LOG.warn("Snapshot '" + snapshotName + "' not found in: " + snapshotDir);</span>
-<span class="source-line-no">431</span><span id="line-431"> return false;</span>
-<span class="source-line-no">432</span><span id="line-432"> }</span>
-<span class="source-line-no">433</span><span id="line-433"></span>
-<span class="source-line-no">434</span><span id="line-434"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">435</span><span id="line-435"> SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);</span>
-<span class="source-line-no">436</span><span id="line-436"> snapshotManifest = SnapshotManifest.open(getConf(), fs, snapshotDir, snapshotDesc);</span>
-<span class="source-line-no">437</span><span id="line-437"> return true;</span>
-<span class="source-line-no">438</span><span id="line-438"> }</span>
-<span class="source-line-no">439</span><span id="line-439"></span>
-<span class="source-line-no">440</span><span id="line-440"> /**</span>
-<span class="source-line-no">441</span><span id="line-441"> * Dump the {@link SnapshotDescription}</span>
-<span class="source-line-no">442</span><span id="line-442"> */</span>
-<span class="source-line-no">443</span><span id="line-443"> private void printInfo() {</span>
-<span class="source-line-no">444</span><span id="line-444"> SnapshotProtos.SnapshotDescription snapshotDesc = snapshotManifest.getSnapshotDescription();</span>
-<span class="source-line-no">445</span><span id="line-445"> SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");</span>
-<span class="source-line-no">446</span><span id="line-446"> System.out.println("Snapshot Info");</span>
-<span class="source-line-no">447</span><span id="line-447"> System.out.println("----------------------------------------");</span>
-<span class="source-line-no">448</span><span id="line-448"> System.out.println(" Name: " + snapshotDesc.getName());</span>
-<span class="source-line-no">449</span><span id="line-449"> System.out.println(" Type: " + snapshotDesc.getType());</span>
-<span class="source-line-no">450</span><span id="line-450"> System.out.println(" Table: " + snapshotDesc.getTable());</span>
-<span class="source-line-no">451</span><span id="line-451"> System.out.println(" Format: " + snapshotDesc.getVersion());</span>
-<span class="source-line-no">452</span><span id="line-452"> System.out.println("Created: " + df.format(new Date(snapshotDesc.getCreationTime())));</span>
-<span class="source-line-no">453</span><span id="line-453"> System.out.println(" Ttl: " + snapshotDesc.getTtl());</span>
-<span class="source-line-no">454</span><span id="line-454"> System.out.println(" Owner: " + snapshotDesc.getOwner());</span>
-<span class="source-line-no">455</span><span id="line-455"> System.out.println();</span>
-<span class="source-line-no">456</span><span id="line-456"> }</span>
-<span class="source-line-no">457</span><span id="line-457"></span>
-<span class="source-line-no">458</span><span id="line-458"> /**</span>
-<span class="source-line-no">459</span><span id="line-459"> * Dump the {@link org.apache.hadoop.hbase.client.TableDescriptor}</span>
-<span class="source-line-no">460</span><span id="line-460"> */</span>
-<span class="source-line-no">461</span><span id="line-461"> private void printSchema() {</span>
-<span class="source-line-no">462</span><span id="line-462"> System.out.println("Table Descriptor");</span>
-<span class="source-line-no">463</span><span id="line-463"> System.out.println("----------------------------------------");</span>
-<span class="source-line-no">464</span><span id="line-464"> System.out.println(snapshotManifest.getTableDescriptor().toString());</span>
-<span class="source-line-no">465</span><span id="line-465"> System.out.println();</span>
-<span class="source-line-no">466</span><span id="line-466"> }</span>
-<span class="source-line-no">467</span><span id="line-467"></span>
-<span class="source-line-no">468</span><span id="line-468"> /**</span>
-<span class="source-line-no">469</span><span id="line-469"> * Collect the hfiles and logs statistics of the snapshot and dump the file list if requested and</span>
-<span class="source-line-no">470</span><span id="line-470"> * the collected information.</span>
-<span class="source-line-no">471</span><span id="line-471"> */</span>
-<span class="source-line-no">472</span><span id="line-472"> private void printFiles(final boolean showFiles, final boolean showStats) throws IOException {</span>
-<span class="source-line-no">473</span><span id="line-473"> if (showFiles) {</span>
-<span class="source-line-no">474</span><span id="line-474"> System.out.println("Snapshot Files");</span>
-<span class="source-line-no">475</span><span id="line-475"> System.out.println("----------------------------------------");</span>
-<span class="source-line-no">476</span><span id="line-476"> }</span>
-<span class="source-line-no">477</span><span id="line-477"></span>
-<span class="source-line-no">478</span><span id="line-478"> // Collect information about hfiles and logs in the snapshot</span>
-<span class="source-line-no">479</span><span id="line-479"> final SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">480</span><span id="line-480"> snapshotManifest.getSnapshotDescription();</span>
-<span class="source-line-no">481</span><span id="line-481"> final String table = snapshotDesc.getTable();</span>
-<span class="source-line-no">482</span><span id="line-482"> final SnapshotDescription desc = ProtobufUtil.createSnapshotDesc(snapshotDesc);</span>
-<span class="source-line-no">483</span><span id="line-483"> final SnapshotStats stats = new SnapshotStats(this.getConf(), this.fs, desc);</span>
-<span class="source-line-no">484</span><span id="line-484"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(getConf(), fs, snapshotManifest,</span>
-<span class="source-line-no">485</span><span id="line-485"> "SnapshotInfo", new SnapshotReferenceUtil.SnapshotVisitor() {</span>
-<span class="source-line-no">486</span><span id="line-486"> @Override</span>
-<span class="source-line-no">487</span><span id="line-487"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
-<span class="source-line-no">488</span><span id="line-488"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
-<span class="source-line-no">489</span><span id="line-489"> if (storeFile.hasReference()) return;</span>
-<span class="source-line-no">490</span><span id="line-490"></span>
-<span class="source-line-no">491</span><span id="line-491"> SnapshotStats.FileInfo info = stats.addStoreFile(regionInfo, family, storeFile, null);</span>
-<span class="source-line-no">492</span><span id="line-492"> if (showFiles) {</span>
-<span class="source-line-no">493</span><span id="line-493"> String state = info.getStateToString();</span>
-<span class="source-line-no">494</span><span id="line-494"> System.out.printf("%8s %s/%s/%s/%s %s%n",</span>
-<span class="source-line-no">495</span><span id="line-495"> (info.isMissing() ? "-" : fileSizeToString(info.getSize())), table,</span>
-<span class="source-line-no">496</span><span id="line-496"> regionInfo.getEncodedName(), family, storeFile.getName(),</span>
-<span class="source-line-no">497</span><span id="line-497"> state == null ? "" : "(" + state + ")");</span>
-<span class="source-line-no">498</span><span id="line-498"> }</span>
-<span class="source-line-no">499</span><span id="line-499"> }</span>
-<span class="source-line-no">500</span><span id="line-500"> });</span>
-<span class="source-line-no">501</span><span id="line-501"></span>
-<span class="source-line-no">502</span><span id="line-502"> // Dump the stats</span>
-<span class="source-line-no">503</span><span id="line-503"> System.out.println();</span>
-<span class="source-line-no">504</span><span id="line-504"> if (stats.isSnapshotCorrupted()) {</span>
-<span class="source-line-no">505</span><span id="line-505"> System.out.println("**************************************************************");</span>
-<span class="source-line-no">506</span><span id="line-506"> System.out.printf("BAD SNAPSHOT: %d hfile(s) and %d log(s) missing.%n",</span>
-<span class="source-line-no">507</span><span id="line-507"> stats.getMissingStoreFilesCount(), stats.getMissingLogsCount());</span>
-<span class="source-line-no">508</span><span id="line-508"> System.out.printf(" %d hfile(s) corrupted.%n",</span>
-<span class="source-line-no">509</span><span id="line-509"> stats.getCorruptedStoreFilesCount());</span>
-<span class="source-line-no">510</span><span id="line-510"> System.out.println("**************************************************************");</span>
-<span class="source-line-no">511</span><span id="line-511"> }</span>
-<span class="source-line-no">512</span><span id="line-512"></span>
-<span class="source-line-no">513</span><span id="line-513"> if (showStats) {</span>
-<span class="source-line-no">514</span><span id="line-514"> System.out.printf(</span>
-<span class="source-line-no">515</span><span id="line-515"> "%d HFiles (%d in archive, %d in mob storage), total size %s "</span>
-<span class="source-line-no">516</span><span id="line-516"> + "(%.2f%% %s shared with the source table, %.2f%% %s in mob dir)%n",</span>
-<span class="source-line-no">517</span><span id="line-517"> stats.getStoreFilesCount(), stats.getArchivedStoreFilesCount(),</span>
-<span class="source-line-no">518</span><span id="line-518"> stats.getMobStoreFilesCount(), fileSizeToString(stats.getStoreFilesSize()),</span>
-<span class="source-line-no">519</span><span id="line-519"> stats.getSharedStoreFilePercentage(), fileSizeToString(stats.getSharedStoreFilesSize()),</span>
-<span class="source-line-no">520</span><span id="line-520"> stats.getMobStoreFilePercentage(), fileSizeToString(stats.getMobStoreFilesSize()));</span>
-<span class="source-line-no">521</span><span id="line-521"> System.out.printf("%d Logs, total size %s%n", stats.getLogsCount(),</span>
-<span class="source-line-no">522</span><span id="line-522"> fileSizeToString(stats.getLogsSize()));</span>
-<span class="source-line-no">523</span><span id="line-523"> System.out.println();</span>
-<span class="source-line-no">524</span><span id="line-524"> }</span>
-<span class="source-line-no">525</span><span id="line-525"> }</span>
-<span class="source-line-no">526</span><span id="line-526"></span>
-<span class="source-line-no">527</span><span id="line-527"> private String fileSizeToString(long size) {</span>
-<span class="source-line-no">528</span><span id="line-528"> return printSizeInBytes ? Long.toString(size) : Strings.humanReadableInt(size);</span>
-<span class="source-line-no">529</span><span id="line-529"> }</span>
-<span class="source-line-no">530</span><span id="line-530"></span>
-<span class="source-line-no">531</span><span id="line-531"> @Override</span>
-<span class="source-line-no">532</span><span id="line-532"> protected void addOptions() {</span>
-<span class="source-line-no">533</span><span id="line-533"> addOption(Options.SNAPSHOT);</span>
-<span class="source-line-no">534</span><span id="line-534"> addOption(Options.REMOTE_DIR);</span>
-<span class="source-line-no">535</span><span id="line-535"> addOption(Options.LIST_SNAPSHOTS);</span>
-<span class="source-line-no">536</span><span id="line-536"> addOption(Options.FILES);</span>
-<span class="source-line-no">537</span><span id="line-537"> addOption(Options.STATS);</span>
-<span class="source-line-no">538</span><span id="line-538"> addOption(Options.SCHEMA);</span>
-<span class="source-line-no">539</span><span id="line-539"> addOption(Options.SIZE_IN_BYTES);</span>
-<span class="source-line-no">540</span><span id="line-540"> }</span>
-<span class="source-line-no">541</span><span id="line-541"></span>
-<span class="source-line-no">542</span><span id="line-542"> @Override</span>
-<span class="source-line-no">543</span><span id="line-543"> protected CommandLineParser newParser() {</span>
-<span class="source-line-no">544</span><span id="line-544"> // Commons-CLI lacks the capability to handle combinations of options, so we do it ourselves</span>
-<span class="source-line-no">545</span><span id="line-545"> // Validate in parse() to get helpful error messages instead of exploding in processOptions()</span>
-<span class="source-line-no">546</span><span id="line-546"> return new DefaultParser() {</span>
-<span class="source-line-no">547</span><span id="line-547"> @Override</span>
-<span class="source-line-no">548</span><span id="line-548"> public CommandLine parse(org.apache.hbase.thirdparty.org.apache.commons.cli.Options opts,</span>
-<span class="source-line-no">549</span><span id="line-549"> String[] args, Properties props, boolean stop) throws ParseException {</span>
-<span class="source-line-no">550</span><span id="line-550"> CommandLine cl = super.parse(opts, args, props, stop);</span>
-<span class="source-line-no">551</span><span id="line-551"> if (!cmd.hasOption(Options.LIST_SNAPSHOTS) && !cmd.hasOption(Options.SNAPSHOT)) {</span>
-<span class="source-line-no">552</span><span id="line-552"> throw new ParseException("Missing required snapshot option!");</span>
-<span class="source-line-no">553</span><span id="line-553"> }</span>
-<span class="source-line-no">554</span><span id="line-554"> return cl;</span>
-<span class="source-line-no">555</span><span id="line-555"> }</span>
-<span class="source-line-no">556</span><span id="line-556"> };</span>
-<span class="source-line-no">557</span><span id="line-557"> }</span>
-<span class="source-line-no">558</span><span id="line-558"></span>
-<span class="source-line-no">559</span><span id="line-559"> @Override</span>
-<span class="source-line-no">560</span><span id="line-560"> protected void processOptions(CommandLine cmd) {</span>
-<span class="source-line-no">561</span><span id="line-561"> snapshotName = cmd.getOptionValue(Options.SNAPSHOT.getLongOpt());</span>
-<span class="source-line-no">562</span><span id="line-562"> showFiles = cmd.hasOption(Options.FILES.getLongOpt());</span>
-<span class="source-line-no">563</span><span id="line-563"> showStats =</span>
-<span class="source-line-no">564</span><span id="line-564"> cmd.hasOption(Options.FILES.getLongOpt()) || cmd.hasOption(Options.STATS.getLongOpt());</span>
-<span class="source-line-no">565</span><span id="line-565"> showSchema = cmd.hasOption(Options.SCHEMA.getLongOpt());</span>
-<span class="source-line-no">566</span><span id="line-566"> listSnapshots = cmd.hasOption(Options.LIST_SNAPSHOTS.getLongOpt());</span>
-<span class="source-line-no">567</span><span id="line-567"> printSizeInBytes = cmd.hasOption(Options.SIZE_IN_BYTES.getLongOpt());</span>
-<span class="source-line-no">568</span><span id="line-568"> if (cmd.hasOption(Options.REMOTE_DIR.getLongOpt())) {</span>
-<span class="source-line-no">569</span><span id="line-569"> remoteDir = new Path(cmd.getOptionValue(Options.REMOTE_DIR.getLongOpt()));</span>
-<span class="source-line-no">570</span><span id="line-570"> }</span>
-<span class="source-line-no">571</span><span id="line-571"> }</span>
-<span class="source-line-no">572</span><span id="line-572"></span>
-<span class="source-line-no">573</span><span id="line-573"> @Override</span>
-<span class="source-line-no">574</span><span id="line-574"> protected void printUsage() {</span>
-<span class="source-line-no">575</span><span id="line-575"> printUsage("hbase snapshot info [options]", "Options:", "");</span>
-<span class="source-line-no">576</span><span id="line-576"> System.err.println("Examples:");</span>
-<span class="source-line-no">577</span><span id="line-577"> System.err.println(" hbase snapshot info --snapshot MySnapshot --files");</span>
+<span class="source-line-no">117</span><span id="line-117"> FileInfo(final boolean inArchive, final long size, final boolean corrupted) {</span>
+<span class="source-line-no">118</span><span id="line-118"> this.corrupted = corrupted;</span>
+<span class="source-line-no">119</span><span id="line-119"> this.inArchive = inArchive;</span>
+<span class="source-line-no">120</span><span id="line-120"> this.size = size;</span>
+<span class="source-line-no">121</span><span id="line-121"> }</span>
+<span class="source-line-no">122</span><span id="line-122"></span>
+<span class="source-line-no">123</span><span id="line-123"> /** Returns true if the file is in the archive */</span>
+<span class="source-line-no">124</span><span id="line-124"> public boolean inArchive() {</span>
+<span class="source-line-no">125</span><span id="line-125"> return this.inArchive;</span>
+<span class="source-line-no">126</span><span id="line-126"> }</span>
+<span class="source-line-no">127</span><span id="line-127"></span>
+<span class="source-line-no">128</span><span id="line-128"> /** Returns true if the file is corrupted */</span>
+<span class="source-line-no">129</span><span id="line-129"> public boolean isCorrupted() {</span>
+<span class="source-line-no">130</span><span id="line-130"> return this.corrupted;</span>
+<span class="source-line-no">131</span><span id="line-131"> }</span>
+<span class="source-line-no">132</span><span id="line-132"></span>
+<span class="source-line-no">133</span><span id="line-133"> /** Returns true if the file is missing */</span>
+<span class="source-line-no">134</span><span id="line-134"> public boolean isMissing() {</span>
+<span class="source-line-no">135</span><span id="line-135"> return this.size < 0;</span>
+<span class="source-line-no">136</span><span id="line-136"> }</span>
+<span class="source-line-no">137</span><span id="line-137"></span>
+<span class="source-line-no">138</span><span id="line-138"> /** Returns the file size */</span>
+<span class="source-line-no">139</span><span id="line-139"> public long getSize() {</span>
+<span class="source-line-no">140</span><span id="line-140"> return this.size;</span>
+<span class="source-line-no">141</span><span id="line-141"> }</span>
+<span class="source-line-no">142</span><span id="line-142"></span>
+<span class="source-line-no">143</span><span id="line-143"> String getStateToString() {</span>
+<span class="source-line-no">144</span><span id="line-144"> if (isCorrupted()) return "CORRUPTED";</span>
+<span class="source-line-no">145</span><span id="line-145"> if (isMissing()) return "NOT FOUND";</span>
+<span class="source-line-no">146</span><span id="line-146"> if (inArchive()) return "archive";</span>
+<span class="source-line-no">147</span><span id="line-147"> return null;</span>
+<span class="source-line-no">148</span><span id="line-148"> }</span>
+<span class="source-line-no">149</span><span id="line-149"> }</span>
+<span class="source-line-no">150</span><span id="line-150"></span>
+<span class="source-line-no">151</span><span id="line-151"> private AtomicInteger hfilesArchiveCount = new AtomicInteger();</span>
+<span class="source-line-no">152</span><span id="line-152"> private AtomicInteger hfilesCorrupted = new AtomicInteger();</span>
+<span class="source-line-no">153</span><span id="line-153"> private AtomicInteger hfilesMissing = new AtomicInteger();</span>
+<span class="source-line-no">154</span><span id="line-154"> private AtomicInteger hfilesCount = new AtomicInteger();</span>
+<span class="source-line-no">155</span><span id="line-155"> private AtomicInteger hfilesMobCount = new AtomicInteger();</span>
+<span class="source-line-no">156</span><span id="line-156"> private AtomicInteger logsMissing = new AtomicInteger();</span>
+<span class="source-line-no">157</span><span id="line-157"> private AtomicInteger logsCount = new AtomicInteger();</span>
+<span class="source-line-no">158</span><span id="line-158"> private AtomicLong hfilesArchiveSize = new AtomicLong();</span>
+<span class="source-line-no">159</span><span id="line-159"> private AtomicLong hfilesSize = new AtomicLong();</span>
+<span class="source-line-no">160</span><span id="line-160"> private AtomicLong hfilesMobSize = new AtomicLong();</span>
+<span class="source-line-no">161</span><span id="line-161"> private AtomicLong nonSharedHfilesArchiveSize = new AtomicLong();</span>
+<span class="source-line-no">162</span><span id="line-162"> private AtomicLong logSize = new AtomicLong();</span>
+<span class="source-line-no">163</span><span id="line-163"></span>
+<span class="source-line-no">164</span><span id="line-164"> private final SnapshotProtos.SnapshotDescription snapshot;</span>
+<span class="source-line-no">165</span><span id="line-165"> private final TableName snapshotTable;</span>
+<span class="source-line-no">166</span><span id="line-166"> private final Configuration conf;</span>
+<span class="source-line-no">167</span><span id="line-167"> private final FileSystem fs;</span>
+<span class="source-line-no">168</span><span id="line-168"></span>
+<span class="source-line-no">169</span><span id="line-169"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
+<span class="source-line-no">170</span><span id="line-170"> final SnapshotDescription snapshot) {</span>
+<span class="source-line-no">171</span><span id="line-171"> this.snapshot = ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
+<span class="source-line-no">172</span><span id="line-172"> this.snapshotTable = snapshot.getTableName();</span>
+<span class="source-line-no">173</span><span id="line-173"> this.conf = conf;</span>
+<span class="source-line-no">174</span><span id="line-174"> this.fs = fs;</span>
+<span class="source-line-no">175</span><span id="line-175"> }</span>
+<span class="source-line-no">176</span><span id="line-176"></span>
+<span class="source-line-no">177</span><span id="line-177"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
+<span class="source-line-no">178</span><span id="line-178"> final SnapshotProtos.SnapshotDescription snapshot) {</span>
+<span class="source-line-no">179</span><span id="line-179"> this.snapshot = snapshot;</span>
+<span class="source-line-no">180</span><span id="line-180"> this.snapshotTable = TableName.valueOf(snapshot.getTable());</span>
+<span class="source-line-no">181</span><span id="line-181"> this.conf = conf;</span>
+<span class="source-line-no">182</span><span id="line-182"> this.fs = fs;</span>
+<span class="source-line-no">183</span><span id="line-183"> }</span>
+<span class="source-line-no">184</span><span id="line-184"></span>
+<span class="source-line-no">185</span><span id="line-185"> /** Returns the snapshot descriptor */</span>
+<span class="source-line-no">186</span><span id="line-186"> public SnapshotDescription getSnapshotDescription() {</span>
+<span class="source-line-no">187</span><span id="line-187"> return ProtobufUtil.createSnapshotDesc(this.snapshot);</span>
+<span class="source-line-no">188</span><span id="line-188"> }</span>
+<span class="source-line-no">189</span><span id="line-189"></span>
+<span class="source-line-no">190</span><span id="line-190"> /** Returns true if the snapshot is corrupted */</span>
+<span class="source-line-no">191</span><span id="line-191"> public boolean isSnapshotCorrupted() {</span>
+<span class="source-line-no">192</span><span id="line-192"> return hfilesMissing.get() > 0 || logsMissing.get() > 0 || hfilesCorrupted.get() > 0;</span>
+<span class="source-line-no">193</span><span id="line-193"> }</span>
+<span class="source-line-no">194</span><span id="line-194"></span>
+<span class="source-line-no">195</span><span id="line-195"> /** Returns the number of available store files */</span>
+<span class="source-line-no">196</span><span id="line-196"> public int getStoreFilesCount() {</span>
+<span class="source-line-no">197</span><span id="line-197"> return hfilesCount.get() + hfilesArchiveCount.get() + hfilesMobCount.get();</span>
+<span class="source-line-no">198</span><span id="line-198"> }</span>
+<span class="source-line-no">199</span><span id="line-199"></span>
+<span class="source-line-no">200</span><span id="line-200"> /** Returns the number of available store files in the archive */</span>
+<span class="source-line-no">201</span><span id="line-201"> public int getArchivedStoreFilesCount() {</span>
+<span class="source-line-no">202</span><span id="line-202"> return hfilesArchiveCount.get();</span>
+<span class="source-line-no">203</span><span id="line-203"> }</span>
+<span class="source-line-no">204</span><span id="line-204"></span>
+<span class="source-line-no">205</span><span id="line-205"> /** Returns the number of available store files in the mob dir */</span>
+<span class="source-line-no">206</span><span id="line-206"> public int getMobStoreFilesCount() {</span>
+<span class="source-line-no">207</span><span id="line-207"> return hfilesMobCount.get();</span>
+<span class="source-line-no">208</span><span id="line-208"> }</span>
+<span class="source-line-no">209</span><span id="line-209"></span>
+<span class="source-line-no">210</span><span id="line-210"> /** Returns the number of available log files */</span>
+<span class="source-line-no">211</span><span id="line-211"> public int getLogsCount() {</span>
+<span class="source-line-no">212</span><span id="line-212"> return logsCount.get();</span>
+<span class="source-line-no">213</span><span id="line-213"> }</span>
+<span class="source-line-no">214</span><span id="line-214"></span>
+<span class="source-line-no">215</span><span id="line-215"> /** Returns the number of missing store files */</span>
+<span class="source-line-no">216</span><span id="line-216"> public int getMissingStoreFilesCount() {</span>
+<span class="source-line-no">217</span><span id="line-217"> return hfilesMissing.get();</span>
+<span class="source-line-no">218</span><span id="line-218"> }</span>
+<span class="source-line-no">219</span><span id="line-219"></span>
+<span class="source-line-no">220</span><span id="line-220"> /** Returns the number of corrupted store files */</span>
+<span class="source-line-no">221</span><span id="line-221"> public int getCorruptedStoreFilesCount() {</span>
+<span class="source-line-no">222</span><span id="line-222"> return hfilesCorrupted.get();</span>
+<span class="source-line-no">223</span><span id="line-223"> }</span>
+<span class="source-line-no">224</span><span id="line-224"></span>
+<span class="source-line-no">225</span><span id="line-225"> /** Returns the number of missing log files */</span>
+<span class="source-line-no">226</span><span id="line-226"> public int getMissingLogsCount() {</span>
+<span class="source-line-no">227</span><span id="line-227"> return logsMissing.get();</span>
+<span class="source-line-no">228</span><span id="line-228"> }</span>
+<span class="source-line-no">229</span><span id="line-229"></span>
+<span class="source-line-no">230</span><span id="line-230"> /** Returns the total size of the store files referenced by the snapshot */</span>
+<span class="source-line-no">231</span><span id="line-231"> public long getStoreFilesSize() {</span>
+<span class="source-line-no">232</span><span id="line-232"> return hfilesSize.get() + hfilesArchiveSize.get() + hfilesMobSize.get();</span>
+<span class="source-line-no">233</span><span id="line-233"> }</span>
+<span class="source-line-no">234</span><span id="line-234"></span>
+<span class="source-line-no">235</span><span id="line-235"> /** Returns the total size of the store files shared */</span>
+<span class="source-line-no">236</span><span id="line-236"> public long getSharedStoreFilesSize() {</span>
+<span class="source-line-no">237</span><span id="line-237"> return hfilesSize.get();</span>
+<span class="source-line-no">238</span><span id="line-238"> }</span>
+<span class="source-line-no">239</span><span id="line-239"></span>
+<span class="source-line-no">240</span><span id="line-240"> /** Returns the total size of the store files in the archive */</span>
+<span class="source-line-no">241</span><span id="line-241"> public long getArchivedStoreFileSize() {</span>
+<span class="source-line-no">242</span><span id="line-242"> return hfilesArchiveSize.get();</span>
+<span class="source-line-no">243</span><span id="line-243"> }</span>
+<span class="source-line-no">244</span><span id="line-244"></span>
+<span class="source-line-no">245</span><span id="line-245"> /** Returns the total size of the store files in the mob store */</span>
+<span class="source-line-no">246</span><span id="line-246"> public long getMobStoreFilesSize() {</span>
+<span class="source-line-no">247</span><span id="line-247"> return hfilesMobSize.get();</span>
+<span class="source-line-no">248</span><span id="line-248"> }</span>
+<span class="source-line-no">249</span><span id="line-249"></span>
+<span class="source-line-no">250</span><span id="line-250"> /**</span>
+<span class="source-line-no">251</span><span id="line-251"> * @return the total size of the store files in the archive which is not shared with other</span>
+<span class="source-line-no">252</span><span id="line-252"> * snapshots and tables This is only calculated when</span>
+<span class="source-line-no">253</span><span id="line-253"> * {@link #getSnapshotStats(Configuration, SnapshotProtos.SnapshotDescription, Map)} is</span>
+<span class="source-line-no">254</span><span id="line-254"> * called with a non-null Map</span>
+<span class="source-line-no">255</span><span id="line-255"> */</span>
+<span class="source-line-no">256</span><span id="line-256"> public long getNonSharedArchivedStoreFilesSize() {</span>
+<span class="source-line-no">257</span><span id="line-257"> return nonSharedHfilesArchiveSize.get();</span>
+<span class="source-line-no">258</span><span id="line-258"> }</span>
+<span class="source-line-no">259</span><span id="line-259"></span>
+<span class="source-line-no">260</span><span id="line-260"> /** Returns the percentage of the shared store files */</span>
+<span class="source-line-no">261</span><span id="line-261"> public float getSharedStoreFilePercentage() {</span>
+<span class="source-line-no">262</span><span id="line-262"> return getStoreFilesSize() == 0</span>
+<span class="source-line-no">263</span><span id="line-263"> ? 0</span>
+<span class="source-line-no">264</span><span id="line-264"> : ((float) hfilesSize.get() / (getStoreFilesSize())) * 100;</span>
+<span class="source-line-no">265</span><span id="line-265"> }</span>
+<span class="source-line-no">266</span><span id="line-266"></span>
+<span class="source-line-no">267</span><span id="line-267"> /** Returns the percentage of the mob store files */</span>
+<span class="source-line-no">268</span><span id="line-268"> public float getMobStoreFilePercentage() {</span>
+<span class="source-line-no">269</span><span id="line-269"> return getStoreFilesSize() == 0</span>
+<span class="source-line-no">270</span><span id="line-270"> ? 0</span>
+<span class="source-line-no">271</span><span id="line-271"> : ((float) hfilesMobSize.get() / (getStoreFilesSize())) * 100;</span>
+<span class="source-line-no">272</span><span id="line-272"> }</span>
+<span class="source-line-no">273</span><span id="line-273"></span>
+<span class="source-line-no">274</span><span id="line-274"> /** Returns the total log size */</span>
+<span class="source-line-no">275</span><span id="line-275"> public long getLogsSize() {</span>
+<span class="source-line-no">276</span><span id="line-276"> return logSize.get();</span>
+<span class="source-line-no">277</span><span id="line-277"> }</span>
+<span class="source-line-no">278</span><span id="line-278"></span>
+<span class="source-line-no">279</span><span id="line-279"> /**</span>
+<span class="source-line-no">280</span><span id="line-280"> * Check if for a give file in archive, if there are other snapshots/tables still reference it.</span>
+<span class="source-line-no">281</span><span id="line-281"> * @param filePath file path in archive</span>
+<span class="source-line-no">282</span><span id="line-282"> * @param snapshotFilesMap a map for store files in snapshots about how many snapshots refer to</span>
+<span class="source-line-no">283</span><span id="line-283"> * it.</span>
+<span class="source-line-no">284</span><span id="line-284"> * @return true or false</span>
+<span class="source-line-no">285</span><span id="line-285"> */</span>
+<span class="source-line-no">286</span><span id="line-286"> private boolean isArchivedFileStillReferenced(final Path filePath,</span>
+<span class="source-line-no">287</span><span id="line-287"> final Map<Path, Integer> snapshotFilesMap) {</span>
+<span class="source-line-no">288</span><span id="line-288"></span>
+<span class="source-line-no">289</span><span id="line-289"> Integer c = snapshotFilesMap.get(filePath);</span>
+<span class="source-line-no">290</span><span id="line-290"></span>
+<span class="source-line-no">291</span><span id="line-291"> // Check if there are other snapshots or table from clone_snapshot() (via back-reference)</span>
+<span class="source-line-no">292</span><span id="line-292"> // still reference to it.</span>
+<span class="source-line-no">293</span><span id="line-293"> if ((c != null) && (c == 1)) {</span>
+<span class="source-line-no">294</span><span id="line-294"> Path parentDir = filePath.getParent();</span>
+<span class="source-line-no">295</span><span id="line-295"> Path backRefDir = HFileLink.getBackReferencesDir(parentDir, filePath.getName());</span>
+<span class="source-line-no">296</span><span id="line-296"> try {</span>
+<span class="source-line-no">297</span><span id="line-297"> if (CommonFSUtils.listStatus(fs, backRefDir) == null) {</span>
+<span class="source-line-no">298</span><span id="line-298"> return false;</span>
+<span class="source-line-no">299</span><span id="line-299"> }</span>
+<span class="source-line-no">300</span><span id="line-300"> } catch (IOException e) {</span>
+<span class="source-line-no">301</span><span id="line-301"> // For the purpose of this function, IOException is ignored and treated as</span>
+<span class="source-line-no">302</span><span id="line-302"> // the file is still being referenced.</span>
+<span class="source-line-no">303</span><span id="line-303"> }</span>
+<span class="source-line-no">304</span><span id="line-304"> }</span>
+<span class="source-line-no">305</span><span id="line-305"> return true;</span>
+<span class="source-line-no">306</span><span id="line-306"> }</span>
+<span class="source-line-no">307</span><span id="line-307"></span>
+<span class="source-line-no">308</span><span id="line-308"> /**</span>
+<span class="source-line-no">309</span><span id="line-309"> * Add the specified store file to the stats</span>
+<span class="source-line-no">310</span><span id="line-310"> * @param region region encoded Name</span>
+<span class="source-line-no">311</span><span id="line-311"> * @param family family name</span>
+<span class="source-line-no">312</span><span id="line-312"> * @param storeFile store file name</span>
+<span class="source-line-no">313</span><span id="line-313"> * @param filesMap store files map for all snapshots, it may be null</span>
+<span class="source-line-no">314</span><span id="line-314"> * @return the store file information</span>
+<span class="source-line-no">315</span><span id="line-315"> */</span>
+<span class="source-line-no">316</span><span id="line-316"> FileInfo addStoreFile(final RegionInfo region, final String family,</span>
+<span class="source-line-no">317</span><span id="line-317"> final SnapshotRegionManifest.StoreFile storeFile, final Map<Path, Integer> filesMap)</span>
+<span class="source-line-no">318</span><span id="line-318"> throws IOException {</span>
+<span class="source-line-no">319</span><span id="line-319"> HFileLink link =</span>
+<span class="source-line-no">320</span><span id="line-320"> HFileLink.build(conf, snapshotTable, region.getEncodedName(), family, storeFile.getName());</span>
+<span class="source-line-no">321</span><span id="line-321"> boolean isCorrupted = false;</span>
+<span class="source-line-no">322</span><span id="line-322"> boolean inArchive = false;</span>
+<span class="source-line-no">323</span><span id="line-323"> long size = -1;</span>
+<span class="source-line-no">324</span><span id="line-324"> try {</span>
+<span class="source-line-no">325</span><span id="line-325"> if (fs.exists(link.getArchivePath())) {</span>
+<span class="source-line-no">326</span><span id="line-326"> inArchive = true;</span>
+<span class="source-line-no">327</span><span id="line-327"> size = fs.getFileStatus(link.getArchivePath()).getLen();</span>
+<span class="source-line-no">328</span><span id="line-328"> hfilesArchiveSize.addAndGet(size);</span>
+<span class="source-line-no">329</span><span id="line-329"> hfilesArchiveCount.incrementAndGet();</span>
+<span class="source-line-no">330</span><span id="line-330"></span>
+<span class="source-line-no">331</span><span id="line-331"> // If store file is not shared with other snapshots and tables,</span>
+<span class="source-line-no">332</span><span id="line-332"> // increase nonSharedHfilesArchiveSize</span>
+<span class="source-line-no">333</span><span id="line-333"> if (</span>
+<span class="source-line-no">334</span><span id="line-334"> (filesMap != null) && !isArchivedFileStillReferenced(link.getArchivePath(), filesMap)</span>
+<span class="source-line-no">335</span><span id="line-335"> ) {</span>
+<span class="source-line-no">336</span><span id="line-336"> nonSharedHfilesArchiveSize.addAndGet(size);</span>
+<span class="source-line-no">337</span><span id="line-337"> }</span>
+<span class="source-line-no">338</span><span id="line-338"> } else if (fs.exists(link.getMobPath())) {</span>
+<span class="source-line-no">339</span><span id="line-339"> inArchive = true;</span>
+<span class="source-line-no">340</span><span id="line-340"> size = fs.getFileStatus(link.getMobPath()).getLen();</span>
+<span class="source-line-no">341</span><span id="line-341"> hfilesMobSize.addAndGet(size);</span>
+<span class="source-line-no">342</span><span id="line-342"> hfilesMobCount.incrementAndGet();</span>
+<span class="source-line-no">343</span><span id="line-343"> } else {</span>
+<span class="source-line-no">344</span><span id="line-344"> size = link.getFileStatus(fs).getLen();</span>
+<span class="source-line-no">345</span><span id="line-345"> hfilesSize.addAndGet(size);</span>
+<span class="source-line-no">346</span><span id="line-346"> hfilesCount.incrementAndGet();</span>
+<span class="source-line-no">347</span><span id="line-347"> }</span>
+<span class="source-line-no">348</span><span id="line-348"> isCorrupted = (storeFile.hasFileSize() && storeFile.getFileSize() != size);</span>
+<span class="source-line-no">349</span><span id="line-349"> if (isCorrupted) hfilesCorrupted.incrementAndGet();</span>
+<span class="source-line-no">350</span><span id="line-350"> } catch (FileNotFoundException e) {</span>
+<span class="source-line-no">351</span><span id="line-351"> hfilesMissing.incrementAndGet();</span>
+<span class="source-line-no">352</span><span id="line-352"> }</span>
+<span class="source-line-no">353</span><span id="line-353"> return new FileInfo(inArchive, size, isCorrupted);</span>
+<span class="source-line-no">354</span><span id="line-354"> }</span>
+<span class="source-line-no">355</span><span id="line-355"></span>
+<span class="source-line-no">356</span><span id="line-356"> /**</span>
+<span class="source-line-no">357</span><span id="line-357"> * Add the specified log file to the stats</span>
+<span class="source-line-no">358</span><span id="line-358"> * @param server server name</span>
+<span class="source-line-no">359</span><span id="line-359"> * @param logfile log file name</span>
+<span class="source-line-no">360</span><span id="line-360"> * @return the log information</span>
+<span class="source-line-no">361</span><span id="line-361"> */</span>
+<span class="source-line-no">362</span><span id="line-362"> FileInfo addLogFile(final String server, final String logfile) throws IOException {</span>
+<span class="source-line-no">363</span><span id="line-363"> WALLink logLink = new WALLink(conf, server, logfile);</span>
+<span class="source-line-no">364</span><span id="line-364"> long size = -1;</span>
+<span class="source-line-no">365</span><span id="line-365"> try {</span>
+<span class="source-line-no">366</span><span id="line-366"> size = logLink.getFileStatus(fs).getLen();</span>
+<span class="source-line-no">367</span><span id="line-367"> logSize.addAndGet(size);</span>
+<span class="source-line-no">368</span><span id="line-368"> logsCount.incrementAndGet();</span>
+<span class="source-line-no">369</span><span id="line-369"> } catch (FileNotFoundException e) {</span>
+<span class="source-line-no">370</span><span id="line-370"> logsMissing.incrementAndGet();</span>
+<span class="source-line-no">371</span><span id="line-371"> }</span>
+<span class="source-line-no">372</span><span id="line-372"> return new FileInfo(false, size, false);</span>
+<span class="source-line-no">373</span><span id="line-373"> }</span>
+<span class="source-line-no">374</span><span id="line-374"> }</span>
+<span class="source-line-no">375</span><span id="line-375"></span>
+<span class="source-line-no">376</span><span id="line-376"> private FileSystem fs;</span>
+<span class="source-line-no">377</span><span id="line-377"> private Path rootDir;</span>
+<span class="source-line-no">378</span><span id="line-378"></span>
+<span class="source-line-no">379</span><span id="line-379"> private SnapshotManifest snapshotManifest;</span>
+<span class="source-line-no">380</span><span id="line-380"></span>
+<span class="source-line-no">381</span><span id="line-381"> private boolean listSnapshots = false;</span>
+<span class="source-line-no">382</span><span id="line-382"> private String snapshotName;</span>
+<span class="source-line-no">383</span><span id="line-383"> private Path remoteDir;</span>
+<span class="source-line-no">384</span><span id="line-384"> private boolean showSchema = false;</span>
+<span class="source-line-no">385</span><span id="line-385"> private boolean showFiles = false;</span>
+<span class="source-line-no">386</span><span id="line-386"> private boolean showStats = false;</span>
+<span class="source-line-no">387</span><span id="line-387"> private boolean printSizeInBytes = false;</span>
+<span class="source-line-no">388</span><span id="line-388"></span>
+<span class="source-line-no">389</span><span id="line-389"> @Override</span>
+<span class="source-line-no">390</span><span id="line-390"> public int doWork() throws IOException, InterruptedException {</span>
+<span class="source-line-no">391</span><span id="line-391"> if (remoteDir != null) {</span>
+<span class="source-line-no">392</span><span id="line-392"> URI defaultFs = remoteDir.getFileSystem(conf).getUri();</span>
+<span class="source-line-no">393</span><span id="line-393"> CommonFSUtils.setFsDefault(conf, new Path(defaultFs));</span>
+<span class="source-line-no">394</span><span id="line-394"> CommonFSUtils.setRootDir(conf, remoteDir);</span>
+<span class="source-line-no">395</span><span id="line-395"> }</span>
+<span class="source-line-no">396</span><span id="line-396"></span>
+<span class="source-line-no">397</span><span id="line-397"> // List Available Snapshots</span>
+<span class="source-line-no">398</span><span id="line-398"> if (listSnapshots) {</span>
+<span class="source-line-no">399</span><span id="line-399"> SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");</span>
+<span class="source-line-no">400</span><span id="line-400"> List<SnapshotDescription> snapshotDescriptions = getSnapshotList(conf);</span>
+<span class="source-line-no">401</span><span id="line-401"> System.out.printf("%-20s | %-20s | %-20s | %-20s | %s%n", "SNAPSHOT", "CREATION TIME",</span>
+<span class="source-line-no">402</span><span id="line-402"> "TTL(Sec)", "EXPIRED", "TABLE NAME");</span>
+<span class="source-line-no">403</span><span id="line-403"> long currentTime = System.currentTimeMillis();</span>
+<span class="source-line-no">404</span><span id="line-404"> for (SnapshotDescription desc : snapshotDescriptions) {</span>
+<span class="source-line-no">405</span><span id="line-405"> String ttlInfo =</span>
+<span class="source-line-no">406</span><span id="line-406"> desc.getTtl() == DEFAULT_SNAPSHOT_TTL ? TTL_FOREVER : String.valueOf(desc.getTtl());</span>
+<span class="source-line-no">407</span><span id="line-407"> String expired = SnapshotDescriptionUtils.isExpiredSnapshot(desc.getTtl(),</span>
+<span class="source-line-no">408</span><span id="line-408"> desc.getCreationTime(), currentTime) ? EXPIRED_LABEL : NOT_EXPIRED_LABEL;</span>
+<span class="source-line-no">409</span><span id="line-409"> System.out.printf("%-20s | %20s | %20s | %20s | %s%n", desc.getName(),</span>
+<span class="source-line-no">410</span><span id="line-410"> df.format(new Date(desc.getCreationTime())), ttlInfo, expired,</span>
+<span class="source-line-no">411</span><span id="line-411"> desc.getTableNameAsString());</span>
+<span class="source-line-no">412</span><span id="line-412"> }</span>
+<span class="source-line-no">413</span><span id="line-413"> return 0;</span>
+<span class="source-line-no">414</span><span id="line-414"> }</span>
+<span class="source-line-no">415</span><span id="line-415"></span>
+<span class="source-line-no">416</span><span id="line-416"> rootDir = CommonFSUtils.getRootDir(conf);</span>
+<span class="source-line-no">417</span><span id="line-417"> fs = FileSystem.get(rootDir.toUri(), conf);</span>
+<span class="source-line-no">418</span><span id="line-418"> LOG.debug("fs=" + fs.getUri().toString() + " root=" + rootDir);</span>
+<span class="source-line-no">419</span><span id="line-419"></span>
+<span class="source-line-no">420</span><span id="line-420"> // Load snapshot information</span>
+<span class="source-line-no">421</span><span id="line-421"> if (!loadSnapshotInfo(snapshotName)) {</span>
+<span class="source-line-no">422</span><span id="line-422"> System.err.println("Snapshot '" + snapshotName + "' not found!");</span>
+<span class="source-line-no">423</span><span id="line-423"> return 1;</span>
+<span class="source-line-no">424</span><span id="line-424"> }</span>
+<span class="source-line-no">425</span><span id="line-425"></span>
+<span class="source-line-no">426</span><span id="line-426"> printInfo();</span>
+<span class="source-line-no">427</span><span id="line-427"> if (showSchema) {</span>
+<span class="source-line-no">428</span><span id="line-428"> printSchema();</span>
+<span class="source-line-no">429</span><span id="line-429"> }</span>
+<span class="source-line-no">430</span><span id="line-430"> printFiles(showFiles, showStats);</span>
+<span class="source-line-no">431</span><span id="line-431"></span>
+<span class="source-line-no">432</span><span id="line-432"> return 0;</span>
+<span class="source-line-no">433</span><span id="line-433"> }</span>
+<span class="source-line-no">434</span><span id="line-434"></span>
+<span class="source-line-no">435</span><span id="line-435"> /**</span>
+<span class="source-line-no">436</span><span id="line-436"> * Load snapshot info and table descriptor for the specified snapshot</span>
+<span class="source-line-no">437</span><span id="line-437"> * @param snapshotName name of the snapshot to load</span>
+<span class="source-line-no">438</span><span id="line-438"> * @return false if snapshot is not found</span>
+<span class="source-line-no">439</span><span id="line-439"> */</span>
+<span class="source-line-no">440</span><span id="line-440"> private boolean loadSnapshotInfo(final String snapshotName) throws IOException {</span>
+<span class="source-line-no">441</span><span id="line-441"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);</span>
+<span class="source-line-no">442</span><span id="line-442"> if (!fs.exists(snapshotDir)) {</span>
+<span class="source-line-no">443</span><span id="line-443"> LOG.warn("Snapshot '" + snapshotName + "' not found in: " + snapshotDir);</span>
+<span class="source-line-no">444</span><span id="line-444"> return false;</span>
+<span class="source-line-no">445</span><span id="line-445"> }</span>
+<span class="source-line-no">446</span><span id="line-446"></span>
+<span class="source-line-no">447</span><span id="line-447"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">448</span><span id="line-448"> SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);</span>
+<span class="source-line-no">449</span><span id="line-449"> snapshotManifest = SnapshotManifest.open(getConf(), fs, snapshotDir, snapshotDesc);</span>
+<span class="source-line-no">450</span><span id="line-450"> return true;</span>
+<span class="source-line-no">451</span><span id="line-451"> }</span>
+<span class="source-line-no">452</span><span id="line-452"></span>
+<span class="source-line-no">453</span><span id="line-453"> /**</span>
+<span class="source-line-no">454</span><span id="line-454"> * Dump the {@link SnapshotDescription}</span>
+<span class="source-line-no">455</span><span id="line-455"> */</span>
+<span class="source-line-no">456</span><span id="line-456"> private void printInfo() {</span>
+<span class="source-line-no">457</span><span id="line-457"> SnapshotProtos.SnapshotDescription snapshotDesc = snapshotManifest.getSnapshotDescription();</span>
+<span class="source-line-no">458</span><span id="line-458"> SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");</span>
+<span class="source-line-no">459</span><span id="line-459"> String ttlInfo = snapshotDesc.getTtl() == DEFAULT_SNAPSHOT_TTL</span>
+<span class="source-line-no">460</span><span id="line-460"> ? TTL_FOREVER</span>
+<span class="source-line-no">461</span><span id="line-461"> : String.valueOf(snapshotDesc.getTtl());</span>
+<span class="source-line-no">462</span><span id="line-462"> String expired = SnapshotDescriptionUtils.isExpiredSnapshot(snapshotDesc.getTtl(),</span>
+<span class="source-line-no">463</span><span id="line-463"> snapshotDesc.getCreationTime(), System.currentTimeMillis())</span>
+<span class="source-line-no">464</span><span id="line-464"> ? EXPIRED_LABEL</span>
+<span class="source-line-no">465</span><span id="line-465"> : NOT_EXPIRED_LABEL;</span>
+<span class="source-line-no">466</span><span id="line-466"> System.out.println("Snapshot Info");</span>
+<span class="source-line-no">467</span><span id="line-467"> System.out.println("-----------------------------------------");</span>
+<span class="source-line-no">468</span><span id="line-468"> System.out.println(" Name: " + snapshotDesc.getName());</span>
+<span class="source-line-no">469</span><span id="line-469"> System.out.println(" Type: " + snapshotDesc.getType());</span>
+<span class="source-line-no">470</span><span id="line-470"> System.out.println(" Table: " + snapshotDesc.getTable());</span>
+<span class="source-line-no">471</span><span id="line-471"> System.out.println(" Format: " + snapshotDesc.getVersion());</span>
+<span class="source-line-no">472</span><span id="line-472"> System.out.println(" Created: " + df.format(new Date(snapshotDesc.getCreationTime())));</span>
+<span class="source-line-no">473</span><span id="line-473"> System.out.println("Ttl(Sec): " + ttlInfo);</span>
+<span class="source-line-no">474</span><span id="line-474"> System.out.println(" Expired: " + expired);</span>
+<span class="source-line-no">475</span><span id="line-475"> System.out.println(" Owner: " + snapshotDesc.getOwner());</span>
+<span class="source-line-no">476</span><span id="line-476"> System.out.println();</span>
+<span class="source-line-no">477</span><span id="line-477"> }</span>
+<span class="source-line-no">478</span><span id="line-478"></span>
+<span class="source-line-no">479</span><span id="line-479"> /**</span>
+<span class="source-line-no">480</span><span id="line-480"> * Dump the {@link org.apache.hadoop.hbase.client.TableDescriptor}</span>
+<span class="source-line-no">481</span><span id="line-481"> */</span>
+<span class="source-line-no">482</span><span id="line-482"> private void printSchema() {</span>
+<span class="source-line-no">483</span><span id="line-483"> System.out.println("Table Descriptor");</span>
+<span class="source-line-no">484</span><span id="line-484"> System.out.println("----------------------------------------");</span>
+<span class="source-line-no">485</span><span id="line-485"> System.out.println(snapshotManifest.getTableDescriptor().toString());</span>
+<span class="source-line-no">486</span><span id="line-486"> System.out.println();</span>
+<span class="source-line-no">487</span><span id="line-487"> }</span>
+<span class="source-line-no">488</span><span id="line-488"></span>
+<span class="source-line-no">489</span><span id="line-489"> /**</span>
+<span class="source-line-no">490</span><span id="line-490"> * Collect the hfiles and logs statistics of the snapshot and dump the file list if requested and</span>
+<span class="source-line-no">491</span><span id="line-491"> * the collected information.</span>
+<span class="source-line-no">492</span><span id="line-492"> */</span>
+<span class="source-line-no">493</span><span id="line-493"> private void printFiles(final boolean showFiles, final boolean showStats) throws IOException {</span>
+<span class="source-line-no">494</span><span id="line-494"> if (showFiles) {</span>
+<span class="source-line-no">495</span><span id="line-495"> System.out.println("Snapshot Files");</span>
+<span class="source-line-no">496</span><span id="line-496"> System.out.println("----------------------------------------");</span>
+<span class="source-line-no">497</span><span id="line-497"> }</span>
+<span class="source-line-no">498</span><span id="line-498"></span>
+<span class="source-line-no">499</span><span id="line-499"> // Collect information about hfiles and logs in the snapshot</span>
+<span class="source-line-no">500</span><span id="line-500"> final SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">501</span><span id="line-501"> snapshotManifest.getSnapshotDescription();</span>
+<span class="source-line-no">502</span><span id="line-502"> final String table = snapshotDesc.getTable();</span>
+<span class="source-line-no">503</span><span id="line-503"> final SnapshotDescription desc = ProtobufUtil.createSnapshotDesc(snapshotDesc);</span>
+<span class="source-line-no">504</span><span id="line-504"> final SnapshotStats stats = new SnapshotStats(this.getConf(), this.fs, desc);</span>
+<span class="source-line-no">505</span><span id="line-505"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(getConf(), fs, snapshotManifest,</span>
+<span class="source-line-no">506</span><span id="line-506"> "SnapshotInfo", new SnapshotReferenceUtil.SnapshotVisitor() {</span>
+<span class="source-line-no">507</span><span id="line-507"> @Override</span>
+<span class="source-line-no">508</span><span id="line-508"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
+<span class="source-line-no">509</span><span id="line-509"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
+<span class="source-line-no">510</span><span id="line-510"> if (storeFile.hasReference()) return;</span>
+<span class="source-line-no">511</span><span id="line-511"></span>
+<span class="source-line-no">512</span><span id="line-512"> SnapshotStats.FileInfo info = stats.addStoreFile(regionInfo, family, storeFile, null);</span>
+<span class="source-line-no">513</span><span id="line-513"> if (showFiles) {</span>
+<span class="source-line-no">514</span><span id="line-514"> String state = info.getStateToString();</span>
+<span class="source-line-no">515</span><span id="line-515"> System.out.printf("%8s %s/%s/%s/%s %s%n",</span>
+<span class="source-line-no">516</span><span id="line-516"> (info.isMissing() ? "-" : fileSizeToString(info.getSize())), table,</span>
+<span class="source-line-no">517</span><span id="line-517"> regionInfo.getEncodedName(), family, storeFile.getName(),</span>
+<span class="source-line-no">518</span><span id="line-518"> state == null ? "" : "(" + state + ")");</span>
+<span class="source-line-no">519</span><span id="line-519"> }</span>
+<span class="source-line-no">520</span><span id="line-520"> }</span>
+<span class="source-line-no">521</span><span id="line-521"> });</span>
+<span class="source-line-no">522</span><span id="line-522"></span>
+<span class="source-line-no">523</span><span id="line-523"> // Dump the stats</span>
+<span class="source-line-no">524</span><span id="line-524"> System.out.println();</span>
+<span class="source-line-no">525</span><span id="line-525"> if (stats.isSnapshotCorrupted()) {</span>
+<span class="source-line-no">526</span><span id="line-526"> System.out.println("**************************************************************");</span>
+<span class="source-line-no">527</span><span id="line-527"> System.out.printf("BAD SNAPSHOT: %d hfile(s) and %d log(s) missing.%n",</span>
+<span class="source-line-no">528</span><span id="line-528"> stats.getMissingStoreFilesCount(), stats.getMissingLogsCount());</span>
+<span class="source-line-no">529</span><span id="line-529"> System.out.printf(" %d hfile(s) corrupted.%n",</span>
+<span class="source-line-no">530</span><span id="line-530"> stats.getCorruptedStoreFilesCount());</span>
+<span class="source-line-no">531</span><span id="line-531"> System.out.println("**************************************************************");</span>
+<span class="source-line-no">532</span><span id="line-532"> }</span>
+<span class="source-line-no">533</span><span id="line-533"></span>
+<span class="source-line-no">534</span><span id="line-534"> if (showStats) {</span>
+<span class="source-line-no">535</span><span id="line-535"> System.out.printf(</span>
+<span class="source-line-no">536</span><span id="line-536"> "%d HFiles (%d in archive, %d in mob storage), total size %s "</span>
+<span class="source-line-no">537</span><span id="line-537"> + "(%.2f%% %s shared with the source table, %.2f%% %s in mob dir)%n",</span>
+<span class="source-line-no">538</span><span id="line-538"> stats.getStoreFilesCount(), stats.getArchivedStoreFilesCount(),</span>
+<span class="source-line-no">539</span><span id="line-539"> stats.getMobStoreFilesCount(), fileSizeToString(stats.getStoreFilesSize()),</span>
+<span class="source-line-no">540</span><span id="line-540"> stats.getSharedStoreFilePercentage(), fileSizeToString(stats.getSharedStoreFilesSize()),</span>
+<span class="source-line-no">541</span><span id="line-541"> stats.getMobStoreFilePercentage(), fileSizeToString(stats.getMobStoreFilesSize()));</span>
+<span class="source-line-no">542</span><span id="line-542"> System.out.printf("%d Logs, total size %s%n", stats.getLogsCount(),</span>
+<span class="source-line-no">543</span><span id="line-543"> fileSizeToString(stats.getLogsSize()));</span>
+<span class="source-line-no">544</span><span id="line-544"> System.out.println();</span>
+<span class="source-line-no">545</span><span id="line-545"> }</span>
+<span class="source-line-no">546</span><span id="line-546"> }</span>
+<span class="source-line-no">547</span><span id="line-547"></span>
+<span class="source-line-no">548</span><span id="line-548"> private String fileSizeToString(long size) {</span>
+<span class="source-line-no">549</span><span id="line-549"> return printSizeInBytes ? Long.toString(size) : Strings.humanReadableInt(size);</span>
+<span class="source-line-no">550</span><span id="line-550"> }</span>
+<span class="source-line-no">551</span><span id="line-551"></span>
+<span class="source-line-no">552</span><span id="line-552"> @Override</span>
+<span class="source-line-no">553</span><span id="line-553"> protected void addOptions() {</span>
+<span class="source-line-no">554</span><span id="line-554"> addOption(Options.SNAPSHOT);</span>
+<span class="source-line-no">555</span><span id="line-555"> addOption(Options.REMOTE_DIR);</span>
+<span class="source-line-no">556</span><span id="line-556"> addOption(Options.LIST_SNAPSHOTS);</span>
+<span class="source-line-no">557</span><span id="line-557"> addOption(Options.FILES);</span>
+<span class="source-line-no">558</span><span id="line-558"> addOption(Options.STATS);</span>
+<span class="source-line-no">559</span><span id="line-559"> addOption(Options.SCHEMA);</span>
+<span class="source-line-no">560</span><span id="line-560"> addOption(Options.SIZE_IN_BYTES);</span>
+<span class="source-line-no">561</span><span id="line-561"> }</span>
+<span class="source-line-no">562</span><span id="line-562"></span>
+<span class="source-line-no">563</span><span id="line-563"> @Override</span>
+<span class="source-line-no">564</span><span id="line-564"> protected CommandLineParser newParser() {</span>
+<span class="source-line-no">565</span><span id="line-565"> // Commons-CLI lacks the capability to handle combinations of options, so we do it ourselves</span>
+<span class="source-line-no">566</span><span id="line-566"> // Validate in parse() to get helpful error messages instead of exploding in processOptions()</span>
+<span class="source-line-no">567</span><span id="line-567"> return new DefaultParser() {</span>
+<span class="source-line-no">568</span><span id="line-568"> @Override</span>
+<span class="source-line-no">569</span><span id="line-569"> public CommandLine parse(org.apache.hbase.thirdparty.org.apache.commons.cli.Options opts,</span>
+<span class="source-line-no">570</span><span id="line-570"> String[] args, Properties props, boolean stop) throws ParseException {</span>
+<span class="source-line-no">571</span><span id="line-571"> CommandLine cl = super.parse(opts, args, props, stop);</span>
+<span class="source-line-no">572</span><span id="line-572"> if (!cmd.hasOption(Options.LIST_SNAPSHOTS) && !cmd.hasOption(Options.SNAPSHOT)) {</span>
+<span class="source-line-no">573</span><span id="line-573"> throw new ParseException("Missing required snapshot option!");</span>
+<span class="source-line-no">574</span><span id="line-574"> }</span>
+<span class="source-line-no">575</span><span id="line-575"> return cl;</span>
+<span class="source-line-no">576</span><span id="line-576"> }</span>
+<span class="source-line-no">577</span><span id="line-577"> };</span>
<span class="source-line-no">578</span><span id="line-578"> }</span>
<span class="source-line-no">579</span><span id="line-579"></span>
-<span class="source-line-no">580</span><span id="line-580"> /**</span>
-<span class="source-line-no">581</span><span id="line-581"> * Returns the snapshot stats</span>
-<span class="source-line-no">582</span><span id="line-582"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">583</span><span id="line-583"> * @param snapshot {@link SnapshotDescription} to get stats from</span>
-<span class="source-line-no">584</span><span id="line-584"> * @return the snapshot stats</span>
-<span class="source-line-no">585</span><span id="line-585"> */</span>
-<span class="source-line-no">586</span><span id="line-586"> public static SnapshotStats getSnapshotStats(final Configuration conf,</span>
-<span class="source-line-no">587</span><span id="line-587"> final SnapshotDescription snapshot) throws IOException {</span>
-<span class="source-line-no">588</span><span id="line-588"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">589</span><span id="line-589"> ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
-<span class="source-line-no">590</span><span id="line-590"> return getSnapshotStats(conf, snapshotDesc, null);</span>
-<span class="source-line-no">591</span><span id="line-591"> }</span>
-<span class="source-line-no">592</span><span id="line-592"></span>
-<span class="source-line-no">593</span><span id="line-593"> /**</span>
-<span class="source-line-no">594</span><span id="line-594"> * Returns the snapshot stats</span>
-<span class="source-line-no">595</span><span id="line-595"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">596</span><span id="line-596"> * @param snapshotDesc HBaseProtos.SnapshotDescription to get stats from</span>
-<span class="source-line-no">597</span><span id="line-597"> * @param filesMap {@link Map} store files map for all snapshots, it may be null</span>
-<span class="source-line-no">598</span><span id="line-598"> * @return the snapshot stats</span>
-<span class="source-line-no">599</span><span id="line-599"> */</span>
-<span class="source-line-no">600</span><span id="line-600"> public static SnapshotStats getSnapshotStats(final Configuration conf,</span>
-<span class="source-line-no">601</span><span id="line-601"> final SnapshotProtos.SnapshotDescription snapshotDesc, final Map<Path, Integer> filesMap)</span>
-<span class="source-line-no">602</span><span id="line-602"> throws IOException {</span>
-<span class="source-line-no">603</span><span id="line-603"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
-<span class="source-line-no">604</span><span id="line-604"> FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
-<span class="source-line-no">605</span><span id="line-605"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotDesc, rootDir);</span>
-<span class="source-line-no">606</span><span id="line-606"> SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);</span>
-<span class="source-line-no">607</span><span id="line-607"> final SnapshotStats stats = new SnapshotStats(conf, fs, snapshotDesc);</span>
-<span class="source-line-no">608</span><span id="line-608"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(conf, fs, manifest,</span>
-<span class="source-line-no">609</span><span id="line-609"> "SnapshotsStatsAggregation", new SnapshotReferenceUtil.SnapshotVisitor() {</span>
-<span class="source-line-no">610</span><span id="line-610"> @Override</span>
-<span class="source-line-no">611</span><span id="line-611"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
-<span class="source-line-no">612</span><span id="line-612"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
-<span class="source-line-no">613</span><span id="line-613"> if (!storeFile.hasReference()) {</span>
-<span class="source-line-no">614</span><span id="line-614"> stats.addStoreFile(regionInfo, family, storeFile, filesMap);</span>
-<span class="source-line-no">615</span><span id="line-615"> }</span>
-<span class="source-line-no">616</span><span id="line-616"> }</span>
-<span class="source-line-no">617</span><span id="line-617"> });</span>
-<span class="source-line-no">618</span><span id="line-618"> return stats;</span>
-<span class="source-line-no">619</span><span id="line-619"> }</span>
-<span class="source-line-no">620</span><span id="line-620"></span>
-<span class="source-line-no">621</span><span id="line-621"> /**</span>
-<span class="source-line-no">622</span><span id="line-622"> * Returns the list of available snapshots in the specified location</span>
-<span class="source-line-no">623</span><span id="line-623"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">624</span><span id="line-624"> * @return the list of snapshots</span>
-<span class="source-line-no">625</span><span id="line-625"> */</span>
-<span class="source-line-no">626</span><span id="line-626"> public static List<SnapshotDescription> getSnapshotList(final Configuration conf)</span>
-<span class="source-line-no">627</span><span id="line-627"> throws IOException {</span>
-<span class="source-line-no">628</span><span id="line-628"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
-<span class="source-line-no">629</span><span id="line-629"> FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
-<span class="source-line-no">630</span><span id="line-630"> Path snapshotDir = SnapshotDescriptionUtils.getSnapshotsDir(rootDir);</span>
-<span class="source-line-no">631</span><span id="line-631"> FileStatus[] snapshots = CommonFSUtils.listStatus(fs, snapshotDir,</span>
-<span class="source-line-no">632</span><span id="line-632"> new SnapshotDescriptionUtils.CompletedSnaphotDirectoriesFilter(fs));</span>
-<span class="source-line-no">633</span><span id="line-633"> if (snapshots == null) {</span>
-<span class="source-line-no">634</span><span id="line-634"> return Collections.emptyList();</span>
-<span class="source-line-no">635</span><span id="line-635"> }</span>
-<span class="source-line-no">636</span><span id="line-636"> List<SnapshotDescription> snapshotLists = new ArrayList<>(snapshots.length);</span>
-<span class="source-line-no">637</span><span id="line-637"> for (FileStatus snapshotDirStat : snapshots) {</span>
-<span class="source-line-no">638</span><span id="line-638"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">639</span><span id="line-639"> SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDirStat.getPath());</span>
-<span class="source-line-no">640</span><span id="line-640"> snapshotLists.add(ProtobufUtil.createSnapshotDesc(snapshotDesc));</span>
-<span class="source-line-no">641</span><span id="line-641"> }</span>
-<span class="source-line-no">642</span><span id="line-642"> return snapshotLists;</span>
-<span class="source-line-no">643</span><span id="line-643"> }</span>
-<span class="source-line-no">644</span><span id="line-644"></span>
-<span class="source-line-no">645</span><span id="line-645"> /**</span>
-<span class="source-line-no">646</span><span id="line-646"> * Gets the store files map for snapshot</span>
-<span class="source-line-no">647</span><span id="line-647"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">648</span><span id="line-648"> * @param snapshot {@link SnapshotDescription} to get stats from</span>
-<span class="source-line-no">649</span><span id="line-649"> * @param exec the {@link ExecutorService} to use</span>
-<span class="source-line-no">650</span><span id="line-650"> * @param filesMap {@link Map} the map to put the mapping entries</span>
-<span class="source-line-no">651</span><span id="line-651"> * @param uniqueHFilesArchiveSize {@link AtomicLong} the accumulated store file size in archive</span>
-<span class="source-line-no">652</span><span id="line-652"> * @param uniqueHFilesSize {@link AtomicLong} the accumulated store file size shared</span>
-<span class="source-line-no">653</span><span id="line-653"> * @param uniqueHFilesMobSize {@link AtomicLong} the accumulated mob store file size shared</span>
-<span class="source-line-no">654</span><span id="line-654"> */</span>
-<span class="source-line-no">655</span><span id="line-655"> private static void getSnapshotFilesMap(final Configuration conf,</span>
-<span class="source-line-no">656</span><span id="line-656"> final SnapshotDescription snapshot, final ExecutorService exec,</span>
-<span class="source-line-no">657</span><span id="line-657"> final ConcurrentHashMap<Path, Integer> filesMap, final AtomicLong uniqueHFilesArchiveSize,</span>
-<span class="source-line-no">658</span><span id="line-658"> final AtomicLong uniqueHFilesSize, final AtomicLong uniqueHFilesMobSize) throws IOException {</span>
-<span class="source-line-no">659</span><span id="line-659"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">660</span><span id="line-660"> ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
-<span class="source-line-no">661</span><span id="line-661"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
-<span class="source-line-no">662</span><span id="line-662"> final FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
-<span class="source-line-no">663</span><span id="line-663"></span>
-<span class="source-line-no">664</span><span id="line-664"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotDesc, rootDir);</span>
-<span class="source-line-no">665</span><span id="line-665"> SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);</span>
-<span class="source-line-no">666</span><span id="line-666"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(conf, fs, manifest, exec,</span>
-<span class="source-line-no">667</span><span id="line-667"> new SnapshotReferenceUtil.SnapshotVisitor() {</span>
-<span class="source-line-no">668</span><span id="line-668"> @Override</span>
-<span class="source-line-no">669</span><span id="line-669"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
-<span class="source-line-no">670</span><span id="line-670"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
-<span class="source-line-no">671</span><span id="line-671"> if (!storeFile.hasReference()) {</span>
-<span class="source-line-no">672</span><span id="line-672"> HFileLink link = HFileLink.build(conf, snapshot.getTableName(),</span>
-<span class="source-line-no">673</span><span id="line-673"> regionInfo.getEncodedName(), family, storeFile.getName());</span>
-<span class="source-line-no">674</span><span id="line-674"> long size;</span>
-<span class="source-line-no">675</span><span id="line-675"> Integer count;</span>
-<span class="source-line-no">676</span><span id="line-676"> Path p;</span>
-<span class="source-line-no">677</span><span id="line-677"> AtomicLong al;</span>
-<span class="source-line-no">678</span><span id="line-678"> int c = 0;</span>
-<span class="source-line-no">679</span><span id="line-679"></span>
-<span class="source-line-no">680</span><span id="line-680"> if (fs.exists(link.getArchivePath())) {</span>
-<span class="source-line-no">681</span><span id="line-681"> p = link.getArchivePath();</span>
-<span class="source-line-no">682</span><span id="line-682"> al = uniqueHFilesArchiveSize;</span>
-<span class="source-line-no">683</span><span id="line-683"> size = fs.getFileStatus(p).getLen();</span>
-<span class="source-line-no">684</span><span id="line-684"> } else if (fs.exists(link.getMobPath())) {</span>
-<span class="source-line-no">685</span><span id="line-685"> p = link.getMobPath();</span>
-<span class="source-line-no">686</span><span id="line-686"> al = uniqueHFilesMobSize;</span>
-<span class="source-line-no">687</span><span id="line-687"> size = fs.getFileStatus(p).getLen();</span>
-<span class="source-line-no">688</span><span id="line-688"> } else {</span>
-<span class="source-line-no">689</span><span id="line-689"> p = link.getOriginPath();</span>
-<span class="source-line-no">690</span><span id="line-690"> al = uniqueHFilesSize;</span>
-<span class="source-line-no">691</span><span id="line-691"> size = link.getFileStatus(fs).getLen();</span>
-<span class="source-line-no">692</span><span id="line-692"> }</span>
-<span class="source-line-no">693</span><span id="line-693"></span>
-<span class="source-line-no">694</span><span id="line-694"> // If it has been counted, do not double count</span>
-<span class="source-line-no">695</span><span id="line-695"> count = filesMap.get(p);</span>
-<span class="source-line-no">696</span><span id="line-696"> if (count != null) {</span>
-<span class="source-line-no">697</span><span id="line-697"> c = count.intValue();</span>
-<span class="source-line-no">698</span><span id="line-698"> } else {</span>
-<span class="source-line-no">699</span><span id="line-699"> al.addAndGet(size);</span>
-<span class="source-line-no">700</span><span id="line-700"> }</span>
-<span class="source-line-no">701</span><span id="line-701"></span>
-<span class="source-line-no">702</span><span id="line-702"> filesMap.put(p, ++c);</span>
-<span class="source-line-no">703</span><span id="line-703"> }</span>
-<span class="source-line-no">704</span><span id="line-704"> }</span>
-<span class="source-line-no">705</span><span id="line-705"> });</span>
-<span class="source-line-no">706</span><span id="line-706"> }</span>
-<span class="source-line-no">707</span><span id="line-707"></span>
-<span class="source-line-no">708</span><span id="line-708"> /**</span>
-<span class="source-line-no">709</span><span id="line-709"> * Returns the map of store files based on path for all snapshots</span>
-<span class="source-line-no">710</span><span id="line-710"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">711</span><span id="line-711"> * @param uniqueHFilesArchiveSize pass out the size for store files in archive</span>
-<span class="source-line-no">712</span><span id="line-712"> * @param uniqueHFilesSize pass out the size for store files shared</span>
-<span class="source-line-no">713</span><span id="line-713"> * @param uniqueHFilesMobSize pass out the size for mob store files shared</span>
-<span class="source-line-no">714</span><span id="line-714"> * @return the map of store files</span>
-<span class="source-line-no">715</span><span id="line-715"> */</span>
-<span class="source-line-no">716</span><span id="line-716"> public static Map<Path, Integer> getSnapshotsFilesMap(final Configuration conf,</span>
-<span class="source-line-no">717</span><span id="line-717"> AtomicLong uniqueHFilesArchiveSize, AtomicLong uniqueHFilesSize, AtomicLong uniqueHFilesMobSize)</span>
-<span class="source-line-no">718</span><span id="line-718"> throws IOException {</span>
-<span class="source-line-no">719</span><span id="line-719"> List<SnapshotDescription> snapshotList = getSnapshotList(conf);</span>
-<span class="source-line-no">720</span><span id="line-720"></span>
-<span class="source-line-no">721</span><span id="line-721"> if (snapshotList.isEmpty()) {</span>
-<span class="source-line-no">722</span><span id="line-722"> return Collections.emptyMap();</span>
-<span class="source-line-no">723</span><span id="line-723"> }</span>
-<span class="source-line-no">724</span><span id="line-724"></span>
-<span class="source-line-no">725</span><span id="line-725"> ConcurrentHashMap<Path, Integer> fileMap = new ConcurrentHashMap<>();</span>
-<span class="source-line-no">726</span><span id="line-726"></span>
-<span class="source-line-no">727</span><span id="line-727"> ExecutorService exec = SnapshotManifest.createExecutor(conf, "SnapshotsFilesMapping");</span>
+<span class="source-line-no">580</span><span id="line-580"> @Override</span>
+<span class="source-line-no">581</span><span id="line-581"> protected void processOptions(CommandLine cmd) {</span>
+<span class="source-line-no">582</span><span id="line-582"> snapshotName = cmd.getOptionValue(Options.SNAPSHOT.getLongOpt());</span>
+<span class="source-line-no">583</span><span id="line-583"> showFiles = cmd.hasOption(Options.FILES.getLongOpt());</span>
+<span class="source-line-no">584</span><span id="line-584"> showStats =</span>
+<span class="source-line-no">585</span><span id="line-585"> cmd.hasOption(Options.FILES.getLongOpt()) || cmd.hasOption(Options.STATS.getLongOpt());</span>
+<span class="source-line-no">586</span><span id="line-586"> showSchema = cmd.hasOption(Options.SCHEMA.getLongOpt());</span>
+<span class="source-line-no">587</span><span id="line-587"> listSnapshots = cmd.hasOption(Options.LIST_SNAPSHOTS.getLongOpt());</span>
+<span class="source-line-no">588</span><span id="line-588"> printSizeInBytes = cmd.hasOption(Options.SIZE_IN_BYTES.getLongOpt());</span>
+<span class="source-line-no">589</span><span id="line-589"> if (cmd.hasOption(Options.REMOTE_DIR.getLongOpt())) {</span>
+<span class="source-line-no">590</span><span id="line-590"> remoteDir = new Path(cmd.getOptionValue(Options.REMOTE_DIR.getLongOpt()));</span>
+<span class="source-line-no">591</span><span id="line-591"> }</span>
+<span class="source-line-no">592</span><span id="line-592"> }</span>
+<span class="source-line-no">593</span><span id="line-593"></span>
+<span class="source-line-no">594</span><span id="line-594"> @Override</span>
+<span class="source-line-no">595</span><span id="line-595"> protected void printUsage() {</span>
+<span class="source-line-no">596</span><span id="line-596"> printUsage("hbase snapshot info [options]", "Options:", "");</span>
+<span class="source-line-no">597</span><span id="line-597"> System.err.println("Examples:");</span>
+<span class="source-line-no">598</span><span id="line-598"> System.err.println(" hbase snapshot info --snapshot MySnapshot --files");</span>
+<span class="source-line-no">599</span><span id="line-599"> }</span>
+<span class="source-line-no">600</span><span id="line-600"></span>
+<span class="source-line-no">601</span><span id="line-601"> /**</span>
+<span class="source-line-no">602</span><span id="line-602"> * Returns the snapshot stats</span>
+<span class="source-line-no">603</span><span id="line-603"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">604</span><span id="line-604"> * @param snapshot {@link SnapshotDescription} to get stats from</span>
+<span class="source-line-no">605</span><span id="line-605"> * @return the snapshot stats</span>
+<span class="source-line-no">606</span><span id="line-606"> */</span>
+<span class="source-line-no">607</span><span id="line-607"> public static SnapshotStats getSnapshotStats(final Configuration conf,</span>
+<span class="source-line-no">608</span><span id="line-608"> final SnapshotDescription snapshot) throws IOException {</span>
+<span class="source-line-no">609</span><span id="line-609"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">610</span><span id="line-610"> ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
+<span class="source-line-no">611</span><span id="line-611"> return getSnapshotStats(conf, snapshotDesc, null);</span>
+<span class="source-line-no">612</span><span id="line-612"> }</span>
+<span class="source-line-no">613</span><span id="line-613"></span>
+<span class="source-line-no">614</span><span id="line-614"> /**</span>
+<span class="source-line-no">615</span><span id="line-615"> * Returns the snapshot stats</span>
+<span class="source-line-no">616</span><span id="line-616"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">617</span><span id="line-617"> * @param snapshotDesc HBaseProtos.SnapshotDescription to get stats from</span>
+<span class="source-line-no">618</span><span id="line-618"> * @param filesMap {@link Map} store files map for all snapshots, it may be null</span>
+<span class="source-line-no">619</span><span id="line-619"> * @return the snapshot stats</span>
+<span class="source-line-no">620</span><span id="line-620"> */</span>
+<span class="source-line-no">621</span><span id="line-621"> public static SnapshotStats getSnapshotStats(final Configuration conf,</span>
+<span class="source-line-no">622</span><span id="line-622"> final SnapshotProtos.SnapshotDescription snapshotDesc, final Map<Path, Integer> filesMap)</span>
+<span class="source-line-no">623</span><span id="line-623"> throws IOException {</span>
+<span class="source-line-no">624</span><span id="line-624"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
+<span class="source-line-no">625</span><span id="line-625"> FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
+<span class="source-line-no">626</span><span id="line-626"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotDesc, rootDir);</span>
+<span class="source-line-no">627</span><span id="line-627"> SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);</span>
+<span class="source-line-no">628</span><span id="line-628"> final SnapshotStats stats = new SnapshotStats(conf, fs, snapshotDesc);</span>
+<span class="source-line-no">629</span><span id="line-629"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(conf, fs, manifest,</span>
+<span class="source-line-no">630</span><span id="line-630"> "SnapshotsStatsAggregation", new SnapshotReferenceUtil.SnapshotVisitor() {</span>
+<span class="source-line-no">631</span><span id="line-631"> @Override</span>
+<span class="source-line-no">632</span><span id="line-632"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
+<span class="source-line-no">633</span><span id="line-633"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
+<span class="source-line-no">634</span><span id="line-634"> if (!storeFile.hasReference()) {</span>
+<span class="source-line-no">635</span><span id="line-635"> stats.addStoreFile(regionInfo, family, storeFile, filesMap);</span>
+<span class="source-line-no">636</span><span id="line-636"> }</span>
+<span class="source-line-no">637</span><span id="line-637"> }</span>
+<span class="source-line-no">638</span><span id="line-638"> });</span>
+<span class="source-line-no">639</span><span id="line-639"> return stats;</span>
+<span class="source-line-no">640</span><span id="line-640"> }</span>
+<span class="source-line-no">641</span><span id="line-641"></span>
+<span class="source-line-no">642</span><span id="line-642"> /**</span>
+<span class="source-line-no">643</span><span id="line-643"> * Returns the list of available snapshots in the specified location</span>
+<span class="source-line-no">644</span><span id="line-644"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">645</span><span id="line-645"> * @return the list of snapshots</span>
+<span class="source-line-no">646</span><span id="line-646"> */</span>
+<span class="source-line-no">647</span><span id="line-647"> public static List<SnapshotDescription> getSnapshotList(final Configuration conf)</span>
+<span class="source-line-no">648</span><span id="line-648"> throws IOException {</span>
+<span class="source-line-no">649</span><span id="line-649"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
+<span class="source-line-no">650</span><span id="line-650"> FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
+<span class="source-line-no">651</span><span id="line-651"> Path snapshotDir = SnapshotDescriptionUtils.getSnapshotsDir(rootDir);</span>
+<span class="source-line-no">652</span><span id="line-652"> FileStatus[] snapshots = CommonFSUtils.listStatus(fs, snapshotDir,</span>
+<span class="source-line-no">653</span><span id="line-653"> new SnapshotDescriptionUtils.CompletedSnaphotDirectoriesFilter(fs));</span>
+<span class="source-line-no">654</span><span id="line-654"> if (snapshots == null) {</span>
+<span class="source-line-no">655</span><span id="line-655"> return Collections.emptyList();</span>
+<span class="source-line-no">656</span><span id="line-656"> }</span>
+<span class="source-line-no">657</span><span id="line-657"> List<SnapshotDescription> snapshotLists = new ArrayList<>(snapshots.length);</span>
+<span class="source-line-no">658</span><span id="line-658"> for (FileStatus snapshotDirStat : snapshots) {</span>
+<span class="source-line-no">659</span><span id="line-659"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">660</span><span id="line-660"> SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDirStat.getPath());</span>
+<span class="source-line-no">661</span><span id="line-661"> snapshotLists.add(ProtobufUtil.createSnapshotDesc(snapshotDesc));</span>
+<span class="source-line-no">662</span><span id="line-662"> }</span>
+<span class="source-line-no">663</span><span id="line-663"> return snapshotLists;</span>
+<span class="source-line-no">664</span><span id="line-664"> }</span>
+<span class="source-line-no">665</span><span id="line-665"></span>
+<span class="source-line-no">666</span><span id="line-666"> /**</span>
+<span class="source-line-no">667</span><span id="line-667"> * Gets the store files map for snapshot</span>
+<span class="source-line-no">668</span><span id="line-668"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">669</span><span id="line-669"> * @param snapshot {@link SnapshotDescription} to get stats from</span>
+<span class="source-line-no">670</span><span id="line-670"> * @param exec the {@link ExecutorService} to use</span>
+<span class="source-line-no">671</span><span id="line-671"> * @param filesMap {@link Map} the map to put the mapping entries</span>
+<span class="source-line-no">672</span><span id="line-672"> * @param uniqueHFilesArchiveSize {@link AtomicLong} the accumulated store file size in archive</span>
+<span class="source-line-no">673</span><span id="line-673"> * @param uniqueHFilesSize {@link AtomicLong} the accumulated store file size shared</span>
+<span class="source-line-no">674</span><span id="line-674"> * @param uniqueHFilesMobSize {@link AtomicLong} the accumulated mob store file size shared</span>
+<span class="source-line-no">675</span><span id="line-675"> */</span>
+<span class="source-line-no">676</span><span id="line-676"> private static void getSnapshotFilesMap(final Configuration conf,</span>
+<span class="source-line-no">677</span><span id="line-677"> final SnapshotDescription snapshot, final ExecutorService exec,</span>
+<span class="source-line-no">678</span><span id="line-678"> final ConcurrentHashMap<Path, Integer> filesMap, final AtomicLong uniqueHFilesArchiveSize,</span>
+<span class="source-line-no">679</span><span id="line-679"> final AtomicLong uniqueHFilesSize, final AtomicLong uniqueHFilesMobSize) throws IOException {</span>
+<span class="source-line-no">680</span><span id="line-680"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">681</span><span id="line-681"> ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
+<span class="source-line-no">682</span><span id="line-682"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
+<span class="source-line-no">683</span><span id="line-683"> final FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
+<span class="source-line-no">684</span><span id="line-684"></span>
+<span class="source-line-no">685</span><span id="line-685"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotDesc, rootDir);</span>
+<span class="source-line-no">686</span><span id="line-686"> SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);</span>
+<span class="source-line-no">687</span><span id="line-687"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(conf, fs, manifest, exec,</span>
+<span class="source-line-no">688</span><span id="line-688"> new SnapshotReferenceUtil.SnapshotVisitor() {</span>
+<span class="source-line-no">689</span><span id="line-689"> @Override</span>
+<span class="source-line-no">690</span><span id="line-690"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
+<span class="source-line-no">691</span><span id="line-691"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
+<span class="source-line-no">692</span><span id="line-692"> if (!storeFile.hasReference()) {</span>
+<span class="source-line-no">693</span><span id="line-693"> HFileLink link = HFileLink.build(conf, snapshot.getTableName(),</span>
+<span class="source-line-no">694</span><span id="line-694"> regionInfo.getEncodedName(), family, storeFile.getName());</span>
+<span class="source-line-no">695</span><span id="line-695"> long size;</span>
+<span class="source-line-no">696</span><span id="line-696"> Integer count;</span>
+<span class="source-line-no">697</span><span id="line-697"> Path p;</span>
+<span class="source-line-no">698</span><span id="line-698"> AtomicLong al;</span>
+<span class="source-line-no">699</span><span id="line-699"> int c = 0;</span>
+<span class="source-line-no">700</span><span id="line-700"></span>
+<span class="source-line-no">701</span><span id="line-701"> if (fs.exists(link.getArchivePath())) {</span>
+<span class="source-line-no">702</span><span id="line-702"> p = link.getArchivePath();</span>
+<span class="source-line-no">703</span><span id="line-703"> al = uniqueHFilesArchiveSize;</span>
+<span class="source-line-no">704</span><span id="line-704"> size = fs.getFileStatus(p).getLen();</span>
+<span class="source-line-no">705</span><span id="line-705"> } else if (fs.exists(link.getMobPath())) {</span>
+<span class="source-line-no">706</span><span id="line-706"> p = link.getMobPath();</span>
+<span class="source-line-no">707</span><span id="line-707"> al = uniqueHFilesMobSize;</span>
+<span class="source-line-no">708</span><span id="line-708"> size = fs.getFileStatus(p).getLen();</span>
+<span class="source-line-no">709</span><span id="line-709"> } else {</span>
+<span class="source-line-no">710</span><span id="line-710"> p = link.getOriginPath();</span>
+<span class="source-line-no">711</span><span id="line-711"> al = uniqueHFilesSize;</span>
+<span class="source-line-no">712</span><span id="line-712"> size = link.getFileStatus(fs).getLen();</span>
+<span class="source-line-no">713</span><span id="line-713"> }</span>
+<span class="source-line-no">714</span><span id="line-714"></span>
+<span class="source-line-no">715</span><span id="line-715"> // If it has been counted, do not double count</span>
+<span class="source-line-no">716</span><span id="line-716"> count = filesMap.get(p);</span>
+<span class="source-line-no">717</span><span id="line-717"> if (count != null) {</span>
+<span class="source-line-no">718</span><span id="line-718"> c = count.intValue();</span>
+<span class="source-line-no">719</span><span id="line-719"> } else {</span>
+<span class="source-line-no">720</span><span id="line-720"> al.addAndGet(size);</span>
+<span class="source-line-no">721</span><span id="line-721"> }</span>
+<span class="source-line-no">722</span><span id="line-722"></span>
+<span class="source-line-no">723</span><span id="line-723"> filesMap.put(p, ++c);</span>
+<span class="source-line-no">724</span><span id="line-724"> }</span>
+<span class="source-line-no">725</span><span id="line-725"> }</span>
+<span class="source-line-no">726</span><span id="line-726"> });</span>
+<span class="source-line-no">727</span><span id="line-727"> }</span>
<span class="source-line-no">728</span><span id="line-728"></span>
-<span class="source-line-no">729</span><span id="line-729"> try {</span>
-<span class="source-line-no">730</span><span id="line-730"> for (final SnapshotDescription snapshot : snapshotList) {</span>
-<span class="source-line-no">731</span><span id="line-731"> getSnapshotFilesMap(conf, snapshot, exec, fileMap, uniqueHFilesArchiveSize,</span>
-<span class="source-line-no">732</span><span id="line-732"> uniqueHFilesSize, uniqueHFilesMobSize);</span>
-<span class="source-line-no">733</span><span id="line-733"> }</span>
-<span class="source-line-no">734</span><span id="line-734"> } finally {</span>
-<span class="source-line-no">735</span><span id="line-735"> exec.shutdown();</span>
-<span class="source-line-no">736</span><span id="line-736"> }</span>
-<span class="source-line-no">737</span><span id="line-737"></span>
-<span class="source-line-no">738</span><span id="line-738"> return fileMap;</span>
-<span class="source-line-no">739</span><span id="line-739"> }</span>
-<span class="source-line-no">740</span><span id="line-740"></span>
-<span class="source-line-no">741</span><span id="line-741"> public static void main(String[] args) {</span>
-<span class="source-line-no">742</span><span id="line-742"> new SnapshotInfo().doStaticMain(args);</span>
-<span class="source-line-no">743</span><span id="line-743"> }</span>
-<span class="source-line-no">744</span><span id="line-744">}</span>
+<span class="source-line-no">729</span><span id="line-729"> /**</span>
+<span class="source-line-no">730</span><span id="line-730"> * Returns the map of store files based on path for all snapshots</span>
+<span class="source-line-no">731</span><span id="line-731"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">732</span><span id="line-732"> * @param uniqueHFilesArchiveSize pass out the size for store files in archive</span>
+<span class="source-line-no">733</span><span id="line-733"> * @param uniqueHFilesSize pass out the size for store files shared</span>
+<span class="source-line-no">734</span><span id="line-734"> * @param uniqueHFilesMobSize pass out the size for mob store files shared</span>
+<span class="source-line-no">735</span><span id="line-735"> * @return the map of store files</span>
+<span class="source-line-no">736</span><span id="line-736"> */</span>
+<span class="source-line-no">737</span><span id="line-737"> public static Map<Path, Integer> getSnapshotsFilesMap(final Configuration conf,</span>
+<span class="source-line-no">738</span><span id="line-738"> AtomicLong uniqueHFilesArchiveSize, AtomicLong uniqueHFilesSize, AtomicLong uniqueHFilesMobSize)</span>
+<span class="source-line-no">739</span><span id="line-739"> throws IOException {</span>
+<span class="source-line-no">740</span><span id="line-740"> List<SnapshotDescription> snapshotList = getSnapshotList(conf);</span>
+<span class="source-line-no">741</span><span id="line-741"></span>
+<span class="source-line-no">742</span><span id="line-742"> if (snapshotList.isEmpty()) {</span>
+<span class="source-line-no">743</span><span id="line-743"> return Collections.emptyMap();</span>
+<span class="source-line-no">744</span><span id="line-744"> }</span>
+<span class="source-line-no">745</span><span id="line-745"></span>
+<span class="source-line-no">746</span><span id="line-746"> ConcurrentHashMap<Path, Integer> fileMap = new ConcurrentHashMap<>();</span>
+<span class="source-line-no">747</span><span id="line-747"></span>
+<span class="source-line-no">748</span><span id="line-748"> ExecutorService exec = SnapshotManifest.createExecutor(conf, "SnapshotsFilesMapping");</span>
+<span class="source-line-no">749</span><span id="line-749"></span>
+<span class="source-line-no">750</span><span id="line-750"> try {</span>
+<span class="source-line-no">751</span><span id="line-751"> for (final SnapshotDescription snapshot : snapshotList) {</span>
+<span class="source-line-no">752</span><span id="line-752"> getSnapshotFilesMap(conf, snapshot, exec, fileMap, uniqueHFilesArchiveSize,</span>
+<span class="source-line-no">753</span><span id="line-753"> uniqueHFilesSize, uniqueHFilesMobSize);</span>
+<span class="source-line-no">754</span><span id="line-754"> }</span>
+<span class="source-line-no">755</span><span id="line-755"> } finally {</span>
+<span class="source-line-no">756</span><span id="line-756"> exec.shutdown();</span>
+<span class="source-line-no">757</span><span id="line-757"> }</span>
+<span class="source-line-no">758</span><span id="line-758"></span>
+<span class="source-line-no">759</span><span id="line-759"> return fileMap;</span>
+<span class="source-line-no">760</span><span id="line-760"> }</span>
+<span class="source-line-no">761</span><span id="line-761"></span>
+<span class="source-line-no">762</span><span id="line-762"> public static void main(String[] args) {</span>
+<span class="source-line-no">763</span><span id="line-763"> new SnapshotInfo().doStaticMain(args);</span>
+<span class="source-line-no">764</span><span id="line-764"> }</span>
+<span class="source-line-no">765</span><span id="line-765">}</span>
diff --git a/books/apache-hbase-reference-guide-dark-mode.pdf b/books/apache-hbase-reference-guide-dark-mode.pdf
index 82c3ea5a6ab..6f7d3d7bd34 100644
Binary files a/books/apache-hbase-reference-guide-dark-mode.pdf and b/books/apache-hbase-reference-guide-dark-mode.pdf differ
diff --git a/books/apache-hbase-reference-guide.pdf b/books/apache-hbase-reference-guide.pdf
index 0d110fb2c3e..a44c2e64c11 100644
Binary files a/books/apache-hbase-reference-guide.pdf and b/books/apache-hbase-reference-guide.pdf differ
diff --git a/checkstyle-aggregate.html b/checkstyle-aggregate.html
index b87effcc577..478cb664489 100644
--- a/checkstyle-aggregate.html
+++ b/checkstyle-aggregate.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-checkstyle-plugin:3.6.0:checkstyle-aggregate at 2026-06-23
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-checkstyle-plugin:3.6.0:checkstyle-aggregate at 2026-06-24
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
@@ -109,7 +109,7 @@
<th><img src="images/icon_warning_sml.gif" /> Warnings</th>
<th><img src="images/icon_error_sml.gif" /> Errors</th></tr>
<tr class="b">
-<td>5354</td>
+<td>5358</td>
<td>0</td>
<td>0</td>
<td>1817</td></tr></table></section><section><a id="Files"></a>
@@ -17112,37 +17112,37 @@
<td>imports</td>
<td>UnusedImports</td>
<td>Unused import - org.apache.hbase.thirdparty.org.apache.commons.cli.Options.</td>
-<td>54</td></tr>
+<td>56</td></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'if' construct must use '{}'s.</td>
-<td>138</td></tr>
+<td>144</td></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'if' construct must use '{}'s.</td>
-<td>139</td></tr>
+<td>145</td></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'if' construct must use '{}'s.</td>
-<td>140</td></tr>
+<td>146</td></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'if' construct must use '{}'s.</td>
-<td>343</td></tr>
+<td>349</td></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'if' construct must use '{}'s.</td>
-<td>489</td></tr></table></section><section><a id="org.2Fapache.2Fhadoop.2Fhbase.2Fsnapshot.2FSnapshotManifest.java"></a>
+<td>510</td></tr></table></section><section><a id="org.2Fapache.2Fhadoop.2Fhbase.2Fsnapshot.2FSnapshotManifest.java"></a>
<h3>org/apache/hadoop/hbase/snapshot/SnapshotManifest.java</h3>
<table class="table table-striped">
<tr class="a">
diff --git a/dependency-convergence.html b/dependency-convergence.html
index 453e8d8250b..2bb9d0a9e95 100644
--- a/dependency-convergence.html
+++ b/dependency-convergence.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-convergence at 2026-06-23
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-convergence at 2026-06-24
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/dependency-info.html b/dependency-info.html
index 63c71e72259..d6b970b9ed5 100644
--- a/dependency-info.html
+++ b/dependency-info.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-info at 2026-06-23
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-info at 2026-06-24
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/dependency-management.html b/dependency-management.html
index f7edc0e6a3e..94aeb090be8 100644
--- a/dependency-management.html
+++ b/dependency-management.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-management at 2026-06-23
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-management at 2026-06-24
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/devapidocs/constant-values.html b/devapidocs/constant-values.html
index 211442abb63..f11bfff8a1d 100644
--- a/devapidocs/constant-values.html
+++ b/devapidocs/constant-values.html
@@ -16327,9 +16327,21 @@ loadScripts(document, 'script');</script>
<div class="table-header col-first">Modifier and Type</div>
<div class="table-header col-second">Constant Field</div>
<div class="table-header col-last">Value</div>
+<div class="col-first even-row-color"><code id="org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper.DEFAULT_OFFSET_UPDATE_INTERVAL_MS">private static final long</code></div>
+<div class="col-second even-row-color"><code><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#DEFAULT_OFFSET_UPDATE_INTERVAL_MS">DEFAULT_OFFSET_UPDATE_INTERVAL_MS</a></code></div>
+<div class="col-last even-row-color"><code>9223372036854775807L</code></div>
+<div class="col-first odd-row-color"><code id="org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper.DEFAULT_OFFSET_UPDATE_SIZE_THRESHOLD">private static final long</code></div>
+<div class="col-second odd-row-color"><code><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#DEFAULT_OFFSET_UPDATE_SIZE_THRESHOLD">DEFAULT_OFFSET_UPDATE_SIZE_THRESHOLD</a></code></div>
+<div class="col-last odd-row-color"><code>-1L</code></div>
<div class="col-first even-row-color"><code id="org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper.DEFAULT_TIMEOUT">private final int</code></div>
<div class="col-second even-row-color"><code><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#DEFAULT_TIMEOUT">DEFAULT_TIMEOUT</a></code></div>
<div class="col-last even-row-color"><code>20000</code></div>
+<div class="col-first odd-row-color"><code id="org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper.OFFSET_UPDATE_INTERVAL_MS_KEY">private static final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></code></div>
+<div class="col-second odd-row-color"><code><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#OFFSET_UPDATE_INTERVAL_MS_KEY">OFFSET_UPDATE_INTERVAL_MS_KEY</a></code></div>
+<div class="col-last odd-row-color"><code>"hbase.replication.shipper.offset.update.interval.ms"</code></div>
+<div class="col-first even-row-color"><code id="org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper.OFFSET_UPDATE_SIZE_THRESHOLD_KEY">private static final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></code></div>
+<div class="col-second even-row-color"><code><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#OFFSET_UPDATE_SIZE_THRESHOLD_KEY">OFFSET_UPDATE_SIZE_THRESHOLD_KEY</a></code></div>
+<div class="col-last even-row-color"><code>"hbase.replication.shipper.offset.update.size.threshold"</code></div>
</div>
</li>
<li>
@@ -17789,6 +17801,23 @@ loadScripts(document, 'script');</script>
</div>
</li>
<li>
+<div class="caption"><span>org.apache.hadoop.hbase.snapshot.<a href="org/apache/hadoop/hbase/snapshot/SnapshotInfo.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotInfo</a></span></div>
+<div class="summary-table three-column-summary">
+<div class="table-header col-first">Modifier and Type</div>
+<div class="table-header col-second">Constant Field</div>
+<div class="table-header col-last">Value</div>
+<div class="col-first even-row-color"><code id="org.apache.hadoop.hbase.snapshot.SnapshotInfo.EXPIRED_LABEL">private static final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></code></div>
+<div class="col-second even-row-color"><code><a href="org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#EXPIRED_LABEL">EXPIRED_LABEL</a></code></div>
+<div class="col-last even-row-color"><code>"Yes"</code></div>
+<div class="col-first odd-row-color"><code id="org.apache.hadoop.hbase.snapshot.SnapshotInfo.NOT_EXPIRED_LABEL">private static final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></code></div>
+<div class="col-second odd-row-color"><code><a href="org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#NOT_EXPIRED_LABEL">NOT_EXPIRED_LABEL</a></code></div>
+<div class="col-last odd-row-color"><code>"No"</code></div>
+<div class="col-first even-row-color"><code id="org.apache.hadoop.hbase.snapshot.SnapshotInfo.TTL_FOREVER">private static final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></code></div>
+<div class="col-second even-row-color"><code><a href="org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#TTL_FOREVER">TTL_FOREVER</a></code></div>
+<div class="col-last even-row-color"><code>"FOREVER"</code></div>
+</div>
+</li>
+<li>
<div class="caption"><span>org.apache.hadoop.hbase.snapshot.<a href="org/apache/hadoop/hbase/snapshot/SnapshotManifest.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotManifest</a></span></div>
<div class="summary-table three-column-summary">
<div class="table-header col-first">Modifier and Type</div>
diff --git a/devapidocs/index-all.html b/devapidocs/index-all.html
index ac18f9b93ef..bc03f914f27 100644
--- a/devapidocs/index-all.html
+++ b/devapidocs/index-all.html
@@ -266,6 +266,8 @@ loadScripts(document, 'script');</script>
<dd>
<div class="block">Interface to support the aborting of a given server or client.</div>
</dd>
+<dt><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#abortAndRestart(java.lang.Throwable)" class="member-name-link">abortAndRestart(Throwable)</a> - Method in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceManager.html#abortAndThrowIOExceptionWhenFail(org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceManager.ReplicationQueueOperation)" class="member-name-link">abortAndThrowIOExceptionWhenFail(ReplicationSourceManager.ReplicationQueueOperation)</a> - Method in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceManager.h [...]
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/regionserver/wal/AbstractFSWAL.html#abortCacheFlush(byte%5B%5D)" class="member-name-link">abortCacheFlush(byte[])</a> - Method in class org.apache.hadoop.hbase.regionserver.wal.<a href="org/apache/hadoop/hbase/regionserver/wal/AbstractFSWAL.html" title="class in org.apache.hadoop.hbase.regionserver.wal">AbstractFSWAL</a></dt>
@@ -860,6 +862,8 @@ loadScripts(document, 'script');</script>
<div class="block">Checks if the user has access to the full table or at least a family/qualifier for the
specified action.</div>
</dd>
+<dt><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#accumulatedSizeSinceLastUpdate" class="member-name-link">accumulatedSizeSinceLastUpdate</a> - Variable in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/util/RegionMover.html#ack" class="member-name-link">ack</a> - Variable in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/RegionMover.html" title="class in org.apache.hadoop.hbase.util">RegionMover</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/util/RegionMover.RegionMoverBuilder.html#ack" class="member-name-link">ack</a> - Variable in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/RegionMover.RegionMoverBuilder.html" title="class in org.apache.hadoop.hbase.util">RegionMover.RegionMoverBuilder</a></dt>
@@ -7381,6 +7385,10 @@ loadScripts(document, 'script');</script>
</dd>
<dt><a href="org/apache/hadoop/hbase/util/test/LoadTestDataGeneratorWithACL.html#beforeMutate(long,org.apache.hadoop.hbase.client.Mutation)" class="member-name-link">beforeMutate(long, Mutation)</a> - Method in class org.apache.hadoop.hbase.util.test.<a href="org/apache/hadoop/hbase/util/test/LoadTestDataGeneratorWithACL.html" title="class in org.apache.hadoop.hbase.util.test">LoadTestDataGeneratorWithACL</a></dt>
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/replication/ReplicationEndpoint.html#beforePersistingReplicationOffset()" class="member-name-link">beforePersistingReplicationOffset()</a> - Method in interface org.apache.hadoop.hbase.replication.<a href="org/apache/hadoop/hbase/replication/ReplicationEndpoint.html" title="interface in org.apache.hadoop.hbase.replication">ReplicationEndpoint</a></dt>
+<dd>
+<div class="block">Hook invoked before persisting replication offsets.</div>
+</dd>
<dt><a href="org/apache/hadoop/hbase/master/locking/LockProcedure.html#beforeReplay(org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv)" class="member-name-link">beforeReplay(MasterProcedureEnv)</a> - Method in class org.apache.hadoop.hbase.master.locking.<a href="org/apache/hadoop/hbase/master/locking/LockProcedure.html" title="class in org.apache.hadoop.hbase.master.locking">LockProcedure</a></dt>
<dd>
<div class="block">On recovery, re-execute from start to acquire the locks.</div>
@@ -29776,6 +29784,10 @@ loadScripts(document, 'script');</script>
<dd>
<div class="block">The number of reader/writer threads if not specified</div>
</dd>
+<dt><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#DEFAULT_OFFSET_UPDATE_INTERVAL_MS" class="member-name-link">DEFAULT_OFFSET_UPDATE_INTERVAL_MS</a> - Static variable in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a></dt>
+<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#DEFAULT_OFFSET_UPDATE_SIZE_THRESHOLD" class="member-name-link">DEFAULT_OFFSET_UPDATE_SIZE_THRESHOLD</a> - Static variable in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/master/cleaner/LogCleaner.html#DEFAULT_OLD_WALS_CLEANER_THREAD_SIZE" class="member-name-link">DEFAULT_OLD_WALS_CLEANER_THREAD_SIZE</a> - Static variable in class org.apache.hadoop.hbase.master.cleaner.<a href="org/apache/hadoop/hbase/master/cleaner/LogCleaner.html" title="class in org.apache.hadoop.hbase.master.cleaner">LogCleaner</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/master/cleaner/LogCleaner.html#DEFAULT_OLD_WALS_CLEANER_THREAD_TIMEOUT_MSEC" class="member-name-link">DEFAULT_OLD_WALS_CLEANER_THREAD_TIMEOUT_MSEC</a> - Static variable in class org.apache.hadoop.hbase.master.cleaner.<a href="org/apache/hadoop/hbase/master/cleaner/LogCleaner.html" title="class in org.apache.hadoop.hbase.master.cleaner">LogCleaner</a></dt>
@@ -37714,6 +37726,8 @@ loadScripts(document, 'script');</script>
<dd>
<div class="block">Called when a region server is dead.</div>
</dd>
+<dt><a href="org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#EXPIRED_LABEL" class="member-name-link">EXPIRED_LABEL</a> - Static variable in class org.apache.hadoop.hbase.snapshot.<a href="org/apache/hadoop/hbase/snapshot/SnapshotInfo.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotInfo</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/util/HbckErrorReporter.ERROR_CODE.html#EXPIRED_TABLE_LOCK" class="member-name-link">EXPIRED_TABLE_LOCK</a> - Enum constant in enum class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/HbckErrorReporter.ERROR_CODE.html" title="enum class in org.apache.hadoop.hbase.util">HbckErrorReporter.ERROR_CODE</a></dt>
<dd>
<div class="deprecation-block"><span class="deprecated-label">Deprecated.</span></div>
@@ -86248,6 +86262,8 @@ loadScripts(document, 'script');</script>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/rest/client/Client.html#lastNodeId" class="member-name-link">lastNodeId</a> - Variable in class org.apache.hadoop.hbase.rest.client.<a href="org/apache/hadoop/hbase/rest/client/Client.html" title="class in org.apache.hadoop.hbase.rest.client">Client</a></dt>
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#lastOffsetUpdateTime" class="member-name-link">lastOffsetUpdateTime</a> - Variable in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/PrivateCellUtil.LastOnRowByteBufferExtendedCell.html#%3Cinit%3E(java.nio.ByteBuffer,int,short)" class="member-name-link">LastOnRowByteBufferExtendedCell(ByteBuffer, int, short)</a> - Constructor for class org.apache.hadoop.hbase.<a href="org/apache/hadoop/hbase/PrivateCellUtil.LastOnRowByteBufferExtendedCell.html" title="class in org.apache.hadoop.hbase">PrivateCellUtil.LastOnRowByteBufferExtendedCell</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/PrivateCellUtil.LastOnRowCell.html#%3Cinit%3E(byte%5B%5D,int,short)" class="member-name-link">LastOnRowCell(byte[], int, short)</a> - Constructor for class org.apache.hadoop.hbase.<a href="org/apache/hadoop/hbase/PrivateCellUtil.LastOnRowCell.html" title="class in org.apache.hadoop.hbase">PrivateCellUtil.LastOnRowCell</a></dt>
@@ -86350,6 +86366,8 @@ loadScripts(document, 'script');</script>
</dd>
<dt><a href="org/apache/hadoop/hbase/master/replication/OfflineTableReplicationQueueStorage.html#lastSequenceIds" class="member-name-link">lastSequenceIds</a> - Variable in class org.apache.hadoop.hbase.master.replication.<a href="org/apache/hadoop/hbase/master/replication/OfflineTableReplicationQueueStorage.html" title="class in org.apache.hadoop.hbase.master.replication">OfflineTableReplicationQueueStorage</a></dt>
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#lastShippedBatch" class="member-name-link">lastShippedBatch</a> - Variable in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/replication/regionserver/MetricsSource.html#lastShippedTimeStamps" class="member-name-link">lastShippedTimeStamps</a> - Variable in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/MetricsSource.html" title="class in org.apache.hadoop.hbase.replication.regionserver">MetricsSource</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/replication/regionserver/HBaseInterClusterReplicationEndpoint.html#lastSinkFetchTime" class="member-name-link">lastSinkFetchTime</a> - Variable in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/HBaseInterClusterReplicationEndpoint.html" title="class in org.apache.hadoop.hbase.replication.regionserver">HBaseInterClusterReplicationEndpoint</a></dt>
@@ -101587,6 +101605,8 @@ loadScripts(document, 'script');</script>
</dd>
<dt><a href="org/apache/hadoop/hbase/filter/ParseConstants.html#NOT_EQUAL_TO_BUFFER" class="member-name-link">NOT_EQUAL_TO_BUFFER</a> - Static variable in class org.apache.hadoop.hbase.filter.<a href="org/apache/hadoop/hbase/filter/ParseConstants.html" title="class in org.apache.hadoop.hbase.filter">ParseConstants</a></dt>
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#NOT_EXPIRED_LABEL" class="member-name-link">NOT_EXPIRED_LABEL</a> - Static variable in class org.apache.hadoop.hbase.snapshot.<a href="org/apache/hadoop/hbase/snapshot/SnapshotInfo.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotInfo</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/HConstants.html#NOT_IMPLEMENTED" class="member-name-link">NOT_IMPLEMENTED</a> - Static variable in class org.apache.hadoop.hbase.<a href="org/apache/hadoop/hbase/HConstants.html" title="class in org.apache.hadoop.hbase">HConstants</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/io/util/Dictionary.html#NOT_IN_DICTIONARY" class="member-name-link">NOT_IN_DICTIONARY</a> - Static variable in interface org.apache.hadoop.hbase.io.util.<a href="org/apache/hadoop/hbase/io/util/Dictionary.html" title="interface in org.apache.hadoop.hbase.io.util">Dictionary</a></dt>
@@ -102815,6 +102835,10 @@ loadScripts(document, 'script');</script>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/replication/master/ReplicationSinkTrackerTableCreator.html#OFFSET_COLUMN" class="member-name-link">OFFSET_COLUMN</a> - Static variable in class org.apache.hadoop.hbase.replication.master.<a href="org/apache/hadoop/hbase/replication/master/ReplicationSinkTrackerTableCreator.html" title="class in org.apache.hadoop.hbase.replication.master">ReplicationSinkTrackerTableCreator</a></dt>
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#OFFSET_UPDATE_INTERVAL_MS_KEY" class="member-name-link">OFFSET_UPDATE_INTERVAL_MS_KEY</a> - Static variable in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a></dt>
+<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#OFFSET_UPDATE_SIZE_THRESHOLD_KEY" class="member-name-link">OFFSET_UPDATE_SIZE_THRESHOLD_KEY</a> - Static variable in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/io/hfile/bucket/BucketEntry.html#offset1" class="member-name-link">offset1</a> - Variable in class org.apache.hadoop.hbase.io.hfile.bucket.<a href="org/apache/hadoop/hbase/io/hfile/bucket/BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketEntry</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/io/hfile/bucket/BucketEntry.html#offsetBase" class="member-name-link">offsetBase</a> - Variable in class org.apache.hadoop.hbase.io.hfile.bucket.<a href="org/apache/hadoop/hbase/io/hfile/bucket/BucketEntry.html" title="class in org.apache.hadoop.hbase.io.hfile.bucket">BucketEntry</a></dt>
@@ -102831,6 +102855,10 @@ loadScripts(document, 'script');</script>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/replication/ReplicationQueueData.html#offsets" class="member-name-link">offsets</a> - Variable in class org.apache.hadoop.hbase.replication.<a href="org/apache/hadoop/hbase/replication/ReplicationQueueData.html" title="class in org.apache.hadoop.hbase.replication">ReplicationQueueData</a></dt>
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#offsetUpdateIntervalMs" class="member-name-link">offsetUpdateIntervalMs</a> - Variable in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a></dt>
+<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#offsetUpdateSizeThresholdBytes" class="member-name-link">offsetUpdateSizeThresholdBytes</a> - Variable in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/master/janitor/MetaFixer.Either.html#ofLeft(L)" class="member-name-link">ofLeft(L)</a> - Static method in class org.apache.hadoop.hbase.master.janitor.<a href="org/apache/hadoop/hbase/master/janitor/MetaFixer.Either.html" title="class in org.apache.hadoop.hbase.master.janitor">MetaFixer.Either</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/master/janitor/MetaFixer.Either.html#ofRight(R)" class="member-name-link">ofRight(R)</a> - Static method in class org.apache.hadoop.hbase.master.janitor.<a href="org/apache/hadoop/hbase/master/janitor/MetaFixer.Either.html" title="class in org.apache.hadoop.hbase.master.janitor">MetaFixer.Either</a></dt>
@@ -106735,6 +106763,8 @@ service.</div>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/master/ServerManager.html#persistFlushedSequenceId" class="member-name-link">persistFlushedSequenceId</a> - Variable in class org.apache.hadoop.hbase.master.<a href="org/apache/hadoop/hbase/master/ServerManager.html" title="class in org.apache.hadoop.hbase.master">ServerManager</a></dt>
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#persistLogPosition()" class="member-name-link">persistLogPosition()</a> - Method in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/master/ServerManager.html#persistRegionLastFlushedSequenceIds()" class="member-name-link">persistRegionLastFlushedSequenceIds()</a> - Method in class org.apache.hadoop.hbase.master.<a href="org/apache/hadoop/hbase/master/ServerManager.html" title="class in org.apache.hadoop.hbase.master">ServerManager</a></dt>
<dd>
<div class="block">Persist last flushed sequence id of each region to HDFS</div>
@@ -123159,6 +123189,8 @@ service.</div>
<dd>
<div class="deprecation-block"><span class="deprecated-label">Deprecated.</span></div>
</dd>
+<dt><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSource.html#restartShipper(java.lang.String,org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper)" class="member-name-link">restartShipper(String, ReplicationSourceShipper)</a> - Method in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSource.html" title="class in org.apache.hadoop.hbase.replication.regionserver">Replic [...]
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/replication/regionserver/MetricsReplicationGlobalSourceSourceImpl.html#restartWALReading" class="member-name-link">restartWALReading</a> - Variable in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/MetricsReplicationGlobalSourceSourceImpl.html" title="class in org.apache.hadoop.hbase.replication.regionserver">MetricsReplicationGlobalSourceSourceImpl</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/replication/regionserver/MetricsReplicationSourceSourceImpl.html#restartWALReading" class="member-name-link">restartWALReading</a> - Variable in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/MetricsReplicationSourceSourceImpl.html" title="class in org.apache.hadoop.hbase.replication.regionserver">MetricsReplicationSourceSourceImpl</a></dt>
@@ -136493,6 +136525,8 @@ service.</div>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/regionserver/compactions/StripeCompactionPolicy.html#shouldPerformMajorCompaction(java.util.Collection)" class="member-name-link">shouldPerformMajorCompaction(Collection<HStoreFile>)</a> - Method in class org.apache.hadoop.hbase.regionserver.compactions.<a href="org/apache/hadoop/hbase/regionserver/compactions/StripeCompactionPolicy.html" title="class in org.apache.hadoop.hbase.regionserver.compactions">StripeCompactionPolicy</a></dt>
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#shouldPersistLogPosition()" class="member-name-link">shouldPersistLogPosition()</a> - Method in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/io/hfile/CacheConfig.html#shouldPrefetchOnOpen()" class="member-name-link">shouldPrefetchOnOpen()</a> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/CacheConfig.html" title="class in org.apache.hadoop.hbase.io.hfile">CacheConfig</a></dt>
<dd>
<div class="block">Returns true if blocks should be prefetched into the cache on open, false if not</div>
@@ -151306,6 +151340,8 @@ service.</div>
<dd>
<div class="deprecation-block"><span class="deprecated-label">Deprecated.</span></div>
</dd>
+<dt><a href="org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#TTL_FOREVER" class="member-name-link">TTL_FOREVER</a> - Static variable in class org.apache.hadoop.hbase.snapshot.<a href="org/apache/hadoop/hbase/snapshot/SnapshotInfo.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotInfo</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/TagType.html#TTL_TAG_TYPE" class="member-name-link">TTL_TAG_TYPE</a> - Static variable in class org.apache.hadoop.hbase.<a href="org/apache/hadoop/hbase/TagType.html" title="class in org.apache.hadoop.hbase">TagType</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/master/cleaner/BaseTimeToLiveFileCleaner.html#ttlMs" class="member-name-link">ttlMs</a> - Variable in class org.apache.hadoop.hbase.master.cleaner.<a href="org/apache/hadoop/hbase/master/cleaner/BaseTimeToLiveFileCleaner.html" title="class in org.apache.hadoop.hbase.master.cleaner">BaseTimeToLiveFileCleaner</a></dt>
diff --git a/devapidocs/member-search-index.js b/devapidocs/member-search-index.js
index 03910cb896b..94726a45f14 100644
--- a/devapidocs/member-search-index.js
+++ b/devapidocs/member-search-index.js
@@ -1 +1 @@
-memberSearchIndex = [{"p":"org.apache.hadoop.hbase.rest.model","c":"ColumnSchemaModel","l":"__getBlockcache()"},{"p":"org.apache.hadoop.hbase.rest.model","c":"ColumnSchemaModel","l":"__getBlocksize()"},{"p":"org.apache.hadoop.hbase.rest.model","c":"ColumnSchemaModel","l":"__getBloomfilter()"},{"p":"org.apache.hadoop.hbase.rest.model","c":"ColumnSchemaModel","l":"__getCompression()"},{"p":"org.apache.hadoop.hbase.rest.model","c":"ColumnSchemaModel","l":"__getInMemory()"},{"p":"org.apache. [...]
\ No newline at end of file
+memberSearchIndex = [{"p":"org.apache.hadoop.hbase.rest.model","c":"ColumnSchemaModel","l":"__getBlockcache()"},{"p":"org.apache.hadoop.hbase.rest.model","c":"ColumnSchemaModel","l":"__getBlocksize()"},{"p":"org.apache.hadoop.hbase.rest.model","c":"ColumnSchemaModel","l":"__getBloomfilter()"},{"p":"org.apache.hadoop.hbase.rest.model","c":"ColumnSchemaModel","l":"__getCompression()"},{"p":"org.apache.hadoop.hbase.rest.model","c":"ColumnSchemaModel","l":"__getInMemory()"},{"p":"org.apache. [...]
\ No newline at end of file
diff --git a/devapidocs/org/apache/hadoop/hbase/replication/BaseReplicationEndpoint.html b/devapidocs/org/apache/hadoop/hbase/replication/BaseReplicationEndpoint.html
index d782e60217c..57c67560892 100644
--- a/devapidocs/org/apache/hadoop/hbase/replication/BaseReplicationEndpoint.html
+++ b/devapidocs/org/apache/hadoop/hbase/replication/BaseReplicationEndpoint.html
@@ -200,7 +200,7 @@ implements <a href="ReplicationEndpoint.html" title="interface in org.apache.had
<code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#clone()" title="class or interface in java.lang" class="external-link">clone</a>, <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#equals(java.lang.Object)" title="class or interface in java.lang" class="external-link">equals</a>, <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#finalize()" title="class or [...]
<div class="inherited-list">
<h3 id="methods-inherited-from-class-org.apache.hadoop.hbase.replication.ReplicationEndpoint">Methods inherited from interface org.apache.hadoop.hbase.replication.<a href="ReplicationEndpoint.html" title="interface in org.apache.hadoop.hbase.replication">ReplicationEndpoint</a></h3>
-<code><a href="ReplicationEndpoint.html#awaitRunning()">awaitRunning</a>, <a href="ReplicationEndpoint.html#awaitRunning(long,java.util.concurrent.TimeUnit)">awaitRunning</a>, <a href="ReplicationEndpoint.html#awaitTerminated()">awaitTerminated</a>, <a href="ReplicationEndpoint.html#awaitTerminated(long,java.util.concurrent.TimeUnit)">awaitTerminated</a>, <a href="ReplicationEndpoint.html#failureCause()">failureCause</a>, <a href="ReplicationEndpoint.html#getPeerUUID()">getPeerUUID</a>, [...]
+<code><a href="ReplicationEndpoint.html#awaitRunning()">awaitRunning</a>, <a href="ReplicationEndpoint.html#awaitRunning(long,java.util.concurrent.TimeUnit)">awaitRunning</a>, <a href="ReplicationEndpoint.html#awaitTerminated()">awaitTerminated</a>, <a href="ReplicationEndpoint.html#awaitTerminated(long,java.util.concurrent.TimeUnit)">awaitTerminated</a>, <a href="ReplicationEndpoint.html#beforePersistingReplicationOffset()">beforePersistingReplicationOffset</a>, <a href="ReplicationEndp [...]
</section>
</li>
</ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/replication/HBaseReplicationEndpoint.html b/devapidocs/org/apache/hadoop/hbase/replication/HBaseReplicationEndpoint.html
index ecb3a9dd99c..a48244fcdc3 100644
--- a/devapidocs/org/apache/hadoop/hbase/replication/HBaseReplicationEndpoint.html
+++ b/devapidocs/org/apache/hadoop/hbase/replication/HBaseReplicationEndpoint.html
@@ -296,7 +296,7 @@ implements <a href="../Abortable.html" title="interface in org.apache.hadoop.hba
<code><a href="../Abortable.html#abort(java.lang.String)">abort</a></code></div>
<div class="inherited-list">
<h3 id="methods-inherited-from-class-org.apache.hadoop.hbase.replication.ReplicationEndpoint">Methods inherited from interface org.apache.hadoop.hbase.replication.<a href="ReplicationEndpoint.html" title="interface in org.apache.hadoop.hbase.replication">ReplicationEndpoint</a></h3>
-<code><a href="ReplicationEndpoint.html#awaitRunning()">awaitRunning</a>, <a href="ReplicationEndpoint.html#awaitRunning(long,java.util.concurrent.TimeUnit)">awaitRunning</a>, <a href="ReplicationEndpoint.html#awaitTerminated()">awaitTerminated</a>, <a href="ReplicationEndpoint.html#awaitTerminated(long,java.util.concurrent.TimeUnit)">awaitTerminated</a>, <a href="ReplicationEndpoint.html#failureCause()">failureCause</a>, <a href="ReplicationEndpoint.html#isRunning()">isRunning</a>, <a h [...]
+<code><a href="ReplicationEndpoint.html#awaitRunning()">awaitRunning</a>, <a href="ReplicationEndpoint.html#awaitRunning(long,java.util.concurrent.TimeUnit)">awaitRunning</a>, <a href="ReplicationEndpoint.html#awaitTerminated()">awaitTerminated</a>, <a href="ReplicationEndpoint.html#awaitTerminated(long,java.util.concurrent.TimeUnit)">awaitTerminated</a>, <a href="ReplicationEndpoint.html#beforePersistingReplicationOffset()">beforePersistingReplicationOffset</a>, <a href="ReplicationEndp [...]
</section>
</li>
</ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/replication/ReplicationEndpoint.html b/devapidocs/org/apache/hadoop/hbase/replication/ReplicationEndpoint.html
index 601a7c93992..fbf8af07480 100644
--- a/devapidocs/org/apache/hadoop/hbase/replication/ReplicationEndpoint.html
+++ b/devapidocs/org/apache/hadoop/hbase/replication/ReplicationEndpoint.html
@@ -123,7 +123,7 @@ extends <a href="ReplicationPeerConfigListener.html" title="interface in org.apa
<section class="method-summary" id="method-summary">
<h2>Method Summary</h2>
<div id="method-summary-table">
-<div class="table-tabs" role="tablist" aria-orientation="horizontal"><button id="method-summary-table-tab0" role="tab" aria-selected="true" aria-controls="method-summary-table.tabpanel" tabindex="0" onkeydown="switchTab(event)" onclick="show('method-summary-table', 'method-summary-table', 3)" class="active-table-tab">All Methods</button><button id="method-summary-table-tab2" role="tab" aria-selected="false" aria-controls="method-summary-table.tabpanel" tabindex="-1" onkeydown="switchTab( [...]
+<div class="table-tabs" role="tablist" aria-orientation="horizontal"><button id="method-summary-table-tab0" role="tab" aria-selected="true" aria-controls="method-summary-table.tabpanel" tabindex="0" onkeydown="switchTab(event)" onclick="show('method-summary-table', 'method-summary-table', 3)" class="active-table-tab">All Methods</button><button id="method-summary-table-tab2" role="tab" aria-selected="false" aria-controls="method-summary-table.tabpanel" tabindex="-1" onkeydown="switchTab( [...]
<div id="method-summary-table.tabpanel" role="tabpanel">
<div class="summary-table three-column-summary" aria-labelledby="method-summary-table-tab0">
<div class="table-header col-first">Modifier and Type</div>
@@ -153,55 +153,60 @@ extends <a href="ReplicationPeerConfigListener.html" title="interface in org.apa
<div class="block">Waits for the <a href="ReplicationEndpoint.html" title="interface in org.apache.hadoop.hbase.replication"><code>ReplicationEndpoint</code></a> to reach a terminal state for no more than the given
time.</div>
</div>
-<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code>boolean</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#canReplicateToSameCluster()" class="member-name-link">canReplicateToSameCluster</a>()</code></div>
-<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
-<div class="block">Whether or not, the replication endpoint can replicate to it's source cluster with the same
- UUID</div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab5"><code>default void</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab5"><code><a href="#beforePersistingReplicationOffset()" class="member-name-link">beforePersistingReplicationOffset</a>()</code></div>
+<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab5">
+<div class="block">Hook invoked before persisting replication offsets.</div>
</div>
-<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Throwable.html" title="class or interface in java.lang" class="external-link">Throwable</a></code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#failureCause()" class="member-name-link">failureCause</a>()</code></div>
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code>boolean</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#canReplicateToSameCluster()" class="member-name-link">canReplicateToSameCluster</a>()</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
-<div class="block">Returns the <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Throwable.html" title="class or interface in java.lang" class="external-link"><code>Throwable</code></a> that caused this service to fail.</div>
+<div class="block">Whether or not, the replication endpoint can replicate to it's source cluster with the same
+ UUID</div>
</div>
-<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/UUID.html" title="class or interface in java.util" class="external-link">UUID</a></code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#getPeerUUID()" class="member-name-link">getPeerUUID</a>()</code></div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Throwable.html" title="class or interface in java.lang" class="external-link">Throwable</a></code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#failureCause()" class="member-name-link">failureCause</a>()</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
-<div class="block">Returns a UUID of the provided peer id.</div>
+<div class="block">Returns the <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Throwable.html" title="class or interface in java.lang" class="external-link"><code>Throwable</code></a> that caused this service to fail.</div>
</div>
-<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="WALEntryFilter.html" title="interface in org.apache.hadoop.hbase.replication">WALEntryFilter</a></code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#getWALEntryfilter()" class="member-name-link">getWALEntryfilter</a>()</code></div>
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/UUID.html" title="class or interface in java.util" class="external-link">UUID</a></code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#getPeerUUID()" class="member-name-link">getPeerUUID</a>()</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
-<div class="block">Returns a WALEntryFilter to use for filtering out WALEntries from the log.</div>
+<div class="block">Returns a UUID of the provided peer id.</div>
</div>
-<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code>void</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#init(org.apache.hadoop.hbase.replication.ReplicationEndpoint.Context)" class="member-name-link">init</a><wbr>(<a href="ReplicationEndpoint.Context.html" title="class in org.apache.hadoop.hbase.replication">ReplicationEndpoint.Context</a> context)</code></div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="WALEntryFilter.html" title="interface in org.apache.hadoop.hbase.replication">WALEntryFilter</a></code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#getWALEntryfilter()" class="member-name-link">getWALEntryfilter</a>()</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
-<div class="block">Initialize the replication endpoint with the given context.</div>
+<div class="block">Returns a WALEntryFilter to use for filtering out WALEntries from the log.</div>
</div>
-<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code>boolean</code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#isRunning()" class="member-name-link">isRunning</a>()</code></div>
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code>void</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#init(org.apache.hadoop.hbase.replication.ReplicationEndpoint.Context)" class="member-name-link">init</a><wbr>(<a href="ReplicationEndpoint.Context.html" title="class in org.apache.hadoop.hbase.replication">ReplicationEndpoint.Context</a> context)</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
-<div class="block">Returns <code>true</code> if this service is RUNNING.</div>
+<div class="block">Initialize the replication endpoint with the given context.</div>
</div>
<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code>boolean</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#isStarting()" class="member-name-link">isStarting</a>()</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#isRunning()" class="member-name-link">isRunning</a>()</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
-<div class="block">Returns Return <code>true</code> is this service is STARTING (but not yet RUNNING).</div>
+<div class="block">Returns <code>true</code> if this service is RUNNING.</div>
</div>
<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code>boolean</code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#replicate(org.apache.hadoop.hbase.replication.ReplicationEndpoint.ReplicateContext)" class="member-name-link">replicate</a><wbr>(<a href="ReplicationEndpoint.ReplicateContext.html" title="class in org.apache.hadoop.hbase.replication">ReplicationEndpoint.ReplicateContext</a> replicateContext)</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#isStarting()" class="member-name-link">isStarting</a>()</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
-<div class="block">Replicate the given set of entries (in the context) to the other cluster.</div>
+<div class="block">Returns Return <code>true</code> is this service is STARTING (but not yet RUNNING).</div>
</div>
-<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code>void</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#start()" class="member-name-link">start</a>()</code></div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code>boolean</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#replicate(org.apache.hadoop.hbase.replication.ReplicationEndpoint.ReplicateContext)" class="member-name-link">replicate</a><wbr>(<a href="ReplicationEndpoint.ReplicateContext.html" title="class in org.apache.hadoop.hbase.replication">ReplicationEndpoint.ReplicateContext</a> replicateContext)</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
-<div class="block">Initiates service startup and returns immediately.</div>
+<div class="block">Replicate the given set of entries (in the context) to the other cluster.</div>
</div>
<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code>void</code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#stop()" class="member-name-link">stop</a>()</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#start()" class="member-name-link">start</a>()</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
+<div class="block">Initiates service startup and returns immediately.</div>
+</div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code>void</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3"><code><a href="#stop()" class="member-name-link">stop</a>()</code></div>
+<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab3">
<div class="block">If the service is starting or running, this initiates service shutdown and returns immediately.</div>
</div>
</div>
@@ -393,6 +398,19 @@ extends <a href="ReplicationPeerConfigListener.html" title="interface in org.apa
</dl>
</section>
</li>
+<li>
+<section class="detail" id="beforePersistingReplicationOffset()">
+<h3>beforePersistingReplicationOffset</h3>
+<div class="member-signature"><span class="modifiers">default</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.html#line-291">beforePersistingReplicationOffset</a></span>()
+ throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
+<div class="block">Hook invoked before persisting replication offsets. Eg: Buffered endpoints can flush/close WALs
+ here.</div>
+<dl class="notes">
+<dt>Throws:</dt>
+<dd><code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></code></dd>
+</dl>
+</section>
+</li>
</ul>
</section>
</li>
diff --git a/devapidocs/org/apache/hadoop/hbase/replication/VerifyWALEntriesReplicationEndpoint.html b/devapidocs/org/apache/hadoop/hbase/replication/VerifyWALEntriesReplicationEndpoint.html
index 1ddb317e92b..ce8a2a098a5 100644
--- a/devapidocs/org/apache/hadoop/hbase/replication/VerifyWALEntriesReplicationEndpoint.html
+++ b/devapidocs/org/apache/hadoop/hbase/replication/VerifyWALEntriesReplicationEndpoint.html
@@ -197,7 +197,7 @@ loadScripts(document, 'script');</script>
<code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#clone()" title="class or interface in java.lang" class="external-link">clone</a>, <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#equals(java.lang.Object)" title="class or interface in java.lang" class="external-link">equals</a>, <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#finalize()" title="class or [...]
<div class="inherited-list">
<h3 id="methods-inherited-from-class-org.apache.hadoop.hbase.replication.ReplicationEndpoint">Methods inherited from interface org.apache.hadoop.hbase.replication.<a href="ReplicationEndpoint.html" title="interface in org.apache.hadoop.hbase.replication">ReplicationEndpoint</a></h3>
-<code><a href="ReplicationEndpoint.html#awaitRunning()">awaitRunning</a>, <a href="ReplicationEndpoint.html#awaitRunning(long,java.util.concurrent.TimeUnit)">awaitRunning</a>, <a href="ReplicationEndpoint.html#awaitTerminated()">awaitTerminated</a>, <a href="ReplicationEndpoint.html#awaitTerminated(long,java.util.concurrent.TimeUnit)">awaitTerminated</a>, <a href="ReplicationEndpoint.html#failureCause()">failureCause</a>, <a href="ReplicationEndpoint.html#isRunning()">isRunning</a></code></div>
+<code><a href="ReplicationEndpoint.html#awaitRunning()">awaitRunning</a>, <a href="ReplicationEndpoint.html#awaitRunning(long,java.util.concurrent.TimeUnit)">awaitRunning</a>, <a href="ReplicationEndpoint.html#awaitTerminated()">awaitTerminated</a>, <a href="ReplicationEndpoint.html#awaitTerminated(long,java.util.concurrent.TimeUnit)">awaitTerminated</a>, <a href="ReplicationEndpoint.html#beforePersistingReplicationOffset()">beforePersistingReplicationOffset</a>, <a href="ReplicationEndp [...]
</section>
</li>
</ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/HBaseInterClusterReplicationEndpoint.html b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/HBaseInterClusterReplicationEndpoint.html
index e52d9a4f066..2d10445aecf 100644
--- a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/HBaseInterClusterReplicationEndpoint.html
+++ b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/HBaseInterClusterReplicationEndpoint.html
@@ -325,7 +325,7 @@ loadScripts(document, 'script');</script>
<code><a href="../../Abortable.html#abort(java.lang.String)">abort</a></code></div>
<div class="inherited-list">
<h3 id="methods-inherited-from-class-org.apache.hadoop.hbase.replication.ReplicationEndpoint">Methods inherited from interface org.apache.hadoop.hbase.replication.<a href="../ReplicationEndpoint.html" title="interface in org.apache.hadoop.hbase.replication">ReplicationEndpoint</a></h3>
-<code><a href="../ReplicationEndpoint.html#awaitRunning()">awaitRunning</a>, <a href="../ReplicationEndpoint.html#awaitRunning(long,java.util.concurrent.TimeUnit)">awaitRunning</a>, <a href="../ReplicationEndpoint.html#awaitTerminated()">awaitTerminated</a>, <a href="../ReplicationEndpoint.html#awaitTerminated(long,java.util.concurrent.TimeUnit)">awaitTerminated</a>, <a href="../ReplicationEndpoint.html#failureCause()">failureCause</a>, <a href="../ReplicationEndpoint.html#isRunning()">i [...]
+<code><a href="../ReplicationEndpoint.html#awaitRunning()">awaitRunning</a>, <a href="../ReplicationEndpoint.html#awaitRunning(long,java.util.concurrent.TimeUnit)">awaitRunning</a>, <a href="../ReplicationEndpoint.html#awaitTerminated()">awaitTerminated</a>, <a href="../ReplicationEndpoint.html#awaitTerminated(long,java.util.concurrent.TimeUnit)">awaitTerminated</a>, <a href="../ReplicationEndpoint.html#beforePersistingReplicationOffset()">beforePersistingReplicationOffset</a>, <a href=" [...]
</section>
</li>
</ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/RecoveredReplicationSource.html b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/RecoveredReplicationSource.html
index 034c6c2eec7..2cad5ece5c6 100644
--- a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/RecoveredReplicationSource.html
+++ b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/RecoveredReplicationSource.html
@@ -136,7 +136,7 @@ loadScripts(document, 'script');</script>
</div>
<div class="inherited-list">
<h3 id="methods-inherited-from-class-org.apache.hadoop.hbase.replication.regionserver.ReplicationSource">Methods inherited from class org.apache.hadoop.hbase.replication.regionserver.<a href="ReplicationSource.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSource</a></h3>
-<code><a href="ReplicationSource.html#addHFileRefs(org.apache.hadoop.hbase.TableName,byte%5B%5D,java.util.List)">addHFileRefs</a>, <a href="ReplicationSource.html#createNewShipper(java.lang.String)">createNewShipper</a>, <a href="ReplicationSource.html#enqueueLog(org.apache.hadoop.fs.Path)">enqueueLog</a>, <a href="ReplicationSource.html#getCurrentPath()">getCurrentPath</a>, <a href="ReplicationSource.html#getPeer()">getPeer</a>, <a href="ReplicationSource.html#getQueueId()">getQueueId</ [...]
+<code><a href="ReplicationSource.html#addHFileRefs(org.apache.hadoop.hbase.TableName,byte%5B%5D,java.util.List)">addHFileRefs</a>, <a href="ReplicationSource.html#createNewShipper(java.lang.String)">createNewShipper</a>, <a href="ReplicationSource.html#enqueueLog(org.apache.hadoop.fs.Path)">enqueueLog</a>, <a href="ReplicationSource.html#getCurrentPath()">getCurrentPath</a>, <a href="ReplicationSource.html#getPeer()">getPeer</a>, <a href="ReplicationSource.html#getQueueId()">getQueueId</ [...]
<div class="inherited-list">
<h3 id="methods-inherited-from-class-java.lang.Object">Methods inherited from class java.lang.<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html" title="class or interface in java.lang" class="external-link">Object</a></h3>
<code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#clone()" title="class or interface in java.lang" class="external-link">clone</a>, <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#equals(java.lang.Object)" title="class or interface in java.lang" class="external-link">equals</a>, <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#finalize()" title="class or [...]
diff --git a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/RecoveredReplicationSourceShipper.html b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/RecoveredReplicationSourceShipper.html
index c6d795e8d7c..ae36bd75601 100644
--- a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/RecoveredReplicationSourceShipper.html
+++ b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/RecoveredReplicationSourceShipper.html
@@ -162,7 +162,7 @@ loadScripts(document, 'script');</script>
</div>
<div class="inherited-list">
<h3 id="methods-inherited-from-class-org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper">Methods inherited from class org.apache.hadoop.hbase.replication.regionserver.<a href="ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a></h3>
-<code><a href="ReplicationSourceShipper.html#clearWALEntryBatch()">clearWALEntryBatch</a>, <a href="ReplicationSourceShipper.html#getCurrentPath()">getCurrentPath</a>, <a href="ReplicationSourceShipper.html#getCurrentPosition()">getCurrentPosition</a>, <a href="ReplicationSourceShipper.html#getSleepForRetries()">getSleepForRetries</a>, <a href="ReplicationSourceShipper.html#isActive()">isActive</a>, <a href="ReplicationSourceShipper.html#isFinished()">isFinished</a>, <a href="Replication [...]
+<code><a href="ReplicationSourceShipper.html#abortAndRestart(java.lang.Throwable)">abortAndRestart</a>, <a href="ReplicationSourceShipper.html#cleanUpHFileRefs(org.apache.hadoop.hbase.wal.WALEdit)">cleanUpHFileRefs</a>, <a href="ReplicationSourceShipper.html#clearWALEntryBatch()">clearWALEntryBatch</a>, <a href="ReplicationSourceShipper.html#getCurrentPath()">getCurrentPath</a>, <a href="ReplicationSourceShipper.html#getCurrentPosition()">getCurrentPosition</a>, <a href="ReplicationSourc [...]
<div class="inherited-list">
<h3 id="methods-inherited-from-class-java.lang.Thread">Methods inherited from class java.lang.<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Thread.html" title="class or interface in java.lang" class="external-link">Thread</a></h3>
<code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Thread.html#activeCount()" title="class or interface in java.lang" class="external-link">activeCount</a>, <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Thread.html#checkAccess()" title="class or interface in java.lang" class="external-link">checkAccess</a>, <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Thread.html#clone()" title="class [...]
diff --git a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/ReplicationSource.html b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/ReplicationSource.html
index 749cf67af3f..245109c636d 100644
--- a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/ReplicationSource.html
+++ b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/ReplicationSource.html
@@ -404,60 +404,64 @@ implements <a href="ReplicationSourceInterface.html" title="interface in org.apa
<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>(package private) void</code></div>
<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#removeWorker(org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper)" class="member-name-link">removeWorker</a><wbr>(<a href="ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a> worker)</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
-<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>private void</code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#retryRefreshing(java.lang.Thread,java.lang.Throwable)" class="member-name-link">retryRefreshing</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Thread.html" title="class or interface in java.lang" class="external-link">Thread</a> t,
- <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Throwable.html" title="class or interface in java.lang" class="external-link">Throwable</a> error)</code></div>
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>(package private) void</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#restartShipper(java.lang.String,org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper)" class="member-name-link">restartShipper</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> walGroupId,
+ <a href="ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a> oldWorker)</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>private void</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#setSourceStartupStatus(boolean)" class="member-name-link">setSourceStartupStatus</a><wbr>(boolean initializing)</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#retryRefreshing(java.lang.Thread,java.lang.Throwable)" class="member-name-link">retryRefreshing</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Thread.html" title="class or interface in java.lang" class="external-link">Thread</a> t,
+ <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Throwable.html" title="class or interface in java.lang" class="external-link">Throwable</a> error)</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
-<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>private boolean</code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#sleepForRetries(java.lang.String,int)" class="member-name-link">sleepForRetries</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> msg,
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>private void</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#setSourceStartupStatus(boolean)" class="member-name-link">setSourceStartupStatus</a><wbr>(boolean initializing)</code></div>
+<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>private boolean</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#sleepForRetries(java.lang.String,int)" class="member-name-link">sleepForRetries</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> msg,
int sleepMultiplier)</code></div>
-<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4">
+<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4">
<div class="block">Do the sleeping logic</div>
</div>
-<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>protected final void</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#startShipper(org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper)" class="member-name-link">startShipper</a><wbr>(<a href="ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a> worker)</code></div>
-<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
-<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>protected void</code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#startShippers()" class="member-name-link">startShippers</a>()</code></div>
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>protected final void</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#startShipper(org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper)" class="member-name-link">startShipper</a><wbr>(<a href="ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a> worker)</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
-<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="ReplicationSourceInterface.html" title="interface in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceInterface</a></code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#startup()" class="member-name-link">startup</a>()</code></div>
-<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4">
-<div class="block">Start the replication</div>
-</div>
-<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>void</code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#terminate(java.lang.String)" class="member-name-link">terminate</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> reason)</code></div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>protected void</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#startShippers()" class="member-name-link">startShippers</a>()</code></div>
+<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="ReplicationSourceInterface.html" title="interface in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceInterface</a></code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#startup()" class="member-name-link">startup</a>()</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4">
-<div class="block">End the replication</div>
+<div class="block">Start the replication</div>
</div>
<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>void</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#terminate(java.lang.String,java.lang.Exception)" class="member-name-link">terminate</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> reason,
- <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Exception.html" title="class or interface in java.lang" class="external-link">Exception</a> cause)</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#terminate(java.lang.String)" class="member-name-link">terminate</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> reason)</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4">
<div class="block">End the replication</div>
</div>
<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>void</code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#terminate(java.lang.String,java.lang.Exception,boolean)" class="member-name-link">terminate</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> reason,
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#terminate(java.lang.String,java.lang.Exception)" class="member-name-link">terminate</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> reason,
+ <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Exception.html" title="class or interface in java.lang" class="external-link">Exception</a> cause)</code></div>
+<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4">
+<div class="block">End the replication</div>
+</div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>void</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#terminate(java.lang.String,java.lang.Exception,boolean)" class="member-name-link">terminate</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> reason,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Exception.html" title="class or interface in java.lang" class="external-link">Exception</a> cause,
boolean clearMetrics)</code></div>
-<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4">
+<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4">
<div class="block">End the replication</div>
</div>
-<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>private void</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#terminate(java.lang.String,java.lang.Exception,boolean,boolean)" class="member-name-link">terminate</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> reason,
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>private void</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#terminate(java.lang.String,java.lang.Exception,boolean,boolean)" class="member-name-link">terminate</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> reason,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Exception.html" title="class or interface in java.lang" class="external-link">Exception</a> cause,
boolean clearMetrics,
boolean join)</code></div>
-<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
-<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>private void</code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#tryStartNewShipper(java.lang.String)" class="member-name-link">tryStartNewShipper</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> walGroupId)</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
-<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>void</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#tryThrottle(int)" class="member-name-link">tryThrottle</a><wbr>(int batchSize)</code></div>
-<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4">
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>private void</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#tryStartNewShipper(java.lang.String)" class="member-name-link">tryStartNewShipper</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> walGroupId)</code></div>
+<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>void</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#tryThrottle(int)" class="member-name-link">tryThrottle</a><wbr>(int batchSize)</code></div>
+<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4">
<div class="block">Try to throttle when the peer config with a bandwidth</div>
</div>
</div>
@@ -1280,6 +1284,13 @@ implements <a href="ReplicationSourceInterface.html" title="interface in org.apa
<div class="member-signature"><span class="return-type">long</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSource.html#line-866">getSleepForRetries</a></span>()</div>
</section>
</li>
+<li>
+<section class="detail" id="restartShipper(java.lang.String,org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper)">
+<h3>restartShipper</h3>
+<div class="member-signature"><span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSource.html#line-870">restartShipper</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> walGroupId,
+ <a href="ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a> oldWorker)</span></div>
+</section>
+</li>
</ul>
</section>
</li>
diff --git a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html
index 63bddb12da4..1aaa754afef 100644
--- a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html
+++ b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html
@@ -122,45 +122,72 @@ loadScripts(document, 'script');</script>
<div class="table-header col-first">Modifier and Type</div>
<div class="table-header col-second">Field</div>
<div class="table-header col-last">Description</div>
-<div class="col-first even-row-color"><code>private final org.apache.hadoop.conf.Configuration</code></div>
-<div class="col-second even-row-color"><code><a href="#conf" class="member-name-link">conf</a></code></div>
+<div class="col-first even-row-color"><code>private long</code></div>
+<div class="col-second even-row-color"><code><a href="#accumulatedSizeSinceLastUpdate" class="member-name-link">accumulatedSizeSinceLastUpdate</a></code></div>
<div class="col-last even-row-color"> </div>
-<div class="col-first odd-row-color"><code>private org.apache.hadoop.fs.Path</code></div>
-<div class="col-second odd-row-color"><code><a href="#currentPath" class="member-name-link">currentPath</a></code></div>
+<div class="col-first odd-row-color"><code>private final org.apache.hadoop.conf.Configuration</code></div>
+<div class="col-second odd-row-color"><code><a href="#conf" class="member-name-link">conf</a></code></div>
<div class="col-last odd-row-color"> </div>
-<div class="col-first even-row-color"><code>private long</code></div>
-<div class="col-second even-row-color"><code><a href="#currentPosition" class="member-name-link">currentPosition</a></code></div>
+<div class="col-first even-row-color"><code>private org.apache.hadoop.fs.Path</code></div>
+<div class="col-second even-row-color"><code><a href="#currentPath" class="member-name-link">currentPath</a></code></div>
<div class="col-last even-row-color"> </div>
-<div class="col-first odd-row-color"><code>private final int</code></div>
-<div class="col-second odd-row-color"><code><a href="#DEFAULT_TIMEOUT" class="member-name-link">DEFAULT_TIMEOUT</a></code></div>
+<div class="col-first odd-row-color"><code>private long</code></div>
+<div class="col-second odd-row-color"><code><a href="#currentPosition" class="member-name-link">currentPosition</a></code></div>
<div class="col-last odd-row-color"> </div>
-<div class="col-first even-row-color"><code>(package private) final <a href="ReplicationSourceWALReader.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceWALReader</a></code></div>
-<div class="col-second even-row-color"><code><a href="#entryReader" class="member-name-link">entryReader</a></code></div>
+<div class="col-first even-row-color"><code>private static final long</code></div>
+<div class="col-second even-row-color"><code><a href="#DEFAULT_OFFSET_UPDATE_INTERVAL_MS" class="member-name-link">DEFAULT_OFFSET_UPDATE_INTERVAL_MS</a></code></div>
<div class="col-last even-row-color"> </div>
-<div class="col-first odd-row-color"><code>private final int</code></div>
-<div class="col-second odd-row-color"><code><a href="#getEntriesTimeout" class="member-name-link">getEntriesTimeout</a></code></div>
+<div class="col-first odd-row-color"><code>private static final long</code></div>
+<div class="col-second odd-row-color"><code><a href="#DEFAULT_OFFSET_UPDATE_SIZE_THRESHOLD" class="member-name-link">DEFAULT_OFFSET_UPDATE_SIZE_THRESHOLD</a></code></div>
<div class="col-last odd-row-color"> </div>
-<div class="col-first even-row-color"><code>private static final org.slf4j.Logger</code></div>
-<div class="col-second even-row-color"><code><a href="#LOG" class="member-name-link">LOG</a></code></div>
+<div class="col-first even-row-color"><code>private final int</code></div>
+<div class="col-second even-row-color"><code><a href="#DEFAULT_TIMEOUT" class="member-name-link">DEFAULT_TIMEOUT</a></code></div>
<div class="col-last even-row-color"> </div>
-<div class="col-first odd-row-color"><code>private final int</code></div>
-<div class="col-second odd-row-color"><code><a href="#maxRetriesMultiplier" class="member-name-link">maxRetriesMultiplier</a></code></div>
+<div class="col-first odd-row-color"><code>(package private) final <a href="ReplicationSourceWALReader.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceWALReader</a></code></div>
+<div class="col-second odd-row-color"><code><a href="#entryReader" class="member-name-link">entryReader</a></code></div>
+<div class="col-last odd-row-color"> </div>
+<div class="col-first even-row-color"><code>private final int</code></div>
+<div class="col-second even-row-color"><code><a href="#getEntriesTimeout" class="member-name-link">getEntriesTimeout</a></code></div>
+<div class="col-last even-row-color"> </div>
+<div class="col-first odd-row-color"><code>private long</code></div>
+<div class="col-second odd-row-color"><code><a href="#lastOffsetUpdateTime" class="member-name-link">lastOffsetUpdateTime</a></code></div>
+<div class="col-last odd-row-color"> </div>
+<div class="col-first even-row-color"><code>private <a href="WALEntryBatch.html" title="class in org.apache.hadoop.hbase.replication.regionserver">WALEntryBatch</a></code></div>
+<div class="col-second even-row-color"><code><a href="#lastShippedBatch" class="member-name-link">lastShippedBatch</a></code></div>
+<div class="col-last even-row-color"> </div>
+<div class="col-first odd-row-color"><code>private static final org.slf4j.Logger</code></div>
+<div class="col-second odd-row-color"><code><a href="#LOG" class="member-name-link">LOG</a></code></div>
<div class="col-last odd-row-color"> </div>
<div class="col-first even-row-color"><code>private final int</code></div>
-<div class="col-second even-row-color"><code><a href="#shipEditsTimeout" class="member-name-link">shipEditsTimeout</a></code></div>
+<div class="col-second even-row-color"><code><a href="#maxRetriesMultiplier" class="member-name-link">maxRetriesMultiplier</a></code></div>
+<div class="col-last even-row-color"> </div>
+<div class="col-first odd-row-color"><code>private static final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></code></div>
+<div class="col-second odd-row-color"><code><a href="#OFFSET_UPDATE_INTERVAL_MS_KEY" class="member-name-link">OFFSET_UPDATE_INTERVAL_MS_KEY</a></code></div>
+<div class="col-last odd-row-color"> </div>
+<div class="col-first even-row-color"><code>private static final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></code></div>
+<div class="col-second even-row-color"><code><a href="#OFFSET_UPDATE_SIZE_THRESHOLD_KEY" class="member-name-link">OFFSET_UPDATE_SIZE_THRESHOLD_KEY</a></code></div>
<div class="col-last even-row-color"> </div>
<div class="col-first odd-row-color"><code>private final long</code></div>
-<div class="col-second odd-row-color"><code><a href="#sleepForRetries" class="member-name-link">sleepForRetries</a></code></div>
+<div class="col-second odd-row-color"><code><a href="#offsetUpdateIntervalMs" class="member-name-link">offsetUpdateIntervalMs</a></code></div>
<div class="col-last odd-row-color"> </div>
-<div class="col-first even-row-color"><code>private final <a href="ReplicationSource.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSource</a></code></div>
-<div class="col-second even-row-color"><code><a href="#source" class="member-name-link">source</a></code></div>
+<div class="col-first even-row-color"><code>private final long</code></div>
+<div class="col-second even-row-color"><code><a href="#offsetUpdateSizeThresholdBytes" class="member-name-link">offsetUpdateSizeThresholdBytes</a></code></div>
<div class="col-last even-row-color"> </div>
-<div class="col-first odd-row-color"><code>private <a href="ReplicationSourceShipper.WorkerState.html" title="enum class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper.WorkerState</a></code></div>
-<div class="col-second odd-row-color"><code><a href="#state" class="member-name-link">state</a></code></div>
+<div class="col-first odd-row-color"><code>private final int</code></div>
+<div class="col-second odd-row-color"><code><a href="#shipEditsTimeout" class="member-name-link">shipEditsTimeout</a></code></div>
<div class="col-last odd-row-color"> </div>
-<div class="col-first even-row-color"><code>(package private) final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></code></div>
-<div class="col-second even-row-color"><code><a href="#walGroupId" class="member-name-link">walGroupId</a></code></div>
+<div class="col-first even-row-color"><code>private final long</code></div>
+<div class="col-second even-row-color"><code><a href="#sleepForRetries" class="member-name-link">sleepForRetries</a></code></div>
<div class="col-last even-row-color"> </div>
+<div class="col-first odd-row-color"><code>private final <a href="ReplicationSource.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSource</a></code></div>
+<div class="col-second odd-row-color"><code><a href="#source" class="member-name-link">source</a></code></div>
+<div class="col-last odd-row-color"> </div>
+<div class="col-first even-row-color"><code>private <a href="ReplicationSourceShipper.WorkerState.html" title="enum class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper.WorkerState</a></code></div>
+<div class="col-second even-row-color"><code><a href="#state" class="member-name-link">state</a></code></div>
+<div class="col-last even-row-color"> </div>
+<div class="col-first odd-row-color"><code>(package private) final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></code></div>
+<div class="col-second odd-row-color"><code><a href="#walGroupId" class="member-name-link">walGroupId</a></code></div>
+<div class="col-last odd-row-color"> </div>
</div>
<div class="inherited-list">
<h3 id="fields-inherited-from-class-java.lang.Thread">Fields inherited from class java.lang.<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Thread.html" title="class or interface in java.lang" class="external-link">Thread</a></h3>
@@ -194,33 +221,39 @@ loadScripts(document, 'script');</script>
<div class="table-header col-first">Modifier and Type</div>
<div class="table-header col-second">Method</div>
<div class="table-header col-last">Description</div>
-<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>private void</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#cleanUpHFileRefs(org.apache.hadoop.hbase.wal.WALEdit)" class="member-name-link">cleanUpHFileRefs</a><wbr>(<a href="../../wal/WALEdit.html" title="class in org.apache.hadoop.hbase.wal">WALEdit</a> edit)</code></div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>(package private) void</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#abortAndRestart(java.lang.Throwable)" class="member-name-link">abortAndRestart</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Throwable.html" title="class or interface in java.lang" class="external-link">Throwable</a> cause)</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>(package private) void</code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#clearWALEntryBatch()" class="member-name-link">clearWALEntryBatch</a>()</code></div>
-<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4">
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#cleanUpHFileRefs(org.apache.hadoop.hbase.wal.WALEdit)" class="member-name-link">cleanUpHFileRefs</a><wbr>(<a href="../../wal/WALEdit.html" title="class in org.apache.hadoop.hbase.wal">WALEdit</a> edit)</code></div>
+<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>(package private) void</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#clearWALEntryBatch()" class="member-name-link">clearWALEntryBatch</a>()</code></div>
+<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4">
<div class="block">Attempts to properly update <code>ReplicationSourceManager.totalBufferUser</code>, in case
there were unprocessed entries batched by the reader to the shipper, but the shipper didn't
manage to ship those because the replication source is being terminated.</div>
</div>
-<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>(package private) org.apache.hadoop.fs.Path</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#getCurrentPath()" class="member-name-link">getCurrentPath</a>()</code></div>
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>(package private) org.apache.hadoop.fs.Path</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#getCurrentPath()" class="member-name-link">getCurrentPath</a>()</code></div>
+<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>(package private) long</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#getCurrentPosition()" class="member-name-link">getCurrentPosition</a>()</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>(package private) long</code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#getCurrentPosition()" class="member-name-link">getCurrentPosition</a>()</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#getSleepForRetries()" class="member-name-link">getSleepForRetries</a>()</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
-<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>(package private) long</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#getSleepForRetries()" class="member-name-link">getSleepForRetries</a>()</code></div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>protected boolean</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#isActive()" class="member-name-link">isActive</a>()</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
-<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>protected boolean</code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#isActive()" class="member-name-link">isActive</a>()</code></div>
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>boolean</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#isFinished()" class="member-name-link">isFinished</a>()</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
-<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>boolean</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#isFinished()" class="member-name-link">isFinished</a>()</code></div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>private void</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#noMoreData()" class="member-name-link">noMoreData</a>()</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
-<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>private void</code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#noMoreData()" class="member-name-link">noMoreData</a>()</code></div>
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>(package private) void</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#persistLogPosition()" class="member-name-link">persistLogPosition</a>()</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>protected void</code></div>
<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#postFinish()" class="member-name-link">postFinish</a>()</code></div>
@@ -231,20 +264,23 @@ loadScripts(document, 'script');</script>
<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>protected final void</code></div>
<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#setWorkerState(org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper.WorkerState)" class="member-name-link">setWorkerState</a><wbr>(<a href="ReplicationSourceShipper.WorkerState.html" title="enum class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper.WorkerState</a> state)</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
-<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>private void</code></div>
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>(package private) void</code></div>
<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#shipEdits(org.apache.hadoop.hbase.replication.regionserver.WALEntryBatch)" class="member-name-link">shipEdits</a><wbr>(<a href="WALEntryBatch.html" title="class in org.apache.hadoop.hbase.replication.regionserver">WALEntryBatch</a> entryBatch)</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4">
<div class="block">Do the shipping logic</div>
</div>
-<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>void</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#startup(java.lang.Thread.UncaughtExceptionHandler)" class="member-name-link">startup</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Thread.UncaughtExceptionHandler.html" title="class or interface in java.lang" class="external-link">Thread.UncaughtExceptionHandler</a> handler)</code></div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>private boolean</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#shouldPersistLogPosition()" class="member-name-link">shouldPersistLogPosition</a>()</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
-<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>(package private) void</code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#stopWorker()" class="member-name-link">stopWorker</a>()</code></div>
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>void</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#startup(java.lang.Thread.UncaughtExceptionHandler)" class="member-name-link">startup</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Thread.UncaughtExceptionHandler.html" title="class or interface in java.lang" class="external-link">Thread.UncaughtExceptionHandler</a> handler)</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
-<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>private boolean</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#updateLogPosition(org.apache.hadoop.hbase.replication.regionserver.WALEntryBatch)" class="member-name-link">updateLogPosition</a><wbr>(<a href="WALEntryBatch.html" title="class in org.apache.hadoop.hbase.replication.regionserver">WALEntryBatch</a> batch)</code></div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>(package private) void</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#stopWorker()" class="member-name-link">stopWorker</a>()</code></div>
<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>private boolean</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#updateLogPosition(org.apache.hadoop.hbase.replication.regionserver.WALEntryBatch)" class="member-name-link">updateLogPosition</a><wbr>(<a href="WALEntryBatch.html" title="class in org.apache.hadoop.hbase.replication.regionserver">WALEntryBatch</a> batch)</code></div>
+<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
</div>
</div>
</div>
@@ -351,6 +387,92 @@ loadScripts(document, 'script');</script>
<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-76">shipEditsTimeout</a></span></div>
</section>
</li>
+<li>
+<section class="detail" id="accumulatedSizeSinceLastUpdate">
+<h3>accumulatedSizeSinceLastUpdate</h3>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-77">accumulatedSizeSinceLastUpdate</a></span></div>
+</section>
+</li>
+<li>
+<section class="detail" id="lastOffsetUpdateTime">
+<h3>lastOffsetUpdateTime</h3>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-78">lastOffsetUpdateTime</a></span></div>
+</section>
+</li>
+<li>
+<section class="detail" id="offsetUpdateIntervalMs">
+<h3>offsetUpdateIntervalMs</h3>
+<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-79">offsetUpdateIntervalMs</a></span></div>
+</section>
+</li>
+<li>
+<section class="detail" id="offsetUpdateSizeThresholdBytes">
+<h3>offsetUpdateSizeThresholdBytes</h3>
+<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-80">offsetUpdateSizeThresholdBytes</a></span></div>
+</section>
+</li>
+<li>
+<section class="detail" id="lastShippedBatch">
+<h3>lastShippedBatch</h3>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="WALEntryBatch.html" title="class in org.apache.hadoop.hbase.replication.regionserver">WALEntryBatch</a></span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-81">lastShippedBatch</a></span></div>
+</section>
+</li>
+<li>
+<section class="detail" id="OFFSET_UPDATE_INTERVAL_MS_KEY">
+<h3>OFFSET_UPDATE_INTERVAL_MS_KEY</h3>
+<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-83">OFFSET_UPDATE_INTERVAL_MS_KEY</a></span></div>
+<dl class="notes">
+<dt>See Also:</dt>
+<dd>
+<ul class="see-list">
+<li><a href="../../../../../../constant-values.html#org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper.OFFSET_UPDATE_INTERVAL_MS_KEY">Constant Field Values</a></li>
+</ul>
+</dd>
+</dl>
+</section>
+</li>
+<li>
+<section class="detail" id="OFFSET_UPDATE_SIZE_THRESHOLD_KEY">
+<h3>OFFSET_UPDATE_SIZE_THRESHOLD_KEY</h3>
+<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-85">OFFSET_UPDATE_SIZE_THRESHOLD_KEY</a></span></div>
+<dl class="notes">
+<dt>See Also:</dt>
+<dd>
+<ul class="see-list">
+<li><a href="../../../../../../constant-values.html#org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper.OFFSET_UPDATE_SIZE_THRESHOLD_KEY">Constant Field Values</a></li>
+</ul>
+</dd>
+</dl>
+</section>
+</li>
+<li>
+<section class="detail" id="DEFAULT_OFFSET_UPDATE_INTERVAL_MS">
+<h3>DEFAULT_OFFSET_UPDATE_INTERVAL_MS</h3>
+<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-87">DEFAULT_OFFSET_UPDATE_INTERVAL_MS</a></span></div>
+<dl class="notes">
+<dt>See Also:</dt>
+<dd>
+<ul class="see-list">
+<li><a href="../../../../../../constant-values.html#org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper.DEFAULT_OFFSET_UPDATE_INTERVAL_MS">Constant Field Values</a></li>
+</ul>
+</dd>
+</dl>
+</section>
+</li>
+<li>
+<section class="detail" id="DEFAULT_OFFSET_UPDATE_SIZE_THRESHOLD">
+<h3>DEFAULT_OFFSET_UPDATE_SIZE_THRESHOLD</h3>
+<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-88">DEFAULT_OFFSET_UPDATE_SIZE_THRESHOLD</a></span></div>
+<dl class="notes">
+<dt>See Also:</dt>
+<dd>
+<ul class="see-list">
+<li><a href="../../../../../../constant-values.html#org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper.DEFAULT_OFFSET_UPDATE_SIZE_THRESHOLD">Constant Field Values</a></li>
+</ul>
+</dd>
+</dl>
+</section>
+</li>
</ul>
</section>
</li>
@@ -362,7 +484,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="<init>(org.apache.hadoop.conf.Configuration,java.lang.String,org.apache.hadoop.hbase.replication.regionserver.ReplicationSource,org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceWALReader)">
<h3>ReplicationSourceShipper</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-78">ReplicationSourceShipper</a></span><wbr><span class="parameters">(org.apache.hadoop.conf.Configuration conf,
+<div class="member-signature"><span class="modifiers">public</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-90">ReplicationSourceShipper</a></span><wbr><span class="parameters">(org.apache.hadoop.conf.Configuration conf,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> walGroupId,
<a href="ReplicationSource.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSource</a> source,
<a href="ReplicationSourceWALReader.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceWALReader</a> walReader)</span></div>
@@ -379,7 +501,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="run()">
<h3>run</h3>
-<div class="member-signature"><span class="modifiers">public final</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-95">run</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public final</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-111">run</a></span>()</div>
<dl class="notes">
<dt>Specified by:</dt>
<dd><code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Runnable.html#run()" title="class or interface in java.lang" class="external-link">run</a></code> in interface <code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Runnable.html" title="class or interface in java.lang" class="external-link">Runnable</a></code></dd>
@@ -391,27 +513,54 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="noMoreData()">
<h3>noMoreData</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-136">noMoreData</a></span>()</div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-181">noMoreData</a></span>()
+ throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
+<dl class="notes">
+<dt>Throws:</dt>
+<dd><code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></code></dd>
+</dl>
</section>
</li>
<li>
<section class="detail" id="postFinish()">
<h3>postFinish</h3>
-<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-148">postFinish</a></span>()</div>
+<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-198">postFinish</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="shipEdits(org.apache.hadoop.hbase.replication.regionserver.WALEntryBatch)">
<h3>shipEdits</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-154">shipEdits</a></span><wbr><span class="parameters">(<a href="WALEntryBatch.html" title="class in org.apache.hadoop.hbase.replication.regionserver">WALEntryBatch</a> entryBatch)</span></div>
+<div class="member-signature"><span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-204">shipEdits</a></span><wbr><span class="parameters">(<a href="WALEntryBatch.html" title="class in org.apache.hadoop.hbase.replication.regionserver">WALEntryBatch</a> entryBatch)</span>
+ throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
<div class="block">Do the shipping logic</div>
+<dl class="notes">
+<dt>Throws:</dt>
+<dd><code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></code></dd>
+</dl>
+</section>
+</li>
+<li>
+<section class="detail" id="shouldPersistLogPosition()">
+<h3>shouldPersistLogPosition</h3>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-290">shouldPersistLogPosition</a></span>()</div>
+</section>
+</li>
+<li>
+<section class="detail" id="persistLogPosition()">
+<h3>persistLogPosition</h3>
+<div class="member-signature"><span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-303">persistLogPosition</a></span>()
+ throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
+<dl class="notes">
+<dt>Throws:</dt>
+<dd><code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></code></dd>
+</dl>
</section>
</li>
<li>
<section class="detail" id="cleanUpHFileRefs(org.apache.hadoop.hbase.wal.WALEdit)">
<h3>cleanUpHFileRefs</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-232">cleanUpHFileRefs</a></span><wbr><span class="parameters">(<a href="../../wal/WALEdit.html" title="class in org.apache.hadoop.hbase.wal">WALEdit</a> edit)</span>
- throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
+<div class="member-signature"><span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-325">cleanUpHFileRefs</a></span><wbr><span class="parameters">(<a href="../../wal/WALEdit.html" title="class in org.apache.hadoop.hbase.wal">WALEdit</a> edit)</span>
+ throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
<dl class="notes">
<dt>Throws:</dt>
<dd><code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></code></dd>
@@ -421,55 +570,55 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="updateLogPosition(org.apache.hadoop.hbase.replication.regionserver.WALEntryBatch)">
<h3>updateLogPosition</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-256">updateLogPosition</a></span><wbr><span class="parameters">(<a href="WALEntryBatch.html" title="class in org.apache.hadoop.hbase.replication.regionserver">WALEntryBatch</a> batch)</span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-349">updateLogPosition</a></span><wbr><span class="parameters">(<a href="WALEntryBatch.html" title="class in org.apache.hadoop.hbase.replication.regionserver">WALEntryBatch</a> batch)</span></div>
</section>
</li>
<li>
<section class="detail" id="startup(java.lang.Thread.UncaughtExceptionHandler)">
<h3>startup</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-282">startup</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Thread.UncaughtExceptionHandler.html" title="class or interface in java.lang" class="external-l [...]
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-375">startup</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Thread.UncaughtExceptionHandler.html" title="class or interface in java.lang" class="external-l [...]
</section>
</li>
<li>
<section class="detail" id="getCurrentPath()">
<h3>getCurrentPath</h3>
-<div class="member-signature"><span class="return-type">org.apache.hadoop.fs.Path</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-289">getCurrentPath</a></span>()</div>
+<div class="member-signature"><span class="return-type">org.apache.hadoop.fs.Path</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-382">getCurrentPath</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="getCurrentPosition()">
<h3>getCurrentPosition</h3>
-<div class="member-signature"><span class="return-type">long</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-293">getCurrentPosition</a></span>()</div>
+<div class="member-signature"><span class="return-type">long</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-386">getCurrentPosition</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="isActive()">
<h3>isActive</h3>
-<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-297">isActive</a></span>()</div>
+<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-390">isActive</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="setWorkerState(org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper.WorkerState)">
<h3>setWorkerState</h3>
-<div class="member-signature"><span class="modifiers">protected final</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-301">setWorkerState</a></span><wbr><span class="parameters">(<a href="ReplicationSourceShipper.WorkerState.html" title="enum class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper.WorkerState [...]
+<div class="member-signature"><span class="modifiers">protected final</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-394">setWorkerState</a></span><wbr><span class="parameters">(<a href="ReplicationSourceShipper.WorkerState.html" title="enum class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper.WorkerState [...]
</section>
</li>
<li>
<section class="detail" id="stopWorker()">
<h3>stopWorker</h3>
-<div class="member-signature"><span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-305">stopWorker</a></span>()</div>
+<div class="member-signature"><span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-398">stopWorker</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="isFinished()">
<h3>isFinished</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-309">isFinished</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-402">isFinished</a></span>()</div>
</section>
</li>
<li>
<section class="detail" id="clearWALEntryBatch()">
<h3>clearWALEntryBatch</h3>
-<div class="member-signature"><span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-326">clearWALEntryBatch</a></span>()</div>
+<div class="member-signature"><span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-419">clearWALEntryBatch</a></span>()</div>
<div class="block">Attempts to properly update <code>ReplicationSourceManager.totalBufferUser</code>, in case
there were unprocessed entries batched by the reader to the shipper, but the shipper didn't
manage to ship those because the replication source is being terminated. In that case, it
@@ -486,7 +635,13 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="getSleepForRetries()">
<h3>getSleepForRetries</h3>
-<div class="member-signature"><span class="return-type">long</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-359">getSleepForRetries</a></span>()</div>
+<div class="member-signature"><span class="return-type">long</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-452">getSleepForRetries</a></span>()</div>
+</section>
+</li>
+<li>
+<section class="detail" id="abortAndRestart(java.lang.Throwable)">
+<h3>abortAndRestart</h3>
+<div class="member-signature"><span class="return-type">void</span> <span class="element-name"><a href="../../../../../../src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html#line-457">abortAndRestart</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Throwable.html" title="class or interface in java.lang" class="external-link">Throwable</a> cause)</span></div>
</section>
</li>
</ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/class-use/ReplicationSourceShipper.html b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/class-use/ReplicationSourceShipper.html
index b10b3d7e721..3359a705717 100644
--- a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/class-use/ReplicationSourceShipper.html
+++ b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/class-use/ReplicationSourceShipper.html
@@ -104,9 +104,13 @@ loadScripts(document, 'script');</script>
<div class="col-first even-row-color"><code>(package private) void</code></div>
<div class="col-second even-row-color"><span class="type-name-label">ReplicationSource.</span><code><a href="../ReplicationSource.html#removeWorker(org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper)" class="member-name-link">removeWorker</a><wbr>(<a href="../ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a> worker)</code></div>
<div class="col-last even-row-color"> </div>
-<div class="col-first odd-row-color"><code>protected final void</code></div>
-<div class="col-second odd-row-color"><span class="type-name-label">ReplicationSource.</span><code><a href="../ReplicationSource.html#startShipper(org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper)" class="member-name-link">startShipper</a><wbr>(<a href="../ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a> worker)</code></div>
+<div class="col-first odd-row-color"><code>(package private) void</code></div>
+<div class="col-second odd-row-color"><span class="type-name-label">ReplicationSource.</span><code><a href="../ReplicationSource.html#restartShipper(java.lang.String,org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper)" class="member-name-link">restartShipper</a><wbr>(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> walGroupId,
+ <a href="../ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a> oldWorker)</code></div>
<div class="col-last odd-row-color"> </div>
+<div class="col-first even-row-color"><code>protected final void</code></div>
+<div class="col-second even-row-color"><span class="type-name-label">ReplicationSource.</span><code><a href="../ReplicationSource.html#startShipper(org.apache.hadoop.hbase.replication.regionserver.ReplicationSourceShipper)" class="member-name-link">startShipper</a><wbr>(<a href="../ReplicationSourceShipper.html" title="class in org.apache.hadoop.hbase.replication.regionserver">ReplicationSourceShipper</a> worker)</code></div>
+<div class="col-last even-row-color"> </div>
</div>
</section>
</li>
diff --git a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/class-use/WALEntryBatch.html b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/class-use/WALEntryBatch.html
index 209a8b29678..db75e6dad03 100644
--- a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/class-use/WALEntryBatch.html
+++ b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/class-use/WALEntryBatch.html
@@ -68,9 +68,12 @@ loadScripts(document, 'script');</script>
<div class="table-header col-first">Modifier and Type</div>
<div class="table-header col-second">Field</div>
<div class="table-header col-last">Description</div>
-<div class="col-first even-row-color"><code>static final <a href="../WALEntryBatch.html" title="class in org.apache.hadoop.hbase.replication.regionserver">WALEntryBatch</a></code></div>
-<div class="col-second even-row-color"><span class="type-name-label">WALEntryBatch.</span><code><a href="../WALEntryBatch.html#NO_MORE_DATA" class="member-name-link">NO_MORE_DATA</a></code></div>
+<div class="col-first even-row-color"><code>private <a href="../WALEntryBatch.html" title="class in org.apache.hadoop.hbase.replication.regionserver">WALEntryBatch</a></code></div>
+<div class="col-second even-row-color"><span class="type-name-label">ReplicationSourceShipper.</span><code><a href="../ReplicationSourceShipper.html#lastShippedBatch" class="member-name-link">lastShippedBatch</a></code></div>
<div class="col-last even-row-color"> </div>
+<div class="col-first odd-row-color"><code>static final <a href="../WALEntryBatch.html" title="class in org.apache.hadoop.hbase.replication.regionserver">WALEntryBatch</a></code></div>
+<div class="col-second odd-row-color"><span class="type-name-label">WALEntryBatch.</span><code><a href="../WALEntryBatch.html#NO_MORE_DATA" class="member-name-link">NO_MORE_DATA</a></code></div>
+<div class="col-last odd-row-color"> </div>
</div>
<div class="caption"><span>Fields in <a href="../package-summary.html">org.apache.hadoop.hbase.replication.regionserver</a> with type parameters of type <a href="../WALEntryBatch.html" title="class in org.apache.hadoop.hbase.replication.regionserver">WALEntryBatch</a></span></div>
<div class="summary-table three-column-summary">
@@ -147,7 +150,7 @@ loadScripts(document, 'script');</script>
<a href="../WALEntryStream.html" title="class in org.apache.hadoop.hbase.replication.regionserver">WALEntryStream</a> entryStream,
<a href="../WALEntryBatch.html" title="class in org.apache.hadoop.hbase.replication.regionserver">WALEntryBatch</a> batch)</code></div>
<div class="col-last odd-row-color"> </div>
-<div class="col-first even-row-color"><code>private void</code></div>
+<div class="col-first even-row-color"><code>(package private) void</code></div>
<div class="col-second even-row-color"><span class="type-name-label">ReplicationSourceShipper.</span><code><a href="../ReplicationSourceShipper.html#shipEdits(org.apache.hadoop.hbase.replication.regionserver.WALEntryBatch)" class="member-name-link">shipEdits</a><wbr>(<a href="../WALEntryBatch.html" title="class in org.apache.hadoop.hbase.replication.regionserver">WALEntryBatch</a> entryBatch)</code></div>
<div class="col-last even-row-color">
<div class="block">Do the shipping logic</div>
diff --git a/devapidocs/org/apache/hadoop/hbase/security/visibility/VisibilityReplicationEndpoint.html b/devapidocs/org/apache/hadoop/hbase/security/visibility/VisibilityReplicationEndpoint.html
index 922444a7690..7285429ae56 100644
--- a/devapidocs/org/apache/hadoop/hbase/security/visibility/VisibilityReplicationEndpoint.html
+++ b/devapidocs/org/apache/hadoop/hbase/security/visibility/VisibilityReplicationEndpoint.html
@@ -229,6 +229,9 @@ implements <a href="../../replication/ReplicationEndpoint.html" title="interface
<div class="inherited-list">
<h3 id="methods-inherited-from-class-java.lang.Object">Methods inherited from class java.lang.<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html" title="class or interface in java.lang" class="external-link">Object</a></h3>
<code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#clone()" title="class or interface in java.lang" class="external-link">clone</a>, <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#equals(java.lang.Object)" title="class or interface in java.lang" class="external-link">equals</a>, <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html#finalize()" title="class or [...]
+<div class="inherited-list">
+<h3 id="methods-inherited-from-class-org.apache.hadoop.hbase.replication.ReplicationEndpoint">Methods inherited from interface org.apache.hadoop.hbase.replication.<a href="../../replication/ReplicationEndpoint.html" title="interface in org.apache.hadoop.hbase.replication">ReplicationEndpoint</a></h3>
+<code><a href="../../replication/ReplicationEndpoint.html#beforePersistingReplicationOffset()">beforePersistingReplicationOffset</a></code></div>
</section>
</li>
</ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html b/devapidocs/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html
index e56bd2a4edf..72dd6d0246b 100644
--- a/devapidocs/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html
+++ b/devapidocs/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html
@@ -77,7 +77,7 @@ loadScripts(document, 'script');</script>
<dd><a href="SnapshotInfo.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotInfo</a></dd>
</dl>
<hr>
-<div class="type-signature"><span class="modifiers">static final class </span><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-74">SnapshotInfo.Options</a></span>
+<div class="type-signature"><span class="modifiers">static final class </span><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-80">SnapshotInfo.Options</a></span>
<span class="extends-implements">extends <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html" title="class or interface in java.lang" class="external-link">Object</a></span></div>
</section>
<section class="summary">
@@ -149,43 +149,43 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="SNAPSHOT">
<h3>SNAPSHOT</h3>
-<div class="member-signature"><span class="modifiers">static final</span> <span class="return-type">org.apache.hbase.thirdparty.org.apache.commons.cli.Option</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html#line-75">SNAPSHOT</a></span></div>
+<div class="member-signature"><span class="modifiers">static final</span> <span class="return-type">org.apache.hbase.thirdparty.org.apache.commons.cli.Option</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html#line-81">SNAPSHOT</a></span></div>
</section>
</li>
<li>
<section class="detail" id="REMOTE_DIR">
<h3>REMOTE_DIR</h3>
-<div class="member-signature"><span class="modifiers">static final</span> <span class="return-type">org.apache.hbase.thirdparty.org.apache.commons.cli.Option</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html#line-77">REMOTE_DIR</a></span></div>
+<div class="member-signature"><span class="modifiers">static final</span> <span class="return-type">org.apache.hbase.thirdparty.org.apache.commons.cli.Option</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html#line-83">REMOTE_DIR</a></span></div>
</section>
</li>
<li>
<section class="detail" id="LIST_SNAPSHOTS">
<h3>LIST_SNAPSHOTS</h3>
-<div class="member-signature"><span class="modifiers">static final</span> <span class="return-type">org.apache.hbase.thirdparty.org.apache.commons.cli.Option</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html#line-80">LIST_SNAPSHOTS</a></span></div>
+<div class="member-signature"><span class="modifiers">static final</span> <span class="return-type">org.apache.hbase.thirdparty.org.apache.commons.cli.Option</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html#line-86">LIST_SNAPSHOTS</a></span></div>
</section>
</li>
<li>
<section class="detail" id="FILES">
<h3>FILES</h3>
-<div class="member-signature"><span class="modifiers">static final</span> <span class="return-type">org.apache.hbase.thirdparty.org.apache.commons.cli.Option</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html#line-82">FILES</a></span></div>
+<div class="member-signature"><span class="modifiers">static final</span> <span class="return-type">org.apache.hbase.thirdparty.org.apache.commons.cli.Option</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html#line-88">FILES</a></span></div>
</section>
</li>
<li>
<section class="detail" id="STATS">
<h3>STATS</h3>
-<div class="member-signature"><span class="modifiers">static final</span> <span class="return-type">org.apache.hbase.thirdparty.org.apache.commons.cli.Option</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html#line-85">STATS</a></span></div>
+<div class="member-signature"><span class="modifiers">static final</span> <span class="return-type">org.apache.hbase.thirdparty.org.apache.commons.cli.Option</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html#line-91">STATS</a></span></div>
</section>
</li>
<li>
<section class="detail" id="SCHEMA">
<h3>SCHEMA</h3>
-<div class="member-signature"><span class="modifiers">static final</span> <span class="return-type">org.apache.hbase.thirdparty.org.apache.commons.cli.Option</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html#line-88">SCHEMA</a></span></div>
+<div class="member-signature"><span class="modifiers">static final</span> <span class="return-type">org.apache.hbase.thirdparty.org.apache.commons.cli.Option</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html#line-94">SCHEMA</a></span></div>
</section>
</li>
<li>
<section class="detail" id="SIZE_IN_BYTES">
<h3>SIZE_IN_BYTES</h3>
-<div class="member-signature"><span class="modifiers">static final</span> <span class="return-type">org.apache.hbase.thirdparty.org.apache.commons.cli.Option</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html#line-91">SIZE_IN_BYTES</a></span></div>
+<div class="member-signature"><span class="modifiers">static final</span> <span class="return-type">org.apache.hbase.thirdparty.org.apache.commons.cli.Option</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html#line-97">SIZE_IN_BYTES</a></span></div>
</section>
</li>
</ul>
@@ -199,7 +199,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="<init>()">
<h3>Options</h3>
-<div class="member-signature"><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html#line-74">Options</a></span>()</div>
+<div class="member-signature"><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html#line-80">Options</a></span>()</div>
</section>
</li>
</ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html b/devapidocs/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html
index c22099ba5cf..935f58c4e58 100644
--- a/devapidocs/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html
+++ b/devapidocs/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html
@@ -81,7 +81,7 @@ loadScripts(document, 'script');</script>
<dd><a href="SnapshotInfo.SnapshotStats.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotInfo.SnapshotStats</a></dd>
</dl>
<hr>
-<div class="type-signature"><span class="modifiers">static class </span><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-106">SnapshotInfo.SnapshotStats.FileInfo</a></span>
+<div class="type-signature"><span class="modifiers">static class </span><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-112">SnapshotInfo.SnapshotStats.FileInfo</a></span>
<span class="extends-implements">extends <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html" title="class or interface in java.lang" class="external-link">Object</a></span></div>
<div class="block">Information about the file referenced by the snapshot</div>
</section>
@@ -177,19 +177,19 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="corrupted">
<h3>corrupted</h3>
-<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-107">corrupted</a></span></div>
+<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-113">corrupted</a></span></div>
</section>
</li>
<li>
<section class="detail" id="inArchive">
<h3>inArchive</h3>
-<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-108">inArchive</a></span></div>
+<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-114">inArchive</a></span></div>
</section>
</li>
<li>
<section class="detail" id="size">
<h3>size</h3>
-<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-109">size</a></span></div>
+<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-115">size</a></span></div>
</section>
</li>
</ul>
@@ -203,7 +203,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="<init>(boolean,long,boolean)">
<h3>FileInfo</h3>
-<div class="member-signature"><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-111">FileInfo</a></span><wbr><span class="parameters">(boolean inArchive,
+<div class="member-signature"><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-117">FileInfo</a></span><wbr><span class="parameters">(boolean inArchive,
long size,
boolean corrupted)</span></div>
</section>
@@ -219,35 +219,35 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="inArchive()">
<h3>inArchive</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-118">inArchive</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-124">inArchive</a></span>()</div>
<div class="block">Returns true if the file is in the archive</div>
</section>
</li>
<li>
<section class="detail" id="isCorrupted()">
<h3>isCorrupted</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-123">isCorrupted</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-129">isCorrupted</a></span>()</div>
<div class="block">Returns true if the file is corrupted</div>
</section>
</li>
<li>
<section class="detail" id="isMissing()">
<h3>isMissing</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-128">isMissing</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-134">isMissing</a></span>()</div>
<div class="block">Returns true if the file is missing</div>
</section>
</li>
<li>
<section class="detail" id="getSize()">
<h3>getSize</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-133">getSize</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-139">getSize</a></span>()</div>
<div class="block">Returns the file size</div>
</section>
</li>
<li>
<section class="detail" id="getStateToString()">
<h3>getStateToString</h3>
-<div class="member-signature"><span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-137">getStateToString</a></span>()</div>
+<div class="member-signature"><span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html#line-143">getStateToString</a></span>()</div>
</section>
</li>
</ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html b/devapidocs/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html
index 330943e04e9..58be6119762 100644
--- a/devapidocs/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html
+++ b/devapidocs/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html
@@ -81,7 +81,7 @@ loadScripts(document, 'script');</script>
<dd><a href="SnapshotInfo.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotInfo</a></dd>
</dl>
<hr>
-<div class="type-signature"><span class="modifiers">public static class </span><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-104">SnapshotInfo.SnapshotStats</a></span>
+<div class="type-signature"><span class="modifiers">public static class </span><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-110">SnapshotInfo.SnapshotStats</a></span>
<span class="extends-implements">extends <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html" title="class or interface in java.lang" class="external-link">Object</a></span></div>
<div class="block">Statistics about the snapshot
<ol>
@@ -322,97 +322,97 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="hfilesArchiveCount">
<h3>hfilesArchiveCount</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-145">hfilesArchiveCount</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-151">hfilesArchiveCount</a></span></div>
</section>
</li>
<li>
<section class="detail" id="hfilesCorrupted">
<h3>hfilesCorrupted</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-146">hfilesCorrupted</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-152">hfilesCorrupted</a></span></div>
</section>
</li>
<li>
<section class="detail" id="hfilesMissing">
<h3>hfilesMissing</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-147">hfilesMissing</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-153">hfilesMissing</a></span></div>
</section>
</li>
<li>
<section class="detail" id="hfilesCount">
<h3>hfilesCount</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-148">hfilesCount</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-154">hfilesCount</a></span></div>
</section>
</li>
<li>
<section class="detail" id="hfilesMobCount">
<h3>hfilesMobCount</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-149">hfilesMobCount</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-155">hfilesMobCount</a></span></div>
</section>
</li>
<li>
<section class="detail" id="logsMissing">
<h3>logsMissing</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-150">logsMissing</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-156">logsMissing</a></span></div>
</section>
</li>
<li>
<section class="detail" id="logsCount">
<h3>logsCount</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-151">logsCount</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-157">logsCount</a></span></div>
</section>
</li>
<li>
<section class="detail" id="hfilesArchiveSize">
<h3>hfilesArchiveSize</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicLong</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-152">hfilesArchiveSize</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicLong</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-158">hfilesArchiveSize</a></span></div>
</section>
</li>
<li>
<section class="detail" id="hfilesSize">
<h3>hfilesSize</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicLong</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-153">hfilesSize</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicLong</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-159">hfilesSize</a></span></div>
</section>
</li>
<li>
<section class="detail" id="hfilesMobSize">
<h3>hfilesMobSize</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicLong</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-154">hfilesMobSize</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicLong</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-160">hfilesMobSize</a></span></div>
</section>
</li>
<li>
<section class="detail" id="nonSharedHfilesArchiveSize">
<h3>nonSharedHfilesArchiveSize</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicLong</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-155">nonSharedHfilesArchiveSize</a></spa [...]
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicLong</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-161">nonSharedHfilesArchiveSize</a></spa [...]
</section>
</li>
<li>
<section class="detail" id="logSize">
<h3>logSize</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicLong</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-156">logSize</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicLong</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-162">logSize</a></span></div>
</section>
</li>
<li>
<section class="detail" id="snapshot">
<h3>snapshot</h3>
-<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type">org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-158">snapshot</a></span></div>
+<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type">org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-164">snapshot</a></span></div>
</section>
</li>
<li>
<section class="detail" id="snapshotTable">
<h3>snapshotTable</h3>
-<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type"><a href="../TableName.html" title="class in org.apache.hadoop.hbase">TableName</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-159">snapshotTable</a></span></div>
+<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type"><a href="../TableName.html" title="class in org.apache.hadoop.hbase">TableName</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-165">snapshotTable</a></span></div>
</section>
</li>
<li>
<section class="detail" id="conf">
<h3>conf</h3>
-<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type">org.apache.hadoop.conf.Configuration</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-160">conf</a></span></div>
+<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type">org.apache.hadoop.conf.Configuration</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-166">conf</a></span></div>
</section>
</li>
<li>
<section class="detail" id="fs">
<h3>fs</h3>
-<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type">org.apache.hadoop.fs.FileSystem</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-161">fs</a></span></div>
+<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type">org.apache.hadoop.fs.FileSystem</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-167">fs</a></span></div>
</section>
</li>
</ul>
@@ -426,7 +426,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="<init>(org.apache.hadoop.conf.Configuration,org.apache.hadoop.fs.FileSystem,org.apache.hadoop.hbase.client.SnapshotDescription)">
<h3>SnapshotStats</h3>
-<div class="member-signature"><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-163">SnapshotStats</a></span><wbr><span class="parameters">(org.apache.hadoop.conf.Configuration conf,
+<div class="member-signature"><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-169">SnapshotStats</a></span><wbr><span class="parameters">(org.apache.hadoop.conf.Configuration conf,
org.apache.hadoop.fs.FileSystem fs,
<a href="../client/SnapshotDescription.html" title="class in org.apache.hadoop.hbase.client">SnapshotDescription</a> snapshot)</span></div>
</section>
@@ -434,7 +434,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="<init>(org.apache.hadoop.conf.Configuration,org.apache.hadoop.fs.FileSystem,org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription)">
<h3>SnapshotStats</h3>
-<div class="member-signature"><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-171">SnapshotStats</a></span><wbr><span class="parameters">(org.apache.hadoop.conf.Configuration conf,
+<div class="member-signature"><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-177">SnapshotStats</a></span><wbr><span class="parameters">(org.apache.hadoop.conf.Configuration conf,
org.apache.hadoop.fs.FileSystem fs,
org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription snapshot)</span></div>
</section>
@@ -450,98 +450,98 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="getSnapshotDescription()">
<h3>getSnapshotDescription</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="../client/SnapshotDescription.html" title="class in org.apache.hadoop.hbase.client">SnapshotDescription</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-180">getSnapshotDescription</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type"><a href="../client/SnapshotDescription.html" title="class in org.apache.hadoop.hbase.client">SnapshotDescription</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-186">getSnapshotDescription</a></span>()</div>
<div class="block">Returns the snapshot descriptor</div>
</section>
</li>
<li>
<section class="detail" id="isSnapshotCorrupted()">
<h3>isSnapshotCorrupted</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-185">isSnapshotCorrupted</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-191">isSnapshotCorrupted</a></span>()</div>
<div class="block">Returns true if the snapshot is corrupted</div>
</section>
</li>
<li>
<section class="detail" id="getStoreFilesCount()">
<h3>getStoreFilesCount</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-190">getStoreFilesCount</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-196">getStoreFilesCount</a></span>()</div>
<div class="block">Returns the number of available store files</div>
</section>
</li>
<li>
<section class="detail" id="getArchivedStoreFilesCount()">
<h3>getArchivedStoreFilesCount</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-195">getArchivedStoreFilesCount</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-201">getArchivedStoreFilesCount</a></span>()</div>
<div class="block">Returns the number of available store files in the archive</div>
</section>
</li>
<li>
<section class="detail" id="getMobStoreFilesCount()">
<h3>getMobStoreFilesCount</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-200">getMobStoreFilesCount</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-206">getMobStoreFilesCount</a></span>()</div>
<div class="block">Returns the number of available store files in the mob dir</div>
</section>
</li>
<li>
<section class="detail" id="getLogsCount()">
<h3>getLogsCount</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-205">getLogsCount</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-211">getLogsCount</a></span>()</div>
<div class="block">Returns the number of available log files</div>
</section>
</li>
<li>
<section class="detail" id="getMissingStoreFilesCount()">
<h3>getMissingStoreFilesCount</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-210">getMissingStoreFilesCount</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-216">getMissingStoreFilesCount</a></span>()</div>
<div class="block">Returns the number of missing store files</div>
</section>
</li>
<li>
<section class="detail" id="getCorruptedStoreFilesCount()">
<h3>getCorruptedStoreFilesCount</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-215">getCorruptedStoreFilesCount</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-221">getCorruptedStoreFilesCount</a></span>()</div>
<div class="block">Returns the number of corrupted store files</div>
</section>
</li>
<li>
<section class="detail" id="getMissingLogsCount()">
<h3>getMissingLogsCount</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-220">getMissingLogsCount</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-226">getMissingLogsCount</a></span>()</div>
<div class="block">Returns the number of missing log files</div>
</section>
</li>
<li>
<section class="detail" id="getStoreFilesSize()">
<h3>getStoreFilesSize</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-225">getStoreFilesSize</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-231">getStoreFilesSize</a></span>()</div>
<div class="block">Returns the total size of the store files referenced by the snapshot</div>
</section>
</li>
<li>
<section class="detail" id="getSharedStoreFilesSize()">
<h3>getSharedStoreFilesSize</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-230">getSharedStoreFilesSize</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-236">getSharedStoreFilesSize</a></span>()</div>
<div class="block">Returns the total size of the store files shared</div>
</section>
</li>
<li>
<section class="detail" id="getArchivedStoreFileSize()">
<h3>getArchivedStoreFileSize</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-235">getArchivedStoreFileSize</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-241">getArchivedStoreFileSize</a></span>()</div>
<div class="block">Returns the total size of the store files in the archive</div>
</section>
</li>
<li>
<section class="detail" id="getMobStoreFilesSize()">
<h3>getMobStoreFilesSize</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-240">getMobStoreFilesSize</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-246">getMobStoreFilesSize</a></span>()</div>
<div class="block">Returns the total size of the store files in the mob store</div>
</section>
</li>
<li>
<section class="detail" id="getNonSharedArchivedStoreFilesSize()">
<h3>getNonSharedArchivedStoreFilesSize</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-250">getNonSharedArchivedStoreFilesSize</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-256">getNonSharedArchivedStoreFilesSize</a></span>()</div>
<dl class="notes">
<dt>Returns:</dt>
<dd>the total size of the store files in the archive which is not shared with other
@@ -554,28 +554,28 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="getSharedStoreFilePercentage()">
<h3>getSharedStoreFilePercentage</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">float</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-255">getSharedStoreFilePercentage</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">float</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-261">getSharedStoreFilePercentage</a></span>()</div>
<div class="block">Returns the percentage of the shared store files</div>
</section>
</li>
<li>
<section class="detail" id="getMobStoreFilePercentage()">
<h3>getMobStoreFilePercentage</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">float</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-262">getMobStoreFilePercentage</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">float</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-268">getMobStoreFilePercentage</a></span>()</div>
<div class="block">Returns the percentage of the mob store files</div>
</section>
</li>
<li>
<section class="detail" id="getLogsSize()">
<h3>getLogsSize</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-269">getLogsSize</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">long</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-275">getLogsSize</a></span>()</div>
<div class="block">Returns the total log size</div>
</section>
</li>
<li>
<section class="detail" id="isArchivedFileStillReferenced(org.apache.hadoop.fs.Path,java.util.Map)">
<h3>isArchivedFileStillReferenced</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-280">isArchivedFileStillReferenced</a></span><wbr><span class="parameters">(org.apache.hadoop.fs.Path filePath,
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-286">isArchivedFileStillReferenced</a></span><wbr><span class="parameters">(org.apache.hadoop.fs.Path filePath,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html" title="class or interface in java.util" class="external-link">Map</a><org.apache.hadoop.fs.Path,<wbr><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html" title="class or interface in java.lang" class="external-link">Integer</a>> snapshotFilesMap)</span></div>
<div class="block">Check if for a give file in archive, if there are other snapshots/tables still reference it.</div>
<dl class="notes">
@@ -591,7 +591,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="addStoreFile(org.apache.hadoop.hbase.client.RegionInfo,java.lang.String,org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest.StoreFile,java.util.Map)">
<h3>addStoreFile</h3>
-<div class="member-signature"><span class="return-type"><a href="SnapshotInfo.SnapshotStats.FileInfo.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotInfo.SnapshotStats.FileInfo</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-310">addStoreFile</a></span><wbr><span class="parameters">(<a href="../client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">Region [...]
+<div class="member-signature"><span class="return-type"><a href="SnapshotInfo.SnapshotStats.FileInfo.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotInfo.SnapshotStats.FileInfo</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-316">addStoreFile</a></span><wbr><span class="parameters">(<a href="../client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">Region [...]
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> family,
org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest.StoreFile storeFile,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html" title="class or interface in java.util" class="external-link">Map</a><org.apache.hadoop.fs.Path,<wbr><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html" title="class or interface in java.lang" class="external-link">Integer</a>> filesMap)</span>
@@ -613,7 +613,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="addLogFile(java.lang.String,java.lang.String)">
<h3>addLogFile</h3>
-<div class="member-signature"><span class="return-type"><a href="SnapshotInfo.SnapshotStats.FileInfo.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotInfo.SnapshotStats.FileInfo</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-356">addLogFile</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" tit [...]
+<div class="member-signature"><span class="return-type"><a href="SnapshotInfo.SnapshotStats.FileInfo.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotInfo.SnapshotStats.FileInfo</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html#line-362">addLogFile</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" tit [...]
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> logfile)</span>
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
<div class="block">Add the specified log file to the stats</div>
diff --git a/devapidocs/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html b/devapidocs/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html
index 9093ded7dba..1e90a057b1f 100644
--- a/devapidocs/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html
+++ b/devapidocs/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html
@@ -84,7 +84,7 @@ loadScripts(document, 'script');</script>
</dl>
<hr>
<div class="type-signature"><span class="annotations">@Public
-</span><span class="modifiers">public final class </span><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-70">SnapshotInfo</a></span>
+</span><span class="modifiers">public final class </span><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-72">SnapshotInfo</a></span>
<span class="extends-implements">extends <a href="../util/AbstractHBaseTool.html" title="class in org.apache.hadoop.hbase.util">AbstractHBaseTool</a></span></div>
<div class="block">Tool for dumping snapshot information.
<ol>
@@ -133,14 +133,20 @@ loadScripts(document, 'script');</script>
<div class="table-header col-first">Modifier and Type</div>
<div class="table-header col-second">Field</div>
<div class="table-header col-last">Description</div>
-<div class="col-first even-row-color"><code>private org.apache.hadoop.fs.FileSystem</code></div>
-<div class="col-second even-row-color"><code><a href="#fs" class="member-name-link">fs</a></code></div>
+<div class="col-first even-row-color"><code>private static final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></code></div>
+<div class="col-second even-row-color"><code><a href="#EXPIRED_LABEL" class="member-name-link">EXPIRED_LABEL</a></code></div>
<div class="col-last even-row-color"> </div>
-<div class="col-first odd-row-color"><code>private boolean</code></div>
-<div class="col-second odd-row-color"><code><a href="#listSnapshots" class="member-name-link">listSnapshots</a></code></div>
+<div class="col-first odd-row-color"><code>private org.apache.hadoop.fs.FileSystem</code></div>
+<div class="col-second odd-row-color"><code><a href="#fs" class="member-name-link">fs</a></code></div>
+<div class="col-last odd-row-color"> </div>
+<div class="col-first even-row-color"><code>private boolean</code></div>
+<div class="col-second even-row-color"><code><a href="#listSnapshots" class="member-name-link">listSnapshots</a></code></div>
+<div class="col-last even-row-color"> </div>
+<div class="col-first odd-row-color"><code>private static final org.slf4j.Logger</code></div>
+<div class="col-second odd-row-color"><code><a href="#LOG" class="member-name-link">LOG</a></code></div>
<div class="col-last odd-row-color"> </div>
-<div class="col-first even-row-color"><code>private static final org.slf4j.Logger</code></div>
-<div class="col-second even-row-color"><code><a href="#LOG" class="member-name-link">LOG</a></code></div>
+<div class="col-first even-row-color"><code>private static final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></code></div>
+<div class="col-second even-row-color"><code><a href="#NOT_EXPIRED_LABEL" class="member-name-link">NOT_EXPIRED_LABEL</a></code></div>
<div class="col-last even-row-color"> </div>
<div class="col-first odd-row-color"><code>private boolean</code></div>
<div class="col-second odd-row-color"><code><a href="#printSizeInBytes" class="member-name-link">printSizeInBytes</a></code></div>
@@ -166,6 +172,9 @@ loadScripts(document, 'script');</script>
<div class="col-first even-row-color"><code>private <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></code></div>
<div class="col-second even-row-color"><code><a href="#snapshotName" class="member-name-link">snapshotName</a></code></div>
<div class="col-last even-row-color"> </div>
+<div class="col-first odd-row-color"><code>private static final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></code></div>
+<div class="col-second odd-row-color"><code><a href="#TTL_FOREVER" class="member-name-link">TTL_FOREVER</a></code></div>
+<div class="col-last odd-row-color"> </div>
</div>
<div class="inherited-list">
<h3 id="fields-inherited-from-class-org.apache.hadoop.hbase.util.AbstractHBaseTool">Fields inherited from class org.apache.hadoop.hbase.util.<a href="../util/AbstractHBaseTool.html" title="class in org.apache.hadoop.hbase.util">AbstractHBaseTool</a></h3>
@@ -307,67 +316,109 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="LOG">
<h3>LOG</h3>
-<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type">org.slf4j.Logger</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-72">LOG</a></span></div>
+<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type">org.slf4j.Logger</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-74">LOG</a></span></div>
+</section>
+</li>
+<li>
+<section class="detail" id="EXPIRED_LABEL">
+<h3>EXPIRED_LABEL</h3>
+<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-76">EXPIRED_LABEL</a></span></div>
+<dl class="notes">
+<dt>See Also:</dt>
+<dd>
+<ul class="see-list">
+<li><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.snapshot.SnapshotInfo.EXPIRED_LABEL">Constant Field Values</a></li>
+</ul>
+</dd>
+</dl>
+</section>
+</li>
+<li>
+<section class="detail" id="NOT_EXPIRED_LABEL">
+<h3>NOT_EXPIRED_LABEL</h3>
+<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-77">NOT_EXPIRED_LABEL</a></span></div>
+<dl class="notes">
+<dt>See Also:</dt>
+<dd>
+<ul class="see-list">
+<li><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.snapshot.SnapshotInfo.NOT_EXPIRED_LABEL">Constant Field Values</a></li>
+</ul>
+</dd>
+</dl>
+</section>
+</li>
+<li>
+<section class="detail" id="TTL_FOREVER">
+<h3>TTL_FOREVER</h3>
+<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-78">TTL_FOREVER</a></span></div>
+<dl class="notes">
+<dt>See Also:</dt>
+<dd>
+<ul class="see-list">
+<li><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.snapshot.SnapshotInfo.TTL_FOREVER">Constant Field Values</a></li>
+</ul>
+</dd>
+</dl>
</section>
</li>
<li>
<section class="detail" id="fs">
<h3>fs</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">org.apache.hadoop.fs.FileSystem</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-370">fs</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">org.apache.hadoop.fs.FileSystem</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-376">fs</a></span></div>
</section>
</li>
<li>
<section class="detail" id="rootDir">
<h3>rootDir</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">org.apache.hadoop.fs.Path</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-371">rootDir</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">org.apache.hadoop.fs.Path</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-377">rootDir</a></span></div>
</section>
</li>
<li>
<section class="detail" id="snapshotManifest">
<h3>snapshotManifest</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="SnapshotManifest.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotManifest</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-373">snapshotManifest</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="SnapshotManifest.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotManifest</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-379">snapshotManifest</a></span></div>
</section>
</li>
<li>
<section class="detail" id="listSnapshots">
<h3>listSnapshots</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-375">listSnapshots</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-381">listSnapshots</a></span></div>
</section>
</li>
<li>
<section class="detail" id="snapshotName">
<h3>snapshotName</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-376">snapshotName</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-382">snapshotName</a></span></div>
</section>
</li>
<li>
<section class="detail" id="remoteDir">
<h3>remoteDir</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">org.apache.hadoop.fs.Path</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-377">remoteDir</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">org.apache.hadoop.fs.Path</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-383">remoteDir</a></span></div>
</section>
</li>
<li>
<section class="detail" id="showSchema">
<h3>showSchema</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-378">showSchema</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-384">showSchema</a></span></div>
</section>
</li>
<li>
<section class="detail" id="showFiles">
<h3>showFiles</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-379">showFiles</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-385">showFiles</a></span></div>
</section>
</li>
<li>
<section class="detail" id="showStats">
<h3>showStats</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-380">showStats</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-386">showStats</a></span></div>
</section>
</li>
<li>
<section class="detail" id="printSizeInBytes">
<h3>printSizeInBytes</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-381">printSizeInBytes</a></span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-387">printSizeInBytes</a></span></div>
</section>
</li>
</ul>
@@ -381,7 +432,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="<init>()">
<h3>SnapshotInfo</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-71">SnapshotInfo</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-73">SnapshotInfo</a></span>()</div>
</section>
</li>
</ul>
@@ -395,7 +446,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="doWork()">
<h3>doWork</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-383">doWork</a></span>()
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-389">doWork</a></span>()
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a>,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/InterruptedException.html" title="class or interface in java.lang" class="external-link">InterruptedException</a></span></div>
<div class="block"><span class="descfrm-type-label">Description copied from class: <code><a href="../util/AbstractHBaseTool.html#doWork()">AbstractHBaseTool</a></code></span></div>
@@ -412,7 +463,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="loadSnapshotInfo(java.lang.String)">
<h3>loadSnapshotInfo</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-427">loadSnapshotInfo</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> snapshotName)</span>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-440">loadSnapshotInfo</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a> snapshotName)</span>
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
<div class="block">Load snapshot info and table descriptor for the specified snapshot</div>
<dl class="notes">
@@ -428,21 +479,21 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="printInfo()">
<h3>printInfo</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-443">printInfo</a></span>()</div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-456">printInfo</a></span>()</div>
<div class="block">Dump the <a href="../client/SnapshotDescription.html" title="class in org.apache.hadoop.hbase.client"><code>SnapshotDescription</code></a></div>
</section>
</li>
<li>
<section class="detail" id="printSchema()">
<h3>printSchema</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-461">printSchema</a></span>()</div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-482">printSchema</a></span>()</div>
<div class="block">Dump the <a href="../client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client"><code>TableDescriptor</code></a></div>
</section>
</li>
<li>
<section class="detail" id="printFiles(boolean,boolean)">
<h3>printFiles</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-472">printFiles</a></span><wbr><span class="parameters">(boolean showFiles,
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-493">printFiles</a></span><wbr><span class="parameters">(boolean showFiles,
boolean showStats)</span>
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
<div class="block">Collect the hfiles and logs statistics of the snapshot and dump the file list if requested and
@@ -456,13 +507,13 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="fileSizeToString(long)">
<h3>fileSizeToString</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-527">fileSizeToString</a></span><wbr><span class="parameters">(long size)</span></div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-548">fileSizeToString</a></span><wbr><span class="parameters">(long size)</span></div>
</section>
</li>
<li>
<section class="detail" id="addOptions()">
<h3>addOptions</h3>
-<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-531">addOptions</a></span>()</div>
+<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-552">addOptions</a></span>()</div>
<div class="block"><span class="descfrm-type-label">Description copied from class: <code><a href="../util/AbstractHBaseTool.html#addOptions()">AbstractHBaseTool</a></code></span></div>
<div class="block">Override this to add command-line options using <a href="../util/AbstractHBaseTool.html#addOptWithArg(java.lang.String,java.lang.String)"><code>AbstractHBaseTool.addOptWithArg(java.lang.String, java.lang.String)</code></a> and similar methods.</div>
<dl class="notes">
@@ -474,7 +525,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="newParser()">
<h3>newParser</h3>
-<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type">org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLineParser</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-542">newParser</a></span>()</div>
+<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type">org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLineParser</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-563">newParser</a></span>()</div>
<div class="block"><span class="descfrm-type-label">Description copied from class: <code><a href="../util/AbstractHBaseTool.html#newParser()">AbstractHBaseTool</a></code></span></div>
<div class="block">Create the parser to use for parsing and validating the command line. Since commons-cli lacks
the capability to validate arbitrary combination of options, it may be helpful to bake custom
@@ -490,7 +541,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="processOptions(org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine)">
<h3>processOptions</h3>
-<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-559">processOptions</a></span><wbr><span class="parameters">(org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine cmd)</span></div>
+<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-580">processOptions</a></span><wbr><span class="parameters">(org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine cmd)</span></div>
<div class="block"><span class="descfrm-type-label">Description copied from class: <code><a href="../util/AbstractHBaseTool.html#processOptions(org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine)">AbstractHBaseTool</a></code></span></div>
<div class="block">This method is called to process the options after they have been parsed.</div>
<dl class="notes">
@@ -502,7 +553,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="printUsage()">
<h3>printUsage</h3>
-<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-573">printUsage</a></span>()</div>
+<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-594">printUsage</a></span>()</div>
<dl class="notes">
<dt>Overrides:</dt>
<dd><code><a href="../util/AbstractHBaseTool.html#printUsage()">printUsage</a></code> in class <code><a href="../util/AbstractHBaseTool.html" title="class in org.apache.hadoop.hbase.util">AbstractHBaseTool</a></code></dd>
@@ -512,7 +563,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="getSnapshotStats(org.apache.hadoop.conf.Configuration,org.apache.hadoop.hbase.client.SnapshotDescription)">
<h3>getSnapshotStats</h3>
-<div class="member-signature"><span class="modifiers">public static</span> <span class="return-type"><a href="SnapshotInfo.SnapshotStats.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotInfo.SnapshotStats</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-586">getSnapshotStats</a></span><wbr><span class="parameters">(org.apache.hadoop.conf.Configuration conf,
+<div class="member-signature"><span class="modifiers">public static</span> <span class="return-type"><a href="SnapshotInfo.SnapshotStats.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotInfo.SnapshotStats</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-607">getSnapshotStats</a></span><wbr><span class="parameters">(org.apache.hadoop.conf.Configuration conf,
<a href="../client/SnapshotDescription.html" title="class in org.apache.hadoop.hbase.client">SnapshotDescription</a> snapshot)</span>
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
<div class="block">Returns the snapshot stats</div>
@@ -530,7 +581,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="getSnapshotStats(org.apache.hadoop.conf.Configuration,org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription,java.util.Map)">
<h3>getSnapshotStats</h3>
-<div class="member-signature"><span class="modifiers">public static</span> <span class="return-type"><a href="SnapshotInfo.SnapshotStats.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotInfo.SnapshotStats</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-600">getSnapshotStats</a></span><wbr><span class="parameters">(org.apache.hadoop.conf.Configuration conf,
+<div class="member-signature"><span class="modifiers">public static</span> <span class="return-type"><a href="SnapshotInfo.SnapshotStats.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotInfo.SnapshotStats</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-621">getSnapshotStats</a></span><wbr><span class="parameters">(org.apache.hadoop.conf.Configuration conf,
org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription snapshotDesc,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html" title="class or interface in java.util" class="external-link">Map</a><org.apache.hadoop.fs.Path,<wbr><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html" title="class or interface in java.lang" class="external-link">Integer</a>> filesMap)</span>
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
@@ -550,7 +601,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="getSnapshotList(org.apache.hadoop.conf.Configuration)">
<h3>getSnapshotList</h3>
-<div class="member-signature"><span class="modifiers">public static</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/List.html" title="class or interface in java.util" class="external-link">List</a><<a href="../client/SnapshotDescription.html" title="class in org.apache.hadoop.hbase.client">SnapshotDescription</a>></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snap [...]
+<div class="member-signature"><span class="modifiers">public static</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/List.html" title="class or interface in java.util" class="external-link">List</a><<a href="../client/SnapshotDescription.html" title="class in org.apache.hadoop.hbase.client">SnapshotDescription</a>></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snap [...]
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
<div class="block">Returns the list of available snapshots in the specified location</div>
<dl class="notes">
@@ -566,7 +617,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="getSnapshotFilesMap(org.apache.hadoop.conf.Configuration,org.apache.hadoop.hbase.client.SnapshotDescription,java.util.concurrent.ExecutorService,java.util.concurrent.ConcurrentHashMap,java.util.concurrent.atomic.AtomicLong,java.util.concurrent.atomic.AtomicLong,java.util.concurrent.atomic.AtomicLong)">
<h3>getSnapshotFilesMap</h3>
-<div class="member-signature"><span class="modifiers">private static</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-655">getSnapshotFilesMap</a></span><wbr><span class="parameters">(org.apache.hadoop.conf.Configuration conf,
+<div class="member-signature"><span class="modifiers">private static</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-676">getSnapshotFilesMap</a></span><wbr><span class="parameters">(org.apache.hadoop.conf.Configuration conf,
<a href="../client/SnapshotDescription.html" title="class in org.apache.hadoop.hbase.client">SnapshotDescription</a> snapshot,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/ExecutorService.html" title="class or interface in java.util.concurrent" class="external-link">ExecutorService</a> exec,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/ConcurrentHashMap.html" title="class or interface in java.util.concurrent" class="external-link">ConcurrentHashMap</a><org.apache.hadoop.fs.Path,<wbr><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html" title="class or interface in java.lang" class="external-link">Integer</a>> filesMap,
@@ -592,7 +643,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="getSnapshotsFilesMap(org.apache.hadoop.conf.Configuration,java.util.concurrent.atomic.AtomicLong,java.util.concurrent.atomic.AtomicLong,java.util.concurrent.atomic.AtomicLong)">
<h3>getSnapshotsFilesMap</h3>
-<div class="member-signature"><span class="modifiers">public static</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html" title="class or interface in java.util" class="external-link">Map</a><org.apache.hadoop.fs.Path,<wbr><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html" title="class or interface in java.lang" class="external-link">Integer</a>></span> <span cl [...]
+<div class="member-signature"><span class="modifiers">public static</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html" title="class or interface in java.util" class="external-link">Map</a><org.apache.hadoop.fs.Path,<wbr><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html" title="class or interface in java.lang" class="external-link">Integer</a>></span> <span cl [...]
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicLong</a> uniqueHFilesArchiveSize,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicLong</a> uniqueHFilesSize,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicLong.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicLong</a> uniqueHFilesMobSize)</span>
@@ -614,7 +665,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="main(java.lang.String[])">
<h3>main</h3>
-<div class="member-signature"><span class="modifiers">public static</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-741">main</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a>[] args)</span></div>
+<div class="member-signature"><span class="modifiers">public static</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.html#line-762">main</a></span><wbr><span class="parameters">(<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a>[] args)</span></div>
</section>
</li>
</ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/wal/class-use/WALEdit.html b/devapidocs/org/apache/hadoop/hbase/wal/class-use/WALEdit.html
index 0d013d4611d..f3eaa9807d1 100644
--- a/devapidocs/org/apache/hadoop/hbase/wal/class-use/WALEdit.html
+++ b/devapidocs/org/apache/hadoop/hbase/wal/class-use/WALEdit.html
@@ -692,7 +692,7 @@ Input/OutputFormats, a table indexing MapReduce job, and utility methods.</div>
<div class="table-header col-first">Modifier and Type</div>
<div class="table-header col-second">Method</div>
<div class="table-header col-last">Description</div>
-<div class="col-first even-row-color"><code>private void</code></div>
+<div class="col-first even-row-color"><code>(package private) void</code></div>
<div class="col-second even-row-color"><span class="type-name-label">ReplicationSourceShipper.</span><code><a href="../../replication/regionserver/ReplicationSourceShipper.html#cleanUpHFileRefs(org.apache.hadoop.hbase.wal.WALEdit)" class="member-name-link">cleanUpHFileRefs</a><wbr>(<a href="../WALEdit.html" title="class in org.apache.hadoop.hbase.wal">WALEdit</a> edit)</code></div>
<div class="col-last even-row-color"> </div>
<div class="col-first odd-row-color"><code>private <a href="../../util/Pair.html" title="class in org.apache.hadoop.hbase.util">Pair</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html" title="class or interface in java.lang" class="external-link">Integer</a>,<wbr><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Integer.html" title="class or interface in java.lang" class="external-link">Integer</a>></code></div>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.Context.html b/devapidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.Context.html
index 4cc0b718ec2..ea6d1c4fbdd 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.Context.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.Context.html
@@ -296,7 +296,14 @@
<span class="source-line-no">283</span><span id="line-283"> * @throws IllegalStateException if this service's state isn't FAILED.</span>
<span class="source-line-no">284</span><span id="line-284"> */</span>
<span class="source-line-no">285</span><span id="line-285"> Throwable failureCause();</span>
-<span class="source-line-no">286</span><span id="line-286">}</span>
+<span class="source-line-no">286</span><span id="line-286"></span>
+<span class="source-line-no">287</span><span id="line-287"> /**</span>
+<span class="source-line-no">288</span><span id="line-288"> * Hook invoked before persisting replication offsets. Eg: Buffered endpoints can flush/close WALs</span>
+<span class="source-line-no">289</span><span id="line-289"> * here.</span>
+<span class="source-line-no">290</span><span id="line-290"> */</span>
+<span class="source-line-no">291</span><span id="line-291"> default void beforePersistingReplicationOffset() throws IOException {</span>
+<span class="source-line-no">292</span><span id="line-292"> }</span>
+<span class="source-line-no">293</span><span id="line-293">}</span>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.ReplicateContext.html b/devapidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.ReplicateContext.html
index e2835872952..c1ce59df9ef 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.ReplicateContext.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.ReplicateContext.html
@@ -296,7 +296,14 @@
<span class="source-line-no">283</span><span id="line-283"> * @throws IllegalStateException if this service's state isn't FAILED.</span>
<span class="source-line-no">284</span><span id="line-284"> */</span>
<span class="source-line-no">285</span><span id="line-285"> Throwable failureCause();</span>
-<span class="source-line-no">286</span><span id="line-286">}</span>
+<span class="source-line-no">286</span><span id="line-286"></span>
+<span class="source-line-no">287</span><span id="line-287"> /**</span>
+<span class="source-line-no">288</span><span id="line-288"> * Hook invoked before persisting replication offsets. Eg: Buffered endpoints can flush/close WALs</span>
+<span class="source-line-no">289</span><span id="line-289"> * here.</span>
+<span class="source-line-no">290</span><span id="line-290"> */</span>
+<span class="source-line-no">291</span><span id="line-291"> default void beforePersistingReplicationOffset() throws IOException {</span>
+<span class="source-line-no">292</span><span id="line-292"> }</span>
+<span class="source-line-no">293</span><span id="line-293">}</span>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.html b/devapidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.html
index 962ebe7fc25..35301e30ed6 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/replication/ReplicationEndpoint.html
@@ -296,7 +296,14 @@
<span class="source-line-no">283</span><span id="line-283"> * @throws IllegalStateException if this service's state isn't FAILED.</span>
<span class="source-line-no">284</span><span id="line-284"> */</span>
<span class="source-line-no">285</span><span id="line-285"> Throwable failureCause();</span>
-<span class="source-line-no">286</span><span id="line-286">}</span>
+<span class="source-line-no">286</span><span id="line-286"></span>
+<span class="source-line-no">287</span><span id="line-287"> /**</span>
+<span class="source-line-no">288</span><span id="line-288"> * Hook invoked before persisting replication offsets. Eg: Buffered endpoints can flush/close WALs</span>
+<span class="source-line-no">289</span><span id="line-289"> * here.</span>
+<span class="source-line-no">290</span><span id="line-290"> */</span>
+<span class="source-line-no">291</span><span id="line-291"> default void beforePersistingReplicationOffset() throws IOException {</span>
+<span class="source-line-no">292</span><span id="line-292"> }</span>
+<span class="source-line-no">293</span><span id="line-293">}</span>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSource.html b/devapidocs/src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSource.html
index a70f52ab434..9348d64caea 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSource.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSource.html
@@ -879,7 +879,19 @@
<span class="source-line-no">866</span><span id="line-866"> long getSleepForRetries() {</span>
<span class="source-line-no">867</span><span id="line-867"> return sleepForRetries;</span>
<span class="source-line-no">868</span><span id="line-868"> }</span>
-<span class="source-line-no">869</span><span id="line-869">}</span>
+<span class="source-line-no">869</span><span id="line-869"></span>
+<span class="source-line-no">870</span><span id="line-870"> void restartShipper(String walGroupId, ReplicationSourceShipper oldWorker) {</span>
+<span class="source-line-no">871</span><span id="line-871"> boolean removed = workerThreads.remove(walGroupId, oldWorker);</span>
+<span class="source-line-no">872</span><span id="line-872"> if (!removed) {</span>
+<span class="source-line-no">873</span><span id="line-873"> // Worker was already replaced (e.g. concurrent restart)</span>
+<span class="source-line-no">874</span><span id="line-874"> LOG.debug("Skip restart for walGroupId={} as worker already replaced", walGroupId);</span>
+<span class="source-line-no">875</span><span id="line-875"> return;</span>
+<span class="source-line-no">876</span><span id="line-876"> }</span>
+<span class="source-line-no">877</span><span id="line-877"></span>
+<span class="source-line-no">878</span><span id="line-878"> tryStartNewShipper(walGroupId);</span>
+<span class="source-line-no">879</span><span id="line-879"> }</span>
+<span class="source-line-no">880</span><span id="line-880"></span>
+<span class="source-line-no">881</span><span id="line-881">}</span>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.WorkerState.html b/devapidocs/src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.WorkerState.html
index ee6cfcb8b2b..5adb2f37b0a 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.WorkerState.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.WorkerState.html
@@ -87,292 +87,397 @@
<span class="source-line-no">074</span><span id="line-74"> private final int DEFAULT_TIMEOUT = 20000;</span>
<span class="source-line-no">075</span><span id="line-75"> private final int getEntriesTimeout;</span>
<span class="source-line-no">076</span><span id="line-76"> private final int shipEditsTimeout;</span>
-<span class="source-line-no">077</span><span id="line-77"></span>
-<span class="source-line-no">078</span><span id="line-78"> public ReplicationSourceShipper(Configuration conf, String walGroupId, ReplicationSource source,</span>
-<span class="source-line-no">079</span><span id="line-79"> ReplicationSourceWALReader walReader) {</span>
-<span class="source-line-no">080</span><span id="line-80"> this.conf = conf;</span>
-<span class="source-line-no">081</span><span id="line-81"> this.walGroupId = walGroupId;</span>
-<span class="source-line-no">082</span><span id="line-82"> this.source = source;</span>
-<span class="source-line-no">083</span><span id="line-83"> this.entryReader = walReader;</span>
-<span class="source-line-no">084</span><span id="line-84"> // 1 second</span>
-<span class="source-line-no">085</span><span id="line-85"> this.sleepForRetries = this.conf.getLong("replication.source.sleepforretries", 1000);</span>
-<span class="source-line-no">086</span><span id="line-86"> // 5 minutes @ 1 sec per</span>
-<span class="source-line-no">087</span><span id="line-87"> this.maxRetriesMultiplier = this.conf.getInt("replication.source.maxretriesmultiplier", 300);</span>
-<span class="source-line-no">088</span><span id="line-88"> // 20 seconds</span>
-<span class="source-line-no">089</span><span id="line-89"> this.getEntriesTimeout =</span>
-<span class="source-line-no">090</span><span id="line-90"> this.conf.getInt("replication.source.getEntries.timeout", DEFAULT_TIMEOUT);</span>
-<span class="source-line-no">091</span><span id="line-91"> this.shipEditsTimeout = this.conf.getInt(HConstants.REPLICATION_SOURCE_SHIPEDITS_TIMEOUT,</span>
-<span class="source-line-no">092</span><span id="line-92"> HConstants.REPLICATION_SOURCE_SHIPEDITS_TIMEOUT_DFAULT);</span>
-<span class="source-line-no">093</span><span id="line-93"> }</span>
-<span class="source-line-no">094</span><span id="line-94"></span>
-<span class="source-line-no">095</span><span id="line-95"> @Override</span>
-<span class="source-line-no">096</span><span id="line-96"> public final void run() {</span>
-<span class="source-line-no">097</span><span id="line-97"> setWorkerState(WorkerState.RUNNING);</span>
-<span class="source-line-no">098</span><span id="line-98"> LOG.info("Running ReplicationSourceShipper Thread for wal group: {}", this.walGroupId);</span>
-<span class="source-line-no">099</span><span id="line-99"> // Loop until we close down</span>
-<span class="source-line-no">100</span><span id="line-100"> while (isActive()) {</span>
-<span class="source-line-no">101</span><span id="line-101"> // Sleep until replication is enabled again</span>
-<span class="source-line-no">102</span><span id="line-102"> if (!source.isPeerEnabled()) {</span>
-<span class="source-line-no">103</span><span id="line-103"> // The peer enabled check is in memory, not expensive, so do not need to increase the</span>
-<span class="source-line-no">104</span><span id="line-104"> // sleep interval as it may cause a long lag when we enable the peer.</span>
-<span class="source-line-no">105</span><span id="line-105"> sleepForRetries("Replication is disabled", sleepForRetries, 1, maxRetriesMultiplier);</span>
-<span class="source-line-no">106</span><span id="line-106"> continue;</span>
-<span class="source-line-no">107</span><span id="line-107"> }</span>
-<span class="source-line-no">108</span><span id="line-108"> try {</span>
-<span class="source-line-no">109</span><span id="line-109"> WALEntryBatch entryBatch = entryReader.poll(getEntriesTimeout);</span>
-<span class="source-line-no">110</span><span id="line-110"> LOG.debug("Shipper from source {} got entry batch from reader: {}", source.getQueueId(),</span>
-<span class="source-line-no">111</span><span id="line-111"> entryBatch);</span>
-<span class="source-line-no">112</span><span id="line-112"> if (entryBatch == null) {</span>
-<span class="source-line-no">113</span><span id="line-113"> continue;</span>
-<span class="source-line-no">114</span><span id="line-114"> }</span>
-<span class="source-line-no">115</span><span id="line-115"> // the NO_MORE_DATA instance has no path so do not call shipEdits</span>
-<span class="source-line-no">116</span><span id="line-116"> if (entryBatch == WALEntryBatch.NO_MORE_DATA) {</span>
-<span class="source-line-no">117</span><span id="line-117"> noMoreData();</span>
-<span class="source-line-no">118</span><span id="line-118"> } else {</span>
-<span class="source-line-no">119</span><span id="line-119"> shipEdits(entryBatch);</span>
-<span class="source-line-no">120</span><span id="line-120"> }</span>
-<span class="source-line-no">121</span><span id="line-121"> } catch (InterruptedException | ReplicationRuntimeException e) {</span>
-<span class="source-line-no">122</span><span id="line-122"> // It is interrupted and needs to quit.</span>
-<span class="source-line-no">123</span><span id="line-123"> LOG.warn("Interrupted while waiting for next replication entry batch", e);</span>
-<span class="source-line-no">124</span><span id="line-124"> Thread.currentThread().interrupt();</span>
-<span class="source-line-no">125</span><span id="line-125"> }</span>
-<span class="source-line-no">126</span><span id="line-126"> }</span>
-<span class="source-line-no">127</span><span id="line-127"> // If the worker exits run loop without finishing its task, mark it as stopped.</span>
-<span class="source-line-no">128</span><span id="line-128"> if (!isFinished()) {</span>
-<span class="source-line-no">129</span><span id="line-129"> setWorkerState(WorkerState.STOPPED);</span>
-<span class="source-line-no">130</span><span id="line-130"> } else {</span>
-<span class="source-line-no">131</span><span id="line-131"> source.removeWorker(this);</span>
-<span class="source-line-no">132</span><span id="line-132"> postFinish();</span>
-<span class="source-line-no">133</span><span id="line-133"> }</span>
-<span class="source-line-no">134</span><span id="line-134"> }</span>
-<span class="source-line-no">135</span><span id="line-135"></span>
-<span class="source-line-no">136</span><span id="line-136"> private void noMoreData() {</span>
-<span class="source-line-no">137</span><span id="line-137"> if (source.isRecovered()) {</span>
-<span class="source-line-no">138</span><span id="line-138"> LOG.debug("Finished recovering queue for group {} of peer {}", walGroupId,</span>
-<span class="source-line-no">139</span><span id="line-139"> source.getQueueId());</span>
-<span class="source-line-no">140</span><span id="line-140"> source.getSourceMetrics().incrCompletedRecoveryQueue();</span>
-<span class="source-line-no">141</span><span id="line-141"> } else {</span>
-<span class="source-line-no">142</span><span id="line-142"> LOG.debug("Finished queue for group {} of peer {}", walGroupId, source.getQueueId());</span>
-<span class="source-line-no">143</span><span id="line-143"> }</span>
-<span class="source-line-no">144</span><span id="line-144"> setWorkerState(WorkerState.FINISHED);</span>
-<span class="source-line-no">145</span><span id="line-145"> }</span>
-<span class="source-line-no">146</span><span id="line-146"></span>
-<span class="source-line-no">147</span><span id="line-147"> // To be implemented by recovered shipper</span>
-<span class="source-line-no">148</span><span id="line-148"> protected void postFinish() {</span>
-<span class="source-line-no">149</span><span id="line-149"> }</span>
-<span class="source-line-no">150</span><span id="line-150"></span>
-<span class="source-line-no">151</span><span id="line-151"> /**</span>
-<span class="source-line-no">152</span><span id="line-152"> * Do the shipping logic</span>
-<span class="source-line-no">153</span><span id="line-153"> */</span>
-<span class="source-line-no">154</span><span id="line-154"> private void shipEdits(WALEntryBatch entryBatch) {</span>
-<span class="source-line-no">155</span><span id="line-155"> List<Entry> entries = entryBatch.getWalEntries();</span>
-<span class="source-line-no">156</span><span id="line-156"> int sleepMultiplier = 0;</span>
-<span class="source-line-no">157</span><span id="line-157"> if (entries.isEmpty()) {</span>
-<span class="source-line-no">158</span><span id="line-158"> updateLogPosition(entryBatch);</span>
-<span class="source-line-no">159</span><span id="line-159"> return;</span>
-<span class="source-line-no">160</span><span id="line-160"> }</span>
-<span class="source-line-no">161</span><span id="line-161"> int currentSize = (int) entryBatch.getHeapSize();</span>
-<span class="source-line-no">162</span><span id="line-162"> source.getSourceMetrics()</span>
-<span class="source-line-no">163</span><span id="line-163"> .setTimeStampNextToReplicate(entries.get(entries.size() - 1).getKey().getWriteTime());</span>
-<span class="source-line-no">164</span><span id="line-164"> while (isActive()) {</span>
-<span class="source-line-no">165</span><span id="line-165"> try {</span>
-<span class="source-line-no">166</span><span id="line-166"> try {</span>
-<span class="source-line-no">167</span><span id="line-167"> source.tryThrottle(currentSize);</span>
-<span class="source-line-no">168</span><span id="line-168"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">169</span><span id="line-169"> LOG.debug("Interrupted while sleeping for throttling control");</span>
-<span class="source-line-no">170</span><span id="line-170"> Thread.currentThread().interrupt();</span>
-<span class="source-line-no">171</span><span id="line-171"> // current thread might be interrupted to terminate</span>
-<span class="source-line-no">172</span><span id="line-172"> // directly go back to while() for confirm this</span>
-<span class="source-line-no">173</span><span id="line-173"> continue;</span>
-<span class="source-line-no">174</span><span id="line-174"> }</span>
-<span class="source-line-no">175</span><span id="line-175"> // create replicateContext here, so the entries can be GC'd upon return from this call</span>
-<span class="source-line-no">176</span><span id="line-176"> // stack</span>
-<span class="source-line-no">177</span><span id="line-177"> ReplicationEndpoint.ReplicateContext replicateContext =</span>
-<span class="source-line-no">178</span><span id="line-178"> new ReplicationEndpoint.ReplicateContext();</span>
-<span class="source-line-no">179</span><span id="line-179"> replicateContext.setEntries(entries).setSize(currentSize);</span>
-<span class="source-line-no">180</span><span id="line-180"> replicateContext.setWalGroupId(walGroupId);</span>
-<span class="source-line-no">181</span><span id="line-181"> replicateContext.setTimeout(getAdaptiveTimeout(this.shipEditsTimeout, sleepMultiplier));</span>
-<span class="source-line-no">182</span><span id="line-182"></span>
-<span class="source-line-no">183</span><span id="line-183"> long startTimeNs = System.nanoTime();</span>
-<span class="source-line-no">184</span><span id="line-184"> // send the edits to the endpoint. Will block until the edits are shipped and acknowledged</span>
-<span class="source-line-no">185</span><span id="line-185"> boolean replicated = source.getReplicationEndpoint().replicate(replicateContext);</span>
-<span class="source-line-no">186</span><span id="line-186"> long endTimeNs = System.nanoTime();</span>
-<span class="source-line-no">187</span><span id="line-187"></span>
-<span class="source-line-no">188</span><span id="line-188"> if (!replicated) {</span>
-<span class="source-line-no">189</span><span id="line-189"> continue;</span>
-<span class="source-line-no">190</span><span id="line-190"> } else {</span>
-<span class="source-line-no">191</span><span id="line-191"> sleepMultiplier = Math.max(sleepMultiplier - 1, 0);</span>
-<span class="source-line-no">192</span><span id="line-192"> }</span>
-<span class="source-line-no">193</span><span id="line-193"> // Clean up hfile references</span>
-<span class="source-line-no">194</span><span id="line-194"> for (Entry entry : entries) {</span>
-<span class="source-line-no">195</span><span id="line-195"> cleanUpHFileRefs(entry.getEdit());</span>
-<span class="source-line-no">196</span><span id="line-196"> LOG.trace("shipped entry {}: ", entry);</span>
-<span class="source-line-no">197</span><span id="line-197"> }</span>
-<span class="source-line-no">198</span><span id="line-198"> // Log and clean up WAL logs</span>
-<span class="source-line-no">199</span><span id="line-199"> updateLogPosition(entryBatch);</span>
+<span class="source-line-no">077</span><span id="line-77"> private long accumulatedSizeSinceLastUpdate = 0L;</span>
+<span class="source-line-no">078</span><span id="line-78"> private long lastOffsetUpdateTime = EnvironmentEdgeManager.currentTime();</span>
+<span class="source-line-no">079</span><span id="line-79"> private final long offsetUpdateIntervalMs;</span>
+<span class="source-line-no">080</span><span id="line-80"> private final long offsetUpdateSizeThresholdBytes;</span>
+<span class="source-line-no">081</span><span id="line-81"> private WALEntryBatch lastShippedBatch;</span>
+<span class="source-line-no">082</span><span id="line-82"></span>
+<span class="source-line-no">083</span><span id="line-83"> private static final String OFFSET_UPDATE_INTERVAL_MS_KEY =</span>
+<span class="source-line-no">084</span><span id="line-84"> "hbase.replication.shipper.offset.update.interval.ms";</span>
+<span class="source-line-no">085</span><span id="line-85"> private static final String OFFSET_UPDATE_SIZE_THRESHOLD_KEY =</span>
+<span class="source-line-no">086</span><span id="line-86"> "hbase.replication.shipper.offset.update.size.threshold";</span>
+<span class="source-line-no">087</span><span id="line-87"> private static final long DEFAULT_OFFSET_UPDATE_INTERVAL_MS = Long.MAX_VALUE;</span>
+<span class="source-line-no">088</span><span id="line-88"> private static final long DEFAULT_OFFSET_UPDATE_SIZE_THRESHOLD = -1L;</span>
+<span class="source-line-no">089</span><span id="line-89"></span>
+<span class="source-line-no">090</span><span id="line-90"> public ReplicationSourceShipper(Configuration conf, String walGroupId, ReplicationSource source,</span>
+<span class="source-line-no">091</span><span id="line-91"> ReplicationSourceWALReader walReader) {</span>
+<span class="source-line-no">092</span><span id="line-92"> this.conf = conf;</span>
+<span class="source-line-no">093</span><span id="line-93"> this.walGroupId = walGroupId;</span>
+<span class="source-line-no">094</span><span id="line-94"> this.source = source;</span>
+<span class="source-line-no">095</span><span id="line-95"> this.entryReader = walReader;</span>
+<span class="source-line-no">096</span><span id="line-96"> // 1 second</span>
+<span class="source-line-no">097</span><span id="line-97"> this.sleepForRetries = this.conf.getLong("replication.source.sleepforretries", 1000);</span>
+<span class="source-line-no">098</span><span id="line-98"> // 5 minutes @ 1 sec per</span>
+<span class="source-line-no">099</span><span id="line-99"> this.maxRetriesMultiplier = this.conf.getInt("replication.source.maxretriesmultiplier", 300);</span>
+<span class="source-line-no">100</span><span id="line-100"> // 20 seconds</span>
+<span class="source-line-no">101</span><span id="line-101"> this.getEntriesTimeout =</span>
+<span class="source-line-no">102</span><span id="line-102"> this.conf.getInt("replication.source.getEntries.timeout", DEFAULT_TIMEOUT);</span>
+<span class="source-line-no">103</span><span id="line-103"> this.shipEditsTimeout = this.conf.getInt(HConstants.REPLICATION_SOURCE_SHIPEDITS_TIMEOUT,</span>
+<span class="source-line-no">104</span><span id="line-104"> HConstants.REPLICATION_SOURCE_SHIPEDITS_TIMEOUT_DFAULT);</span>
+<span class="source-line-no">105</span><span id="line-105"> this.offsetUpdateIntervalMs =</span>
+<span class="source-line-no">106</span><span id="line-106"> conf.getLong(OFFSET_UPDATE_INTERVAL_MS_KEY, DEFAULT_OFFSET_UPDATE_INTERVAL_MS);</span>
+<span class="source-line-no">107</span><span id="line-107"> this.offsetUpdateSizeThresholdBytes =</span>
+<span class="source-line-no">108</span><span id="line-108"> conf.getLong(OFFSET_UPDATE_SIZE_THRESHOLD_KEY, DEFAULT_OFFSET_UPDATE_SIZE_THRESHOLD);</span>
+<span class="source-line-no">109</span><span id="line-109"> }</span>
+<span class="source-line-no">110</span><span id="line-110"></span>
+<span class="source-line-no">111</span><span id="line-111"> @Override</span>
+<span class="source-line-no">112</span><span id="line-112"> public final void run() {</span>
+<span class="source-line-no">113</span><span id="line-113"> setWorkerState(WorkerState.RUNNING);</span>
+<span class="source-line-no">114</span><span id="line-114"> LOG.info("Running ReplicationSourceShipper Thread for wal group: {}", this.walGroupId);</span>
+<span class="source-line-no">115</span><span id="line-115"> // Loop until we close down</span>
+<span class="source-line-no">116</span><span id="line-116"> while (isActive()) {</span>
+<span class="source-line-no">117</span><span id="line-117"> // Sleep until replication is enabled again</span>
+<span class="source-line-no">118</span><span id="line-118"> if (!source.isPeerEnabled()) {</span>
+<span class="source-line-no">119</span><span id="line-119"> // The peer enabled check is in memory, not expensive, so do not need to increase the</span>
+<span class="source-line-no">120</span><span id="line-120"> // sleep interval as it may cause a long lag when we enable the peer.</span>
+<span class="source-line-no">121</span><span id="line-121"> sleepForRetries("Replication is disabled", sleepForRetries, 1, maxRetriesMultiplier);</span>
+<span class="source-line-no">122</span><span id="line-122"> continue;</span>
+<span class="source-line-no">123</span><span id="line-123"> }</span>
+<span class="source-line-no">124</span><span id="line-124"> try {</span>
+<span class="source-line-no">125</span><span id="line-125"> // check time-based offset persistence</span>
+<span class="source-line-no">126</span><span id="line-126"> if (shouldPersistLogPosition()) {</span>
+<span class="source-line-no">127</span><span id="line-127"> persistLogPosition();</span>
+<span class="source-line-no">128</span><span id="line-128"> }</span>
+<span class="source-line-no">129</span><span id="line-129"></span>
+<span class="source-line-no">130</span><span id="line-130"> long pollTimeout = getEntriesTimeout;</span>
+<span class="source-line-no">131</span><span id="line-131"> if (offsetUpdateIntervalMs != Long.MAX_VALUE) {</span>
+<span class="source-line-no">132</span><span id="line-132"> long elapsed = EnvironmentEdgeManager.currentTime() - lastOffsetUpdateTime;</span>
+<span class="source-line-no">133</span><span id="line-133"> long remaining = offsetUpdateIntervalMs - elapsed;</span>
+<span class="source-line-no">134</span><span id="line-134"> if (remaining > 0) {</span>
+<span class="source-line-no">135</span><span id="line-135"> pollTimeout = Math.min(getEntriesTimeout, remaining);</span>
+<span class="source-line-no">136</span><span id="line-136"> }</span>
+<span class="source-line-no">137</span><span id="line-137"> }</span>
+<span class="source-line-no">138</span><span id="line-138"> WALEntryBatch entryBatch = entryReader.poll(pollTimeout);</span>
+<span class="source-line-no">139</span><span id="line-139"> LOG.debug("Shipper from source {} got entry batch from reader: {}", source.getQueueId(),</span>
+<span class="source-line-no">140</span><span id="line-140"> entryBatch);</span>
+<span class="source-line-no">141</span><span id="line-141"></span>
+<span class="source-line-no">142</span><span id="line-142"> if (entryBatch == null) {</span>
+<span class="source-line-no">143</span><span id="line-143"> continue;</span>
+<span class="source-line-no">144</span><span id="line-144"> }</span>
+<span class="source-line-no">145</span><span id="line-145"> // the NO_MORE_DATA instance has no path so do not call shipEdits</span>
+<span class="source-line-no">146</span><span id="line-146"> if (entryBatch == WALEntryBatch.NO_MORE_DATA) {</span>
+<span class="source-line-no">147</span><span id="line-147"> noMoreData();</span>
+<span class="source-line-no">148</span><span id="line-148"> } else {</span>
+<span class="source-line-no">149</span><span id="line-149"> shipEdits(entryBatch);</span>
+<span class="source-line-no">150</span><span id="line-150"> }</span>
+<span class="source-line-no">151</span><span id="line-151"> } catch (InterruptedException | ReplicationRuntimeException e) {</span>
+<span class="source-line-no">152</span><span id="line-152"> LOG.warn("Interrupted while waiting for next replication entry batch", e);</span>
+<span class="source-line-no">153</span><span id="line-153"> Thread.currentThread().interrupt();</span>
+<span class="source-line-no">154</span><span id="line-154"> } catch (Exception e) {</span>
+<span class="source-line-no">155</span><span id="line-155"> // During source shutdown / peer removal we can see interrupted IOEs</span>
+<span class="source-line-no">156</span><span id="line-156"> // from replication queue updates. Do not restart in this case.</span>
+<span class="source-line-no">157</span><span id="line-157"> if (!source.isSourceActive() || isInterrupted() || !source.isPeerEnabled()) {</span>
+<span class="source-line-no">158</span><span id="line-158"> LOG.info("Ignoring persist failure during shutdown for walGroupId={}", walGroupId, e);</span>
+<span class="source-line-no">159</span><span id="line-159"> break;</span>
+<span class="source-line-no">160</span><span id="line-160"> }</span>
+<span class="source-line-no">161</span><span id="line-161"> LOG.error("Shipper {} failed to persist offset, restarting", walGroupId, e);</span>
+<span class="source-line-no">162</span><span id="line-162"> abortAndRestart(e);</span>
+<span class="source-line-no">163</span><span id="line-163"> return;</span>
+<span class="source-line-no">164</span><span id="line-164"> }</span>
+<span class="source-line-no">165</span><span id="line-165"> }</span>
+<span class="source-line-no">166</span><span id="line-166"></span>
+<span class="source-line-no">167</span><span id="line-167"> // If the worker exits run loop without finishing its task, mark it as stopped.</span>
+<span class="source-line-no">168</span><span id="line-168"> if (!isFinished()) {</span>
+<span class="source-line-no">169</span><span id="line-169"> try {</span>
+<span class="source-line-no">170</span><span id="line-170"> persistLogPosition();</span>
+<span class="source-line-no">171</span><span id="line-171"> } catch (Exception e) {</span>
+<span class="source-line-no">172</span><span id="line-172"> LOG.error("Failed persisting final offset for walGroupId={}", walGroupId, e);</span>
+<span class="source-line-no">173</span><span id="line-173"> }</span>
+<span class="source-line-no">174</span><span id="line-174"> setWorkerState(WorkerState.STOPPED);</span>
+<span class="source-line-no">175</span><span id="line-175"> } else {</span>
+<span class="source-line-no">176</span><span id="line-176"> source.removeWorker(this);</span>
+<span class="source-line-no">177</span><span id="line-177"> postFinish();</span>
+<span class="source-line-no">178</span><span id="line-178"> }</span>
+<span class="source-line-no">179</span><span id="line-179"> }</span>
+<span class="source-line-no">180</span><span id="line-180"></span>
+<span class="source-line-no">181</span><span id="line-181"> private void noMoreData() throws IOException {</span>
+<span class="source-line-no">182</span><span id="line-182"> // Flush any outstanding replication offset before marking the queue finished.</span>
+<span class="source-line-no">183</span><span id="line-183"> // Offset persistence may be delayed by size/time thresholds, so ensure the</span>
+<span class="source-line-no">184</span><span id="line-184"> // latest replicated position is stored before transitioning to FINISHED state.</span>
+<span class="source-line-no">185</span><span id="line-185"> persistLogPosition();</span>
+<span class="source-line-no">186</span><span id="line-186"></span>
+<span class="source-line-no">187</span><span id="line-187"> if (source.isRecovered()) {</span>
+<span class="source-line-no">188</span><span id="line-188"> LOG.debug("Finished recovering queue for group {} of peer {}", walGroupId,</span>
+<span class="source-line-no">189</span><span id="line-189"> source.getQueueId());</span>
+<span class="source-line-no">190</span><span id="line-190"> source.getSourceMetrics().incrCompletedRecoveryQueue();</span>
+<span class="source-line-no">191</span><span id="line-191"> } else {</span>
+<span class="source-line-no">192</span><span id="line-192"> LOG.debug("Finished queue for group {} of peer {}", walGroupId, source.getQueueId());</span>
+<span class="source-line-no">193</span><span id="line-193"> }</span>
+<span class="source-line-no">194</span><span id="line-194"> setWorkerState(WorkerState.FINISHED);</span>
+<span class="source-line-no">195</span><span id="line-195"> }</span>
+<span class="source-line-no">196</span><span id="line-196"></span>
+<span class="source-line-no">197</span><span id="line-197"> // To be implemented by recovered shipper</span>
+<span class="source-line-no">198</span><span id="line-198"> protected void postFinish() {</span>
+<span class="source-line-no">199</span><span id="line-199"> }</span>
<span class="source-line-no">200</span><span id="line-200"></span>
-<span class="source-line-no">201</span><span id="line-201"> // offsets totalBufferUsed by deducting shipped batchSize (excludes bulk load size)</span>
-<span class="source-line-no">202</span><span id="line-202"> // this sizeExcludeBulkLoad has to use same calculation that when calling</span>
-<span class="source-line-no">203</span><span id="line-203"> // acquireBufferQuota() in ReplicationSourceWALReader because they maintain</span>
-<span class="source-line-no">204</span><span id="line-204"> // same variable: totalBufferUsed</span>
-<span class="source-line-no">205</span><span id="line-205"> source.postShipEdits(entries, entryBatch.getUsedBufferSize());</span>
-<span class="source-line-no">206</span><span id="line-206"> // FIXME check relationship between wal group and overall</span>
-<span class="source-line-no">207</span><span id="line-207"> source.getSourceMetrics().shipBatch(entryBatch.getNbOperations(), currentSize,</span>
-<span class="source-line-no">208</span><span id="line-208"> entryBatch.getNbHFiles());</span>
-<span class="source-line-no">209</span><span id="line-209"> source.getSourceMetrics().setAgeOfLastShippedOp(</span>
-<span class="source-line-no">210</span><span id="line-210"> entries.get(entries.size() - 1).getKey().getWriteTime(), walGroupId);</span>
-<span class="source-line-no">211</span><span id="line-211"> source.getSourceMetrics().updateTableLevelMetrics(entryBatch.getWalEntriesWithSize());</span>
-<span class="source-line-no">212</span><span id="line-212"></span>
-<span class="source-line-no">213</span><span id="line-213"> if (LOG.isTraceEnabled()) {</span>
-<span class="source-line-no">214</span><span id="line-214"> LOG.debug("Replicated {} entries or {} operations in {} ms", entries.size(),</span>
-<span class="source-line-no">215</span><span id="line-215"> entryBatch.getNbOperations(), (endTimeNs - startTimeNs) / 1000000);</span>
-<span class="source-line-no">216</span><span id="line-216"> }</span>
-<span class="source-line-no">217</span><span id="line-217"> break;</span>
-<span class="source-line-no">218</span><span id="line-218"> } catch (Exception ex) {</span>
-<span class="source-line-no">219</span><span id="line-219"> source.getSourceMetrics().incrementFailedBatches();</span>
-<span class="source-line-no">220</span><span id="line-220"> LOG.warn("{} threw unknown exception:",</span>
-<span class="source-line-no">221</span><span id="line-221"> source.getReplicationEndpoint().getClass().getName(), ex);</span>
-<span class="source-line-no">222</span><span id="line-222"> if (</span>
-<span class="source-line-no">223</span><span id="line-223"> sleepForRetries("ReplicationEndpoint threw exception", sleepForRetries, sleepMultiplier,</span>
-<span class="source-line-no">224</span><span id="line-224"> maxRetriesMultiplier)</span>
-<span class="source-line-no">225</span><span id="line-225"> ) {</span>
-<span class="source-line-no">226</span><span id="line-226"> sleepMultiplier++;</span>
-<span class="source-line-no">227</span><span id="line-227"> }</span>
-<span class="source-line-no">228</span><span id="line-228"> }</span>
-<span class="source-line-no">229</span><span id="line-229"> }</span>
-<span class="source-line-no">230</span><span id="line-230"> }</span>
-<span class="source-line-no">231</span><span id="line-231"></span>
-<span class="source-line-no">232</span><span id="line-232"> private void cleanUpHFileRefs(WALEdit edit) throws IOException {</span>
-<span class="source-line-no">233</span><span id="line-233"> String peerId = source.getPeerId();</span>
-<span class="source-line-no">234</span><span id="line-234"> if (peerId.contains("-")) {</span>
-<span class="source-line-no">235</span><span id="line-235"> // peerClusterZnode will be in the form peerId + "-" + rsZNode.</span>
-<span class="source-line-no">236</span><span id="line-236"> // A peerId will not have "-" in its name, see HBASE-11394</span>
-<span class="source-line-no">237</span><span id="line-237"> peerId = peerId.split("-")[0];</span>
-<span class="source-line-no">238</span><span id="line-238"> }</span>
-<span class="source-line-no">239</span><span id="line-239"> List<Cell> cells = edit.getCells();</span>
-<span class="source-line-no">240</span><span id="line-240"> int totalCells = cells.size();</span>
-<span class="source-line-no">241</span><span id="line-241"> for (int i = 0; i < totalCells; i++) {</span>
-<span class="source-line-no">242</span><span id="line-242"> Cell cell = cells.get(i);</span>
-<span class="source-line-no">243</span><span id="line-243"> if (CellUtil.matchingQualifier(cell, WALEdit.BULK_LOAD)) {</span>
-<span class="source-line-no">244</span><span id="line-244"> BulkLoadDescriptor bld = WALEdit.getBulkLoadDescriptor(cell);</span>
-<span class="source-line-no">245</span><span id="line-245"> List<StoreDescriptor> stores = bld.getStoresList();</span>
-<span class="source-line-no">246</span><span id="line-246"> int totalStores = stores.size();</span>
-<span class="source-line-no">247</span><span id="line-247"> for (int j = 0; j < totalStores; j++) {</span>
-<span class="source-line-no">248</span><span id="line-248"> List<String> storeFileList = stores.get(j).getStoreFileList();</span>
-<span class="source-line-no">249</span><span id="line-249"> source.getSourceManager().cleanUpHFileRefs(peerId, storeFileList);</span>
-<span class="source-line-no">250</span><span id="line-250"> source.getSourceMetrics().decrSizeOfHFileRefsQueue(storeFileList.size());</span>
+<span class="source-line-no">201</span><span id="line-201"> /**</span>
+<span class="source-line-no">202</span><span id="line-202"> * Do the shipping logic</span>
+<span class="source-line-no">203</span><span id="line-203"> */</span>
+<span class="source-line-no">204</span><span id="line-204"> void shipEdits(WALEntryBatch entryBatch) throws IOException {</span>
+<span class="source-line-no">205</span><span id="line-205"> List<Entry> entries = entryBatch.getWalEntries();</span>
+<span class="source-line-no">206</span><span id="line-206"> int sleepMultiplier = 0;</span>
+<span class="source-line-no">207</span><span id="line-207"> int currentSize = (int) entryBatch.getHeapSize();</span>
+<span class="source-line-no">208</span><span id="line-208"> MetricsSource metrics = source.getSourceMetrics();</span>
+<span class="source-line-no">209</span><span id="line-209"> if (metrics != null && !entries.isEmpty()) {</span>
+<span class="source-line-no">210</span><span id="line-210"> metrics.setTimeStampNextToReplicate(entries.get(entries.size() - 1).getKey().getWriteTime());</span>
+<span class="source-line-no">211</span><span id="line-211"> }</span>
+<span class="source-line-no">212</span><span id="line-212"> if (entries.isEmpty()) {</span>
+<span class="source-line-no">213</span><span id="line-213"> // empty batch may mean WAL boundary advancement</span>
+<span class="source-line-no">214</span><span id="line-214"> lastShippedBatch = entryBatch;</span>
+<span class="source-line-no">215</span><span id="line-215"> persistLogPosition();</span>
+<span class="source-line-no">216</span><span id="line-216"> return;</span>
+<span class="source-line-no">217</span><span id="line-217"> }</span>
+<span class="source-line-no">218</span><span id="line-218"> while (isActive()) {</span>
+<span class="source-line-no">219</span><span id="line-219"> try {</span>
+<span class="source-line-no">220</span><span id="line-220"> try {</span>
+<span class="source-line-no">221</span><span id="line-221"> source.tryThrottle(currentSize);</span>
+<span class="source-line-no">222</span><span id="line-222"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">223</span><span id="line-223"> LOG.debug("Interrupted while sleeping for throttling control");</span>
+<span class="source-line-no">224</span><span id="line-224"> Thread.currentThread().interrupt();</span>
+<span class="source-line-no">225</span><span id="line-225"> // current thread might be interrupted to terminate</span>
+<span class="source-line-no">226</span><span id="line-226"> // directly go back to while() for confirm this</span>
+<span class="source-line-no">227</span><span id="line-227"> continue;</span>
+<span class="source-line-no">228</span><span id="line-228"> }</span>
+<span class="source-line-no">229</span><span id="line-229"> // create replicateContext here, so the entries can be GC'd upon return from this call</span>
+<span class="source-line-no">230</span><span id="line-230"> // stack</span>
+<span class="source-line-no">231</span><span id="line-231"> ReplicationEndpoint.ReplicateContext replicateContext =</span>
+<span class="source-line-no">232</span><span id="line-232"> new ReplicationEndpoint.ReplicateContext();</span>
+<span class="source-line-no">233</span><span id="line-233"> replicateContext.setEntries(entries).setSize(currentSize);</span>
+<span class="source-line-no">234</span><span id="line-234"> replicateContext.setWalGroupId(walGroupId);</span>
+<span class="source-line-no">235</span><span id="line-235"> replicateContext.setTimeout(getAdaptiveTimeout(this.shipEditsTimeout, sleepMultiplier));</span>
+<span class="source-line-no">236</span><span id="line-236"></span>
+<span class="source-line-no">237</span><span id="line-237"> long startTimeNs = System.nanoTime();</span>
+<span class="source-line-no">238</span><span id="line-238"> // send the edits to the endpoint. Will block until the edits are shipped and acknowledged</span>
+<span class="source-line-no">239</span><span id="line-239"> boolean replicated = source.getReplicationEndpoint().replicate(replicateContext);</span>
+<span class="source-line-no">240</span><span id="line-240"> long endTimeNs = System.nanoTime();</span>
+<span class="source-line-no">241</span><span id="line-241"></span>
+<span class="source-line-no">242</span><span id="line-242"> if (!replicated) {</span>
+<span class="source-line-no">243</span><span id="line-243"> continue;</span>
+<span class="source-line-no">244</span><span id="line-244"> } else {</span>
+<span class="source-line-no">245</span><span id="line-245"> sleepMultiplier = Math.max(sleepMultiplier - 1, 0);</span>
+<span class="source-line-no">246</span><span id="line-246"> }</span>
+<span class="source-line-no">247</span><span id="line-247"> // Clean up hfile references</span>
+<span class="source-line-no">248</span><span id="line-248"> for (Entry entry : entries) {</span>
+<span class="source-line-no">249</span><span id="line-249"> cleanUpHFileRefs(entry.getEdit());</span>
+<span class="source-line-no">250</span><span id="line-250"> LOG.trace("shipped entry {}: ", entry);</span>
<span class="source-line-no">251</span><span id="line-251"> }</span>
-<span class="source-line-no">252</span><span id="line-252"> }</span>
-<span class="source-line-no">253</span><span id="line-253"> }</span>
-<span class="source-line-no">254</span><span id="line-254"> }</span>
-<span class="source-line-no">255</span><span id="line-255"></span>
-<span class="source-line-no">256</span><span id="line-256"> private boolean updateLogPosition(WALEntryBatch batch) {</span>
-<span class="source-line-no">257</span><span id="line-257"> boolean updated = false;</span>
-<span class="source-line-no">258</span><span id="line-258"> // if end of file is true, then the logPositionAndCleanOldLogs method will remove the file</span>
-<span class="source-line-no">259</span><span id="line-259"> // record on zk, so let's call it. The last wal position maybe zero if end of file is true and</span>
-<span class="source-line-no">260</span><span id="line-260"> // there is no entry in the batch. It is OK because that the queue storage will ignore the zero</span>
-<span class="source-line-no">261</span><span id="line-261"> // position and the file will be removed soon in cleanOldLogs.</span>
-<span class="source-line-no">262</span><span id="line-262"> if (</span>
-<span class="source-line-no">263</span><span id="line-263"> batch.isEndOfFile() || !batch.getLastWalPath().equals(currentPath)</span>
-<span class="source-line-no">264</span><span id="line-264"> || batch.getLastWalPosition() != currentPosition</span>
-<span class="source-line-no">265</span><span id="line-265"> ) {</span>
-<span class="source-line-no">266</span><span id="line-266"> source.logPositionAndCleanOldLogs(batch);</span>
-<span class="source-line-no">267</span><span id="line-267"> updated = true;</span>
-<span class="source-line-no">268</span><span id="line-268"> }</span>
-<span class="source-line-no">269</span><span id="line-269"> // if end of file is true, then we can just skip to the next file in queue.</span>
-<span class="source-line-no">270</span><span id="line-270"> // the only exception is for recovered queue, if we reach the end of the queue, then there will</span>
-<span class="source-line-no">271</span><span id="line-271"> // no more files so here the currentPath may be null.</span>
-<span class="source-line-no">272</span><span id="line-272"> if (batch.isEndOfFile()) {</span>
-<span class="source-line-no">273</span><span id="line-273"> currentPath = entryReader.getCurrentPath();</span>
-<span class="source-line-no">274</span><span id="line-274"> currentPosition = 0L;</span>
-<span class="source-line-no">275</span><span id="line-275"> } else {</span>
-<span class="source-line-no">276</span><span id="line-276"> currentPath = batch.getLastWalPath();</span>
-<span class="source-line-no">277</span><span id="line-277"> currentPosition = batch.getLastWalPosition();</span>
-<span class="source-line-no">278</span><span id="line-278"> }</span>
-<span class="source-line-no">279</span><span id="line-279"> return updated;</span>
-<span class="source-line-no">280</span><span id="line-280"> }</span>
-<span class="source-line-no">281</span><span id="line-281"></span>
-<span class="source-line-no">282</span><span id="line-282"> public void startup(UncaughtExceptionHandler handler) {</span>
-<span class="source-line-no">283</span><span id="line-283"> String name = Thread.currentThread().getName();</span>
-<span class="source-line-no">284</span><span id="line-284"> Threads.setDaemonThreadRunning(this,</span>
-<span class="source-line-no">285</span><span id="line-285"> name + ".replicationSource.shipper" + walGroupId + "," + source.getQueueId(),</span>
-<span class="source-line-no">286</span><span id="line-286"> handler::uncaughtException);</span>
-<span class="source-line-no">287</span><span id="line-287"> }</span>
-<span class="source-line-no">288</span><span id="line-288"></span>
-<span class="source-line-no">289</span><span id="line-289"> Path getCurrentPath() {</span>
-<span class="source-line-no">290</span><span id="line-290"> return entryReader.getCurrentPath();</span>
-<span class="source-line-no">291</span><span id="line-291"> }</span>
-<span class="source-line-no">292</span><span id="line-292"></span>
-<span class="source-line-no">293</span><span id="line-293"> long getCurrentPosition() {</span>
-<span class="source-line-no">294</span><span id="line-294"> return currentPosition;</span>
-<span class="source-line-no">295</span><span id="line-295"> }</span>
-<span class="source-line-no">296</span><span id="line-296"></span>
-<span class="source-line-no">297</span><span id="line-297"> protected boolean isActive() {</span>
-<span class="source-line-no">298</span><span id="line-298"> return source.isSourceActive() && state == WorkerState.RUNNING && !isInterrupted();</span>
-<span class="source-line-no">299</span><span id="line-299"> }</span>
-<span class="source-line-no">300</span><span id="line-300"></span>
-<span class="source-line-no">301</span><span id="line-301"> protected final void setWorkerState(WorkerState state) {</span>
-<span class="source-line-no">302</span><span id="line-302"> this.state = state;</span>
-<span class="source-line-no">303</span><span id="line-303"> }</span>
-<span class="source-line-no">304</span><span id="line-304"></span>
-<span class="source-line-no">305</span><span id="line-305"> void stopWorker() {</span>
-<span class="source-line-no">306</span><span id="line-306"> setWorkerState(WorkerState.STOPPED);</span>
-<span class="source-line-no">307</span><span id="line-307"> }</span>
-<span class="source-line-no">308</span><span id="line-308"></span>
-<span class="source-line-no">309</span><span id="line-309"> public boolean isFinished() {</span>
-<span class="source-line-no">310</span><span id="line-310"> return state == WorkerState.FINISHED;</span>
-<span class="source-line-no">311</span><span id="line-311"> }</span>
+<span class="source-line-no">252</span><span id="line-252"></span>
+<span class="source-line-no">253</span><span id="line-253"> // offsets totalBufferUsed by deducting shipped batchSize (excludes bulk load size)</span>
+<span class="source-line-no">254</span><span id="line-254"> // this sizeExcludeBulkLoad has to use same calculation that when calling</span>
+<span class="source-line-no">255</span><span id="line-255"> // acquireBufferQuota() in ReplicationSourceWALReader because they maintain</span>
+<span class="source-line-no">256</span><span id="line-256"> // same variable: totalBufferUsed</span>
+<span class="source-line-no">257</span><span id="line-257"> source.postShipEdits(entries, entryBatch.getUsedBufferSize());</span>
+<span class="source-line-no">258</span><span id="line-258"> // FIXME check relationship between wal group and overall</span>
+<span class="source-line-no">259</span><span id="line-259"> source.getSourceMetrics().shipBatch(entryBatch.getNbOperations(), currentSize,</span>
+<span class="source-line-no">260</span><span id="line-260"> entryBatch.getNbHFiles());</span>
+<span class="source-line-no">261</span><span id="line-261"> source.getSourceMetrics().setAgeOfLastShippedOp(</span>
+<span class="source-line-no">262</span><span id="line-262"> entries.get(entries.size() - 1).getKey().getWriteTime(), walGroupId);</span>
+<span class="source-line-no">263</span><span id="line-263"> source.getSourceMetrics().updateTableLevelMetrics(entryBatch.getWalEntriesWithSize());</span>
+<span class="source-line-no">264</span><span id="line-264"></span>
+<span class="source-line-no">265</span><span id="line-265"> if (LOG.isTraceEnabled()) {</span>
+<span class="source-line-no">266</span><span id="line-266"> LOG.debug("Replicated {} entries or {} operations in {} ms", entries.size(),</span>
+<span class="source-line-no">267</span><span id="line-267"> entryBatch.getNbOperations(), (endTimeNs - startTimeNs) / 1000000);</span>
+<span class="source-line-no">268</span><span id="line-268"> }</span>
+<span class="source-line-no">269</span><span id="line-269"> break;</span>
+<span class="source-line-no">270</span><span id="line-270"> } catch (Exception ex) {</span>
+<span class="source-line-no">271</span><span id="line-271"> source.getSourceMetrics().incrementFailedBatches();</span>
+<span class="source-line-no">272</span><span id="line-272"> LOG.warn("{} threw unknown exception:",</span>
+<span class="source-line-no">273</span><span id="line-273"> source.getReplicationEndpoint().getClass().getName(), ex);</span>
+<span class="source-line-no">274</span><span id="line-274"> if (</span>
+<span class="source-line-no">275</span><span id="line-275"> sleepForRetries("ReplicationEndpoint threw exception", sleepForRetries, sleepMultiplier,</span>
+<span class="source-line-no">276</span><span id="line-276"> maxRetriesMultiplier)</span>
+<span class="source-line-no">277</span><span id="line-277"> ) {</span>
+<span class="source-line-no">278</span><span id="line-278"> sleepMultiplier++;</span>
+<span class="source-line-no">279</span><span id="line-279"> }</span>
+<span class="source-line-no">280</span><span id="line-280"> }</span>
+<span class="source-line-no">281</span><span id="line-281"> }</span>
+<span class="source-line-no">282</span><span id="line-282"></span>
+<span class="source-line-no">283</span><span id="line-283"> accumulatedSizeSinceLastUpdate += currentSize;</span>
+<span class="source-line-no">284</span><span id="line-284"> lastShippedBatch = entryBatch;</span>
+<span class="source-line-no">285</span><span id="line-285"> if (shouldPersistLogPosition()) {</span>
+<span class="source-line-no">286</span><span id="line-286"> persistLogPosition();</span>
+<span class="source-line-no">287</span><span id="line-287"> }</span>
+<span class="source-line-no">288</span><span id="line-288"> }</span>
+<span class="source-line-no">289</span><span id="line-289"></span>
+<span class="source-line-no">290</span><span id="line-290"> private boolean shouldPersistLogPosition() {</span>
+<span class="source-line-no">291</span><span id="line-291"> if (lastShippedBatch == null) {</span>
+<span class="source-line-no">292</span><span id="line-292"> return false;</span>
+<span class="source-line-no">293</span><span id="line-293"> }</span>
+<span class="source-line-no">294</span><span id="line-294"> // Default behaviour to update offset immediately after replicate()</span>
+<span class="source-line-no">295</span><span id="line-295"> if (offsetUpdateSizeThresholdBytes == -1 && offsetUpdateIntervalMs == Long.MAX_VALUE) {</span>
+<span class="source-line-no">296</span><span id="line-296"> return true;</span>
+<span class="source-line-no">297</span><span id="line-297"> }</span>
+<span class="source-line-no">298</span><span id="line-298"></span>
+<span class="source-line-no">299</span><span id="line-299"> return (accumulatedSizeSinceLastUpdate >= offsetUpdateSizeThresholdBytes)</span>
+<span class="source-line-no">300</span><span id="line-300"> || (EnvironmentEdgeManager.currentTime() - lastOffsetUpdateTime >= offsetUpdateIntervalMs);</span>
+<span class="source-line-no">301</span><span id="line-301"> }</span>
+<span class="source-line-no">302</span><span id="line-302"></span>
+<span class="source-line-no">303</span><span id="line-303"> void persistLogPosition() throws IOException {</span>
+<span class="source-line-no">304</span><span id="line-304"> if (lastShippedBatch == null) {</span>
+<span class="source-line-no">305</span><span id="line-305"> return;</span>
+<span class="source-line-no">306</span><span id="line-306"> }</span>
+<span class="source-line-no">307</span><span id="line-307"></span>
+<span class="source-line-no">308</span><span id="line-308"> if (!source.isSourceActive() || isInterrupted() || !source.isPeerEnabled()) {</span>
+<span class="source-line-no">309</span><span id="line-309"> LOG.debug("Skip persistLogPosition for inactive/stopping source");</span>
+<span class="source-line-no">310</span><span id="line-310"> return;</span>
+<span class="source-line-no">311</span><span id="line-311"> }</span>
<span class="source-line-no">312</span><span id="line-312"></span>
-<span class="source-line-no">313</span><span id="line-313"> /**</span>
-<span class="source-line-no">314</span><span id="line-314"> * Attempts to properly update <code>ReplicationSourceManager.totalBufferUser</code>, in case</span>
-<span class="source-line-no">315</span><span id="line-315"> * there were unprocessed entries batched by the reader to the shipper, but the shipper didn't</span>
-<span class="source-line-no">316</span><span id="line-316"> * manage to ship those because the replication source is being terminated. In that case, it</span>
-<span class="source-line-no">317</span><span id="line-317"> * iterates through the batched entries and decrease the pending entries size from</span>
-<span class="source-line-no">318</span><span id="line-318"> * <code>ReplicationSourceManager.totalBufferUser</code></span>
-<span class="source-line-no">319</span><span id="line-319"> * <p/></span>
-<span class="source-line-no">320</span><span id="line-320"> * <b>NOTES</b> 1) This method should only be called upon replication source termination. It</span>
-<span class="source-line-no">321</span><span id="line-321"> * blocks waiting for both shipper and reader threads termination, to make sure no race conditions</span>
-<span class="source-line-no">322</span><span id="line-322"> * when updating <code>ReplicationSourceManager.totalBufferUser</code>. 2) It <b>does not</b></span>
-<span class="source-line-no">323</span><span id="line-323"> * attempt to terminate reader and shipper threads. Those <b>must</b> have been triggered</span>
-<span class="source-line-no">324</span><span id="line-324"> * interruption/termination prior to calling this method.</span>
-<span class="source-line-no">325</span><span id="line-325"> */</span>
-<span class="source-line-no">326</span><span id="line-326"> void clearWALEntryBatch() {</span>
-<span class="source-line-no">327</span><span id="line-327"> long timeout = EnvironmentEdgeManager.currentTime() + this.shipEditsTimeout;</span>
-<span class="source-line-no">328</span><span id="line-328"> while (this.isAlive() || this.entryReader.isAlive()) {</span>
-<span class="source-line-no">329</span><span id="line-329"> try {</span>
-<span class="source-line-no">330</span><span id="line-330"> if (EnvironmentEdgeManager.currentTime() >= timeout) {</span>
-<span class="source-line-no">331</span><span id="line-331"> LOG.warn("Shipper clearWALEntryBatch method timed out while waiting reader/shipper "</span>
-<span class="source-line-no">332</span><span id="line-332"> + "thread to stop. Not cleaning buffer usage. PeerId: {}; Shipper alive: {}; Reader "</span>
-<span class="source-line-no">333</span><span id="line-333"> + "alive: {}", this.source.getPeerId(), this.isAlive(), this.entryReader.isAlive());</span>
-<span class="source-line-no">334</span><span id="line-334"> return;</span>
-<span class="source-line-no">335</span><span id="line-335"> } else {</span>
-<span class="source-line-no">336</span><span id="line-336"> // Wait both shipper and reader threads to stop</span>
-<span class="source-line-no">337</span><span id="line-337"> Thread.sleep(this.sleepForRetries);</span>
-<span class="source-line-no">338</span><span id="line-338"> }</span>
-<span class="source-line-no">339</span><span id="line-339"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">340</span><span id="line-340"> LOG.warn("{} Interrupted while waiting {} to stop on clearWALEntryBatch. "</span>
-<span class="source-line-no">341</span><span id="line-341"> + "Not cleaning buffer usage: {}", this.source.getPeerId(), this.getName(), e);</span>
-<span class="source-line-no">342</span><span id="line-342"> return;</span>
-<span class="source-line-no">343</span><span id="line-343"> }</span>
-<span class="source-line-no">344</span><span id="line-344"> }</span>
-<span class="source-line-no">345</span><span id="line-345"> long totalReleasedBytes = 0;</span>
-<span class="source-line-no">346</span><span id="line-346"> while (true) {</span>
-<span class="source-line-no">347</span><span id="line-347"> WALEntryBatch batch = entryReader.entryBatchQueue.poll();</span>
-<span class="source-line-no">348</span><span id="line-348"> if (batch == null) {</span>
-<span class="source-line-no">349</span><span id="line-349"> break;</span>
-<span class="source-line-no">350</span><span id="line-350"> }</span>
-<span class="source-line-no">351</span><span id="line-351"> totalReleasedBytes += source.getSourceManager().releaseWALEntryBatchBufferQuota(batch);</span>
-<span class="source-line-no">352</span><span id="line-352"> }</span>
-<span class="source-line-no">353</span><span id="line-353"> if (LOG.isTraceEnabled()) {</span>
-<span class="source-line-no">354</span><span id="line-354"> LOG.trace("Decrementing totalBufferUsed by {}B while stopping Replication WAL Readers.",</span>
-<span class="source-line-no">355</span><span id="line-355"> totalReleasedBytes);</span>
-<span class="source-line-no">356</span><span id="line-356"> }</span>
-<span class="source-line-no">357</span><span id="line-357"> }</span>
-<span class="source-line-no">358</span><span id="line-358"></span>
-<span class="source-line-no">359</span><span id="line-359"> long getSleepForRetries() {</span>
-<span class="source-line-no">360</span><span id="line-360"> return sleepForRetries;</span>
-<span class="source-line-no">361</span><span id="line-361"> }</span>
-<span class="source-line-no">362</span><span id="line-362">}</span>
+<span class="source-line-no">313</span><span id="line-313"> ReplicationEndpoint endpoint = source.getReplicationEndpoint();</span>
+<span class="source-line-no">314</span><span id="line-314"> if (endpoint != null) {</span>
+<span class="source-line-no">315</span><span id="line-315"> endpoint.beforePersistingReplicationOffset();</span>
+<span class="source-line-no">316</span><span id="line-316"> }</span>
+<span class="source-line-no">317</span><span id="line-317"></span>
+<span class="source-line-no">318</span><span id="line-318"> // Log and clean up WAL logs</span>
+<span class="source-line-no">319</span><span id="line-319"> updateLogPosition(lastShippedBatch);</span>
+<span class="source-line-no">320</span><span id="line-320"> accumulatedSizeSinceLastUpdate = 0;</span>
+<span class="source-line-no">321</span><span id="line-321"> lastShippedBatch = null;</span>
+<span class="source-line-no">322</span><span id="line-322"> lastOffsetUpdateTime = EnvironmentEdgeManager.currentTime();</span>
+<span class="source-line-no">323</span><span id="line-323"> }</span>
+<span class="source-line-no">324</span><span id="line-324"></span>
+<span class="source-line-no">325</span><span id="line-325"> void cleanUpHFileRefs(WALEdit edit) throws IOException {</span>
+<span class="source-line-no">326</span><span id="line-326"> String peerId = source.getPeerId();</span>
+<span class="source-line-no">327</span><span id="line-327"> if (peerId.contains("-")) {</span>
+<span class="source-line-no">328</span><span id="line-328"> // peerClusterZnode will be in the form peerId + "-" + rsZNode.</span>
+<span class="source-line-no">329</span><span id="line-329"> // A peerId will not have "-" in its name, see HBASE-11394</span>
+<span class="source-line-no">330</span><span id="line-330"> peerId = peerId.split("-")[0];</span>
+<span class="source-line-no">331</span><span id="line-331"> }</span>
+<span class="source-line-no">332</span><span id="line-332"> List<Cell> cells = edit.getCells();</span>
+<span class="source-line-no">333</span><span id="line-333"> int totalCells = cells.size();</span>
+<span class="source-line-no">334</span><span id="line-334"> for (int i = 0; i < totalCells; i++) {</span>
+<span class="source-line-no">335</span><span id="line-335"> Cell cell = cells.get(i);</span>
+<span class="source-line-no">336</span><span id="line-336"> if (CellUtil.matchingQualifier(cell, WALEdit.BULK_LOAD)) {</span>
+<span class="source-line-no">337</span><span id="line-337"> BulkLoadDescriptor bld = WALEdit.getBulkLoadDescriptor(cell);</span>
+<span class="source-line-no">338</span><span id="line-338"> List<StoreDescriptor> stores = bld.getStoresList();</span>
+<span class="source-line-no">339</span><span id="line-339"> int totalStores = stores.size();</span>
+<span class="source-line-no">340</span><span id="line-340"> for (int j = 0; j < totalStores; j++) {</span>
+<span class="source-line-no">341</span><span id="line-341"> List<String> storeFileList = stores.get(j).getStoreFileList();</span>
+<span class="source-line-no">342</span><span id="line-342"> source.getSourceManager().cleanUpHFileRefs(peerId, storeFileList);</span>
+<span class="source-line-no">343</span><span id="line-343"> source.getSourceMetrics().decrSizeOfHFileRefsQueue(storeFileList.size());</span>
+<span class="source-line-no">344</span><span id="line-344"> }</span>
+<span class="source-line-no">345</span><span id="line-345"> }</span>
+<span class="source-line-no">346</span><span id="line-346"> }</span>
+<span class="source-line-no">347</span><span id="line-347"> }</span>
+<span class="source-line-no">348</span><span id="line-348"></span>
+<span class="source-line-no">349</span><span id="line-349"> private boolean updateLogPosition(WALEntryBatch batch) {</span>
+<span class="source-line-no">350</span><span id="line-350"> boolean updated = false;</span>
+<span class="source-line-no">351</span><span id="line-351"> // if end of file is true, then the logPositionAndCleanOldLogs method will remove the file</span>
+<span class="source-line-no">352</span><span id="line-352"> // record on zk, so let's call it. The last wal position maybe zero if end of file is true and</span>
+<span class="source-line-no">353</span><span id="line-353"> // there is no entry in the batch. It is OK because that the queue storage will ignore the zero</span>
+<span class="source-line-no">354</span><span id="line-354"> // position and the file will be removed soon in cleanOldLogs.</span>
+<span class="source-line-no">355</span><span id="line-355"> if (</span>
+<span class="source-line-no">356</span><span id="line-356"> batch.isEndOfFile() || !batch.getLastWalPath().equals(currentPath)</span>
+<span class="source-line-no">357</span><span id="line-357"> || batch.getLastWalPosition() != currentPosition</span>
+<span class="source-line-no">358</span><span id="line-358"> ) {</span>
+<span class="source-line-no">359</span><span id="line-359"> source.logPositionAndCleanOldLogs(batch);</span>
+<span class="source-line-no">360</span><span id="line-360"> updated = true;</span>
+<span class="source-line-no">361</span><span id="line-361"> }</span>
+<span class="source-line-no">362</span><span id="line-362"> // if end of file is true, then we can just skip to the next file in queue.</span>
+<span class="source-line-no">363</span><span id="line-363"> // the only exception is for recovered queue, if we reach the end of the queue, then there will</span>
+<span class="source-line-no">364</span><span id="line-364"> // no more files so here the currentPath may be null.</span>
+<span class="source-line-no">365</span><span id="line-365"> if (batch.isEndOfFile()) {</span>
+<span class="source-line-no">366</span><span id="line-366"> currentPath = entryReader.getCurrentPath();</span>
+<span class="source-line-no">367</span><span id="line-367"> currentPosition = 0L;</span>
+<span class="source-line-no">368</span><span id="line-368"> } else {</span>
+<span class="source-line-no">369</span><span id="line-369"> currentPath = batch.getLastWalPath();</span>
+<span class="source-line-no">370</span><span id="line-370"> currentPosition = batch.getLastWalPosition();</span>
+<span class="source-line-no">371</span><span id="line-371"> }</span>
+<span class="source-line-no">372</span><span id="line-372"> return updated;</span>
+<span class="source-line-no">373</span><span id="line-373"> }</span>
+<span class="source-line-no">374</span><span id="line-374"></span>
+<span class="source-line-no">375</span><span id="line-375"> public void startup(UncaughtExceptionHandler handler) {</span>
+<span class="source-line-no">376</span><span id="line-376"> String name = Thread.currentThread().getName();</span>
+<span class="source-line-no">377</span><span id="line-377"> Threads.setDaemonThreadRunning(this,</span>
+<span class="source-line-no">378</span><span id="line-378"> name + ".replicationSource.shipper" + walGroupId + "," + source.getQueueId(),</span>
+<span class="source-line-no">379</span><span id="line-379"> handler::uncaughtException);</span>
+<span class="source-line-no">380</span><span id="line-380"> }</span>
+<span class="source-line-no">381</span><span id="line-381"></span>
+<span class="source-line-no">382</span><span id="line-382"> Path getCurrentPath() {</span>
+<span class="source-line-no">383</span><span id="line-383"> return entryReader.getCurrentPath();</span>
+<span class="source-line-no">384</span><span id="line-384"> }</span>
+<span class="source-line-no">385</span><span id="line-385"></span>
+<span class="source-line-no">386</span><span id="line-386"> long getCurrentPosition() {</span>
+<span class="source-line-no">387</span><span id="line-387"> return currentPosition;</span>
+<span class="source-line-no">388</span><span id="line-388"> }</span>
+<span class="source-line-no">389</span><span id="line-389"></span>
+<span class="source-line-no">390</span><span id="line-390"> protected boolean isActive() {</span>
+<span class="source-line-no">391</span><span id="line-391"> return source.isSourceActive() && state == WorkerState.RUNNING && !isInterrupted();</span>
+<span class="source-line-no">392</span><span id="line-392"> }</span>
+<span class="source-line-no">393</span><span id="line-393"></span>
+<span class="source-line-no">394</span><span id="line-394"> protected final void setWorkerState(WorkerState state) {</span>
+<span class="source-line-no">395</span><span id="line-395"> this.state = state;</span>
+<span class="source-line-no">396</span><span id="line-396"> }</span>
+<span class="source-line-no">397</span><span id="line-397"></span>
+<span class="source-line-no">398</span><span id="line-398"> void stopWorker() {</span>
+<span class="source-line-no">399</span><span id="line-399"> setWorkerState(WorkerState.STOPPED);</span>
+<span class="source-line-no">400</span><span id="line-400"> }</span>
+<span class="source-line-no">401</span><span id="line-401"></span>
+<span class="source-line-no">402</span><span id="line-402"> public boolean isFinished() {</span>
+<span class="source-line-no">403</span><span id="line-403"> return state == WorkerState.FINISHED;</span>
+<span class="source-line-no">404</span><span id="line-404"> }</span>
+<span class="source-line-no">405</span><span id="line-405"></span>
+<span class="source-line-no">406</span><span id="line-406"> /**</span>
+<span class="source-line-no">407</span><span id="line-407"> * Attempts to properly update <code>ReplicationSourceManager.totalBufferUser</code>, in case</span>
+<span class="source-line-no">408</span><span id="line-408"> * there were unprocessed entries batched by the reader to the shipper, but the shipper didn't</span>
+<span class="source-line-no">409</span><span id="line-409"> * manage to ship those because the replication source is being terminated. In that case, it</span>
+<span class="source-line-no">410</span><span id="line-410"> * iterates through the batched entries and decrease the pending entries size from</span>
+<span class="source-line-no">411</span><span id="line-411"> * <code>ReplicationSourceManager.totalBufferUser</code></span>
+<span class="source-line-no">412</span><span id="line-412"> * <p/></span>
+<span class="source-line-no">413</span><span id="line-413"> * <b>NOTES</b> 1) This method should only be called upon replication source termination. It</span>
+<span class="source-line-no">414</span><span id="line-414"> * blocks waiting for both shipper and reader threads termination, to make sure no race conditions</span>
+<span class="source-line-no">415</span><span id="line-415"> * when updating <code>ReplicationSourceManager.totalBufferUser</code>. 2) It <b>does not</b></span>
+<span class="source-line-no">416</span><span id="line-416"> * attempt to terminate reader and shipper threads. Those <b>must</b> have been triggered</span>
+<span class="source-line-no">417</span><span id="line-417"> * interruption/termination prior to calling this method.</span>
+<span class="source-line-no">418</span><span id="line-418"> */</span>
+<span class="source-line-no">419</span><span id="line-419"> void clearWALEntryBatch() {</span>
+<span class="source-line-no">420</span><span id="line-420"> long timeout = EnvironmentEdgeManager.currentTime() + this.shipEditsTimeout;</span>
+<span class="source-line-no">421</span><span id="line-421"> while (this.isAlive() || this.entryReader.isAlive()) {</span>
+<span class="source-line-no">422</span><span id="line-422"> try {</span>
+<span class="source-line-no">423</span><span id="line-423"> if (EnvironmentEdgeManager.currentTime() >= timeout) {</span>
+<span class="source-line-no">424</span><span id="line-424"> LOG.warn("Shipper clearWALEntryBatch method timed out while waiting reader/shipper "</span>
+<span class="source-line-no">425</span><span id="line-425"> + "thread to stop. Not cleaning buffer usage. PeerId: {}; Shipper alive: {}; Reader "</span>
+<span class="source-line-no">426</span><span id="line-426"> + "alive: {}", this.source.getPeerId(), this.isAlive(), this.entryReader.isAlive());</span>
+<span class="source-line-no">427</span><span id="line-427"> return;</span>
+<span class="source-line-no">428</span><span id="line-428"> } else {</span>
+<span class="source-line-no">429</span><span id="line-429"> // Wait both shipper and reader threads to stop</span>
+<span class="source-line-no">430</span><span id="line-430"> Thread.sleep(this.sleepForRetries);</span>
+<span class="source-line-no">431</span><span id="line-431"> }</span>
+<span class="source-line-no">432</span><span id="line-432"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">433</span><span id="line-433"> LOG.warn("{} Interrupted while waiting {} to stop on clearWALEntryBatch. "</span>
+<span class="source-line-no">434</span><span id="line-434"> + "Not cleaning buffer usage: {}", this.source.getPeerId(), this.getName(), e);</span>
+<span class="source-line-no">435</span><span id="line-435"> return;</span>
+<span class="source-line-no">436</span><span id="line-436"> }</span>
+<span class="source-line-no">437</span><span id="line-437"> }</span>
+<span class="source-line-no">438</span><span id="line-438"> long totalReleasedBytes = 0;</span>
+<span class="source-line-no">439</span><span id="line-439"> while (true) {</span>
+<span class="source-line-no">440</span><span id="line-440"> WALEntryBatch batch = entryReader.entryBatchQueue.poll();</span>
+<span class="source-line-no">441</span><span id="line-441"> if (batch == null) {</span>
+<span class="source-line-no">442</span><span id="line-442"> break;</span>
+<span class="source-line-no">443</span><span id="line-443"> }</span>
+<span class="source-line-no">444</span><span id="line-444"> totalReleasedBytes += source.getSourceManager().releaseWALEntryBatchBufferQuota(batch);</span>
+<span class="source-line-no">445</span><span id="line-445"> }</span>
+<span class="source-line-no">446</span><span id="line-446"> if (LOG.isTraceEnabled()) {</span>
+<span class="source-line-no">447</span><span id="line-447"> LOG.trace("Decrementing totalBufferUsed by {}B while stopping Replication WAL Readers.",</span>
+<span class="source-line-no">448</span><span id="line-448"> totalReleasedBytes);</span>
+<span class="source-line-no">449</span><span id="line-449"> }</span>
+<span class="source-line-no">450</span><span id="line-450"> }</span>
+<span class="source-line-no">451</span><span id="line-451"></span>
+<span class="source-line-no">452</span><span id="line-452"> long getSleepForRetries() {</span>
+<span class="source-line-no">453</span><span id="line-453"> return sleepForRetries;</span>
+<span class="source-line-no">454</span><span id="line-454"> }</span>
+<span class="source-line-no">455</span><span id="line-455"></span>
+<span class="source-line-no">456</span><span id="line-456"> // Restart worker so replication resumes from last persisted offset.</span>
+<span class="source-line-no">457</span><span id="line-457"> void abortAndRestart(Throwable cause) {</span>
+<span class="source-line-no">458</span><span id="line-458"> LOG.warn("Restarting shipper for walGroupId={}", walGroupId, cause);</span>
+<span class="source-line-no">459</span><span id="line-459"> if (!source.isSourceActive() || !source.isPeerEnabled() || isInterrupted()) {</span>
+<span class="source-line-no">460</span><span id="line-460"> LOG.warn("abortAndRestart SKIPPED walGroupId={}, thread={}", walGroupId,</span>
+<span class="source-line-no">461</span><span id="line-461"> Thread.currentThread().getName());</span>
+<span class="source-line-no">462</span><span id="line-462"> return;</span>
+<span class="source-line-no">463</span><span id="line-463"> }</span>
+<span class="source-line-no">464</span><span id="line-464"> setWorkerState(WorkerState.STOPPED);</span>
+<span class="source-line-no">465</span><span id="line-465"> source.restartShipper(walGroupId, this);</span>
+<span class="source-line-no">466</span><span id="line-466"> }</span>
+<span class="source-line-no">467</span><span id="line-467">}</span>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html b/devapidocs/src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html
index 71108403e73..bb40fbc588b 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.html
@@ -87,292 +87,397 @@
<span class="source-line-no">074</span><span id="line-74"> private final int DEFAULT_TIMEOUT = 20000;</span>
<span class="source-line-no">075</span><span id="line-75"> private final int getEntriesTimeout;</span>
<span class="source-line-no">076</span><span id="line-76"> private final int shipEditsTimeout;</span>
-<span class="source-line-no">077</span><span id="line-77"></span>
-<span class="source-line-no">078</span><span id="line-78"> public ReplicationSourceShipper(Configuration conf, String walGroupId, ReplicationSource source,</span>
-<span class="source-line-no">079</span><span id="line-79"> ReplicationSourceWALReader walReader) {</span>
-<span class="source-line-no">080</span><span id="line-80"> this.conf = conf;</span>
-<span class="source-line-no">081</span><span id="line-81"> this.walGroupId = walGroupId;</span>
-<span class="source-line-no">082</span><span id="line-82"> this.source = source;</span>
-<span class="source-line-no">083</span><span id="line-83"> this.entryReader = walReader;</span>
-<span class="source-line-no">084</span><span id="line-84"> // 1 second</span>
-<span class="source-line-no">085</span><span id="line-85"> this.sleepForRetries = this.conf.getLong("replication.source.sleepforretries", 1000);</span>
-<span class="source-line-no">086</span><span id="line-86"> // 5 minutes @ 1 sec per</span>
-<span class="source-line-no">087</span><span id="line-87"> this.maxRetriesMultiplier = this.conf.getInt("replication.source.maxretriesmultiplier", 300);</span>
-<span class="source-line-no">088</span><span id="line-88"> // 20 seconds</span>
-<span class="source-line-no">089</span><span id="line-89"> this.getEntriesTimeout =</span>
-<span class="source-line-no">090</span><span id="line-90"> this.conf.getInt("replication.source.getEntries.timeout", DEFAULT_TIMEOUT);</span>
-<span class="source-line-no">091</span><span id="line-91"> this.shipEditsTimeout = this.conf.getInt(HConstants.REPLICATION_SOURCE_SHIPEDITS_TIMEOUT,</span>
-<span class="source-line-no">092</span><span id="line-92"> HConstants.REPLICATION_SOURCE_SHIPEDITS_TIMEOUT_DFAULT);</span>
-<span class="source-line-no">093</span><span id="line-93"> }</span>
-<span class="source-line-no">094</span><span id="line-94"></span>
-<span class="source-line-no">095</span><span id="line-95"> @Override</span>
-<span class="source-line-no">096</span><span id="line-96"> public final void run() {</span>
-<span class="source-line-no">097</span><span id="line-97"> setWorkerState(WorkerState.RUNNING);</span>
-<span class="source-line-no">098</span><span id="line-98"> LOG.info("Running ReplicationSourceShipper Thread for wal group: {}", this.walGroupId);</span>
-<span class="source-line-no">099</span><span id="line-99"> // Loop until we close down</span>
-<span class="source-line-no">100</span><span id="line-100"> while (isActive()) {</span>
-<span class="source-line-no">101</span><span id="line-101"> // Sleep until replication is enabled again</span>
-<span class="source-line-no">102</span><span id="line-102"> if (!source.isPeerEnabled()) {</span>
-<span class="source-line-no">103</span><span id="line-103"> // The peer enabled check is in memory, not expensive, so do not need to increase the</span>
-<span class="source-line-no">104</span><span id="line-104"> // sleep interval as it may cause a long lag when we enable the peer.</span>
-<span class="source-line-no">105</span><span id="line-105"> sleepForRetries("Replication is disabled", sleepForRetries, 1, maxRetriesMultiplier);</span>
-<span class="source-line-no">106</span><span id="line-106"> continue;</span>
-<span class="source-line-no">107</span><span id="line-107"> }</span>
-<span class="source-line-no">108</span><span id="line-108"> try {</span>
-<span class="source-line-no">109</span><span id="line-109"> WALEntryBatch entryBatch = entryReader.poll(getEntriesTimeout);</span>
-<span class="source-line-no">110</span><span id="line-110"> LOG.debug("Shipper from source {} got entry batch from reader: {}", source.getQueueId(),</span>
-<span class="source-line-no">111</span><span id="line-111"> entryBatch);</span>
-<span class="source-line-no">112</span><span id="line-112"> if (entryBatch == null) {</span>
-<span class="source-line-no">113</span><span id="line-113"> continue;</span>
-<span class="source-line-no">114</span><span id="line-114"> }</span>
-<span class="source-line-no">115</span><span id="line-115"> // the NO_MORE_DATA instance has no path so do not call shipEdits</span>
-<span class="source-line-no">116</span><span id="line-116"> if (entryBatch == WALEntryBatch.NO_MORE_DATA) {</span>
-<span class="source-line-no">117</span><span id="line-117"> noMoreData();</span>
-<span class="source-line-no">118</span><span id="line-118"> } else {</span>
-<span class="source-line-no">119</span><span id="line-119"> shipEdits(entryBatch);</span>
-<span class="source-line-no">120</span><span id="line-120"> }</span>
-<span class="source-line-no">121</span><span id="line-121"> } catch (InterruptedException | ReplicationRuntimeException e) {</span>
-<span class="source-line-no">122</span><span id="line-122"> // It is interrupted and needs to quit.</span>
-<span class="source-line-no">123</span><span id="line-123"> LOG.warn("Interrupted while waiting for next replication entry batch", e);</span>
-<span class="source-line-no">124</span><span id="line-124"> Thread.currentThread().interrupt();</span>
-<span class="source-line-no">125</span><span id="line-125"> }</span>
-<span class="source-line-no">126</span><span id="line-126"> }</span>
-<span class="source-line-no">127</span><span id="line-127"> // If the worker exits run loop without finishing its task, mark it as stopped.</span>
-<span class="source-line-no">128</span><span id="line-128"> if (!isFinished()) {</span>
-<span class="source-line-no">129</span><span id="line-129"> setWorkerState(WorkerState.STOPPED);</span>
-<span class="source-line-no">130</span><span id="line-130"> } else {</span>
-<span class="source-line-no">131</span><span id="line-131"> source.removeWorker(this);</span>
-<span class="source-line-no">132</span><span id="line-132"> postFinish();</span>
-<span class="source-line-no">133</span><span id="line-133"> }</span>
-<span class="source-line-no">134</span><span id="line-134"> }</span>
-<span class="source-line-no">135</span><span id="line-135"></span>
-<span class="source-line-no">136</span><span id="line-136"> private void noMoreData() {</span>
-<span class="source-line-no">137</span><span id="line-137"> if (source.isRecovered()) {</span>
-<span class="source-line-no">138</span><span id="line-138"> LOG.debug("Finished recovering queue for group {} of peer {}", walGroupId,</span>
-<span class="source-line-no">139</span><span id="line-139"> source.getQueueId());</span>
-<span class="source-line-no">140</span><span id="line-140"> source.getSourceMetrics().incrCompletedRecoveryQueue();</span>
-<span class="source-line-no">141</span><span id="line-141"> } else {</span>
-<span class="source-line-no">142</span><span id="line-142"> LOG.debug("Finished queue for group {} of peer {}", walGroupId, source.getQueueId());</span>
-<span class="source-line-no">143</span><span id="line-143"> }</span>
-<span class="source-line-no">144</span><span id="line-144"> setWorkerState(WorkerState.FINISHED);</span>
-<span class="source-line-no">145</span><span id="line-145"> }</span>
-<span class="source-line-no">146</span><span id="line-146"></span>
-<span class="source-line-no">147</span><span id="line-147"> // To be implemented by recovered shipper</span>
-<span class="source-line-no">148</span><span id="line-148"> protected void postFinish() {</span>
-<span class="source-line-no">149</span><span id="line-149"> }</span>
-<span class="source-line-no">150</span><span id="line-150"></span>
-<span class="source-line-no">151</span><span id="line-151"> /**</span>
-<span class="source-line-no">152</span><span id="line-152"> * Do the shipping logic</span>
-<span class="source-line-no">153</span><span id="line-153"> */</span>
-<span class="source-line-no">154</span><span id="line-154"> private void shipEdits(WALEntryBatch entryBatch) {</span>
-<span class="source-line-no">155</span><span id="line-155"> List<Entry> entries = entryBatch.getWalEntries();</span>
-<span class="source-line-no">156</span><span id="line-156"> int sleepMultiplier = 0;</span>
-<span class="source-line-no">157</span><span id="line-157"> if (entries.isEmpty()) {</span>
-<span class="source-line-no">158</span><span id="line-158"> updateLogPosition(entryBatch);</span>
-<span class="source-line-no">159</span><span id="line-159"> return;</span>
-<span class="source-line-no">160</span><span id="line-160"> }</span>
-<span class="source-line-no">161</span><span id="line-161"> int currentSize = (int) entryBatch.getHeapSize();</span>
-<span class="source-line-no">162</span><span id="line-162"> source.getSourceMetrics()</span>
-<span class="source-line-no">163</span><span id="line-163"> .setTimeStampNextToReplicate(entries.get(entries.size() - 1).getKey().getWriteTime());</span>
-<span class="source-line-no">164</span><span id="line-164"> while (isActive()) {</span>
-<span class="source-line-no">165</span><span id="line-165"> try {</span>
-<span class="source-line-no">166</span><span id="line-166"> try {</span>
-<span class="source-line-no">167</span><span id="line-167"> source.tryThrottle(currentSize);</span>
-<span class="source-line-no">168</span><span id="line-168"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">169</span><span id="line-169"> LOG.debug("Interrupted while sleeping for throttling control");</span>
-<span class="source-line-no">170</span><span id="line-170"> Thread.currentThread().interrupt();</span>
-<span class="source-line-no">171</span><span id="line-171"> // current thread might be interrupted to terminate</span>
-<span class="source-line-no">172</span><span id="line-172"> // directly go back to while() for confirm this</span>
-<span class="source-line-no">173</span><span id="line-173"> continue;</span>
-<span class="source-line-no">174</span><span id="line-174"> }</span>
-<span class="source-line-no">175</span><span id="line-175"> // create replicateContext here, so the entries can be GC'd upon return from this call</span>
-<span class="source-line-no">176</span><span id="line-176"> // stack</span>
-<span class="source-line-no">177</span><span id="line-177"> ReplicationEndpoint.ReplicateContext replicateContext =</span>
-<span class="source-line-no">178</span><span id="line-178"> new ReplicationEndpoint.ReplicateContext();</span>
-<span class="source-line-no">179</span><span id="line-179"> replicateContext.setEntries(entries).setSize(currentSize);</span>
-<span class="source-line-no">180</span><span id="line-180"> replicateContext.setWalGroupId(walGroupId);</span>
-<span class="source-line-no">181</span><span id="line-181"> replicateContext.setTimeout(getAdaptiveTimeout(this.shipEditsTimeout, sleepMultiplier));</span>
-<span class="source-line-no">182</span><span id="line-182"></span>
-<span class="source-line-no">183</span><span id="line-183"> long startTimeNs = System.nanoTime();</span>
-<span class="source-line-no">184</span><span id="line-184"> // send the edits to the endpoint. Will block until the edits are shipped and acknowledged</span>
-<span class="source-line-no">185</span><span id="line-185"> boolean replicated = source.getReplicationEndpoint().replicate(replicateContext);</span>
-<span class="source-line-no">186</span><span id="line-186"> long endTimeNs = System.nanoTime();</span>
-<span class="source-line-no">187</span><span id="line-187"></span>
-<span class="source-line-no">188</span><span id="line-188"> if (!replicated) {</span>
-<span class="source-line-no">189</span><span id="line-189"> continue;</span>
-<span class="source-line-no">190</span><span id="line-190"> } else {</span>
-<span class="source-line-no">191</span><span id="line-191"> sleepMultiplier = Math.max(sleepMultiplier - 1, 0);</span>
-<span class="source-line-no">192</span><span id="line-192"> }</span>
-<span class="source-line-no">193</span><span id="line-193"> // Clean up hfile references</span>
-<span class="source-line-no">194</span><span id="line-194"> for (Entry entry : entries) {</span>
-<span class="source-line-no">195</span><span id="line-195"> cleanUpHFileRefs(entry.getEdit());</span>
-<span class="source-line-no">196</span><span id="line-196"> LOG.trace("shipped entry {}: ", entry);</span>
-<span class="source-line-no">197</span><span id="line-197"> }</span>
-<span class="source-line-no">198</span><span id="line-198"> // Log and clean up WAL logs</span>
-<span class="source-line-no">199</span><span id="line-199"> updateLogPosition(entryBatch);</span>
+<span class="source-line-no">077</span><span id="line-77"> private long accumulatedSizeSinceLastUpdate = 0L;</span>
+<span class="source-line-no">078</span><span id="line-78"> private long lastOffsetUpdateTime = EnvironmentEdgeManager.currentTime();</span>
+<span class="source-line-no">079</span><span id="line-79"> private final long offsetUpdateIntervalMs;</span>
+<span class="source-line-no">080</span><span id="line-80"> private final long offsetUpdateSizeThresholdBytes;</span>
+<span class="source-line-no">081</span><span id="line-81"> private WALEntryBatch lastShippedBatch;</span>
+<span class="source-line-no">082</span><span id="line-82"></span>
+<span class="source-line-no">083</span><span id="line-83"> private static final String OFFSET_UPDATE_INTERVAL_MS_KEY =</span>
+<span class="source-line-no">084</span><span id="line-84"> "hbase.replication.shipper.offset.update.interval.ms";</span>
+<span class="source-line-no">085</span><span id="line-85"> private static final String OFFSET_UPDATE_SIZE_THRESHOLD_KEY =</span>
+<span class="source-line-no">086</span><span id="line-86"> "hbase.replication.shipper.offset.update.size.threshold";</span>
+<span class="source-line-no">087</span><span id="line-87"> private static final long DEFAULT_OFFSET_UPDATE_INTERVAL_MS = Long.MAX_VALUE;</span>
+<span class="source-line-no">088</span><span id="line-88"> private static final long DEFAULT_OFFSET_UPDATE_SIZE_THRESHOLD = -1L;</span>
+<span class="source-line-no">089</span><span id="line-89"></span>
+<span class="source-line-no">090</span><span id="line-90"> public ReplicationSourceShipper(Configuration conf, String walGroupId, ReplicationSource source,</span>
+<span class="source-line-no">091</span><span id="line-91"> ReplicationSourceWALReader walReader) {</span>
+<span class="source-line-no">092</span><span id="line-92"> this.conf = conf;</span>
+<span class="source-line-no">093</span><span id="line-93"> this.walGroupId = walGroupId;</span>
+<span class="source-line-no">094</span><span id="line-94"> this.source = source;</span>
+<span class="source-line-no">095</span><span id="line-95"> this.entryReader = walReader;</span>
+<span class="source-line-no">096</span><span id="line-96"> // 1 second</span>
+<span class="source-line-no">097</span><span id="line-97"> this.sleepForRetries = this.conf.getLong("replication.source.sleepforretries", 1000);</span>
+<span class="source-line-no">098</span><span id="line-98"> // 5 minutes @ 1 sec per</span>
+<span class="source-line-no">099</span><span id="line-99"> this.maxRetriesMultiplier = this.conf.getInt("replication.source.maxretriesmultiplier", 300);</span>
+<span class="source-line-no">100</span><span id="line-100"> // 20 seconds</span>
+<span class="source-line-no">101</span><span id="line-101"> this.getEntriesTimeout =</span>
+<span class="source-line-no">102</span><span id="line-102"> this.conf.getInt("replication.source.getEntries.timeout", DEFAULT_TIMEOUT);</span>
+<span class="source-line-no">103</span><span id="line-103"> this.shipEditsTimeout = this.conf.getInt(HConstants.REPLICATION_SOURCE_SHIPEDITS_TIMEOUT,</span>
+<span class="source-line-no">104</span><span id="line-104"> HConstants.REPLICATION_SOURCE_SHIPEDITS_TIMEOUT_DFAULT);</span>
+<span class="source-line-no">105</span><span id="line-105"> this.offsetUpdateIntervalMs =</span>
+<span class="source-line-no">106</span><span id="line-106"> conf.getLong(OFFSET_UPDATE_INTERVAL_MS_KEY, DEFAULT_OFFSET_UPDATE_INTERVAL_MS);</span>
+<span class="source-line-no">107</span><span id="line-107"> this.offsetUpdateSizeThresholdBytes =</span>
+<span class="source-line-no">108</span><span id="line-108"> conf.getLong(OFFSET_UPDATE_SIZE_THRESHOLD_KEY, DEFAULT_OFFSET_UPDATE_SIZE_THRESHOLD);</span>
+<span class="source-line-no">109</span><span id="line-109"> }</span>
+<span class="source-line-no">110</span><span id="line-110"></span>
+<span class="source-line-no">111</span><span id="line-111"> @Override</span>
+<span class="source-line-no">112</span><span id="line-112"> public final void run() {</span>
+<span class="source-line-no">113</span><span id="line-113"> setWorkerState(WorkerState.RUNNING);</span>
+<span class="source-line-no">114</span><span id="line-114"> LOG.info("Running ReplicationSourceShipper Thread for wal group: {}", this.walGroupId);</span>
+<span class="source-line-no">115</span><span id="line-115"> // Loop until we close down</span>
+<span class="source-line-no">116</span><span id="line-116"> while (isActive()) {</span>
+<span class="source-line-no">117</span><span id="line-117"> // Sleep until replication is enabled again</span>
+<span class="source-line-no">118</span><span id="line-118"> if (!source.isPeerEnabled()) {</span>
+<span class="source-line-no">119</span><span id="line-119"> // The peer enabled check is in memory, not expensive, so do not need to increase the</span>
+<span class="source-line-no">120</span><span id="line-120"> // sleep interval as it may cause a long lag when we enable the peer.</span>
+<span class="source-line-no">121</span><span id="line-121"> sleepForRetries("Replication is disabled", sleepForRetries, 1, maxRetriesMultiplier);</span>
+<span class="source-line-no">122</span><span id="line-122"> continue;</span>
+<span class="source-line-no">123</span><span id="line-123"> }</span>
+<span class="source-line-no">124</span><span id="line-124"> try {</span>
+<span class="source-line-no">125</span><span id="line-125"> // check time-based offset persistence</span>
+<span class="source-line-no">126</span><span id="line-126"> if (shouldPersistLogPosition()) {</span>
+<span class="source-line-no">127</span><span id="line-127"> persistLogPosition();</span>
+<span class="source-line-no">128</span><span id="line-128"> }</span>
+<span class="source-line-no">129</span><span id="line-129"></span>
+<span class="source-line-no">130</span><span id="line-130"> long pollTimeout = getEntriesTimeout;</span>
+<span class="source-line-no">131</span><span id="line-131"> if (offsetUpdateIntervalMs != Long.MAX_VALUE) {</span>
+<span class="source-line-no">132</span><span id="line-132"> long elapsed = EnvironmentEdgeManager.currentTime() - lastOffsetUpdateTime;</span>
+<span class="source-line-no">133</span><span id="line-133"> long remaining = offsetUpdateIntervalMs - elapsed;</span>
+<span class="source-line-no">134</span><span id="line-134"> if (remaining > 0) {</span>
+<span class="source-line-no">135</span><span id="line-135"> pollTimeout = Math.min(getEntriesTimeout, remaining);</span>
+<span class="source-line-no">136</span><span id="line-136"> }</span>
+<span class="source-line-no">137</span><span id="line-137"> }</span>
+<span class="source-line-no">138</span><span id="line-138"> WALEntryBatch entryBatch = entryReader.poll(pollTimeout);</span>
+<span class="source-line-no">139</span><span id="line-139"> LOG.debug("Shipper from source {} got entry batch from reader: {}", source.getQueueId(),</span>
+<span class="source-line-no">140</span><span id="line-140"> entryBatch);</span>
+<span class="source-line-no">141</span><span id="line-141"></span>
+<span class="source-line-no">142</span><span id="line-142"> if (entryBatch == null) {</span>
+<span class="source-line-no">143</span><span id="line-143"> continue;</span>
+<span class="source-line-no">144</span><span id="line-144"> }</span>
+<span class="source-line-no">145</span><span id="line-145"> // the NO_MORE_DATA instance has no path so do not call shipEdits</span>
+<span class="source-line-no">146</span><span id="line-146"> if (entryBatch == WALEntryBatch.NO_MORE_DATA) {</span>
+<span class="source-line-no">147</span><span id="line-147"> noMoreData();</span>
+<span class="source-line-no">148</span><span id="line-148"> } else {</span>
+<span class="source-line-no">149</span><span id="line-149"> shipEdits(entryBatch);</span>
+<span class="source-line-no">150</span><span id="line-150"> }</span>
+<span class="source-line-no">151</span><span id="line-151"> } catch (InterruptedException | ReplicationRuntimeException e) {</span>
+<span class="source-line-no">152</span><span id="line-152"> LOG.warn("Interrupted while waiting for next replication entry batch", e);</span>
+<span class="source-line-no">153</span><span id="line-153"> Thread.currentThread().interrupt();</span>
+<span class="source-line-no">154</span><span id="line-154"> } catch (Exception e) {</span>
+<span class="source-line-no">155</span><span id="line-155"> // During source shutdown / peer removal we can see interrupted IOEs</span>
+<span class="source-line-no">156</span><span id="line-156"> // from replication queue updates. Do not restart in this case.</span>
+<span class="source-line-no">157</span><span id="line-157"> if (!source.isSourceActive() || isInterrupted() || !source.isPeerEnabled()) {</span>
+<span class="source-line-no">158</span><span id="line-158"> LOG.info("Ignoring persist failure during shutdown for walGroupId={}", walGroupId, e);</span>
+<span class="source-line-no">159</span><span id="line-159"> break;</span>
+<span class="source-line-no">160</span><span id="line-160"> }</span>
+<span class="source-line-no">161</span><span id="line-161"> LOG.error("Shipper {} failed to persist offset, restarting", walGroupId, e);</span>
+<span class="source-line-no">162</span><span id="line-162"> abortAndRestart(e);</span>
+<span class="source-line-no">163</span><span id="line-163"> return;</span>
+<span class="source-line-no">164</span><span id="line-164"> }</span>
+<span class="source-line-no">165</span><span id="line-165"> }</span>
+<span class="source-line-no">166</span><span id="line-166"></span>
+<span class="source-line-no">167</span><span id="line-167"> // If the worker exits run loop without finishing its task, mark it as stopped.</span>
+<span class="source-line-no">168</span><span id="line-168"> if (!isFinished()) {</span>
+<span class="source-line-no">169</span><span id="line-169"> try {</span>
+<span class="source-line-no">170</span><span id="line-170"> persistLogPosition();</span>
+<span class="source-line-no">171</span><span id="line-171"> } catch (Exception e) {</span>
+<span class="source-line-no">172</span><span id="line-172"> LOG.error("Failed persisting final offset for walGroupId={}", walGroupId, e);</span>
+<span class="source-line-no">173</span><span id="line-173"> }</span>
+<span class="source-line-no">174</span><span id="line-174"> setWorkerState(WorkerState.STOPPED);</span>
+<span class="source-line-no">175</span><span id="line-175"> } else {</span>
+<span class="source-line-no">176</span><span id="line-176"> source.removeWorker(this);</span>
+<span class="source-line-no">177</span><span id="line-177"> postFinish();</span>
+<span class="source-line-no">178</span><span id="line-178"> }</span>
+<span class="source-line-no">179</span><span id="line-179"> }</span>
+<span class="source-line-no">180</span><span id="line-180"></span>
+<span class="source-line-no">181</span><span id="line-181"> private void noMoreData() throws IOException {</span>
+<span class="source-line-no">182</span><span id="line-182"> // Flush any outstanding replication offset before marking the queue finished.</span>
+<span class="source-line-no">183</span><span id="line-183"> // Offset persistence may be delayed by size/time thresholds, so ensure the</span>
+<span class="source-line-no">184</span><span id="line-184"> // latest replicated position is stored before transitioning to FINISHED state.</span>
+<span class="source-line-no">185</span><span id="line-185"> persistLogPosition();</span>
+<span class="source-line-no">186</span><span id="line-186"></span>
+<span class="source-line-no">187</span><span id="line-187"> if (source.isRecovered()) {</span>
+<span class="source-line-no">188</span><span id="line-188"> LOG.debug("Finished recovering queue for group {} of peer {}", walGroupId,</span>
+<span class="source-line-no">189</span><span id="line-189"> source.getQueueId());</span>
+<span class="source-line-no">190</span><span id="line-190"> source.getSourceMetrics().incrCompletedRecoveryQueue();</span>
+<span class="source-line-no">191</span><span id="line-191"> } else {</span>
+<span class="source-line-no">192</span><span id="line-192"> LOG.debug("Finished queue for group {} of peer {}", walGroupId, source.getQueueId());</span>
+<span class="source-line-no">193</span><span id="line-193"> }</span>
+<span class="source-line-no">194</span><span id="line-194"> setWorkerState(WorkerState.FINISHED);</span>
+<span class="source-line-no">195</span><span id="line-195"> }</span>
+<span class="source-line-no">196</span><span id="line-196"></span>
+<span class="source-line-no">197</span><span id="line-197"> // To be implemented by recovered shipper</span>
+<span class="source-line-no">198</span><span id="line-198"> protected void postFinish() {</span>
+<span class="source-line-no">199</span><span id="line-199"> }</span>
<span class="source-line-no">200</span><span id="line-200"></span>
-<span class="source-line-no">201</span><span id="line-201"> // offsets totalBufferUsed by deducting shipped batchSize (excludes bulk load size)</span>
-<span class="source-line-no">202</span><span id="line-202"> // this sizeExcludeBulkLoad has to use same calculation that when calling</span>
-<span class="source-line-no">203</span><span id="line-203"> // acquireBufferQuota() in ReplicationSourceWALReader because they maintain</span>
-<span class="source-line-no">204</span><span id="line-204"> // same variable: totalBufferUsed</span>
-<span class="source-line-no">205</span><span id="line-205"> source.postShipEdits(entries, entryBatch.getUsedBufferSize());</span>
-<span class="source-line-no">206</span><span id="line-206"> // FIXME check relationship between wal group and overall</span>
-<span class="source-line-no">207</span><span id="line-207"> source.getSourceMetrics().shipBatch(entryBatch.getNbOperations(), currentSize,</span>
-<span class="source-line-no">208</span><span id="line-208"> entryBatch.getNbHFiles());</span>
-<span class="source-line-no">209</span><span id="line-209"> source.getSourceMetrics().setAgeOfLastShippedOp(</span>
-<span class="source-line-no">210</span><span id="line-210"> entries.get(entries.size() - 1).getKey().getWriteTime(), walGroupId);</span>
-<span class="source-line-no">211</span><span id="line-211"> source.getSourceMetrics().updateTableLevelMetrics(entryBatch.getWalEntriesWithSize());</span>
-<span class="source-line-no">212</span><span id="line-212"></span>
-<span class="source-line-no">213</span><span id="line-213"> if (LOG.isTraceEnabled()) {</span>
-<span class="source-line-no">214</span><span id="line-214"> LOG.debug("Replicated {} entries or {} operations in {} ms", entries.size(),</span>
-<span class="source-line-no">215</span><span id="line-215"> entryBatch.getNbOperations(), (endTimeNs - startTimeNs) / 1000000);</span>
-<span class="source-line-no">216</span><span id="line-216"> }</span>
-<span class="source-line-no">217</span><span id="line-217"> break;</span>
-<span class="source-line-no">218</span><span id="line-218"> } catch (Exception ex) {</span>
-<span class="source-line-no">219</span><span id="line-219"> source.getSourceMetrics().incrementFailedBatches();</span>
-<span class="source-line-no">220</span><span id="line-220"> LOG.warn("{} threw unknown exception:",</span>
-<span class="source-line-no">221</span><span id="line-221"> source.getReplicationEndpoint().getClass().getName(), ex);</span>
-<span class="source-line-no">222</span><span id="line-222"> if (</span>
-<span class="source-line-no">223</span><span id="line-223"> sleepForRetries("ReplicationEndpoint threw exception", sleepForRetries, sleepMultiplier,</span>
-<span class="source-line-no">224</span><span id="line-224"> maxRetriesMultiplier)</span>
-<span class="source-line-no">225</span><span id="line-225"> ) {</span>
-<span class="source-line-no">226</span><span id="line-226"> sleepMultiplier++;</span>
-<span class="source-line-no">227</span><span id="line-227"> }</span>
-<span class="source-line-no">228</span><span id="line-228"> }</span>
-<span class="source-line-no">229</span><span id="line-229"> }</span>
-<span class="source-line-no">230</span><span id="line-230"> }</span>
-<span class="source-line-no">231</span><span id="line-231"></span>
-<span class="source-line-no">232</span><span id="line-232"> private void cleanUpHFileRefs(WALEdit edit) throws IOException {</span>
-<span class="source-line-no">233</span><span id="line-233"> String peerId = source.getPeerId();</span>
-<span class="source-line-no">234</span><span id="line-234"> if (peerId.contains("-")) {</span>
-<span class="source-line-no">235</span><span id="line-235"> // peerClusterZnode will be in the form peerId + "-" + rsZNode.</span>
-<span class="source-line-no">236</span><span id="line-236"> // A peerId will not have "-" in its name, see HBASE-11394</span>
-<span class="source-line-no">237</span><span id="line-237"> peerId = peerId.split("-")[0];</span>
-<span class="source-line-no">238</span><span id="line-238"> }</span>
-<span class="source-line-no">239</span><span id="line-239"> List<Cell> cells = edit.getCells();</span>
-<span class="source-line-no">240</span><span id="line-240"> int totalCells = cells.size();</span>
-<span class="source-line-no">241</span><span id="line-241"> for (int i = 0; i < totalCells; i++) {</span>
-<span class="source-line-no">242</span><span id="line-242"> Cell cell = cells.get(i);</span>
-<span class="source-line-no">243</span><span id="line-243"> if (CellUtil.matchingQualifier(cell, WALEdit.BULK_LOAD)) {</span>
-<span class="source-line-no">244</span><span id="line-244"> BulkLoadDescriptor bld = WALEdit.getBulkLoadDescriptor(cell);</span>
-<span class="source-line-no">245</span><span id="line-245"> List<StoreDescriptor> stores = bld.getStoresList();</span>
-<span class="source-line-no">246</span><span id="line-246"> int totalStores = stores.size();</span>
-<span class="source-line-no">247</span><span id="line-247"> for (int j = 0; j < totalStores; j++) {</span>
-<span class="source-line-no">248</span><span id="line-248"> List<String> storeFileList = stores.get(j).getStoreFileList();</span>
-<span class="source-line-no">249</span><span id="line-249"> source.getSourceManager().cleanUpHFileRefs(peerId, storeFileList);</span>
-<span class="source-line-no">250</span><span id="line-250"> source.getSourceMetrics().decrSizeOfHFileRefsQueue(storeFileList.size());</span>
+<span class="source-line-no">201</span><span id="line-201"> /**</span>
+<span class="source-line-no">202</span><span id="line-202"> * Do the shipping logic</span>
+<span class="source-line-no">203</span><span id="line-203"> */</span>
+<span class="source-line-no">204</span><span id="line-204"> void shipEdits(WALEntryBatch entryBatch) throws IOException {</span>
+<span class="source-line-no">205</span><span id="line-205"> List<Entry> entries = entryBatch.getWalEntries();</span>
+<span class="source-line-no">206</span><span id="line-206"> int sleepMultiplier = 0;</span>
+<span class="source-line-no">207</span><span id="line-207"> int currentSize = (int) entryBatch.getHeapSize();</span>
+<span class="source-line-no">208</span><span id="line-208"> MetricsSource metrics = source.getSourceMetrics();</span>
+<span class="source-line-no">209</span><span id="line-209"> if (metrics != null && !entries.isEmpty()) {</span>
+<span class="source-line-no">210</span><span id="line-210"> metrics.setTimeStampNextToReplicate(entries.get(entries.size() - 1).getKey().getWriteTime());</span>
+<span class="source-line-no">211</span><span id="line-211"> }</span>
+<span class="source-line-no">212</span><span id="line-212"> if (entries.isEmpty()) {</span>
+<span class="source-line-no">213</span><span id="line-213"> // empty batch may mean WAL boundary advancement</span>
+<span class="source-line-no">214</span><span id="line-214"> lastShippedBatch = entryBatch;</span>
+<span class="source-line-no">215</span><span id="line-215"> persistLogPosition();</span>
+<span class="source-line-no">216</span><span id="line-216"> return;</span>
+<span class="source-line-no">217</span><span id="line-217"> }</span>
+<span class="source-line-no">218</span><span id="line-218"> while (isActive()) {</span>
+<span class="source-line-no">219</span><span id="line-219"> try {</span>
+<span class="source-line-no">220</span><span id="line-220"> try {</span>
+<span class="source-line-no">221</span><span id="line-221"> source.tryThrottle(currentSize);</span>
+<span class="source-line-no">222</span><span id="line-222"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">223</span><span id="line-223"> LOG.debug("Interrupted while sleeping for throttling control");</span>
+<span class="source-line-no">224</span><span id="line-224"> Thread.currentThread().interrupt();</span>
+<span class="source-line-no">225</span><span id="line-225"> // current thread might be interrupted to terminate</span>
+<span class="source-line-no">226</span><span id="line-226"> // directly go back to while() for confirm this</span>
+<span class="source-line-no">227</span><span id="line-227"> continue;</span>
+<span class="source-line-no">228</span><span id="line-228"> }</span>
+<span class="source-line-no">229</span><span id="line-229"> // create replicateContext here, so the entries can be GC'd upon return from this call</span>
+<span class="source-line-no">230</span><span id="line-230"> // stack</span>
+<span class="source-line-no">231</span><span id="line-231"> ReplicationEndpoint.ReplicateContext replicateContext =</span>
+<span class="source-line-no">232</span><span id="line-232"> new ReplicationEndpoint.ReplicateContext();</span>
+<span class="source-line-no">233</span><span id="line-233"> replicateContext.setEntries(entries).setSize(currentSize);</span>
+<span class="source-line-no">234</span><span id="line-234"> replicateContext.setWalGroupId(walGroupId);</span>
+<span class="source-line-no">235</span><span id="line-235"> replicateContext.setTimeout(getAdaptiveTimeout(this.shipEditsTimeout, sleepMultiplier));</span>
+<span class="source-line-no">236</span><span id="line-236"></span>
+<span class="source-line-no">237</span><span id="line-237"> long startTimeNs = System.nanoTime();</span>
+<span class="source-line-no">238</span><span id="line-238"> // send the edits to the endpoint. Will block until the edits are shipped and acknowledged</span>
+<span class="source-line-no">239</span><span id="line-239"> boolean replicated = source.getReplicationEndpoint().replicate(replicateContext);</span>
+<span class="source-line-no">240</span><span id="line-240"> long endTimeNs = System.nanoTime();</span>
+<span class="source-line-no">241</span><span id="line-241"></span>
+<span class="source-line-no">242</span><span id="line-242"> if (!replicated) {</span>
+<span class="source-line-no">243</span><span id="line-243"> continue;</span>
+<span class="source-line-no">244</span><span id="line-244"> } else {</span>
+<span class="source-line-no">245</span><span id="line-245"> sleepMultiplier = Math.max(sleepMultiplier - 1, 0);</span>
+<span class="source-line-no">246</span><span id="line-246"> }</span>
+<span class="source-line-no">247</span><span id="line-247"> // Clean up hfile references</span>
+<span class="source-line-no">248</span><span id="line-248"> for (Entry entry : entries) {</span>
+<span class="source-line-no">249</span><span id="line-249"> cleanUpHFileRefs(entry.getEdit());</span>
+<span class="source-line-no">250</span><span id="line-250"> LOG.trace("shipped entry {}: ", entry);</span>
<span class="source-line-no">251</span><span id="line-251"> }</span>
-<span class="source-line-no">252</span><span id="line-252"> }</span>
-<span class="source-line-no">253</span><span id="line-253"> }</span>
-<span class="source-line-no">254</span><span id="line-254"> }</span>
-<span class="source-line-no">255</span><span id="line-255"></span>
-<span class="source-line-no">256</span><span id="line-256"> private boolean updateLogPosition(WALEntryBatch batch) {</span>
-<span class="source-line-no">257</span><span id="line-257"> boolean updated = false;</span>
-<span class="source-line-no">258</span><span id="line-258"> // if end of file is true, then the logPositionAndCleanOldLogs method will remove the file</span>
-<span class="source-line-no">259</span><span id="line-259"> // record on zk, so let's call it. The last wal position maybe zero if end of file is true and</span>
-<span class="source-line-no">260</span><span id="line-260"> // there is no entry in the batch. It is OK because that the queue storage will ignore the zero</span>
-<span class="source-line-no">261</span><span id="line-261"> // position and the file will be removed soon in cleanOldLogs.</span>
-<span class="source-line-no">262</span><span id="line-262"> if (</span>
-<span class="source-line-no">263</span><span id="line-263"> batch.isEndOfFile() || !batch.getLastWalPath().equals(currentPath)</span>
-<span class="source-line-no">264</span><span id="line-264"> || batch.getLastWalPosition() != currentPosition</span>
-<span class="source-line-no">265</span><span id="line-265"> ) {</span>
-<span class="source-line-no">266</span><span id="line-266"> source.logPositionAndCleanOldLogs(batch);</span>
-<span class="source-line-no">267</span><span id="line-267"> updated = true;</span>
-<span class="source-line-no">268</span><span id="line-268"> }</span>
-<span class="source-line-no">269</span><span id="line-269"> // if end of file is true, then we can just skip to the next file in queue.</span>
-<span class="source-line-no">270</span><span id="line-270"> // the only exception is for recovered queue, if we reach the end of the queue, then there will</span>
-<span class="source-line-no">271</span><span id="line-271"> // no more files so here the currentPath may be null.</span>
-<span class="source-line-no">272</span><span id="line-272"> if (batch.isEndOfFile()) {</span>
-<span class="source-line-no">273</span><span id="line-273"> currentPath = entryReader.getCurrentPath();</span>
-<span class="source-line-no">274</span><span id="line-274"> currentPosition = 0L;</span>
-<span class="source-line-no">275</span><span id="line-275"> } else {</span>
-<span class="source-line-no">276</span><span id="line-276"> currentPath = batch.getLastWalPath();</span>
-<span class="source-line-no">277</span><span id="line-277"> currentPosition = batch.getLastWalPosition();</span>
-<span class="source-line-no">278</span><span id="line-278"> }</span>
-<span class="source-line-no">279</span><span id="line-279"> return updated;</span>
-<span class="source-line-no">280</span><span id="line-280"> }</span>
-<span class="source-line-no">281</span><span id="line-281"></span>
-<span class="source-line-no">282</span><span id="line-282"> public void startup(UncaughtExceptionHandler handler) {</span>
-<span class="source-line-no">283</span><span id="line-283"> String name = Thread.currentThread().getName();</span>
-<span class="source-line-no">284</span><span id="line-284"> Threads.setDaemonThreadRunning(this,</span>
-<span class="source-line-no">285</span><span id="line-285"> name + ".replicationSource.shipper" + walGroupId + "," + source.getQueueId(),</span>
-<span class="source-line-no">286</span><span id="line-286"> handler::uncaughtException);</span>
-<span class="source-line-no">287</span><span id="line-287"> }</span>
-<span class="source-line-no">288</span><span id="line-288"></span>
-<span class="source-line-no">289</span><span id="line-289"> Path getCurrentPath() {</span>
-<span class="source-line-no">290</span><span id="line-290"> return entryReader.getCurrentPath();</span>
-<span class="source-line-no">291</span><span id="line-291"> }</span>
-<span class="source-line-no">292</span><span id="line-292"></span>
-<span class="source-line-no">293</span><span id="line-293"> long getCurrentPosition() {</span>
-<span class="source-line-no">294</span><span id="line-294"> return currentPosition;</span>
-<span class="source-line-no">295</span><span id="line-295"> }</span>
-<span class="source-line-no">296</span><span id="line-296"></span>
-<span class="source-line-no">297</span><span id="line-297"> protected boolean isActive() {</span>
-<span class="source-line-no">298</span><span id="line-298"> return source.isSourceActive() && state == WorkerState.RUNNING && !isInterrupted();</span>
-<span class="source-line-no">299</span><span id="line-299"> }</span>
-<span class="source-line-no">300</span><span id="line-300"></span>
-<span class="source-line-no">301</span><span id="line-301"> protected final void setWorkerState(WorkerState state) {</span>
-<span class="source-line-no">302</span><span id="line-302"> this.state = state;</span>
-<span class="source-line-no">303</span><span id="line-303"> }</span>
-<span class="source-line-no">304</span><span id="line-304"></span>
-<span class="source-line-no">305</span><span id="line-305"> void stopWorker() {</span>
-<span class="source-line-no">306</span><span id="line-306"> setWorkerState(WorkerState.STOPPED);</span>
-<span class="source-line-no">307</span><span id="line-307"> }</span>
-<span class="source-line-no">308</span><span id="line-308"></span>
-<span class="source-line-no">309</span><span id="line-309"> public boolean isFinished() {</span>
-<span class="source-line-no">310</span><span id="line-310"> return state == WorkerState.FINISHED;</span>
-<span class="source-line-no">311</span><span id="line-311"> }</span>
+<span class="source-line-no">252</span><span id="line-252"></span>
+<span class="source-line-no">253</span><span id="line-253"> // offsets totalBufferUsed by deducting shipped batchSize (excludes bulk load size)</span>
+<span class="source-line-no">254</span><span id="line-254"> // this sizeExcludeBulkLoad has to use same calculation that when calling</span>
+<span class="source-line-no">255</span><span id="line-255"> // acquireBufferQuota() in ReplicationSourceWALReader because they maintain</span>
+<span class="source-line-no">256</span><span id="line-256"> // same variable: totalBufferUsed</span>
+<span class="source-line-no">257</span><span id="line-257"> source.postShipEdits(entries, entryBatch.getUsedBufferSize());</span>
+<span class="source-line-no">258</span><span id="line-258"> // FIXME check relationship between wal group and overall</span>
+<span class="source-line-no">259</span><span id="line-259"> source.getSourceMetrics().shipBatch(entryBatch.getNbOperations(), currentSize,</span>
+<span class="source-line-no">260</span><span id="line-260"> entryBatch.getNbHFiles());</span>
+<span class="source-line-no">261</span><span id="line-261"> source.getSourceMetrics().setAgeOfLastShippedOp(</span>
+<span class="source-line-no">262</span><span id="line-262"> entries.get(entries.size() - 1).getKey().getWriteTime(), walGroupId);</span>
+<span class="source-line-no">263</span><span id="line-263"> source.getSourceMetrics().updateTableLevelMetrics(entryBatch.getWalEntriesWithSize());</span>
+<span class="source-line-no">264</span><span id="line-264"></span>
+<span class="source-line-no">265</span><span id="line-265"> if (LOG.isTraceEnabled()) {</span>
+<span class="source-line-no">266</span><span id="line-266"> LOG.debug("Replicated {} entries or {} operations in {} ms", entries.size(),</span>
+<span class="source-line-no">267</span><span id="line-267"> entryBatch.getNbOperations(), (endTimeNs - startTimeNs) / 1000000);</span>
+<span class="source-line-no">268</span><span id="line-268"> }</span>
+<span class="source-line-no">269</span><span id="line-269"> break;</span>
+<span class="source-line-no">270</span><span id="line-270"> } catch (Exception ex) {</span>
+<span class="source-line-no">271</span><span id="line-271"> source.getSourceMetrics().incrementFailedBatches();</span>
+<span class="source-line-no">272</span><span id="line-272"> LOG.warn("{} threw unknown exception:",</span>
+<span class="source-line-no">273</span><span id="line-273"> source.getReplicationEndpoint().getClass().getName(), ex);</span>
+<span class="source-line-no">274</span><span id="line-274"> if (</span>
+<span class="source-line-no">275</span><span id="line-275"> sleepForRetries("ReplicationEndpoint threw exception", sleepForRetries, sleepMultiplier,</span>
+<span class="source-line-no">276</span><span id="line-276"> maxRetriesMultiplier)</span>
+<span class="source-line-no">277</span><span id="line-277"> ) {</span>
+<span class="source-line-no">278</span><span id="line-278"> sleepMultiplier++;</span>
+<span class="source-line-no">279</span><span id="line-279"> }</span>
+<span class="source-line-no">280</span><span id="line-280"> }</span>
+<span class="source-line-no">281</span><span id="line-281"> }</span>
+<span class="source-line-no">282</span><span id="line-282"></span>
+<span class="source-line-no">283</span><span id="line-283"> accumulatedSizeSinceLastUpdate += currentSize;</span>
+<span class="source-line-no">284</span><span id="line-284"> lastShippedBatch = entryBatch;</span>
+<span class="source-line-no">285</span><span id="line-285"> if (shouldPersistLogPosition()) {</span>
+<span class="source-line-no">286</span><span id="line-286"> persistLogPosition();</span>
+<span class="source-line-no">287</span><span id="line-287"> }</span>
+<span class="source-line-no">288</span><span id="line-288"> }</span>
+<span class="source-line-no">289</span><span id="line-289"></span>
+<span class="source-line-no">290</span><span id="line-290"> private boolean shouldPersistLogPosition() {</span>
+<span class="source-line-no">291</span><span id="line-291"> if (lastShippedBatch == null) {</span>
+<span class="source-line-no">292</span><span id="line-292"> return false;</span>
+<span class="source-line-no">293</span><span id="line-293"> }</span>
+<span class="source-line-no">294</span><span id="line-294"> // Default behaviour to update offset immediately after replicate()</span>
+<span class="source-line-no">295</span><span id="line-295"> if (offsetUpdateSizeThresholdBytes == -1 && offsetUpdateIntervalMs == Long.MAX_VALUE) {</span>
+<span class="source-line-no">296</span><span id="line-296"> return true;</span>
+<span class="source-line-no">297</span><span id="line-297"> }</span>
+<span class="source-line-no">298</span><span id="line-298"></span>
+<span class="source-line-no">299</span><span id="line-299"> return (accumulatedSizeSinceLastUpdate >= offsetUpdateSizeThresholdBytes)</span>
+<span class="source-line-no">300</span><span id="line-300"> || (EnvironmentEdgeManager.currentTime() - lastOffsetUpdateTime >= offsetUpdateIntervalMs);</span>
+<span class="source-line-no">301</span><span id="line-301"> }</span>
+<span class="source-line-no">302</span><span id="line-302"></span>
+<span class="source-line-no">303</span><span id="line-303"> void persistLogPosition() throws IOException {</span>
+<span class="source-line-no">304</span><span id="line-304"> if (lastShippedBatch == null) {</span>
+<span class="source-line-no">305</span><span id="line-305"> return;</span>
+<span class="source-line-no">306</span><span id="line-306"> }</span>
+<span class="source-line-no">307</span><span id="line-307"></span>
+<span class="source-line-no">308</span><span id="line-308"> if (!source.isSourceActive() || isInterrupted() || !source.isPeerEnabled()) {</span>
+<span class="source-line-no">309</span><span id="line-309"> LOG.debug("Skip persistLogPosition for inactive/stopping source");</span>
+<span class="source-line-no">310</span><span id="line-310"> return;</span>
+<span class="source-line-no">311</span><span id="line-311"> }</span>
<span class="source-line-no">312</span><span id="line-312"></span>
-<span class="source-line-no">313</span><span id="line-313"> /**</span>
-<span class="source-line-no">314</span><span id="line-314"> * Attempts to properly update <code>ReplicationSourceManager.totalBufferUser</code>, in case</span>
-<span class="source-line-no">315</span><span id="line-315"> * there were unprocessed entries batched by the reader to the shipper, but the shipper didn't</span>
-<span class="source-line-no">316</span><span id="line-316"> * manage to ship those because the replication source is being terminated. In that case, it</span>
-<span class="source-line-no">317</span><span id="line-317"> * iterates through the batched entries and decrease the pending entries size from</span>
-<span class="source-line-no">318</span><span id="line-318"> * <code>ReplicationSourceManager.totalBufferUser</code></span>
-<span class="source-line-no">319</span><span id="line-319"> * <p/></span>
-<span class="source-line-no">320</span><span id="line-320"> * <b>NOTES</b> 1) This method should only be called upon replication source termination. It</span>
-<span class="source-line-no">321</span><span id="line-321"> * blocks waiting for both shipper and reader threads termination, to make sure no race conditions</span>
-<span class="source-line-no">322</span><span id="line-322"> * when updating <code>ReplicationSourceManager.totalBufferUser</code>. 2) It <b>does not</b></span>
-<span class="source-line-no">323</span><span id="line-323"> * attempt to terminate reader and shipper threads. Those <b>must</b> have been triggered</span>
-<span class="source-line-no">324</span><span id="line-324"> * interruption/termination prior to calling this method.</span>
-<span class="source-line-no">325</span><span id="line-325"> */</span>
-<span class="source-line-no">326</span><span id="line-326"> void clearWALEntryBatch() {</span>
-<span class="source-line-no">327</span><span id="line-327"> long timeout = EnvironmentEdgeManager.currentTime() + this.shipEditsTimeout;</span>
-<span class="source-line-no">328</span><span id="line-328"> while (this.isAlive() || this.entryReader.isAlive()) {</span>
-<span class="source-line-no">329</span><span id="line-329"> try {</span>
-<span class="source-line-no">330</span><span id="line-330"> if (EnvironmentEdgeManager.currentTime() >= timeout) {</span>
-<span class="source-line-no">331</span><span id="line-331"> LOG.warn("Shipper clearWALEntryBatch method timed out while waiting reader/shipper "</span>
-<span class="source-line-no">332</span><span id="line-332"> + "thread to stop. Not cleaning buffer usage. PeerId: {}; Shipper alive: {}; Reader "</span>
-<span class="source-line-no">333</span><span id="line-333"> + "alive: {}", this.source.getPeerId(), this.isAlive(), this.entryReader.isAlive());</span>
-<span class="source-line-no">334</span><span id="line-334"> return;</span>
-<span class="source-line-no">335</span><span id="line-335"> } else {</span>
-<span class="source-line-no">336</span><span id="line-336"> // Wait both shipper and reader threads to stop</span>
-<span class="source-line-no">337</span><span id="line-337"> Thread.sleep(this.sleepForRetries);</span>
-<span class="source-line-no">338</span><span id="line-338"> }</span>
-<span class="source-line-no">339</span><span id="line-339"> } catch (InterruptedException e) {</span>
-<span class="source-line-no">340</span><span id="line-340"> LOG.warn("{} Interrupted while waiting {} to stop on clearWALEntryBatch. "</span>
-<span class="source-line-no">341</span><span id="line-341"> + "Not cleaning buffer usage: {}", this.source.getPeerId(), this.getName(), e);</span>
-<span class="source-line-no">342</span><span id="line-342"> return;</span>
-<span class="source-line-no">343</span><span id="line-343"> }</span>
-<span class="source-line-no">344</span><span id="line-344"> }</span>
-<span class="source-line-no">345</span><span id="line-345"> long totalReleasedBytes = 0;</span>
-<span class="source-line-no">346</span><span id="line-346"> while (true) {</span>
-<span class="source-line-no">347</span><span id="line-347"> WALEntryBatch batch = entryReader.entryBatchQueue.poll();</span>
-<span class="source-line-no">348</span><span id="line-348"> if (batch == null) {</span>
-<span class="source-line-no">349</span><span id="line-349"> break;</span>
-<span class="source-line-no">350</span><span id="line-350"> }</span>
-<span class="source-line-no">351</span><span id="line-351"> totalReleasedBytes += source.getSourceManager().releaseWALEntryBatchBufferQuota(batch);</span>
-<span class="source-line-no">352</span><span id="line-352"> }</span>
-<span class="source-line-no">353</span><span id="line-353"> if (LOG.isTraceEnabled()) {</span>
-<span class="source-line-no">354</span><span id="line-354"> LOG.trace("Decrementing totalBufferUsed by {}B while stopping Replication WAL Readers.",</span>
-<span class="source-line-no">355</span><span id="line-355"> totalReleasedBytes);</span>
-<span class="source-line-no">356</span><span id="line-356"> }</span>
-<span class="source-line-no">357</span><span id="line-357"> }</span>
-<span class="source-line-no">358</span><span id="line-358"></span>
-<span class="source-line-no">359</span><span id="line-359"> long getSleepForRetries() {</span>
-<span class="source-line-no">360</span><span id="line-360"> return sleepForRetries;</span>
-<span class="source-line-no">361</span><span id="line-361"> }</span>
-<span class="source-line-no">362</span><span id="line-362">}</span>
+<span class="source-line-no">313</span><span id="line-313"> ReplicationEndpoint endpoint = source.getReplicationEndpoint();</span>
+<span class="source-line-no">314</span><span id="line-314"> if (endpoint != null) {</span>
+<span class="source-line-no">315</span><span id="line-315"> endpoint.beforePersistingReplicationOffset();</span>
+<span class="source-line-no">316</span><span id="line-316"> }</span>
+<span class="source-line-no">317</span><span id="line-317"></span>
+<span class="source-line-no">318</span><span id="line-318"> // Log and clean up WAL logs</span>
+<span class="source-line-no">319</span><span id="line-319"> updateLogPosition(lastShippedBatch);</span>
+<span class="source-line-no">320</span><span id="line-320"> accumulatedSizeSinceLastUpdate = 0;</span>
+<span class="source-line-no">321</span><span id="line-321"> lastShippedBatch = null;</span>
+<span class="source-line-no">322</span><span id="line-322"> lastOffsetUpdateTime = EnvironmentEdgeManager.currentTime();</span>
+<span class="source-line-no">323</span><span id="line-323"> }</span>
+<span class="source-line-no">324</span><span id="line-324"></span>
+<span class="source-line-no">325</span><span id="line-325"> void cleanUpHFileRefs(WALEdit edit) throws IOException {</span>
+<span class="source-line-no">326</span><span id="line-326"> String peerId = source.getPeerId();</span>
+<span class="source-line-no">327</span><span id="line-327"> if (peerId.contains("-")) {</span>
+<span class="source-line-no">328</span><span id="line-328"> // peerClusterZnode will be in the form peerId + "-" + rsZNode.</span>
+<span class="source-line-no">329</span><span id="line-329"> // A peerId will not have "-" in its name, see HBASE-11394</span>
+<span class="source-line-no">330</span><span id="line-330"> peerId = peerId.split("-")[0];</span>
+<span class="source-line-no">331</span><span id="line-331"> }</span>
+<span class="source-line-no">332</span><span id="line-332"> List<Cell> cells = edit.getCells();</span>
+<span class="source-line-no">333</span><span id="line-333"> int totalCells = cells.size();</span>
+<span class="source-line-no">334</span><span id="line-334"> for (int i = 0; i < totalCells; i++) {</span>
+<span class="source-line-no">335</span><span id="line-335"> Cell cell = cells.get(i);</span>
+<span class="source-line-no">336</span><span id="line-336"> if (CellUtil.matchingQualifier(cell, WALEdit.BULK_LOAD)) {</span>
+<span class="source-line-no">337</span><span id="line-337"> BulkLoadDescriptor bld = WALEdit.getBulkLoadDescriptor(cell);</span>
+<span class="source-line-no">338</span><span id="line-338"> List<StoreDescriptor> stores = bld.getStoresList();</span>
+<span class="source-line-no">339</span><span id="line-339"> int totalStores = stores.size();</span>
+<span class="source-line-no">340</span><span id="line-340"> for (int j = 0; j < totalStores; j++) {</span>
+<span class="source-line-no">341</span><span id="line-341"> List<String> storeFileList = stores.get(j).getStoreFileList();</span>
+<span class="source-line-no">342</span><span id="line-342"> source.getSourceManager().cleanUpHFileRefs(peerId, storeFileList);</span>
+<span class="source-line-no">343</span><span id="line-343"> source.getSourceMetrics().decrSizeOfHFileRefsQueue(storeFileList.size());</span>
+<span class="source-line-no">344</span><span id="line-344"> }</span>
+<span class="source-line-no">345</span><span id="line-345"> }</span>
+<span class="source-line-no">346</span><span id="line-346"> }</span>
+<span class="source-line-no">347</span><span id="line-347"> }</span>
+<span class="source-line-no">348</span><span id="line-348"></span>
+<span class="source-line-no">349</span><span id="line-349"> private boolean updateLogPosition(WALEntryBatch batch) {</span>
+<span class="source-line-no">350</span><span id="line-350"> boolean updated = false;</span>
+<span class="source-line-no">351</span><span id="line-351"> // if end of file is true, then the logPositionAndCleanOldLogs method will remove the file</span>
+<span class="source-line-no">352</span><span id="line-352"> // record on zk, so let's call it. The last wal position maybe zero if end of file is true and</span>
+<span class="source-line-no">353</span><span id="line-353"> // there is no entry in the batch. It is OK because that the queue storage will ignore the zero</span>
+<span class="source-line-no">354</span><span id="line-354"> // position and the file will be removed soon in cleanOldLogs.</span>
+<span class="source-line-no">355</span><span id="line-355"> if (</span>
+<span class="source-line-no">356</span><span id="line-356"> batch.isEndOfFile() || !batch.getLastWalPath().equals(currentPath)</span>
+<span class="source-line-no">357</span><span id="line-357"> || batch.getLastWalPosition() != currentPosition</span>
+<span class="source-line-no">358</span><span id="line-358"> ) {</span>
+<span class="source-line-no">359</span><span id="line-359"> source.logPositionAndCleanOldLogs(batch);</span>
+<span class="source-line-no">360</span><span id="line-360"> updated = true;</span>
+<span class="source-line-no">361</span><span id="line-361"> }</span>
+<span class="source-line-no">362</span><span id="line-362"> // if end of file is true, then we can just skip to the next file in queue.</span>
+<span class="source-line-no">363</span><span id="line-363"> // the only exception is for recovered queue, if we reach the end of the queue, then there will</span>
+<span class="source-line-no">364</span><span id="line-364"> // no more files so here the currentPath may be null.</span>
+<span class="source-line-no">365</span><span id="line-365"> if (batch.isEndOfFile()) {</span>
+<span class="source-line-no">366</span><span id="line-366"> currentPath = entryReader.getCurrentPath();</span>
+<span class="source-line-no">367</span><span id="line-367"> currentPosition = 0L;</span>
+<span class="source-line-no">368</span><span id="line-368"> } else {</span>
+<span class="source-line-no">369</span><span id="line-369"> currentPath = batch.getLastWalPath();</span>
+<span class="source-line-no">370</span><span id="line-370"> currentPosition = batch.getLastWalPosition();</span>
+<span class="source-line-no">371</span><span id="line-371"> }</span>
+<span class="source-line-no">372</span><span id="line-372"> return updated;</span>
+<span class="source-line-no">373</span><span id="line-373"> }</span>
+<span class="source-line-no">374</span><span id="line-374"></span>
+<span class="source-line-no">375</span><span id="line-375"> public void startup(UncaughtExceptionHandler handler) {</span>
+<span class="source-line-no">376</span><span id="line-376"> String name = Thread.currentThread().getName();</span>
+<span class="source-line-no">377</span><span id="line-377"> Threads.setDaemonThreadRunning(this,</span>
+<span class="source-line-no">378</span><span id="line-378"> name + ".replicationSource.shipper" + walGroupId + "," + source.getQueueId(),</span>
+<span class="source-line-no">379</span><span id="line-379"> handler::uncaughtException);</span>
+<span class="source-line-no">380</span><span id="line-380"> }</span>
+<span class="source-line-no">381</span><span id="line-381"></span>
+<span class="source-line-no">382</span><span id="line-382"> Path getCurrentPath() {</span>
+<span class="source-line-no">383</span><span id="line-383"> return entryReader.getCurrentPath();</span>
+<span class="source-line-no">384</span><span id="line-384"> }</span>
+<span class="source-line-no">385</span><span id="line-385"></span>
+<span class="source-line-no">386</span><span id="line-386"> long getCurrentPosition() {</span>
+<span class="source-line-no">387</span><span id="line-387"> return currentPosition;</span>
+<span class="source-line-no">388</span><span id="line-388"> }</span>
+<span class="source-line-no">389</span><span id="line-389"></span>
+<span class="source-line-no">390</span><span id="line-390"> protected boolean isActive() {</span>
+<span class="source-line-no">391</span><span id="line-391"> return source.isSourceActive() && state == WorkerState.RUNNING && !isInterrupted();</span>
+<span class="source-line-no">392</span><span id="line-392"> }</span>
+<span class="source-line-no">393</span><span id="line-393"></span>
+<span class="source-line-no">394</span><span id="line-394"> protected final void setWorkerState(WorkerState state) {</span>
+<span class="source-line-no">395</span><span id="line-395"> this.state = state;</span>
+<span class="source-line-no">396</span><span id="line-396"> }</span>
+<span class="source-line-no">397</span><span id="line-397"></span>
+<span class="source-line-no">398</span><span id="line-398"> void stopWorker() {</span>
+<span class="source-line-no">399</span><span id="line-399"> setWorkerState(WorkerState.STOPPED);</span>
+<span class="source-line-no">400</span><span id="line-400"> }</span>
+<span class="source-line-no">401</span><span id="line-401"></span>
+<span class="source-line-no">402</span><span id="line-402"> public boolean isFinished() {</span>
+<span class="source-line-no">403</span><span id="line-403"> return state == WorkerState.FINISHED;</span>
+<span class="source-line-no">404</span><span id="line-404"> }</span>
+<span class="source-line-no">405</span><span id="line-405"></span>
+<span class="source-line-no">406</span><span id="line-406"> /**</span>
+<span class="source-line-no">407</span><span id="line-407"> * Attempts to properly update <code>ReplicationSourceManager.totalBufferUser</code>, in case</span>
+<span class="source-line-no">408</span><span id="line-408"> * there were unprocessed entries batched by the reader to the shipper, but the shipper didn't</span>
+<span class="source-line-no">409</span><span id="line-409"> * manage to ship those because the replication source is being terminated. In that case, it</span>
+<span class="source-line-no">410</span><span id="line-410"> * iterates through the batched entries and decrease the pending entries size from</span>
+<span class="source-line-no">411</span><span id="line-411"> * <code>ReplicationSourceManager.totalBufferUser</code></span>
+<span class="source-line-no">412</span><span id="line-412"> * <p/></span>
+<span class="source-line-no">413</span><span id="line-413"> * <b>NOTES</b> 1) This method should only be called upon replication source termination. It</span>
+<span class="source-line-no">414</span><span id="line-414"> * blocks waiting for both shipper and reader threads termination, to make sure no race conditions</span>
+<span class="source-line-no">415</span><span id="line-415"> * when updating <code>ReplicationSourceManager.totalBufferUser</code>. 2) It <b>does not</b></span>
+<span class="source-line-no">416</span><span id="line-416"> * attempt to terminate reader and shipper threads. Those <b>must</b> have been triggered</span>
+<span class="source-line-no">417</span><span id="line-417"> * interruption/termination prior to calling this method.</span>
+<span class="source-line-no">418</span><span id="line-418"> */</span>
+<span class="source-line-no">419</span><span id="line-419"> void clearWALEntryBatch() {</span>
+<span class="source-line-no">420</span><span id="line-420"> long timeout = EnvironmentEdgeManager.currentTime() + this.shipEditsTimeout;</span>
+<span class="source-line-no">421</span><span id="line-421"> while (this.isAlive() || this.entryReader.isAlive()) {</span>
+<span class="source-line-no">422</span><span id="line-422"> try {</span>
+<span class="source-line-no">423</span><span id="line-423"> if (EnvironmentEdgeManager.currentTime() >= timeout) {</span>
+<span class="source-line-no">424</span><span id="line-424"> LOG.warn("Shipper clearWALEntryBatch method timed out while waiting reader/shipper "</span>
+<span class="source-line-no">425</span><span id="line-425"> + "thread to stop. Not cleaning buffer usage. PeerId: {}; Shipper alive: {}; Reader "</span>
+<span class="source-line-no">426</span><span id="line-426"> + "alive: {}", this.source.getPeerId(), this.isAlive(), this.entryReader.isAlive());</span>
+<span class="source-line-no">427</span><span id="line-427"> return;</span>
+<span class="source-line-no">428</span><span id="line-428"> } else {</span>
+<span class="source-line-no">429</span><span id="line-429"> // Wait both shipper and reader threads to stop</span>
+<span class="source-line-no">430</span><span id="line-430"> Thread.sleep(this.sleepForRetries);</span>
+<span class="source-line-no">431</span><span id="line-431"> }</span>
+<span class="source-line-no">432</span><span id="line-432"> } catch (InterruptedException e) {</span>
+<span class="source-line-no">433</span><span id="line-433"> LOG.warn("{} Interrupted while waiting {} to stop on clearWALEntryBatch. "</span>
+<span class="source-line-no">434</span><span id="line-434"> + "Not cleaning buffer usage: {}", this.source.getPeerId(), this.getName(), e);</span>
+<span class="source-line-no">435</span><span id="line-435"> return;</span>
+<span class="source-line-no">436</span><span id="line-436"> }</span>
+<span class="source-line-no">437</span><span id="line-437"> }</span>
+<span class="source-line-no">438</span><span id="line-438"> long totalReleasedBytes = 0;</span>
+<span class="source-line-no">439</span><span id="line-439"> while (true) {</span>
+<span class="source-line-no">440</span><span id="line-440"> WALEntryBatch batch = entryReader.entryBatchQueue.poll();</span>
+<span class="source-line-no">441</span><span id="line-441"> if (batch == null) {</span>
+<span class="source-line-no">442</span><span id="line-442"> break;</span>
+<span class="source-line-no">443</span><span id="line-443"> }</span>
+<span class="source-line-no">444</span><span id="line-444"> totalReleasedBytes += source.getSourceManager().releaseWALEntryBatchBufferQuota(batch);</span>
+<span class="source-line-no">445</span><span id="line-445"> }</span>
+<span class="source-line-no">446</span><span id="line-446"> if (LOG.isTraceEnabled()) {</span>
+<span class="source-line-no">447</span><span id="line-447"> LOG.trace("Decrementing totalBufferUsed by {}B while stopping Replication WAL Readers.",</span>
+<span class="source-line-no">448</span><span id="line-448"> totalReleasedBytes);</span>
+<span class="source-line-no">449</span><span id="line-449"> }</span>
+<span class="source-line-no">450</span><span id="line-450"> }</span>
+<span class="source-line-no">451</span><span id="line-451"></span>
+<span class="source-line-no">452</span><span id="line-452"> long getSleepForRetries() {</span>
+<span class="source-line-no">453</span><span id="line-453"> return sleepForRetries;</span>
+<span class="source-line-no">454</span><span id="line-454"> }</span>
+<span class="source-line-no">455</span><span id="line-455"></span>
+<span class="source-line-no">456</span><span id="line-456"> // Restart worker so replication resumes from last persisted offset.</span>
+<span class="source-line-no">457</span><span id="line-457"> void abortAndRestart(Throwable cause) {</span>
+<span class="source-line-no">458</span><span id="line-458"> LOG.warn("Restarting shipper for walGroupId={}", walGroupId, cause);</span>
+<span class="source-line-no">459</span><span id="line-459"> if (!source.isSourceActive() || !source.isPeerEnabled() || isInterrupted()) {</span>
+<span class="source-line-no">460</span><span id="line-460"> LOG.warn("abortAndRestart SKIPPED walGroupId={}, thread={}", walGroupId,</span>
+<span class="source-line-no">461</span><span id="line-461"> Thread.currentThread().getName());</span>
+<span class="source-line-no">462</span><span id="line-462"> return;</span>
+<span class="source-line-no">463</span><span id="line-463"> }</span>
+<span class="source-line-no">464</span><span id="line-464"> setWorkerState(WorkerState.STOPPED);</span>
+<span class="source-line-no">465</span><span id="line-465"> source.restartShipper(walGroupId, this);</span>
+<span class="source-line-no">466</span><span id="line-466"> }</span>
+<span class="source-line-no">467</span><span id="line-467">}</span>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html b/devapidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html
index 706f981cbdf..b8a14c91b7d 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.Options.html
@@ -30,731 +30,752 @@
<span class="source-line-no">017</span><span id="line-17"> */</span>
<span class="source-line-no">018</span><span id="line-18">package org.apache.hadoop.hbase.snapshot;</span>
<span class="source-line-no">019</span><span id="line-19"></span>
-<span class="source-line-no">020</span><span id="line-20">import java.io.FileNotFoundException;</span>
-<span class="source-line-no">021</span><span id="line-21">import java.io.IOException;</span>
-<span class="source-line-no">022</span><span id="line-22">import java.net.URI;</span>
-<span class="source-line-no">023</span><span id="line-23">import java.text.SimpleDateFormat;</span>
-<span class="source-line-no">024</span><span id="line-24">import java.util.ArrayList;</span>
-<span class="source-line-no">025</span><span id="line-25">import java.util.Collections;</span>
-<span class="source-line-no">026</span><span id="line-26">import java.util.Date;</span>
-<span class="source-line-no">027</span><span id="line-27">import java.util.List;</span>
-<span class="source-line-no">028</span><span id="line-28">import java.util.Map;</span>
-<span class="source-line-no">029</span><span id="line-29">import java.util.Properties;</span>
-<span class="source-line-no">030</span><span id="line-30">import java.util.concurrent.ConcurrentHashMap;</span>
-<span class="source-line-no">031</span><span id="line-31">import java.util.concurrent.ExecutorService;</span>
-<span class="source-line-no">032</span><span id="line-32">import java.util.concurrent.atomic.AtomicInteger;</span>
-<span class="source-line-no">033</span><span id="line-33">import java.util.concurrent.atomic.AtomicLong;</span>
-<span class="source-line-no">034</span><span id="line-34">import org.apache.hadoop.conf.Configuration;</span>
-<span class="source-line-no">035</span><span id="line-35">import org.apache.hadoop.fs.FileStatus;</span>
-<span class="source-line-no">036</span><span id="line-36">import org.apache.hadoop.fs.FileSystem;</span>
-<span class="source-line-no">037</span><span id="line-37">import org.apache.hadoop.fs.Path;</span>
-<span class="source-line-no">038</span><span id="line-38">import org.apache.hadoop.hbase.TableName;</span>
-<span class="source-line-no">039</span><span id="line-39">import org.apache.hadoop.hbase.client.RegionInfo;</span>
-<span class="source-line-no">040</span><span id="line-40">import org.apache.hadoop.hbase.client.SnapshotDescription;</span>
-<span class="source-line-no">041</span><span id="line-41">import org.apache.hadoop.hbase.io.HFileLink;</span>
-<span class="source-line-no">042</span><span id="line-42">import org.apache.hadoop.hbase.io.WALLink;</span>
-<span class="source-line-no">043</span><span id="line-43">import org.apache.hadoop.hbase.util.AbstractHBaseTool;</span>
-<span class="source-line-no">044</span><span id="line-44">import org.apache.hadoop.hbase.util.CommonFSUtils;</span>
-<span class="source-line-no">045</span><span id="line-45">import org.apache.hadoop.hbase.util.Strings;</span>
-<span class="source-line-no">046</span><span id="line-46">import org.apache.yetus.audience.InterfaceAudience;</span>
-<span class="source-line-no">047</span><span id="line-47">import org.slf4j.Logger;</span>
-<span class="source-line-no">048</span><span id="line-48">import org.slf4j.LoggerFactory;</span>
-<span class="source-line-no">049</span><span id="line-49"></span>
-<span class="source-line-no">050</span><span id="line-50">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;</span>
-<span class="source-line-no">051</span><span id="line-51">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLineParser;</span>
-<span class="source-line-no">052</span><span id="line-52">import org.apache.hbase.thirdparty.org.apache.commons.cli.DefaultParser;</span>
-<span class="source-line-no">053</span><span id="line-53">import org.apache.hbase.thirdparty.org.apache.commons.cli.Option;</span>
-<span class="source-line-no">054</span><span id="line-54">import org.apache.hbase.thirdparty.org.apache.commons.cli.Options;</span>
-<span class="source-line-no">055</span><span id="line-55">import org.apache.hbase.thirdparty.org.apache.commons.cli.ParseException;</span>
-<span class="source-line-no">056</span><span id="line-56"></span>
-<span class="source-line-no">057</span><span id="line-57">import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;</span>
-<span class="source-line-no">058</span><span id="line-58">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos;</span>
-<span class="source-line-no">059</span><span id="line-59">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;</span>
-<span class="source-line-no">060</span><span id="line-60"></span>
-<span class="source-line-no">061</span><span id="line-61">/**</span>
-<span class="source-line-no">062</span><span id="line-62"> * Tool for dumping snapshot information.</span>
-<span class="source-line-no">063</span><span id="line-63"> * <ol></span>
-<span class="source-line-no">064</span><span id="line-64"> * <li>Table Descriptor</span>
-<span class="source-line-no">065</span><span id="line-65"> * <li>Snapshot creation time, type, format version, ...</span>
-<span class="source-line-no">066</span><span id="line-66"> * <li>List of hfiles and wals</span>
-<span class="source-line-no">067</span><span id="line-67"> * <li>Stats about hfiles and logs sizes, percentage of shared with the source table, ...</span>
-<span class="source-line-no">068</span><span id="line-68"> * </ol></span>
-<span class="source-line-no">069</span><span id="line-69"> */</span>
-<span class="source-line-no">070</span><span id="line-70">@InterfaceAudience.Public</span>
-<span class="source-line-no">071</span><span id="line-71">public final class SnapshotInfo extends AbstractHBaseTool {</span>
-<span class="source-line-no">072</span><span id="line-72"> private static final Logger LOG = LoggerFactory.getLogger(SnapshotInfo.class);</span>
-<span class="source-line-no">073</span><span id="line-73"></span>
-<span class="source-line-no">074</span><span id="line-74"> static final class Options {</span>
-<span class="source-line-no">075</span><span id="line-75"> static final Option SNAPSHOT =</span>
-<span class="source-line-no">076</span><span id="line-76"> new Option(null, "snapshot", true, "The name of the snapshot to be detailed.");</span>
-<span class="source-line-no">077</span><span id="line-77"> static final Option REMOTE_DIR =</span>
-<span class="source-line-no">078</span><span id="line-78"> new Option(null, "remote-dir", true, "A custom root directory where snapshots are stored. "</span>
-<span class="source-line-no">079</span><span id="line-79"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">080</span><span id="line-80"> static final Option LIST_SNAPSHOTS =</span>
-<span class="source-line-no">081</span><span id="line-81"> new Option(null, "list-snapshots", false, "List all the available snapshots and exit.");</span>
-<span class="source-line-no">082</span><span id="line-82"> static final Option FILES =</span>
-<span class="source-line-no">083</span><span id="line-83"> new Option(null, "files", false, "The list of files retained by the specified snapshot. "</span>
-<span class="source-line-no">084</span><span id="line-84"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">085</span><span id="line-85"> static final Option STATS =</span>
-<span class="source-line-no">086</span><span id="line-86"> new Option(null, "stats", false, "Additional information about the specified snapshot. "</span>
-<span class="source-line-no">087</span><span id="line-87"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">088</span><span id="line-88"> static final Option SCHEMA = new Option(null, "schema", false,</span>
-<span class="source-line-no">089</span><span id="line-89"> "Show the descriptor of the table for the specified snapshot. "</span>
+<span class="source-line-no">020</span><span id="line-20">import static org.apache.hadoop.hbase.HConstants.DEFAULT_SNAPSHOT_TTL;</span>
+<span class="source-line-no">021</span><span id="line-21"></span>
+<span class="source-line-no">022</span><span id="line-22">import java.io.FileNotFoundException;</span>
+<span class="source-line-no">023</span><span id="line-23">import java.io.IOException;</span>
+<span class="source-line-no">024</span><span id="line-24">import java.net.URI;</span>
+<span class="source-line-no">025</span><span id="line-25">import java.text.SimpleDateFormat;</span>
+<span class="source-line-no">026</span><span id="line-26">import java.util.ArrayList;</span>
+<span class="source-line-no">027</span><span id="line-27">import java.util.Collections;</span>
+<span class="source-line-no">028</span><span id="line-28">import java.util.Date;</span>
+<span class="source-line-no">029</span><span id="line-29">import java.util.List;</span>
+<span class="source-line-no">030</span><span id="line-30">import java.util.Map;</span>
+<span class="source-line-no">031</span><span id="line-31">import java.util.Properties;</span>
+<span class="source-line-no">032</span><span id="line-32">import java.util.concurrent.ConcurrentHashMap;</span>
+<span class="source-line-no">033</span><span id="line-33">import java.util.concurrent.ExecutorService;</span>
+<span class="source-line-no">034</span><span id="line-34">import java.util.concurrent.atomic.AtomicInteger;</span>
+<span class="source-line-no">035</span><span id="line-35">import java.util.concurrent.atomic.AtomicLong;</span>
+<span class="source-line-no">036</span><span id="line-36">import org.apache.hadoop.conf.Configuration;</span>
+<span class="source-line-no">037</span><span id="line-37">import org.apache.hadoop.fs.FileStatus;</span>
+<span class="source-line-no">038</span><span id="line-38">import org.apache.hadoop.fs.FileSystem;</span>
+<span class="source-line-no">039</span><span id="line-39">import org.apache.hadoop.fs.Path;</span>
+<span class="source-line-no">040</span><span id="line-40">import org.apache.hadoop.hbase.TableName;</span>
+<span class="source-line-no">041</span><span id="line-41">import org.apache.hadoop.hbase.client.RegionInfo;</span>
+<span class="source-line-no">042</span><span id="line-42">import org.apache.hadoop.hbase.client.SnapshotDescription;</span>
+<span class="source-line-no">043</span><span id="line-43">import org.apache.hadoop.hbase.io.HFileLink;</span>
+<span class="source-line-no">044</span><span id="line-44">import org.apache.hadoop.hbase.io.WALLink;</span>
+<span class="source-line-no">045</span><span id="line-45">import org.apache.hadoop.hbase.util.AbstractHBaseTool;</span>
+<span class="source-line-no">046</span><span id="line-46">import org.apache.hadoop.hbase.util.CommonFSUtils;</span>
+<span class="source-line-no">047</span><span id="line-47">import org.apache.hadoop.hbase.util.Strings;</span>
+<span class="source-line-no">048</span><span id="line-48">import org.apache.yetus.audience.InterfaceAudience;</span>
+<span class="source-line-no">049</span><span id="line-49">import org.slf4j.Logger;</span>
+<span class="source-line-no">050</span><span id="line-50">import org.slf4j.LoggerFactory;</span>
+<span class="source-line-no">051</span><span id="line-51"></span>
+<span class="source-line-no">052</span><span id="line-52">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;</span>
+<span class="source-line-no">053</span><span id="line-53">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLineParser;</span>
+<span class="source-line-no">054</span><span id="line-54">import org.apache.hbase.thirdparty.org.apache.commons.cli.DefaultParser;</span>
+<span class="source-line-no">055</span><span id="line-55">import org.apache.hbase.thirdparty.org.apache.commons.cli.Option;</span>
+<span class="source-line-no">056</span><span id="line-56">import org.apache.hbase.thirdparty.org.apache.commons.cli.Options;</span>
+<span class="source-line-no">057</span><span id="line-57">import org.apache.hbase.thirdparty.org.apache.commons.cli.ParseException;</span>
+<span class="source-line-no">058</span><span id="line-58"></span>
+<span class="source-line-no">059</span><span id="line-59">import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;</span>
+<span class="source-line-no">060</span><span id="line-60">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos;</span>
+<span class="source-line-no">061</span><span id="line-61">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;</span>
+<span class="source-line-no">062</span><span id="line-62"></span>
+<span class="source-line-no">063</span><span id="line-63">/**</span>
+<span class="source-line-no">064</span><span id="line-64"> * Tool for dumping snapshot information.</span>
+<span class="source-line-no">065</span><span id="line-65"> * <ol></span>
+<span class="source-line-no">066</span><span id="line-66"> * <li>Table Descriptor</span>
+<span class="source-line-no">067</span><span id="line-67"> * <li>Snapshot creation time, type, format version, ...</span>
+<span class="source-line-no">068</span><span id="line-68"> * <li>List of hfiles and wals</span>
+<span class="source-line-no">069</span><span id="line-69"> * <li>Stats about hfiles and logs sizes, percentage of shared with the source table, ...</span>
+<span class="source-line-no">070</span><span id="line-70"> * </ol></span>
+<span class="source-line-no">071</span><span id="line-71"> */</span>
+<span class="source-line-no">072</span><span id="line-72">@InterfaceAudience.Public</span>
+<span class="source-line-no">073</span><span id="line-73">public final class SnapshotInfo extends AbstractHBaseTool {</span>
+<span class="source-line-no">074</span><span id="line-74"> private static final Logger LOG = LoggerFactory.getLogger(SnapshotInfo.class);</span>
+<span class="source-line-no">075</span><span id="line-75"></span>
+<span class="source-line-no">076</span><span id="line-76"> private static final String EXPIRED_LABEL = "Yes";</span>
+<span class="source-line-no">077</span><span id="line-77"> private static final String NOT_EXPIRED_LABEL = "No";</span>
+<span class="source-line-no">078</span><span id="line-78"> private static final String TTL_FOREVER = "FOREVER";</span>
+<span class="source-line-no">079</span><span id="line-79"></span>
+<span class="source-line-no">080</span><span id="line-80"> static final class Options {</span>
+<span class="source-line-no">081</span><span id="line-81"> static final Option SNAPSHOT =</span>
+<span class="source-line-no">082</span><span id="line-82"> new Option(null, "snapshot", true, "The name of the snapshot to be detailed.");</span>
+<span class="source-line-no">083</span><span id="line-83"> static final Option REMOTE_DIR =</span>
+<span class="source-line-no">084</span><span id="line-84"> new Option(null, "remote-dir", true, "A custom root directory where snapshots are stored. "</span>
+<span class="source-line-no">085</span><span id="line-85"> + "Use it together with the --snapshot option.");</span>
+<span class="source-line-no">086</span><span id="line-86"> static final Option LIST_SNAPSHOTS =</span>
+<span class="source-line-no">087</span><span id="line-87"> new Option(null, "list-snapshots", false, "List all the available snapshots and exit.");</span>
+<span class="source-line-no">088</span><span id="line-88"> static final Option FILES =</span>
+<span class="source-line-no">089</span><span id="line-89"> new Option(null, "files", false, "The list of files retained by the specified snapshot. "</span>
<span class="source-line-no">090</span><span id="line-90"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">091</span><span id="line-91"> static final Option SIZE_IN_BYTES =</span>
-<span class="source-line-no">092</span><span id="line-92"> new Option(null, "size-in-bytes", false, "Print the size of the files in bytes. "</span>
-<span class="source-line-no">093</span><span id="line-93"> + "Use it together with the --snapshot and --files options.");</span>
-<span class="source-line-no">094</span><span id="line-94"> }</span>
-<span class="source-line-no">095</span><span id="line-95"></span>
-<span class="source-line-no">096</span><span id="line-96"> /**</span>
-<span class="source-line-no">097</span><span id="line-97"> * Statistics about the snapshot</span>
-<span class="source-line-no">098</span><span id="line-98"> * <ol></span>
-<span class="source-line-no">099</span><span id="line-99"> * <li>How many store files and logs are in the archive</span>
-<span class="source-line-no">100</span><span id="line-100"> * <li>How many store files and logs are shared with the table</span>
-<span class="source-line-no">101</span><span id="line-101"> * <li>Total store files and logs size and shared amount</span>
-<span class="source-line-no">102</span><span id="line-102"> * </ol></span>
-<span class="source-line-no">103</span><span id="line-103"> */</span>
-<span class="source-line-no">104</span><span id="line-104"> public static class SnapshotStats {</span>
-<span class="source-line-no">105</span><span id="line-105"> /** Information about the file referenced by the snapshot */</span>
-<span class="source-line-no">106</span><span id="line-106"> static class FileInfo {</span>
-<span class="source-line-no">107</span><span id="line-107"> private final boolean corrupted;</span>
-<span class="source-line-no">108</span><span id="line-108"> private final boolean inArchive;</span>
-<span class="source-line-no">109</span><span id="line-109"> private final long size;</span>
-<span class="source-line-no">110</span><span id="line-110"></span>
-<span class="source-line-no">111</span><span id="line-111"> FileInfo(final boolean inArchive, final long size, final boolean corrupted) {</span>
-<span class="source-line-no">112</span><span id="line-112"> this.corrupted = corrupted;</span>
-<span class="source-line-no">113</span><span id="line-113"> this.inArchive = inArchive;</span>
-<span class="source-line-no">114</span><span id="line-114"> this.size = size;</span>
-<span class="source-line-no">115</span><span id="line-115"> }</span>
+<span class="source-line-no">091</span><span id="line-91"> static final Option STATS =</span>
+<span class="source-line-no">092</span><span id="line-92"> new Option(null, "stats", false, "Additional information about the specified snapshot. "</span>
+<span class="source-line-no">093</span><span id="line-93"> + "Use it together with the --snapshot option.");</span>
+<span class="source-line-no">094</span><span id="line-94"> static final Option SCHEMA = new Option(null, "schema", false,</span>
+<span class="source-line-no">095</span><span id="line-95"> "Show the descriptor of the table for the specified snapshot. "</span>
+<span class="source-line-no">096</span><span id="line-96"> + "Use it together with the --snapshot option.");</span>
+<span class="source-line-no">097</span><span id="line-97"> static final Option SIZE_IN_BYTES =</span>
+<span class="source-line-no">098</span><span id="line-98"> new Option(null, "size-in-bytes", false, "Print the size of the files in bytes. "</span>
+<span class="source-line-no">099</span><span id="line-99"> + "Use it together with the --snapshot and --files options.");</span>
+<span class="source-line-no">100</span><span id="line-100"> }</span>
+<span class="source-line-no">101</span><span id="line-101"></span>
+<span class="source-line-no">102</span><span id="line-102"> /**</span>
+<span class="source-line-no">103</span><span id="line-103"> * Statistics about the snapshot</span>
+<span class="source-line-no">104</span><span id="line-104"> * <ol></span>
+<span class="source-line-no">105</span><span id="line-105"> * <li>How many store files and logs are in the archive</span>
+<span class="source-line-no">106</span><span id="line-106"> * <li>How many store files and logs are shared with the table</span>
+<span class="source-line-no">107</span><span id="line-107"> * <li>Total store files and logs size and shared amount</span>
+<span class="source-line-no">108</span><span id="line-108"> * </ol></span>
+<span class="source-line-no">109</span><span id="line-109"> */</span>
+<span class="source-line-no">110</span><span id="line-110"> public static class SnapshotStats {</span>
+<span class="source-line-no">111</span><span id="line-111"> /** Information about the file referenced by the snapshot */</span>
+<span class="source-line-no">112</span><span id="line-112"> static class FileInfo {</span>
+<span class="source-line-no">113</span><span id="line-113"> private final boolean corrupted;</span>
+<span class="source-line-no">114</span><span id="line-114"> private final boolean inArchive;</span>
+<span class="source-line-no">115</span><span id="line-115"> private final long size;</span>
<span class="source-line-no">116</span><span id="line-116"></span>
-<span class="source-line-no">117</span><span id="line-117"> /** Returns true if the file is in the archive */</span>
-<span class="source-line-no">118</span><span id="line-118"> public boolean inArchive() {</span>
-<span class="source-line-no">119</span><span id="line-119"> return this.inArchive;</span>
-<span class="source-line-no">120</span><span id="line-120"> }</span>
-<span class="source-line-no">121</span><span id="line-121"></span>
-<span class="source-line-no">122</span><span id="line-122"> /** Returns true if the file is corrupted */</span>
-<span class="source-line-no">123</span><span id="line-123"> public boolean isCorrupted() {</span>
-<span class="source-line-no">124</span><span id="line-124"> return this.corrupted;</span>
-<span class="source-line-no">125</span><span id="line-125"> }</span>
-<span class="source-line-no">126</span><span id="line-126"></span>
-<span class="source-line-no">127</span><span id="line-127"> /** Returns true if the file is missing */</span>
-<span class="source-line-no">128</span><span id="line-128"> public boolean isMissing() {</span>
-<span class="source-line-no">129</span><span id="line-129"> return this.size < 0;</span>
-<span class="source-line-no">130</span><span id="line-130"> }</span>
-<span class="source-line-no">131</span><span id="line-131"></span>
-<span class="source-line-no">132</span><span id="line-132"> /** Returns the file size */</span>
-<span class="source-line-no">133</span><span id="line-133"> public long getSize() {</span>
-<span class="source-line-no">134</span><span id="line-134"> return this.size;</span>
-<span class="source-line-no">135</span><span id="line-135"> }</span>
-<span class="source-line-no">136</span><span id="line-136"></span>
-<span class="source-line-no">137</span><span id="line-137"> String getStateToString() {</span>
-<span class="source-line-no">138</span><span id="line-138"> if (isCorrupted()) return "CORRUPTED";</span>
-<span class="source-line-no">139</span><span id="line-139"> if (isMissing()) return "NOT FOUND";</span>
-<span class="source-line-no">140</span><span id="line-140"> if (inArchive()) return "archive";</span>
-<span class="source-line-no">141</span><span id="line-141"> return null;</span>
-<span class="source-line-no">142</span><span id="line-142"> }</span>
-<span class="source-line-no">143</span><span id="line-143"> }</span>
-<span class="source-line-no">144</span><span id="line-144"></span>
-<span class="source-line-no">145</span><span id="line-145"> private AtomicInteger hfilesArchiveCount = new AtomicInteger();</span>
-<span class="source-line-no">146</span><span id="line-146"> private AtomicInteger hfilesCorrupted = new AtomicInteger();</span>
-<span class="source-line-no">147</span><span id="line-147"> private AtomicInteger hfilesMissing = new AtomicInteger();</span>
-<span class="source-line-no">148</span><span id="line-148"> private AtomicInteger hfilesCount = new AtomicInteger();</span>
-<span class="source-line-no">149</span><span id="line-149"> private AtomicInteger hfilesMobCount = new AtomicInteger();</span>
-<span class="source-line-no">150</span><span id="line-150"> private AtomicInteger logsMissing = new AtomicInteger();</span>
-<span class="source-line-no">151</span><span id="line-151"> private AtomicInteger logsCount = new AtomicInteger();</span>
-<span class="source-line-no">152</span><span id="line-152"> private AtomicLong hfilesArchiveSize = new AtomicLong();</span>
-<span class="source-line-no">153</span><span id="line-153"> private AtomicLong hfilesSize = new AtomicLong();</span>
-<span class="source-line-no">154</span><span id="line-154"> private AtomicLong hfilesMobSize = new AtomicLong();</span>
-<span class="source-line-no">155</span><span id="line-155"> private AtomicLong nonSharedHfilesArchiveSize = new AtomicLong();</span>
-<span class="source-line-no">156</span><span id="line-156"> private AtomicLong logSize = new AtomicLong();</span>
-<span class="source-line-no">157</span><span id="line-157"></span>
-<span class="source-line-no">158</span><span id="line-158"> private final SnapshotProtos.SnapshotDescription snapshot;</span>
-<span class="source-line-no">159</span><span id="line-159"> private final TableName snapshotTable;</span>
-<span class="source-line-no">160</span><span id="line-160"> private final Configuration conf;</span>
-<span class="source-line-no">161</span><span id="line-161"> private final FileSystem fs;</span>
-<span class="source-line-no">162</span><span id="line-162"></span>
-<span class="source-line-no">163</span><span id="line-163"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
-<span class="source-line-no">164</span><span id="line-164"> final SnapshotDescription snapshot) {</span>
-<span class="source-line-no">165</span><span id="line-165"> this.snapshot = ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
-<span class="source-line-no">166</span><span id="line-166"> this.snapshotTable = snapshot.getTableName();</span>
-<span class="source-line-no">167</span><span id="line-167"> this.conf = conf;</span>
-<span class="source-line-no">168</span><span id="line-168"> this.fs = fs;</span>
-<span class="source-line-no">169</span><span id="line-169"> }</span>
-<span class="source-line-no">170</span><span id="line-170"></span>
-<span class="source-line-no">171</span><span id="line-171"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
-<span class="source-line-no">172</span><span id="line-172"> final SnapshotProtos.SnapshotDescription snapshot) {</span>
-<span class="source-line-no">173</span><span id="line-173"> this.snapshot = snapshot;</span>
-<span class="source-line-no">174</span><span id="line-174"> this.snapshotTable = TableName.valueOf(snapshot.getTable());</span>
-<span class="source-line-no">175</span><span id="line-175"> this.conf = conf;</span>
-<span class="source-line-no">176</span><span id="line-176"> this.fs = fs;</span>
-<span class="source-line-no">177</span><span id="line-177"> }</span>
-<span class="source-line-no">178</span><span id="line-178"></span>
-<span class="source-line-no">179</span><span id="line-179"> /** Returns the snapshot descriptor */</span>
-<span class="source-line-no">180</span><span id="line-180"> public SnapshotDescription getSnapshotDescription() {</span>
-<span class="source-line-no">181</span><span id="line-181"> return ProtobufUtil.createSnapshotDesc(this.snapshot);</span>
-<span class="source-line-no">182</span><span id="line-182"> }</span>
-<span class="source-line-no">183</span><span id="line-183"></span>
-<span class="source-line-no">184</span><span id="line-184"> /** Returns true if the snapshot is corrupted */</span>
-<span class="source-line-no">185</span><span id="line-185"> public boolean isSnapshotCorrupted() {</span>
-<span class="source-line-no">186</span><span id="line-186"> return hfilesMissing.get() > 0 || logsMissing.get() > 0 || hfilesCorrupted.get() > 0;</span>
-<span class="source-line-no">187</span><span id="line-187"> }</span>
-<span class="source-line-no">188</span><span id="line-188"></span>
-<span class="source-line-no">189</span><span id="line-189"> /** Returns the number of available store files */</span>
-<span class="source-line-no">190</span><span id="line-190"> public int getStoreFilesCount() {</span>
-<span class="source-line-no">191</span><span id="line-191"> return hfilesCount.get() + hfilesArchiveCount.get() + hfilesMobCount.get();</span>
-<span class="source-line-no">192</span><span id="line-192"> }</span>
-<span class="source-line-no">193</span><span id="line-193"></span>
-<span class="source-line-no">194</span><span id="line-194"> /** Returns the number of available store files in the archive */</span>
-<span class="source-line-no">195</span><span id="line-195"> public int getArchivedStoreFilesCount() {</span>
-<span class="source-line-no">196</span><span id="line-196"> return hfilesArchiveCount.get();</span>
-<span class="source-line-no">197</span><span id="line-197"> }</span>
-<span class="source-line-no">198</span><span id="line-198"></span>
-<span class="source-line-no">199</span><span id="line-199"> /** Returns the number of available store files in the mob dir */</span>
-<span class="source-line-no">200</span><span id="line-200"> public int getMobStoreFilesCount() {</span>
-<span class="source-line-no">201</span><span id="line-201"> return hfilesMobCount.get();</span>
-<span class="source-line-no">202</span><span id="line-202"> }</span>
-<span class="source-line-no">203</span><span id="line-203"></span>
-<span class="source-line-no">204</span><span id="line-204"> /** Returns the number of available log files */</span>
-<span class="source-line-no">205</span><span id="line-205"> public int getLogsCount() {</span>
-<span class="source-line-no">206</span><span id="line-206"> return logsCount.get();</span>
-<span class="source-line-no">207</span><span id="line-207"> }</span>
-<span class="source-line-no">208</span><span id="line-208"></span>
-<span class="source-line-no">209</span><span id="line-209"> /** Returns the number of missing store files */</span>
-<span class="source-line-no">210</span><span id="line-210"> public int getMissingStoreFilesCount() {</span>
-<span class="source-line-no">211</span><span id="line-211"> return hfilesMissing.get();</span>
-<span class="source-line-no">212</span><span id="line-212"> }</span>
-<span class="source-line-no">213</span><span id="line-213"></span>
-<span class="source-line-no">214</span><span id="line-214"> /** Returns the number of corrupted store files */</span>
-<span class="source-line-no">215</span><span id="line-215"> public int getCorruptedStoreFilesCount() {</span>
-<span class="source-line-no">216</span><span id="line-216"> return hfilesCorrupted.get();</span>
-<span class="source-line-no">217</span><span id="line-217"> }</span>
-<span class="source-line-no">218</span><span id="line-218"></span>
-<span class="source-line-no">219</span><span id="line-219"> /** Returns the number of missing log files */</span>
-<span class="source-line-no">220</span><span id="line-220"> public int getMissingLogsCount() {</span>
-<span class="source-line-no">221</span><span id="line-221"> return logsMissing.get();</span>
-<span class="source-line-no">222</span><span id="line-222"> }</span>
-<span class="source-line-no">223</span><span id="line-223"></span>
-<span class="source-line-no">224</span><span id="line-224"> /** Returns the total size of the store files referenced by the snapshot */</span>
-<span class="source-line-no">225</span><span id="line-225"> public long getStoreFilesSize() {</span>
-<span class="source-line-no">226</span><span id="line-226"> return hfilesSize.get() + hfilesArchiveSize.get() + hfilesMobSize.get();</span>
-<span class="source-line-no">227</span><span id="line-227"> }</span>
-<span class="source-line-no">228</span><span id="line-228"></span>
-<span class="source-line-no">229</span><span id="line-229"> /** Returns the total size of the store files shared */</span>
-<span class="source-line-no">230</span><span id="line-230"> public long getSharedStoreFilesSize() {</span>
-<span class="source-line-no">231</span><span id="line-231"> return hfilesSize.get();</span>
-<span class="source-line-no">232</span><span id="line-232"> }</span>
-<span class="source-line-no">233</span><span id="line-233"></span>
-<span class="source-line-no">234</span><span id="line-234"> /** Returns the total size of the store files in the archive */</span>
-<span class="source-line-no">235</span><span id="line-235"> public long getArchivedStoreFileSize() {</span>
-<span class="source-line-no">236</span><span id="line-236"> return hfilesArchiveSize.get();</span>
-<span class="source-line-no">237</span><span id="line-237"> }</span>
-<span class="source-line-no">238</span><span id="line-238"></span>
-<span class="source-line-no">239</span><span id="line-239"> /** Returns the total size of the store files in the mob store */</span>
-<span class="source-line-no">240</span><span id="line-240"> public long getMobStoreFilesSize() {</span>
-<span class="source-line-no">241</span><span id="line-241"> return hfilesMobSize.get();</span>
-<span class="source-line-no">242</span><span id="line-242"> }</span>
-<span class="source-line-no">243</span><span id="line-243"></span>
-<span class="source-line-no">244</span><span id="line-244"> /**</span>
-<span class="source-line-no">245</span><span id="line-245"> * @return the total size of the store files in the archive which is not shared with other</span>
-<span class="source-line-no">246</span><span id="line-246"> * snapshots and tables This is only calculated when</span>
-<span class="source-line-no">247</span><span id="line-247"> * {@link #getSnapshotStats(Configuration, SnapshotProtos.SnapshotDescription, Map)} is</span>
-<span class="source-line-no">248</span><span id="line-248"> * called with a non-null Map</span>
-<span class="source-line-no">249</span><span id="line-249"> */</span>
-<span class="source-line-no">250</span><span id="line-250"> public long getNonSharedArchivedStoreFilesSize() {</span>
-<span class="source-line-no">251</span><span id="line-251"> return nonSharedHfilesArchiveSize.get();</span>
-<span class="source-line-no">252</span><span id="line-252"> }</span>
-<span class="source-line-no">253</span><span id="line-253"></span>
-<span class="source-line-no">254</span><span id="line-254"> /** Returns the percentage of the shared store files */</span>
-<span class="source-line-no">255</span><span id="line-255"> public float getSharedStoreFilePercentage() {</span>
-<span class="source-line-no">256</span><span id="line-256"> return getStoreFilesSize() == 0</span>
-<span class="source-line-no">257</span><span id="line-257"> ? 0</span>
-<span class="source-line-no">258</span><span id="line-258"> : ((float) hfilesSize.get() / (getStoreFilesSize())) * 100;</span>
-<span class="source-line-no">259</span><span id="line-259"> }</span>
-<span class="source-line-no">260</span><span id="line-260"></span>
-<span class="source-line-no">261</span><span id="line-261"> /** Returns the percentage of the mob store files */</span>
-<span class="source-line-no">262</span><span id="line-262"> public float getMobStoreFilePercentage() {</span>
-<span class="source-line-no">263</span><span id="line-263"> return getStoreFilesSize() == 0</span>
-<span class="source-line-no">264</span><span id="line-264"> ? 0</span>
-<span class="source-line-no">265</span><span id="line-265"> : ((float) hfilesMobSize.get() / (getStoreFilesSize())) * 100;</span>
-<span class="source-line-no">266</span><span id="line-266"> }</span>
-<span class="source-line-no">267</span><span id="line-267"></span>
-<span class="source-line-no">268</span><span id="line-268"> /** Returns the total log size */</span>
-<span class="source-line-no">269</span><span id="line-269"> public long getLogsSize() {</span>
-<span class="source-line-no">270</span><span id="line-270"> return logSize.get();</span>
-<span class="source-line-no">271</span><span id="line-271"> }</span>
-<span class="source-line-no">272</span><span id="line-272"></span>
-<span class="source-line-no">273</span><span id="line-273"> /**</span>
-<span class="source-line-no">274</span><span id="line-274"> * Check if for a give file in archive, if there are other snapshots/tables still reference it.</span>
-<span class="source-line-no">275</span><span id="line-275"> * @param filePath file path in archive</span>
-<span class="source-line-no">276</span><span id="line-276"> * @param snapshotFilesMap a map for store files in snapshots about how many snapshots refer to</span>
-<span class="source-line-no">277</span><span id="line-277"> * it.</span>
-<span class="source-line-no">278</span><span id="line-278"> * @return true or false</span>
-<span class="source-line-no">279</span><span id="line-279"> */</span>
-<span class="source-line-no">280</span><span id="line-280"> private boolean isArchivedFileStillReferenced(final Path filePath,</span>
-<span class="source-line-no">281</span><span id="line-281"> final Map<Path, Integer> snapshotFilesMap) {</span>
-<span class="source-line-no">282</span><span id="line-282"></span>
-<span class="source-line-no">283</span><span id="line-283"> Integer c = snapshotFilesMap.get(filePath);</span>
-<span class="source-line-no">284</span><span id="line-284"></span>
-<span class="source-line-no">285</span><span id="line-285"> // Check if there are other snapshots or table from clone_snapshot() (via back-reference)</span>
-<span class="source-line-no">286</span><span id="line-286"> // still reference to it.</span>
-<span class="source-line-no">287</span><span id="line-287"> if ((c != null) && (c == 1)) {</span>
-<span class="source-line-no">288</span><span id="line-288"> Path parentDir = filePath.getParent();</span>
-<span class="source-line-no">289</span><span id="line-289"> Path backRefDir = HFileLink.getBackReferencesDir(parentDir, filePath.getName());</span>
-<span class="source-line-no">290</span><span id="line-290"> try {</span>
-<span class="source-line-no">291</span><span id="line-291"> if (CommonFSUtils.listStatus(fs, backRefDir) == null) {</span>
-<span class="source-line-no">292</span><span id="line-292"> return false;</span>
-<span class="source-line-no">293</span><span id="line-293"> }</span>
-<span class="source-line-no">294</span><span id="line-294"> } catch (IOException e) {</span>
-<span class="source-line-no">295</span><span id="line-295"> // For the purpose of this function, IOException is ignored and treated as</span>
-<span class="source-line-no">296</span><span id="line-296"> // the file is still being referenced.</span>
-<span class="source-line-no">297</span><span id="line-297"> }</span>
-<span class="source-line-no">298</span><span id="line-298"> }</span>
-<span class="source-line-no">299</span><span id="line-299"> return true;</span>
-<span class="source-line-no">300</span><span id="line-300"> }</span>
-<span class="source-line-no">301</span><span id="line-301"></span>
-<span class="source-line-no">302</span><span id="line-302"> /**</span>
-<span class="source-line-no">303</span><span id="line-303"> * Add the specified store file to the stats</span>
-<span class="source-line-no">304</span><span id="line-304"> * @param region region encoded Name</span>
-<span class="source-line-no">305</span><span id="line-305"> * @param family family name</span>
-<span class="source-line-no">306</span><span id="line-306"> * @param storeFile store file name</span>
-<span class="source-line-no">307</span><span id="line-307"> * @param filesMap store files map for all snapshots, it may be null</span>
-<span class="source-line-no">308</span><span id="line-308"> * @return the store file information</span>
-<span class="source-line-no">309</span><span id="line-309"> */</span>
-<span class="source-line-no">310</span><span id="line-310"> FileInfo addStoreFile(final RegionInfo region, final String family,</span>
-<span class="source-line-no">311</span><span id="line-311"> final SnapshotRegionManifest.StoreFile storeFile, final Map<Path, Integer> filesMap)</span>
-<span class="source-line-no">312</span><span id="line-312"> throws IOException {</span>
-<span class="source-line-no">313</span><span id="line-313"> HFileLink link =</span>
-<span class="source-line-no">314</span><span id="line-314"> HFileLink.build(conf, snapshotTable, region.getEncodedName(), family, storeFile.getName());</span>
-<span class="source-line-no">315</span><span id="line-315"> boolean isCorrupted = false;</span>
-<span class="source-line-no">316</span><span id="line-316"> boolean inArchive = false;</span>
-<span class="source-line-no">317</span><span id="line-317"> long size = -1;</span>
-<span class="source-line-no">318</span><span id="line-318"> try {</span>
-<span class="source-line-no">319</span><span id="line-319"> if (fs.exists(link.getArchivePath())) {</span>
-<span class="source-line-no">320</span><span id="line-320"> inArchive = true;</span>
-<span class="source-line-no">321</span><span id="line-321"> size = fs.getFileStatus(link.getArchivePath()).getLen();</span>
-<span class="source-line-no">322</span><span id="line-322"> hfilesArchiveSize.addAndGet(size);</span>
-<span class="source-line-no">323</span><span id="line-323"> hfilesArchiveCount.incrementAndGet();</span>
-<span class="source-line-no">324</span><span id="line-324"></span>
-<span class="source-line-no">325</span><span id="line-325"> // If store file is not shared with other snapshots and tables,</span>
-<span class="source-line-no">326</span><span id="line-326"> // increase nonSharedHfilesArchiveSize</span>
-<span class="source-line-no">327</span><span id="line-327"> if (</span>
-<span class="source-line-no">328</span><span id="line-328"> (filesMap != null) && !isArchivedFileStillReferenced(link.getArchivePath(), filesMap)</span>
-<span class="source-line-no">329</span><span id="line-329"> ) {</span>
-<span class="source-line-no">330</span><span id="line-330"> nonSharedHfilesArchiveSize.addAndGet(size);</span>
-<span class="source-line-no">331</span><span id="line-331"> }</span>
-<span class="source-line-no">332</span><span id="line-332"> } else if (fs.exists(link.getMobPath())) {</span>
-<span class="source-line-no">333</span><span id="line-333"> inArchive = true;</span>
-<span class="source-line-no">334</span><span id="line-334"> size = fs.getFileStatus(link.getMobPath()).getLen();</span>
-<span class="source-line-no">335</span><span id="line-335"> hfilesMobSize.addAndGet(size);</span>
-<span class="source-line-no">336</span><span id="line-336"> hfilesMobCount.incrementAndGet();</span>
-<span class="source-line-no">337</span><span id="line-337"> } else {</span>
-<span class="source-line-no">338</span><span id="line-338"> size = link.getFileStatus(fs).getLen();</span>
-<span class="source-line-no">339</span><span id="line-339"> hfilesSize.addAndGet(size);</span>
-<span class="source-line-no">340</span><span id="line-340"> hfilesCount.incrementAndGet();</span>
-<span class="source-line-no">341</span><span id="line-341"> }</span>
-<span class="source-line-no">342</span><span id="line-342"> isCorrupted = (storeFile.hasFileSize() && storeFile.getFileSize() != size);</span>
-<span class="source-line-no">343</span><span id="line-343"> if (isCorrupted) hfilesCorrupted.incrementAndGet();</span>
-<span class="source-line-no">344</span><span id="line-344"> } catch (FileNotFoundException e) {</span>
-<span class="source-line-no">345</span><span id="line-345"> hfilesMissing.incrementAndGet();</span>
-<span class="source-line-no">346</span><span id="line-346"> }</span>
-<span class="source-line-no">347</span><span id="line-347"> return new FileInfo(inArchive, size, isCorrupted);</span>
-<span class="source-line-no">348</span><span id="line-348"> }</span>
-<span class="source-line-no">349</span><span id="line-349"></span>
-<span class="source-line-no">350</span><span id="line-350"> /**</span>
-<span class="source-line-no">351</span><span id="line-351"> * Add the specified log file to the stats</span>
-<span class="source-line-no">352</span><span id="line-352"> * @param server server name</span>
-<span class="source-line-no">353</span><span id="line-353"> * @param logfile log file name</span>
-<span class="source-line-no">354</span><span id="line-354"> * @return the log information</span>
-<span class="source-line-no">355</span><span id="line-355"> */</span>
-<span class="source-line-no">356</span><span id="line-356"> FileInfo addLogFile(final String server, final String logfile) throws IOException {</span>
-<span class="source-line-no">357</span><span id="line-357"> WALLink logLink = new WALLink(conf, server, logfile);</span>
-<span class="source-line-no">358</span><span id="line-358"> long size = -1;</span>
-<span class="source-line-no">359</span><span id="line-359"> try {</span>
-<span class="source-line-no">360</span><span id="line-360"> size = logLink.getFileStatus(fs).getLen();</span>
-<span class="source-line-no">361</span><span id="line-361"> logSize.addAndGet(size);</span>
-<span class="source-line-no">362</span><span id="line-362"> logsCount.incrementAndGet();</span>
-<span class="source-line-no">363</span><span id="line-363"> } catch (FileNotFoundException e) {</span>
-<span class="source-line-no">364</span><span id="line-364"> logsMissing.incrementAndGet();</span>
-<span class="source-line-no">365</span><span id="line-365"> }</span>
-<span class="source-line-no">366</span><span id="line-366"> return new FileInfo(false, size, false);</span>
-<span class="source-line-no">367</span><span id="line-367"> }</span>
-<span class="source-line-no">368</span><span id="line-368"> }</span>
-<span class="source-line-no">369</span><span id="line-369"></span>
-<span class="source-line-no">370</span><span id="line-370"> private FileSystem fs;</span>
-<span class="source-line-no">371</span><span id="line-371"> private Path rootDir;</span>
-<span class="source-line-no">372</span><span id="line-372"></span>
-<span class="source-line-no">373</span><span id="line-373"> private SnapshotManifest snapshotManifest;</span>
-<span class="source-line-no">374</span><span id="line-374"></span>
-<span class="source-line-no">375</span><span id="line-375"> private boolean listSnapshots = false;</span>
-<span class="source-line-no">376</span><span id="line-376"> private String snapshotName;</span>
-<span class="source-line-no">377</span><span id="line-377"> private Path remoteDir;</span>
-<span class="source-line-no">378</span><span id="line-378"> private boolean showSchema = false;</span>
-<span class="source-line-no">379</span><span id="line-379"> private boolean showFiles = false;</span>
-<span class="source-line-no">380</span><span id="line-380"> private boolean showStats = false;</span>
-<span class="source-line-no">381</span><span id="line-381"> private boolean printSizeInBytes = false;</span>
-<span class="source-line-no">382</span><span id="line-382"></span>
-<span class="source-line-no">383</span><span id="line-383"> @Override</span>
-<span class="source-line-no">384</span><span id="line-384"> public int doWork() throws IOException, InterruptedException {</span>
-<span class="source-line-no">385</span><span id="line-385"> if (remoteDir != null) {</span>
-<span class="source-line-no">386</span><span id="line-386"> URI defaultFs = remoteDir.getFileSystem(conf).getUri();</span>
-<span class="source-line-no">387</span><span id="line-387"> CommonFSUtils.setFsDefault(conf, new Path(defaultFs));</span>
-<span class="source-line-no">388</span><span id="line-388"> CommonFSUtils.setRootDir(conf, remoteDir);</span>
-<span class="source-line-no">389</span><span id="line-389"> }</span>
-<span class="source-line-no">390</span><span id="line-390"></span>
-<span class="source-line-no">391</span><span id="line-391"> // List Available Snapshots</span>
-<span class="source-line-no">392</span><span id="line-392"> if (listSnapshots) {</span>
-<span class="source-line-no">393</span><span id="line-393"> SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");</span>
-<span class="source-line-no">394</span><span id="line-394"> System.out.printf("%-20s | %-20s | %-20s | %s%n", "SNAPSHOT", "CREATION TIME", "TTL IN SEC",</span>
-<span class="source-line-no">395</span><span id="line-395"> "TABLE NAME");</span>
-<span class="source-line-no">396</span><span id="line-396"> for (SnapshotDescription desc : getSnapshotList(conf)) {</span>
-<span class="source-line-no">397</span><span id="line-397"> System.out.printf("%-20s | %20s | %20s | %s%n", desc.getName(),</span>
-<span class="source-line-no">398</span><span id="line-398"> df.format(new Date(desc.getCreationTime())), desc.getTtl(), desc.getTableNameAsString());</span>
-<span class="source-line-no">399</span><span id="line-399"> }</span>
-<span class="source-line-no">400</span><span id="line-400"> return 0;</span>
-<span class="source-line-no">401</span><span id="line-401"> }</span>
-<span class="source-line-no">402</span><span id="line-402"></span>
-<span class="source-line-no">403</span><span id="line-403"> rootDir = CommonFSUtils.getRootDir(conf);</span>
-<span class="source-line-no">404</span><span id="line-404"> fs = FileSystem.get(rootDir.toUri(), conf);</span>
-<span class="source-line-no">405</span><span id="line-405"> LOG.debug("fs=" + fs.getUri().toString() + " root=" + rootDir);</span>
-<span class="source-line-no">406</span><span id="line-406"></span>
-<span class="source-line-no">407</span><span id="line-407"> // Load snapshot information</span>
-<span class="source-line-no">408</span><span id="line-408"> if (!loadSnapshotInfo(snapshotName)) {</span>
-<span class="source-line-no">409</span><span id="line-409"> System.err.println("Snapshot '" + snapshotName + "' not found!");</span>
-<span class="source-line-no">410</span><span id="line-410"> return 1;</span>
-<span class="source-line-no">411</span><span id="line-411"> }</span>
-<span class="source-line-no">412</span><span id="line-412"></span>
-<span class="source-line-no">413</span><span id="line-413"> printInfo();</span>
-<span class="source-line-no">414</span><span id="line-414"> if (showSchema) {</span>
-<span class="source-line-no">415</span><span id="line-415"> printSchema();</span>
-<span class="source-line-no">416</span><span id="line-416"> }</span>
-<span class="source-line-no">417</span><span id="line-417"> printFiles(showFiles, showStats);</span>
-<span class="source-line-no">418</span><span id="line-418"></span>
-<span class="source-line-no">419</span><span id="line-419"> return 0;</span>
-<span class="source-line-no">420</span><span id="line-420"> }</span>
-<span class="source-line-no">421</span><span id="line-421"></span>
-<span class="source-line-no">422</span><span id="line-422"> /**</span>
-<span class="source-line-no">423</span><span id="line-423"> * Load snapshot info and table descriptor for the specified snapshot</span>
-<span class="source-line-no">424</span><span id="line-424"> * @param snapshotName name of the snapshot to load</span>
-<span class="source-line-no">425</span><span id="line-425"> * @return false if snapshot is not found</span>
-<span class="source-line-no">426</span><span id="line-426"> */</span>
-<span class="source-line-no">427</span><span id="line-427"> private boolean loadSnapshotInfo(final String snapshotName) throws IOException {</span>
-<span class="source-line-no">428</span><span id="line-428"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);</span>
-<span class="source-line-no">429</span><span id="line-429"> if (!fs.exists(snapshotDir)) {</span>
-<span class="source-line-no">430</span><span id="line-430"> LOG.warn("Snapshot '" + snapshotName + "' not found in: " + snapshotDir);</span>
-<span class="source-line-no">431</span><span id="line-431"> return false;</span>
-<span class="source-line-no">432</span><span id="line-432"> }</span>
-<span class="source-line-no">433</span><span id="line-433"></span>
-<span class="source-line-no">434</span><span id="line-434"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">435</span><span id="line-435"> SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);</span>
-<span class="source-line-no">436</span><span id="line-436"> snapshotManifest = SnapshotManifest.open(getConf(), fs, snapshotDir, snapshotDesc);</span>
-<span class="source-line-no">437</span><span id="line-437"> return true;</span>
-<span class="source-line-no">438</span><span id="line-438"> }</span>
-<span class="source-line-no">439</span><span id="line-439"></span>
-<span class="source-line-no">440</span><span id="line-440"> /**</span>
-<span class="source-line-no">441</span><span id="line-441"> * Dump the {@link SnapshotDescription}</span>
-<span class="source-line-no">442</span><span id="line-442"> */</span>
-<span class="source-line-no">443</span><span id="line-443"> private void printInfo() {</span>
-<span class="source-line-no">444</span><span id="line-444"> SnapshotProtos.SnapshotDescription snapshotDesc = snapshotManifest.getSnapshotDescription();</span>
-<span class="source-line-no">445</span><span id="line-445"> SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");</span>
-<span class="source-line-no">446</span><span id="line-446"> System.out.println("Snapshot Info");</span>
-<span class="source-line-no">447</span><span id="line-447"> System.out.println("----------------------------------------");</span>
-<span class="source-line-no">448</span><span id="line-448"> System.out.println(" Name: " + snapshotDesc.getName());</span>
-<span class="source-line-no">449</span><span id="line-449"> System.out.println(" Type: " + snapshotDesc.getType());</span>
-<span class="source-line-no">450</span><span id="line-450"> System.out.println(" Table: " + snapshotDesc.getTable());</span>
-<span class="source-line-no">451</span><span id="line-451"> System.out.println(" Format: " + snapshotDesc.getVersion());</span>
-<span class="source-line-no">452</span><span id="line-452"> System.out.println("Created: " + df.format(new Date(snapshotDesc.getCreationTime())));</span>
-<span class="source-line-no">453</span><span id="line-453"> System.out.println(" Ttl: " + snapshotDesc.getTtl());</span>
-<span class="source-line-no">454</span><span id="line-454"> System.out.println(" Owner: " + snapshotDesc.getOwner());</span>
-<span class="source-line-no">455</span><span id="line-455"> System.out.println();</span>
-<span class="source-line-no">456</span><span id="line-456"> }</span>
-<span class="source-line-no">457</span><span id="line-457"></span>
-<span class="source-line-no">458</span><span id="line-458"> /**</span>
-<span class="source-line-no">459</span><span id="line-459"> * Dump the {@link org.apache.hadoop.hbase.client.TableDescriptor}</span>
-<span class="source-line-no">460</span><span id="line-460"> */</span>
-<span class="source-line-no">461</span><span id="line-461"> private void printSchema() {</span>
-<span class="source-line-no">462</span><span id="line-462"> System.out.println("Table Descriptor");</span>
-<span class="source-line-no">463</span><span id="line-463"> System.out.println("----------------------------------------");</span>
-<span class="source-line-no">464</span><span id="line-464"> System.out.println(snapshotManifest.getTableDescriptor().toString());</span>
-<span class="source-line-no">465</span><span id="line-465"> System.out.println();</span>
-<span class="source-line-no">466</span><span id="line-466"> }</span>
-<span class="source-line-no">467</span><span id="line-467"></span>
-<span class="source-line-no">468</span><span id="line-468"> /**</span>
-<span class="source-line-no">469</span><span id="line-469"> * Collect the hfiles and logs statistics of the snapshot and dump the file list if requested and</span>
-<span class="source-line-no">470</span><span id="line-470"> * the collected information.</span>
-<span class="source-line-no">471</span><span id="line-471"> */</span>
-<span class="source-line-no">472</span><span id="line-472"> private void printFiles(final boolean showFiles, final boolean showStats) throws IOException {</span>
-<span class="source-line-no">473</span><span id="line-473"> if (showFiles) {</span>
-<span class="source-line-no">474</span><span id="line-474"> System.out.println("Snapshot Files");</span>
-<span class="source-line-no">475</span><span id="line-475"> System.out.println("----------------------------------------");</span>
-<span class="source-line-no">476</span><span id="line-476"> }</span>
-<span class="source-line-no">477</span><span id="line-477"></span>
-<span class="source-line-no">478</span><span id="line-478"> // Collect information about hfiles and logs in the snapshot</span>
-<span class="source-line-no">479</span><span id="line-479"> final SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">480</span><span id="line-480"> snapshotManifest.getSnapshotDescription();</span>
-<span class="source-line-no">481</span><span id="line-481"> final String table = snapshotDesc.getTable();</span>
-<span class="source-line-no">482</span><span id="line-482"> final SnapshotDescription desc = ProtobufUtil.createSnapshotDesc(snapshotDesc);</span>
-<span class="source-line-no">483</span><span id="line-483"> final SnapshotStats stats = new SnapshotStats(this.getConf(), this.fs, desc);</span>
-<span class="source-line-no">484</span><span id="line-484"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(getConf(), fs, snapshotManifest,</span>
-<span class="source-line-no">485</span><span id="line-485"> "SnapshotInfo", new SnapshotReferenceUtil.SnapshotVisitor() {</span>
-<span class="source-line-no">486</span><span id="line-486"> @Override</span>
-<span class="source-line-no">487</span><span id="line-487"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
-<span class="source-line-no">488</span><span id="line-488"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
-<span class="source-line-no">489</span><span id="line-489"> if (storeFile.hasReference()) return;</span>
-<span class="source-line-no">490</span><span id="line-490"></span>
-<span class="source-line-no">491</span><span id="line-491"> SnapshotStats.FileInfo info = stats.addStoreFile(regionInfo, family, storeFile, null);</span>
-<span class="source-line-no">492</span><span id="line-492"> if (showFiles) {</span>
-<span class="source-line-no">493</span><span id="line-493"> String state = info.getStateToString();</span>
-<span class="source-line-no">494</span><span id="line-494"> System.out.printf("%8s %s/%s/%s/%s %s%n",</span>
-<span class="source-line-no">495</span><span id="line-495"> (info.isMissing() ? "-" : fileSizeToString(info.getSize())), table,</span>
-<span class="source-line-no">496</span><span id="line-496"> regionInfo.getEncodedName(), family, storeFile.getName(),</span>
-<span class="source-line-no">497</span><span id="line-497"> state == null ? "" : "(" + state + ")");</span>
-<span class="source-line-no">498</span><span id="line-498"> }</span>
-<span class="source-line-no">499</span><span id="line-499"> }</span>
-<span class="source-line-no">500</span><span id="line-500"> });</span>
-<span class="source-line-no">501</span><span id="line-501"></span>
-<span class="source-line-no">502</span><span id="line-502"> // Dump the stats</span>
-<span class="source-line-no">503</span><span id="line-503"> System.out.println();</span>
-<span class="source-line-no">504</span><span id="line-504"> if (stats.isSnapshotCorrupted()) {</span>
-<span class="source-line-no">505</span><span id="line-505"> System.out.println("**************************************************************");</span>
-<span class="source-line-no">506</span><span id="line-506"> System.out.printf("BAD SNAPSHOT: %d hfile(s) and %d log(s) missing.%n",</span>
-<span class="source-line-no">507</span><span id="line-507"> stats.getMissingStoreFilesCount(), stats.getMissingLogsCount());</span>
-<span class="source-line-no">508</span><span id="line-508"> System.out.printf(" %d hfile(s) corrupted.%n",</span>
-<span class="source-line-no">509</span><span id="line-509"> stats.getCorruptedStoreFilesCount());</span>
-<span class="source-line-no">510</span><span id="line-510"> System.out.println("**************************************************************");</span>
-<span class="source-line-no">511</span><span id="line-511"> }</span>
-<span class="source-line-no">512</span><span id="line-512"></span>
-<span class="source-line-no">513</span><span id="line-513"> if (showStats) {</span>
-<span class="source-line-no">514</span><span id="line-514"> System.out.printf(</span>
-<span class="source-line-no">515</span><span id="line-515"> "%d HFiles (%d in archive, %d in mob storage), total size %s "</span>
-<span class="source-line-no">516</span><span id="line-516"> + "(%.2f%% %s shared with the source table, %.2f%% %s in mob dir)%n",</span>
-<span class="source-line-no">517</span><span id="line-517"> stats.getStoreFilesCount(), stats.getArchivedStoreFilesCount(),</span>
-<span class="source-line-no">518</span><span id="line-518"> stats.getMobStoreFilesCount(), fileSizeToString(stats.getStoreFilesSize()),</span>
-<span class="source-line-no">519</span><span id="line-519"> stats.getSharedStoreFilePercentage(), fileSizeToString(stats.getSharedStoreFilesSize()),</span>
-<span class="source-line-no">520</span><span id="line-520"> stats.getMobStoreFilePercentage(), fileSizeToString(stats.getMobStoreFilesSize()));</span>
-<span class="source-line-no">521</span><span id="line-521"> System.out.printf("%d Logs, total size %s%n", stats.getLogsCount(),</span>
-<span class="source-line-no">522</span><span id="line-522"> fileSizeToString(stats.getLogsSize()));</span>
-<span class="source-line-no">523</span><span id="line-523"> System.out.println();</span>
-<span class="source-line-no">524</span><span id="line-524"> }</span>
-<span class="source-line-no">525</span><span id="line-525"> }</span>
-<span class="source-line-no">526</span><span id="line-526"></span>
-<span class="source-line-no">527</span><span id="line-527"> private String fileSizeToString(long size) {</span>
-<span class="source-line-no">528</span><span id="line-528"> return printSizeInBytes ? Long.toString(size) : Strings.humanReadableInt(size);</span>
-<span class="source-line-no">529</span><span id="line-529"> }</span>
-<span class="source-line-no">530</span><span id="line-530"></span>
-<span class="source-line-no">531</span><span id="line-531"> @Override</span>
-<span class="source-line-no">532</span><span id="line-532"> protected void addOptions() {</span>
-<span class="source-line-no">533</span><span id="line-533"> addOption(Options.SNAPSHOT);</span>
-<span class="source-line-no">534</span><span id="line-534"> addOption(Options.REMOTE_DIR);</span>
-<span class="source-line-no">535</span><span id="line-535"> addOption(Options.LIST_SNAPSHOTS);</span>
-<span class="source-line-no">536</span><span id="line-536"> addOption(Options.FILES);</span>
-<span class="source-line-no">537</span><span id="line-537"> addOption(Options.STATS);</span>
-<span class="source-line-no">538</span><span id="line-538"> addOption(Options.SCHEMA);</span>
-<span class="source-line-no">539</span><span id="line-539"> addOption(Options.SIZE_IN_BYTES);</span>
-<span class="source-line-no">540</span><span id="line-540"> }</span>
-<span class="source-line-no">541</span><span id="line-541"></span>
-<span class="source-line-no">542</span><span id="line-542"> @Override</span>
-<span class="source-line-no">543</span><span id="line-543"> protected CommandLineParser newParser() {</span>
-<span class="source-line-no">544</span><span id="line-544"> // Commons-CLI lacks the capability to handle combinations of options, so we do it ourselves</span>
-<span class="source-line-no">545</span><span id="line-545"> // Validate in parse() to get helpful error messages instead of exploding in processOptions()</span>
-<span class="source-line-no">546</span><span id="line-546"> return new DefaultParser() {</span>
-<span class="source-line-no">547</span><span id="line-547"> @Override</span>
-<span class="source-line-no">548</span><span id="line-548"> public CommandLine parse(org.apache.hbase.thirdparty.org.apache.commons.cli.Options opts,</span>
-<span class="source-line-no">549</span><span id="line-549"> String[] args, Properties props, boolean stop) throws ParseException {</span>
-<span class="source-line-no">550</span><span id="line-550"> CommandLine cl = super.parse(opts, args, props, stop);</span>
-<span class="source-line-no">551</span><span id="line-551"> if (!cmd.hasOption(Options.LIST_SNAPSHOTS) && !cmd.hasOption(Options.SNAPSHOT)) {</span>
-<span class="source-line-no">552</span><span id="line-552"> throw new ParseException("Missing required snapshot option!");</span>
-<span class="source-line-no">553</span><span id="line-553"> }</span>
-<span class="source-line-no">554</span><span id="line-554"> return cl;</span>
-<span class="source-line-no">555</span><span id="line-555"> }</span>
-<span class="source-line-no">556</span><span id="line-556"> };</span>
-<span class="source-line-no">557</span><span id="line-557"> }</span>
-<span class="source-line-no">558</span><span id="line-558"></span>
-<span class="source-line-no">559</span><span id="line-559"> @Override</span>
-<span class="source-line-no">560</span><span id="line-560"> protected void processOptions(CommandLine cmd) {</span>
-<span class="source-line-no">561</span><span id="line-561"> snapshotName = cmd.getOptionValue(Options.SNAPSHOT.getLongOpt());</span>
-<span class="source-line-no">562</span><span id="line-562"> showFiles = cmd.hasOption(Options.FILES.getLongOpt());</span>
-<span class="source-line-no">563</span><span id="line-563"> showStats =</span>
-<span class="source-line-no">564</span><span id="line-564"> cmd.hasOption(Options.FILES.getLongOpt()) || cmd.hasOption(Options.STATS.getLongOpt());</span>
-<span class="source-line-no">565</span><span id="line-565"> showSchema = cmd.hasOption(Options.SCHEMA.getLongOpt());</span>
-<span class="source-line-no">566</span><span id="line-566"> listSnapshots = cmd.hasOption(Options.LIST_SNAPSHOTS.getLongOpt());</span>
-<span class="source-line-no">567</span><span id="line-567"> printSizeInBytes = cmd.hasOption(Options.SIZE_IN_BYTES.getLongOpt());</span>
-<span class="source-line-no">568</span><span id="line-568"> if (cmd.hasOption(Options.REMOTE_DIR.getLongOpt())) {</span>
-<span class="source-line-no">569</span><span id="line-569"> remoteDir = new Path(cmd.getOptionValue(Options.REMOTE_DIR.getLongOpt()));</span>
-<span class="source-line-no">570</span><span id="line-570"> }</span>
-<span class="source-line-no">571</span><span id="line-571"> }</span>
-<span class="source-line-no">572</span><span id="line-572"></span>
-<span class="source-line-no">573</span><span id="line-573"> @Override</span>
-<span class="source-line-no">574</span><span id="line-574"> protected void printUsage() {</span>
-<span class="source-line-no">575</span><span id="line-575"> printUsage("hbase snapshot info [options]", "Options:", "");</span>
-<span class="source-line-no">576</span><span id="line-576"> System.err.println("Examples:");</span>
-<span class="source-line-no">577</span><span id="line-577"> System.err.println(" hbase snapshot info --snapshot MySnapshot --files");</span>
+<span class="source-line-no">117</span><span id="line-117"> FileInfo(final boolean inArchive, final long size, final boolean corrupted) {</span>
+<span class="source-line-no">118</span><span id="line-118"> this.corrupted = corrupted;</span>
+<span class="source-line-no">119</span><span id="line-119"> this.inArchive = inArchive;</span>
+<span class="source-line-no">120</span><span id="line-120"> this.size = size;</span>
+<span class="source-line-no">121</span><span id="line-121"> }</span>
+<span class="source-line-no">122</span><span id="line-122"></span>
+<span class="source-line-no">123</span><span id="line-123"> /** Returns true if the file is in the archive */</span>
+<span class="source-line-no">124</span><span id="line-124"> public boolean inArchive() {</span>
+<span class="source-line-no">125</span><span id="line-125"> return this.inArchive;</span>
+<span class="source-line-no">126</span><span id="line-126"> }</span>
+<span class="source-line-no">127</span><span id="line-127"></span>
+<span class="source-line-no">128</span><span id="line-128"> /** Returns true if the file is corrupted */</span>
+<span class="source-line-no">129</span><span id="line-129"> public boolean isCorrupted() {</span>
+<span class="source-line-no">130</span><span id="line-130"> return this.corrupted;</span>
+<span class="source-line-no">131</span><span id="line-131"> }</span>
+<span class="source-line-no">132</span><span id="line-132"></span>
+<span class="source-line-no">133</span><span id="line-133"> /** Returns true if the file is missing */</span>
+<span class="source-line-no">134</span><span id="line-134"> public boolean isMissing() {</span>
+<span class="source-line-no">135</span><span id="line-135"> return this.size < 0;</span>
+<span class="source-line-no">136</span><span id="line-136"> }</span>
+<span class="source-line-no">137</span><span id="line-137"></span>
+<span class="source-line-no">138</span><span id="line-138"> /** Returns the file size */</span>
+<span class="source-line-no">139</span><span id="line-139"> public long getSize() {</span>
+<span class="source-line-no">140</span><span id="line-140"> return this.size;</span>
+<span class="source-line-no">141</span><span id="line-141"> }</span>
+<span class="source-line-no">142</span><span id="line-142"></span>
+<span class="source-line-no">143</span><span id="line-143"> String getStateToString() {</span>
+<span class="source-line-no">144</span><span id="line-144"> if (isCorrupted()) return "CORRUPTED";</span>
+<span class="source-line-no">145</span><span id="line-145"> if (isMissing()) return "NOT FOUND";</span>
+<span class="source-line-no">146</span><span id="line-146"> if (inArchive()) return "archive";</span>
+<span class="source-line-no">147</span><span id="line-147"> return null;</span>
+<span class="source-line-no">148</span><span id="line-148"> }</span>
+<span class="source-line-no">149</span><span id="line-149"> }</span>
+<span class="source-line-no">150</span><span id="line-150"></span>
+<span class="source-line-no">151</span><span id="line-151"> private AtomicInteger hfilesArchiveCount = new AtomicInteger();</span>
+<span class="source-line-no">152</span><span id="line-152"> private AtomicInteger hfilesCorrupted = new AtomicInteger();</span>
+<span class="source-line-no">153</span><span id="line-153"> private AtomicInteger hfilesMissing = new AtomicInteger();</span>
+<span class="source-line-no">154</span><span id="line-154"> private AtomicInteger hfilesCount = new AtomicInteger();</span>
+<span class="source-line-no">155</span><span id="line-155"> private AtomicInteger hfilesMobCount = new AtomicInteger();</span>
+<span class="source-line-no">156</span><span id="line-156"> private AtomicInteger logsMissing = new AtomicInteger();</span>
+<span class="source-line-no">157</span><span id="line-157"> private AtomicInteger logsCount = new AtomicInteger();</span>
+<span class="source-line-no">158</span><span id="line-158"> private AtomicLong hfilesArchiveSize = new AtomicLong();</span>
+<span class="source-line-no">159</span><span id="line-159"> private AtomicLong hfilesSize = new AtomicLong();</span>
+<span class="source-line-no">160</span><span id="line-160"> private AtomicLong hfilesMobSize = new AtomicLong();</span>
+<span class="source-line-no">161</span><span id="line-161"> private AtomicLong nonSharedHfilesArchiveSize = new AtomicLong();</span>
+<span class="source-line-no">162</span><span id="line-162"> private AtomicLong logSize = new AtomicLong();</span>
+<span class="source-line-no">163</span><span id="line-163"></span>
+<span class="source-line-no">164</span><span id="line-164"> private final SnapshotProtos.SnapshotDescription snapshot;</span>
+<span class="source-line-no">165</span><span id="line-165"> private final TableName snapshotTable;</span>
+<span class="source-line-no">166</span><span id="line-166"> private final Configuration conf;</span>
+<span class="source-line-no">167</span><span id="line-167"> private final FileSystem fs;</span>
+<span class="source-line-no">168</span><span id="line-168"></span>
+<span class="source-line-no">169</span><span id="line-169"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
+<span class="source-line-no">170</span><span id="line-170"> final SnapshotDescription snapshot) {</span>
+<span class="source-line-no">171</span><span id="line-171"> this.snapshot = ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
+<span class="source-line-no">172</span><span id="line-172"> this.snapshotTable = snapshot.getTableName();</span>
+<span class="source-line-no">173</span><span id="line-173"> this.conf = conf;</span>
+<span class="source-line-no">174</span><span id="line-174"> this.fs = fs;</span>
+<span class="source-line-no">175</span><span id="line-175"> }</span>
+<span class="source-line-no">176</span><span id="line-176"></span>
+<span class="source-line-no">177</span><span id="line-177"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
+<span class="source-line-no">178</span><span id="line-178"> final SnapshotProtos.SnapshotDescription snapshot) {</span>
+<span class="source-line-no">179</span><span id="line-179"> this.snapshot = snapshot;</span>
+<span class="source-line-no">180</span><span id="line-180"> this.snapshotTable = TableName.valueOf(snapshot.getTable());</span>
+<span class="source-line-no">181</span><span id="line-181"> this.conf = conf;</span>
+<span class="source-line-no">182</span><span id="line-182"> this.fs = fs;</span>
+<span class="source-line-no">183</span><span id="line-183"> }</span>
+<span class="source-line-no">184</span><span id="line-184"></span>
+<span class="source-line-no">185</span><span id="line-185"> /** Returns the snapshot descriptor */</span>
+<span class="source-line-no">186</span><span id="line-186"> public SnapshotDescription getSnapshotDescription() {</span>
+<span class="source-line-no">187</span><span id="line-187"> return ProtobufUtil.createSnapshotDesc(this.snapshot);</span>
+<span class="source-line-no">188</span><span id="line-188"> }</span>
+<span class="source-line-no">189</span><span id="line-189"></span>
+<span class="source-line-no">190</span><span id="line-190"> /** Returns true if the snapshot is corrupted */</span>
+<span class="source-line-no">191</span><span id="line-191"> public boolean isSnapshotCorrupted() {</span>
+<span class="source-line-no">192</span><span id="line-192"> return hfilesMissing.get() > 0 || logsMissing.get() > 0 || hfilesCorrupted.get() > 0;</span>
+<span class="source-line-no">193</span><span id="line-193"> }</span>
+<span class="source-line-no">194</span><span id="line-194"></span>
+<span class="source-line-no">195</span><span id="line-195"> /** Returns the number of available store files */</span>
+<span class="source-line-no">196</span><span id="line-196"> public int getStoreFilesCount() {</span>
+<span class="source-line-no">197</span><span id="line-197"> return hfilesCount.get() + hfilesArchiveCount.get() + hfilesMobCount.get();</span>
+<span class="source-line-no">198</span><span id="line-198"> }</span>
+<span class="source-line-no">199</span><span id="line-199"></span>
+<span class="source-line-no">200</span><span id="line-200"> /** Returns the number of available store files in the archive */</span>
+<span class="source-line-no">201</span><span id="line-201"> public int getArchivedStoreFilesCount() {</span>
+<span class="source-line-no">202</span><span id="line-202"> return hfilesArchiveCount.get();</span>
+<span class="source-line-no">203</span><span id="line-203"> }</span>
+<span class="source-line-no">204</span><span id="line-204"></span>
+<span class="source-line-no">205</span><span id="line-205"> /** Returns the number of available store files in the mob dir */</span>
+<span class="source-line-no">206</span><span id="line-206"> public int getMobStoreFilesCount() {</span>
+<span class="source-line-no">207</span><span id="line-207"> return hfilesMobCount.get();</span>
+<span class="source-line-no">208</span><span id="line-208"> }</span>
+<span class="source-line-no">209</span><span id="line-209"></span>
+<span class="source-line-no">210</span><span id="line-210"> /** Returns the number of available log files */</span>
+<span class="source-line-no">211</span><span id="line-211"> public int getLogsCount() {</span>
+<span class="source-line-no">212</span><span id="line-212"> return logsCount.get();</span>
+<span class="source-line-no">213</span><span id="line-213"> }</span>
+<span class="source-line-no">214</span><span id="line-214"></span>
+<span class="source-line-no">215</span><span id="line-215"> /** Returns the number of missing store files */</span>
+<span class="source-line-no">216</span><span id="line-216"> public int getMissingStoreFilesCount() {</span>
+<span class="source-line-no">217</span><span id="line-217"> return hfilesMissing.get();</span>
+<span class="source-line-no">218</span><span id="line-218"> }</span>
+<span class="source-line-no">219</span><span id="line-219"></span>
+<span class="source-line-no">220</span><span id="line-220"> /** Returns the number of corrupted store files */</span>
+<span class="source-line-no">221</span><span id="line-221"> public int getCorruptedStoreFilesCount() {</span>
+<span class="source-line-no">222</span><span id="line-222"> return hfilesCorrupted.get();</span>
+<span class="source-line-no">223</span><span id="line-223"> }</span>
+<span class="source-line-no">224</span><span id="line-224"></span>
+<span class="source-line-no">225</span><span id="line-225"> /** Returns the number of missing log files */</span>
+<span class="source-line-no">226</span><span id="line-226"> public int getMissingLogsCount() {</span>
+<span class="source-line-no">227</span><span id="line-227"> return logsMissing.get();</span>
+<span class="source-line-no">228</span><span id="line-228"> }</span>
+<span class="source-line-no">229</span><span id="line-229"></span>
+<span class="source-line-no">230</span><span id="line-230"> /** Returns the total size of the store files referenced by the snapshot */</span>
+<span class="source-line-no">231</span><span id="line-231"> public long getStoreFilesSize() {</span>
+<span class="source-line-no">232</span><span id="line-232"> return hfilesSize.get() + hfilesArchiveSize.get() + hfilesMobSize.get();</span>
+<span class="source-line-no">233</span><span id="line-233"> }</span>
+<span class="source-line-no">234</span><span id="line-234"></span>
+<span class="source-line-no">235</span><span id="line-235"> /** Returns the total size of the store files shared */</span>
+<span class="source-line-no">236</span><span id="line-236"> public long getSharedStoreFilesSize() {</span>
+<span class="source-line-no">237</span><span id="line-237"> return hfilesSize.get();</span>
+<span class="source-line-no">238</span><span id="line-238"> }</span>
+<span class="source-line-no">239</span><span id="line-239"></span>
+<span class="source-line-no">240</span><span id="line-240"> /** Returns the total size of the store files in the archive */</span>
+<span class="source-line-no">241</span><span id="line-241"> public long getArchivedStoreFileSize() {</span>
+<span class="source-line-no">242</span><span id="line-242"> return hfilesArchiveSize.get();</span>
+<span class="source-line-no">243</span><span id="line-243"> }</span>
+<span class="source-line-no">244</span><span id="line-244"></span>
+<span class="source-line-no">245</span><span id="line-245"> /** Returns the total size of the store files in the mob store */</span>
+<span class="source-line-no">246</span><span id="line-246"> public long getMobStoreFilesSize() {</span>
+<span class="source-line-no">247</span><span id="line-247"> return hfilesMobSize.get();</span>
+<span class="source-line-no">248</span><span id="line-248"> }</span>
+<span class="source-line-no">249</span><span id="line-249"></span>
+<span class="source-line-no">250</span><span id="line-250"> /**</span>
+<span class="source-line-no">251</span><span id="line-251"> * @return the total size of the store files in the archive which is not shared with other</span>
+<span class="source-line-no">252</span><span id="line-252"> * snapshots and tables This is only calculated when</span>
+<span class="source-line-no">253</span><span id="line-253"> * {@link #getSnapshotStats(Configuration, SnapshotProtos.SnapshotDescription, Map)} is</span>
+<span class="source-line-no">254</span><span id="line-254"> * called with a non-null Map</span>
+<span class="source-line-no">255</span><span id="line-255"> */</span>
+<span class="source-line-no">256</span><span id="line-256"> public long getNonSharedArchivedStoreFilesSize() {</span>
+<span class="source-line-no">257</span><span id="line-257"> return nonSharedHfilesArchiveSize.get();</span>
+<span class="source-line-no">258</span><span id="line-258"> }</span>
+<span class="source-line-no">259</span><span id="line-259"></span>
+<span class="source-line-no">260</span><span id="line-260"> /** Returns the percentage of the shared store files */</span>
+<span class="source-line-no">261</span><span id="line-261"> public float getSharedStoreFilePercentage() {</span>
+<span class="source-line-no">262</span><span id="line-262"> return getStoreFilesSize() == 0</span>
+<span class="source-line-no">263</span><span id="line-263"> ? 0</span>
+<span class="source-line-no">264</span><span id="line-264"> : ((float) hfilesSize.get() / (getStoreFilesSize())) * 100;</span>
+<span class="source-line-no">265</span><span id="line-265"> }</span>
+<span class="source-line-no">266</span><span id="line-266"></span>
+<span class="source-line-no">267</span><span id="line-267"> /** Returns the percentage of the mob store files */</span>
+<span class="source-line-no">268</span><span id="line-268"> public float getMobStoreFilePercentage() {</span>
+<span class="source-line-no">269</span><span id="line-269"> return getStoreFilesSize() == 0</span>
+<span class="source-line-no">270</span><span id="line-270"> ? 0</span>
+<span class="source-line-no">271</span><span id="line-271"> : ((float) hfilesMobSize.get() / (getStoreFilesSize())) * 100;</span>
+<span class="source-line-no">272</span><span id="line-272"> }</span>
+<span class="source-line-no">273</span><span id="line-273"></span>
+<span class="source-line-no">274</span><span id="line-274"> /** Returns the total log size */</span>
+<span class="source-line-no">275</span><span id="line-275"> public long getLogsSize() {</span>
+<span class="source-line-no">276</span><span id="line-276"> return logSize.get();</span>
+<span class="source-line-no">277</span><span id="line-277"> }</span>
+<span class="source-line-no">278</span><span id="line-278"></span>
+<span class="source-line-no">279</span><span id="line-279"> /**</span>
+<span class="source-line-no">280</span><span id="line-280"> * Check if for a give file in archive, if there are other snapshots/tables still reference it.</span>
+<span class="source-line-no">281</span><span id="line-281"> * @param filePath file path in archive</span>
+<span class="source-line-no">282</span><span id="line-282"> * @param snapshotFilesMap a map for store files in snapshots about how many snapshots refer to</span>
+<span class="source-line-no">283</span><span id="line-283"> * it.</span>
+<span class="source-line-no">284</span><span id="line-284"> * @return true or false</span>
+<span class="source-line-no">285</span><span id="line-285"> */</span>
+<span class="source-line-no">286</span><span id="line-286"> private boolean isArchivedFileStillReferenced(final Path filePath,</span>
+<span class="source-line-no">287</span><span id="line-287"> final Map<Path, Integer> snapshotFilesMap) {</span>
+<span class="source-line-no">288</span><span id="line-288"></span>
+<span class="source-line-no">289</span><span id="line-289"> Integer c = snapshotFilesMap.get(filePath);</span>
+<span class="source-line-no">290</span><span id="line-290"></span>
+<span class="source-line-no">291</span><span id="line-291"> // Check if there are other snapshots or table from clone_snapshot() (via back-reference)</span>
+<span class="source-line-no">292</span><span id="line-292"> // still reference to it.</span>
+<span class="source-line-no">293</span><span id="line-293"> if ((c != null) && (c == 1)) {</span>
+<span class="source-line-no">294</span><span id="line-294"> Path parentDir = filePath.getParent();</span>
+<span class="source-line-no">295</span><span id="line-295"> Path backRefDir = HFileLink.getBackReferencesDir(parentDir, filePath.getName());</span>
+<span class="source-line-no">296</span><span id="line-296"> try {</span>
+<span class="source-line-no">297</span><span id="line-297"> if (CommonFSUtils.listStatus(fs, backRefDir) == null) {</span>
+<span class="source-line-no">298</span><span id="line-298"> return false;</span>
+<span class="source-line-no">299</span><span id="line-299"> }</span>
+<span class="source-line-no">300</span><span id="line-300"> } catch (IOException e) {</span>
+<span class="source-line-no">301</span><span id="line-301"> // For the purpose of this function, IOException is ignored and treated as</span>
+<span class="source-line-no">302</span><span id="line-302"> // the file is still being referenced.</span>
+<span class="source-line-no">303</span><span id="line-303"> }</span>
+<span class="source-line-no">304</span><span id="line-304"> }</span>
+<span class="source-line-no">305</span><span id="line-305"> return true;</span>
+<span class="source-line-no">306</span><span id="line-306"> }</span>
+<span class="source-line-no">307</span><span id="line-307"></span>
+<span class="source-line-no">308</span><span id="line-308"> /**</span>
+<span class="source-line-no">309</span><span id="line-309"> * Add the specified store file to the stats</span>
+<span class="source-line-no">310</span><span id="line-310"> * @param region region encoded Name</span>
+<span class="source-line-no">311</span><span id="line-311"> * @param family family name</span>
+<span class="source-line-no">312</span><span id="line-312"> * @param storeFile store file name</span>
+<span class="source-line-no">313</span><span id="line-313"> * @param filesMap store files map for all snapshots, it may be null</span>
+<span class="source-line-no">314</span><span id="line-314"> * @return the store file information</span>
+<span class="source-line-no">315</span><span id="line-315"> */</span>
+<span class="source-line-no">316</span><span id="line-316"> FileInfo addStoreFile(final RegionInfo region, final String family,</span>
+<span class="source-line-no">317</span><span id="line-317"> final SnapshotRegionManifest.StoreFile storeFile, final Map<Path, Integer> filesMap)</span>
+<span class="source-line-no">318</span><span id="line-318"> throws IOException {</span>
+<span class="source-line-no">319</span><span id="line-319"> HFileLink link =</span>
+<span class="source-line-no">320</span><span id="line-320"> HFileLink.build(conf, snapshotTable, region.getEncodedName(), family, storeFile.getName());</span>
+<span class="source-line-no">321</span><span id="line-321"> boolean isCorrupted = false;</span>
+<span class="source-line-no">322</span><span id="line-322"> boolean inArchive = false;</span>
+<span class="source-line-no">323</span><span id="line-323"> long size = -1;</span>
+<span class="source-line-no">324</span><span id="line-324"> try {</span>
+<span class="source-line-no">325</span><span id="line-325"> if (fs.exists(link.getArchivePath())) {</span>
+<span class="source-line-no">326</span><span id="line-326"> inArchive = true;</span>
+<span class="source-line-no">327</span><span id="line-327"> size = fs.getFileStatus(link.getArchivePath()).getLen();</span>
+<span class="source-line-no">328</span><span id="line-328"> hfilesArchiveSize.addAndGet(size);</span>
+<span class="source-line-no">329</span><span id="line-329"> hfilesArchiveCount.incrementAndGet();</span>
+<span class="source-line-no">330</span><span id="line-330"></span>
+<span class="source-line-no">331</span><span id="line-331"> // If store file is not shared with other snapshots and tables,</span>
+<span class="source-line-no">332</span><span id="line-332"> // increase nonSharedHfilesArchiveSize</span>
+<span class="source-line-no">333</span><span id="line-333"> if (</span>
+<span class="source-line-no">334</span><span id="line-334"> (filesMap != null) && !isArchivedFileStillReferenced(link.getArchivePath(), filesMap)</span>
+<span class="source-line-no">335</span><span id="line-335"> ) {</span>
+<span class="source-line-no">336</span><span id="line-336"> nonSharedHfilesArchiveSize.addAndGet(size);</span>
+<span class="source-line-no">337</span><span id="line-337"> }</span>
+<span class="source-line-no">338</span><span id="line-338"> } else if (fs.exists(link.getMobPath())) {</span>
+<span class="source-line-no">339</span><span id="line-339"> inArchive = true;</span>
+<span class="source-line-no">340</span><span id="line-340"> size = fs.getFileStatus(link.getMobPath()).getLen();</span>
+<span class="source-line-no">341</span><span id="line-341"> hfilesMobSize.addAndGet(size);</span>
+<span class="source-line-no">342</span><span id="line-342"> hfilesMobCount.incrementAndGet();</span>
+<span class="source-line-no">343</span><span id="line-343"> } else {</span>
+<span class="source-line-no">344</span><span id="line-344"> size = link.getFileStatus(fs).getLen();</span>
+<span class="source-line-no">345</span><span id="line-345"> hfilesSize.addAndGet(size);</span>
+<span class="source-line-no">346</span><span id="line-346"> hfilesCount.incrementAndGet();</span>
+<span class="source-line-no">347</span><span id="line-347"> }</span>
+<span class="source-line-no">348</span><span id="line-348"> isCorrupted = (storeFile.hasFileSize() && storeFile.getFileSize() != size);</span>
+<span class="source-line-no">349</span><span id="line-349"> if (isCorrupted) hfilesCorrupted.incrementAndGet();</span>
+<span class="source-line-no">350</span><span id="line-350"> } catch (FileNotFoundException e) {</span>
+<span class="source-line-no">351</span><span id="line-351"> hfilesMissing.incrementAndGet();</span>
+<span class="source-line-no">352</span><span id="line-352"> }</span>
+<span class="source-line-no">353</span><span id="line-353"> return new FileInfo(inArchive, size, isCorrupted);</span>
+<span class="source-line-no">354</span><span id="line-354"> }</span>
+<span class="source-line-no">355</span><span id="line-355"></span>
+<span class="source-line-no">356</span><span id="line-356"> /**</span>
+<span class="source-line-no">357</span><span id="line-357"> * Add the specified log file to the stats</span>
+<span class="source-line-no">358</span><span id="line-358"> * @param server server name</span>
+<span class="source-line-no">359</span><span id="line-359"> * @param logfile log file name</span>
+<span class="source-line-no">360</span><span id="line-360"> * @return the log information</span>
+<span class="source-line-no">361</span><span id="line-361"> */</span>
+<span class="source-line-no">362</span><span id="line-362"> FileInfo addLogFile(final String server, final String logfile) throws IOException {</span>
+<span class="source-line-no">363</span><span id="line-363"> WALLink logLink = new WALLink(conf, server, logfile);</span>
+<span class="source-line-no">364</span><span id="line-364"> long size = -1;</span>
+<span class="source-line-no">365</span><span id="line-365"> try {</span>
+<span class="source-line-no">366</span><span id="line-366"> size = logLink.getFileStatus(fs).getLen();</span>
+<span class="source-line-no">367</span><span id="line-367"> logSize.addAndGet(size);</span>
+<span class="source-line-no">368</span><span id="line-368"> logsCount.incrementAndGet();</span>
+<span class="source-line-no">369</span><span id="line-369"> } catch (FileNotFoundException e) {</span>
+<span class="source-line-no">370</span><span id="line-370"> logsMissing.incrementAndGet();</span>
+<span class="source-line-no">371</span><span id="line-371"> }</span>
+<span class="source-line-no">372</span><span id="line-372"> return new FileInfo(false, size, false);</span>
+<span class="source-line-no">373</span><span id="line-373"> }</span>
+<span class="source-line-no">374</span><span id="line-374"> }</span>
+<span class="source-line-no">375</span><span id="line-375"></span>
+<span class="source-line-no">376</span><span id="line-376"> private FileSystem fs;</span>
+<span class="source-line-no">377</span><span id="line-377"> private Path rootDir;</span>
+<span class="source-line-no">378</span><span id="line-378"></span>
+<span class="source-line-no">379</span><span id="line-379"> private SnapshotManifest snapshotManifest;</span>
+<span class="source-line-no">380</span><span id="line-380"></span>
+<span class="source-line-no">381</span><span id="line-381"> private boolean listSnapshots = false;</span>
+<span class="source-line-no">382</span><span id="line-382"> private String snapshotName;</span>
+<span class="source-line-no">383</span><span id="line-383"> private Path remoteDir;</span>
+<span class="source-line-no">384</span><span id="line-384"> private boolean showSchema = false;</span>
+<span class="source-line-no">385</span><span id="line-385"> private boolean showFiles = false;</span>
+<span class="source-line-no">386</span><span id="line-386"> private boolean showStats = false;</span>
+<span class="source-line-no">387</span><span id="line-387"> private boolean printSizeInBytes = false;</span>
+<span class="source-line-no">388</span><span id="line-388"></span>
+<span class="source-line-no">389</span><span id="line-389"> @Override</span>
+<span class="source-line-no">390</span><span id="line-390"> public int doWork() throws IOException, InterruptedException {</span>
+<span class="source-line-no">391</span><span id="line-391"> if (remoteDir != null) {</span>
+<span class="source-line-no">392</span><span id="line-392"> URI defaultFs = remoteDir.getFileSystem(conf).getUri();</span>
+<span class="source-line-no">393</span><span id="line-393"> CommonFSUtils.setFsDefault(conf, new Path(defaultFs));</span>
+<span class="source-line-no">394</span><span id="line-394"> CommonFSUtils.setRootDir(conf, remoteDir);</span>
+<span class="source-line-no">395</span><span id="line-395"> }</span>
+<span class="source-line-no">396</span><span id="line-396"></span>
+<span class="source-line-no">397</span><span id="line-397"> // List Available Snapshots</span>
+<span class="source-line-no">398</span><span id="line-398"> if (listSnapshots) {</span>
+<span class="source-line-no">399</span><span id="line-399"> SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");</span>
+<span class="source-line-no">400</span><span id="line-400"> List<SnapshotDescription> snapshotDescriptions = getSnapshotList(conf);</span>
+<span class="source-line-no">401</span><span id="line-401"> System.out.printf("%-20s | %-20s | %-20s | %-20s | %s%n", "SNAPSHOT", "CREATION TIME",</span>
+<span class="source-line-no">402</span><span id="line-402"> "TTL(Sec)", "EXPIRED", "TABLE NAME");</span>
+<span class="source-line-no">403</span><span id="line-403"> long currentTime = System.currentTimeMillis();</span>
+<span class="source-line-no">404</span><span id="line-404"> for (SnapshotDescription desc : snapshotDescriptions) {</span>
+<span class="source-line-no">405</span><span id="line-405"> String ttlInfo =</span>
+<span class="source-line-no">406</span><span id="line-406"> desc.getTtl() == DEFAULT_SNAPSHOT_TTL ? TTL_FOREVER : String.valueOf(desc.getTtl());</span>
+<span class="source-line-no">407</span><span id="line-407"> String expired = SnapshotDescriptionUtils.isExpiredSnapshot(desc.getTtl(),</span>
+<span class="source-line-no">408</span><span id="line-408"> desc.getCreationTime(), currentTime) ? EXPIRED_LABEL : NOT_EXPIRED_LABEL;</span>
+<span class="source-line-no">409</span><span id="line-409"> System.out.printf("%-20s | %20s | %20s | %20s | %s%n", desc.getName(),</span>
+<span class="source-line-no">410</span><span id="line-410"> df.format(new Date(desc.getCreationTime())), ttlInfo, expired,</span>
+<span class="source-line-no">411</span><span id="line-411"> desc.getTableNameAsString());</span>
+<span class="source-line-no">412</span><span id="line-412"> }</span>
+<span class="source-line-no">413</span><span id="line-413"> return 0;</span>
+<span class="source-line-no">414</span><span id="line-414"> }</span>
+<span class="source-line-no">415</span><span id="line-415"></span>
+<span class="source-line-no">416</span><span id="line-416"> rootDir = CommonFSUtils.getRootDir(conf);</span>
+<span class="source-line-no">417</span><span id="line-417"> fs = FileSystem.get(rootDir.toUri(), conf);</span>
+<span class="source-line-no">418</span><span id="line-418"> LOG.debug("fs=" + fs.getUri().toString() + " root=" + rootDir);</span>
+<span class="source-line-no">419</span><span id="line-419"></span>
+<span class="source-line-no">420</span><span id="line-420"> // Load snapshot information</span>
+<span class="source-line-no">421</span><span id="line-421"> if (!loadSnapshotInfo(snapshotName)) {</span>
+<span class="source-line-no">422</span><span id="line-422"> System.err.println("Snapshot '" + snapshotName + "' not found!");</span>
+<span class="source-line-no">423</span><span id="line-423"> return 1;</span>
+<span class="source-line-no">424</span><span id="line-424"> }</span>
+<span class="source-line-no">425</span><span id="line-425"></span>
+<span class="source-line-no">426</span><span id="line-426"> printInfo();</span>
+<span class="source-line-no">427</span><span id="line-427"> if (showSchema) {</span>
+<span class="source-line-no">428</span><span id="line-428"> printSchema();</span>
+<span class="source-line-no">429</span><span id="line-429"> }</span>
+<span class="source-line-no">430</span><span id="line-430"> printFiles(showFiles, showStats);</span>
+<span class="source-line-no">431</span><span id="line-431"></span>
+<span class="source-line-no">432</span><span id="line-432"> return 0;</span>
+<span class="source-line-no">433</span><span id="line-433"> }</span>
+<span class="source-line-no">434</span><span id="line-434"></span>
+<span class="source-line-no">435</span><span id="line-435"> /**</span>
+<span class="source-line-no">436</span><span id="line-436"> * Load snapshot info and table descriptor for the specified snapshot</span>
+<span class="source-line-no">437</span><span id="line-437"> * @param snapshotName name of the snapshot to load</span>
+<span class="source-line-no">438</span><span id="line-438"> * @return false if snapshot is not found</span>
+<span class="source-line-no">439</span><span id="line-439"> */</span>
+<span class="source-line-no">440</span><span id="line-440"> private boolean loadSnapshotInfo(final String snapshotName) throws IOException {</span>
+<span class="source-line-no">441</span><span id="line-441"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);</span>
+<span class="source-line-no">442</span><span id="line-442"> if (!fs.exists(snapshotDir)) {</span>
+<span class="source-line-no">443</span><span id="line-443"> LOG.warn("Snapshot '" + snapshotName + "' not found in: " + snapshotDir);</span>
+<span class="source-line-no">444</span><span id="line-444"> return false;</span>
+<span class="source-line-no">445</span><span id="line-445"> }</span>
+<span class="source-line-no">446</span><span id="line-446"></span>
+<span class="source-line-no">447</span><span id="line-447"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">448</span><span id="line-448"> SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);</span>
+<span class="source-line-no">449</span><span id="line-449"> snapshotManifest = SnapshotManifest.open(getConf(), fs, snapshotDir, snapshotDesc);</span>
+<span class="source-line-no">450</span><span id="line-450"> return true;</span>
+<span class="source-line-no">451</span><span id="line-451"> }</span>
+<span class="source-line-no">452</span><span id="line-452"></span>
+<span class="source-line-no">453</span><span id="line-453"> /**</span>
+<span class="source-line-no">454</span><span id="line-454"> * Dump the {@link SnapshotDescription}</span>
+<span class="source-line-no">455</span><span id="line-455"> */</span>
+<span class="source-line-no">456</span><span id="line-456"> private void printInfo() {</span>
+<span class="source-line-no">457</span><span id="line-457"> SnapshotProtos.SnapshotDescription snapshotDesc = snapshotManifest.getSnapshotDescription();</span>
+<span class="source-line-no">458</span><span id="line-458"> SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");</span>
+<span class="source-line-no">459</span><span id="line-459"> String ttlInfo = snapshotDesc.getTtl() == DEFAULT_SNAPSHOT_TTL</span>
+<span class="source-line-no">460</span><span id="line-460"> ? TTL_FOREVER</span>
+<span class="source-line-no">461</span><span id="line-461"> : String.valueOf(snapshotDesc.getTtl());</span>
+<span class="source-line-no">462</span><span id="line-462"> String expired = SnapshotDescriptionUtils.isExpiredSnapshot(snapshotDesc.getTtl(),</span>
+<span class="source-line-no">463</span><span id="line-463"> snapshotDesc.getCreationTime(), System.currentTimeMillis())</span>
+<span class="source-line-no">464</span><span id="line-464"> ? EXPIRED_LABEL</span>
+<span class="source-line-no">465</span><span id="line-465"> : NOT_EXPIRED_LABEL;</span>
+<span class="source-line-no">466</span><span id="line-466"> System.out.println("Snapshot Info");</span>
+<span class="source-line-no">467</span><span id="line-467"> System.out.println("-----------------------------------------");</span>
+<span class="source-line-no">468</span><span id="line-468"> System.out.println(" Name: " + snapshotDesc.getName());</span>
+<span class="source-line-no">469</span><span id="line-469"> System.out.println(" Type: " + snapshotDesc.getType());</span>
+<span class="source-line-no">470</span><span id="line-470"> System.out.println(" Table: " + snapshotDesc.getTable());</span>
+<span class="source-line-no">471</span><span id="line-471"> System.out.println(" Format: " + snapshotDesc.getVersion());</span>
+<span class="source-line-no">472</span><span id="line-472"> System.out.println(" Created: " + df.format(new Date(snapshotDesc.getCreationTime())));</span>
+<span class="source-line-no">473</span><span id="line-473"> System.out.println("Ttl(Sec): " + ttlInfo);</span>
+<span class="source-line-no">474</span><span id="line-474"> System.out.println(" Expired: " + expired);</span>
+<span class="source-line-no">475</span><span id="line-475"> System.out.println(" Owner: " + snapshotDesc.getOwner());</span>
+<span class="source-line-no">476</span><span id="line-476"> System.out.println();</span>
+<span class="source-line-no">477</span><span id="line-477"> }</span>
+<span class="source-line-no">478</span><span id="line-478"></span>
+<span class="source-line-no">479</span><span id="line-479"> /**</span>
+<span class="source-line-no">480</span><span id="line-480"> * Dump the {@link org.apache.hadoop.hbase.client.TableDescriptor}</span>
+<span class="source-line-no">481</span><span id="line-481"> */</span>
+<span class="source-line-no">482</span><span id="line-482"> private void printSchema() {</span>
+<span class="source-line-no">483</span><span id="line-483"> System.out.println("Table Descriptor");</span>
+<span class="source-line-no">484</span><span id="line-484"> System.out.println("----------------------------------------");</span>
+<span class="source-line-no">485</span><span id="line-485"> System.out.println(snapshotManifest.getTableDescriptor().toString());</span>
+<span class="source-line-no">486</span><span id="line-486"> System.out.println();</span>
+<span class="source-line-no">487</span><span id="line-487"> }</span>
+<span class="source-line-no">488</span><span id="line-488"></span>
+<span class="source-line-no">489</span><span id="line-489"> /**</span>
+<span class="source-line-no">490</span><span id="line-490"> * Collect the hfiles and logs statistics of the snapshot and dump the file list if requested and</span>
+<span class="source-line-no">491</span><span id="line-491"> * the collected information.</span>
+<span class="source-line-no">492</span><span id="line-492"> */</span>
+<span class="source-line-no">493</span><span id="line-493"> private void printFiles(final boolean showFiles, final boolean showStats) throws IOException {</span>
+<span class="source-line-no">494</span><span id="line-494"> if (showFiles) {</span>
+<span class="source-line-no">495</span><span id="line-495"> System.out.println("Snapshot Files");</span>
+<span class="source-line-no">496</span><span id="line-496"> System.out.println("----------------------------------------");</span>
+<span class="source-line-no">497</span><span id="line-497"> }</span>
+<span class="source-line-no">498</span><span id="line-498"></span>
+<span class="source-line-no">499</span><span id="line-499"> // Collect information about hfiles and logs in the snapshot</span>
+<span class="source-line-no">500</span><span id="line-500"> final SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">501</span><span id="line-501"> snapshotManifest.getSnapshotDescription();</span>
+<span class="source-line-no">502</span><span id="line-502"> final String table = snapshotDesc.getTable();</span>
+<span class="source-line-no">503</span><span id="line-503"> final SnapshotDescription desc = ProtobufUtil.createSnapshotDesc(snapshotDesc);</span>
+<span class="source-line-no">504</span><span id="line-504"> final SnapshotStats stats = new SnapshotStats(this.getConf(), this.fs, desc);</span>
+<span class="source-line-no">505</span><span id="line-505"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(getConf(), fs, snapshotManifest,</span>
+<span class="source-line-no">506</span><span id="line-506"> "SnapshotInfo", new SnapshotReferenceUtil.SnapshotVisitor() {</span>
+<span class="source-line-no">507</span><span id="line-507"> @Override</span>
+<span class="source-line-no">508</span><span id="line-508"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
+<span class="source-line-no">509</span><span id="line-509"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
+<span class="source-line-no">510</span><span id="line-510"> if (storeFile.hasReference()) return;</span>
+<span class="source-line-no">511</span><span id="line-511"></span>
+<span class="source-line-no">512</span><span id="line-512"> SnapshotStats.FileInfo info = stats.addStoreFile(regionInfo, family, storeFile, null);</span>
+<span class="source-line-no">513</span><span id="line-513"> if (showFiles) {</span>
+<span class="source-line-no">514</span><span id="line-514"> String state = info.getStateToString();</span>
+<span class="source-line-no">515</span><span id="line-515"> System.out.printf("%8s %s/%s/%s/%s %s%n",</span>
+<span class="source-line-no">516</span><span id="line-516"> (info.isMissing() ? "-" : fileSizeToString(info.getSize())), table,</span>
+<span class="source-line-no">517</span><span id="line-517"> regionInfo.getEncodedName(), family, storeFile.getName(),</span>
+<span class="source-line-no">518</span><span id="line-518"> state == null ? "" : "(" + state + ")");</span>
+<span class="source-line-no">519</span><span id="line-519"> }</span>
+<span class="source-line-no">520</span><span id="line-520"> }</span>
+<span class="source-line-no">521</span><span id="line-521"> });</span>
+<span class="source-line-no">522</span><span id="line-522"></span>
+<span class="source-line-no">523</span><span id="line-523"> // Dump the stats</span>
+<span class="source-line-no">524</span><span id="line-524"> System.out.println();</span>
+<span class="source-line-no">525</span><span id="line-525"> if (stats.isSnapshotCorrupted()) {</span>
+<span class="source-line-no">526</span><span id="line-526"> System.out.println("**************************************************************");</span>
+<span class="source-line-no">527</span><span id="line-527"> System.out.printf("BAD SNAPSHOT: %d hfile(s) and %d log(s) missing.%n",</span>
+<span class="source-line-no">528</span><span id="line-528"> stats.getMissingStoreFilesCount(), stats.getMissingLogsCount());</span>
+<span class="source-line-no">529</span><span id="line-529"> System.out.printf(" %d hfile(s) corrupted.%n",</span>
+<span class="source-line-no">530</span><span id="line-530"> stats.getCorruptedStoreFilesCount());</span>
+<span class="source-line-no">531</span><span id="line-531"> System.out.println("**************************************************************");</span>
+<span class="source-line-no">532</span><span id="line-532"> }</span>
+<span class="source-line-no">533</span><span id="line-533"></span>
+<span class="source-line-no">534</span><span id="line-534"> if (showStats) {</span>
+<span class="source-line-no">535</span><span id="line-535"> System.out.printf(</span>
+<span class="source-line-no">536</span><span id="line-536"> "%d HFiles (%d in archive, %d in mob storage), total size %s "</span>
+<span class="source-line-no">537</span><span id="line-537"> + "(%.2f%% %s shared with the source table, %.2f%% %s in mob dir)%n",</span>
+<span class="source-line-no">538</span><span id="line-538"> stats.getStoreFilesCount(), stats.getArchivedStoreFilesCount(),</span>
+<span class="source-line-no">539</span><span id="line-539"> stats.getMobStoreFilesCount(), fileSizeToString(stats.getStoreFilesSize()),</span>
+<span class="source-line-no">540</span><span id="line-540"> stats.getSharedStoreFilePercentage(), fileSizeToString(stats.getSharedStoreFilesSize()),</span>
+<span class="source-line-no">541</span><span id="line-541"> stats.getMobStoreFilePercentage(), fileSizeToString(stats.getMobStoreFilesSize()));</span>
+<span class="source-line-no">542</span><span id="line-542"> System.out.printf("%d Logs, total size %s%n", stats.getLogsCount(),</span>
+<span class="source-line-no">543</span><span id="line-543"> fileSizeToString(stats.getLogsSize()));</span>
+<span class="source-line-no">544</span><span id="line-544"> System.out.println();</span>
+<span class="source-line-no">545</span><span id="line-545"> }</span>
+<span class="source-line-no">546</span><span id="line-546"> }</span>
+<span class="source-line-no">547</span><span id="line-547"></span>
+<span class="source-line-no">548</span><span id="line-548"> private String fileSizeToString(long size) {</span>
+<span class="source-line-no">549</span><span id="line-549"> return printSizeInBytes ? Long.toString(size) : Strings.humanReadableInt(size);</span>
+<span class="source-line-no">550</span><span id="line-550"> }</span>
+<span class="source-line-no">551</span><span id="line-551"></span>
+<span class="source-line-no">552</span><span id="line-552"> @Override</span>
+<span class="source-line-no">553</span><span id="line-553"> protected void addOptions() {</span>
+<span class="source-line-no">554</span><span id="line-554"> addOption(Options.SNAPSHOT);</span>
+<span class="source-line-no">555</span><span id="line-555"> addOption(Options.REMOTE_DIR);</span>
+<span class="source-line-no">556</span><span id="line-556"> addOption(Options.LIST_SNAPSHOTS);</span>
+<span class="source-line-no">557</span><span id="line-557"> addOption(Options.FILES);</span>
+<span class="source-line-no">558</span><span id="line-558"> addOption(Options.STATS);</span>
+<span class="source-line-no">559</span><span id="line-559"> addOption(Options.SCHEMA);</span>
+<span class="source-line-no">560</span><span id="line-560"> addOption(Options.SIZE_IN_BYTES);</span>
+<span class="source-line-no">561</span><span id="line-561"> }</span>
+<span class="source-line-no">562</span><span id="line-562"></span>
+<span class="source-line-no">563</span><span id="line-563"> @Override</span>
+<span class="source-line-no">564</span><span id="line-564"> protected CommandLineParser newParser() {</span>
+<span class="source-line-no">565</span><span id="line-565"> // Commons-CLI lacks the capability to handle combinations of options, so we do it ourselves</span>
+<span class="source-line-no">566</span><span id="line-566"> // Validate in parse() to get helpful error messages instead of exploding in processOptions()</span>
+<span class="source-line-no">567</span><span id="line-567"> return new DefaultParser() {</span>
+<span class="source-line-no">568</span><span id="line-568"> @Override</span>
+<span class="source-line-no">569</span><span id="line-569"> public CommandLine parse(org.apache.hbase.thirdparty.org.apache.commons.cli.Options opts,</span>
+<span class="source-line-no">570</span><span id="line-570"> String[] args, Properties props, boolean stop) throws ParseException {</span>
+<span class="source-line-no">571</span><span id="line-571"> CommandLine cl = super.parse(opts, args, props, stop);</span>
+<span class="source-line-no">572</span><span id="line-572"> if (!cmd.hasOption(Options.LIST_SNAPSHOTS) && !cmd.hasOption(Options.SNAPSHOT)) {</span>
+<span class="source-line-no">573</span><span id="line-573"> throw new ParseException("Missing required snapshot option!");</span>
+<span class="source-line-no">574</span><span id="line-574"> }</span>
+<span class="source-line-no">575</span><span id="line-575"> return cl;</span>
+<span class="source-line-no">576</span><span id="line-576"> }</span>
+<span class="source-line-no">577</span><span id="line-577"> };</span>
<span class="source-line-no">578</span><span id="line-578"> }</span>
<span class="source-line-no">579</span><span id="line-579"></span>
-<span class="source-line-no">580</span><span id="line-580"> /**</span>
-<span class="source-line-no">581</span><span id="line-581"> * Returns the snapshot stats</span>
-<span class="source-line-no">582</span><span id="line-582"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">583</span><span id="line-583"> * @param snapshot {@link SnapshotDescription} to get stats from</span>
-<span class="source-line-no">584</span><span id="line-584"> * @return the snapshot stats</span>
-<span class="source-line-no">585</span><span id="line-585"> */</span>
-<span class="source-line-no">586</span><span id="line-586"> public static SnapshotStats getSnapshotStats(final Configuration conf,</span>
-<span class="source-line-no">587</span><span id="line-587"> final SnapshotDescription snapshot) throws IOException {</span>
-<span class="source-line-no">588</span><span id="line-588"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">589</span><span id="line-589"> ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
-<span class="source-line-no">590</span><span id="line-590"> return getSnapshotStats(conf, snapshotDesc, null);</span>
-<span class="source-line-no">591</span><span id="line-591"> }</span>
-<span class="source-line-no">592</span><span id="line-592"></span>
-<span class="source-line-no">593</span><span id="line-593"> /**</span>
-<span class="source-line-no">594</span><span id="line-594"> * Returns the snapshot stats</span>
-<span class="source-line-no">595</span><span id="line-595"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">596</span><span id="line-596"> * @param snapshotDesc HBaseProtos.SnapshotDescription to get stats from</span>
-<span class="source-line-no">597</span><span id="line-597"> * @param filesMap {@link Map} store files map for all snapshots, it may be null</span>
-<span class="source-line-no">598</span><span id="line-598"> * @return the snapshot stats</span>
-<span class="source-line-no">599</span><span id="line-599"> */</span>
-<span class="source-line-no">600</span><span id="line-600"> public static SnapshotStats getSnapshotStats(final Configuration conf,</span>
-<span class="source-line-no">601</span><span id="line-601"> final SnapshotProtos.SnapshotDescription snapshotDesc, final Map<Path, Integer> filesMap)</span>
-<span class="source-line-no">602</span><span id="line-602"> throws IOException {</span>
-<span class="source-line-no">603</span><span id="line-603"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
-<span class="source-line-no">604</span><span id="line-604"> FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
-<span class="source-line-no">605</span><span id="line-605"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotDesc, rootDir);</span>
-<span class="source-line-no">606</span><span id="line-606"> SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);</span>
-<span class="source-line-no">607</span><span id="line-607"> final SnapshotStats stats = new SnapshotStats(conf, fs, snapshotDesc);</span>
-<span class="source-line-no">608</span><span id="line-608"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(conf, fs, manifest,</span>
-<span class="source-line-no">609</span><span id="line-609"> "SnapshotsStatsAggregation", new SnapshotReferenceUtil.SnapshotVisitor() {</span>
-<span class="source-line-no">610</span><span id="line-610"> @Override</span>
-<span class="source-line-no">611</span><span id="line-611"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
-<span class="source-line-no">612</span><span id="line-612"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
-<span class="source-line-no">613</span><span id="line-613"> if (!storeFile.hasReference()) {</span>
-<span class="source-line-no">614</span><span id="line-614"> stats.addStoreFile(regionInfo, family, storeFile, filesMap);</span>
-<span class="source-line-no">615</span><span id="line-615"> }</span>
-<span class="source-line-no">616</span><span id="line-616"> }</span>
-<span class="source-line-no">617</span><span id="line-617"> });</span>
-<span class="source-line-no">618</span><span id="line-618"> return stats;</span>
-<span class="source-line-no">619</span><span id="line-619"> }</span>
-<span class="source-line-no">620</span><span id="line-620"></span>
-<span class="source-line-no">621</span><span id="line-621"> /**</span>
-<span class="source-line-no">622</span><span id="line-622"> * Returns the list of available snapshots in the specified location</span>
-<span class="source-line-no">623</span><span id="line-623"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">624</span><span id="line-624"> * @return the list of snapshots</span>
-<span class="source-line-no">625</span><span id="line-625"> */</span>
-<span class="source-line-no">626</span><span id="line-626"> public static List<SnapshotDescription> getSnapshotList(final Configuration conf)</span>
-<span class="source-line-no">627</span><span id="line-627"> throws IOException {</span>
-<span class="source-line-no">628</span><span id="line-628"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
-<span class="source-line-no">629</span><span id="line-629"> FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
-<span class="source-line-no">630</span><span id="line-630"> Path snapshotDir = SnapshotDescriptionUtils.getSnapshotsDir(rootDir);</span>
-<span class="source-line-no">631</span><span id="line-631"> FileStatus[] snapshots = CommonFSUtils.listStatus(fs, snapshotDir,</span>
-<span class="source-line-no">632</span><span id="line-632"> new SnapshotDescriptionUtils.CompletedSnaphotDirectoriesFilter(fs));</span>
-<span class="source-line-no">633</span><span id="line-633"> if (snapshots == null) {</span>
-<span class="source-line-no">634</span><span id="line-634"> return Collections.emptyList();</span>
-<span class="source-line-no">635</span><span id="line-635"> }</span>
-<span class="source-line-no">636</span><span id="line-636"> List<SnapshotDescription> snapshotLists = new ArrayList<>(snapshots.length);</span>
-<span class="source-line-no">637</span><span id="line-637"> for (FileStatus snapshotDirStat : snapshots) {</span>
-<span class="source-line-no">638</span><span id="line-638"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">639</span><span id="line-639"> SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDirStat.getPath());</span>
-<span class="source-line-no">640</span><span id="line-640"> snapshotLists.add(ProtobufUtil.createSnapshotDesc(snapshotDesc));</span>
-<span class="source-line-no">641</span><span id="line-641"> }</span>
-<span class="source-line-no">642</span><span id="line-642"> return snapshotLists;</span>
-<span class="source-line-no">643</span><span id="line-643"> }</span>
-<span class="source-line-no">644</span><span id="line-644"></span>
-<span class="source-line-no">645</span><span id="line-645"> /**</span>
-<span class="source-line-no">646</span><span id="line-646"> * Gets the store files map for snapshot</span>
-<span class="source-line-no">647</span><span id="line-647"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">648</span><span id="line-648"> * @param snapshot {@link SnapshotDescription} to get stats from</span>
-<span class="source-line-no">649</span><span id="line-649"> * @param exec the {@link ExecutorService} to use</span>
-<span class="source-line-no">650</span><span id="line-650"> * @param filesMap {@link Map} the map to put the mapping entries</span>
-<span class="source-line-no">651</span><span id="line-651"> * @param uniqueHFilesArchiveSize {@link AtomicLong} the accumulated store file size in archive</span>
-<span class="source-line-no">652</span><span id="line-652"> * @param uniqueHFilesSize {@link AtomicLong} the accumulated store file size shared</span>
-<span class="source-line-no">653</span><span id="line-653"> * @param uniqueHFilesMobSize {@link AtomicLong} the accumulated mob store file size shared</span>
-<span class="source-line-no">654</span><span id="line-654"> */</span>
-<span class="source-line-no">655</span><span id="line-655"> private static void getSnapshotFilesMap(final Configuration conf,</span>
-<span class="source-line-no">656</span><span id="line-656"> final SnapshotDescription snapshot, final ExecutorService exec,</span>
-<span class="source-line-no">657</span><span id="line-657"> final ConcurrentHashMap<Path, Integer> filesMap, final AtomicLong uniqueHFilesArchiveSize,</span>
-<span class="source-line-no">658</span><span id="line-658"> final AtomicLong uniqueHFilesSize, final AtomicLong uniqueHFilesMobSize) throws IOException {</span>
-<span class="source-line-no">659</span><span id="line-659"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">660</span><span id="line-660"> ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
-<span class="source-line-no">661</span><span id="line-661"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
-<span class="source-line-no">662</span><span id="line-662"> final FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
-<span class="source-line-no">663</span><span id="line-663"></span>
-<span class="source-line-no">664</span><span id="line-664"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotDesc, rootDir);</span>
-<span class="source-line-no">665</span><span id="line-665"> SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);</span>
-<span class="source-line-no">666</span><span id="line-666"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(conf, fs, manifest, exec,</span>
-<span class="source-line-no">667</span><span id="line-667"> new SnapshotReferenceUtil.SnapshotVisitor() {</span>
-<span class="source-line-no">668</span><span id="line-668"> @Override</span>
-<span class="source-line-no">669</span><span id="line-669"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
-<span class="source-line-no">670</span><span id="line-670"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
-<span class="source-line-no">671</span><span id="line-671"> if (!storeFile.hasReference()) {</span>
-<span class="source-line-no">672</span><span id="line-672"> HFileLink link = HFileLink.build(conf, snapshot.getTableName(),</span>
-<span class="source-line-no">673</span><span id="line-673"> regionInfo.getEncodedName(), family, storeFile.getName());</span>
-<span class="source-line-no">674</span><span id="line-674"> long size;</span>
-<span class="source-line-no">675</span><span id="line-675"> Integer count;</span>
-<span class="source-line-no">676</span><span id="line-676"> Path p;</span>
-<span class="source-line-no">677</span><span id="line-677"> AtomicLong al;</span>
-<span class="source-line-no">678</span><span id="line-678"> int c = 0;</span>
-<span class="source-line-no">679</span><span id="line-679"></span>
-<span class="source-line-no">680</span><span id="line-680"> if (fs.exists(link.getArchivePath())) {</span>
-<span class="source-line-no">681</span><span id="line-681"> p = link.getArchivePath();</span>
-<span class="source-line-no">682</span><span id="line-682"> al = uniqueHFilesArchiveSize;</span>
-<span class="source-line-no">683</span><span id="line-683"> size = fs.getFileStatus(p).getLen();</span>
-<span class="source-line-no">684</span><span id="line-684"> } else if (fs.exists(link.getMobPath())) {</span>
-<span class="source-line-no">685</span><span id="line-685"> p = link.getMobPath();</span>
-<span class="source-line-no">686</span><span id="line-686"> al = uniqueHFilesMobSize;</span>
-<span class="source-line-no">687</span><span id="line-687"> size = fs.getFileStatus(p).getLen();</span>
-<span class="source-line-no">688</span><span id="line-688"> } else {</span>
-<span class="source-line-no">689</span><span id="line-689"> p = link.getOriginPath();</span>
-<span class="source-line-no">690</span><span id="line-690"> al = uniqueHFilesSize;</span>
-<span class="source-line-no">691</span><span id="line-691"> size = link.getFileStatus(fs).getLen();</span>
-<span class="source-line-no">692</span><span id="line-692"> }</span>
-<span class="source-line-no">693</span><span id="line-693"></span>
-<span class="source-line-no">694</span><span id="line-694"> // If it has been counted, do not double count</span>
-<span class="source-line-no">695</span><span id="line-695"> count = filesMap.get(p);</span>
-<span class="source-line-no">696</span><span id="line-696"> if (count != null) {</span>
-<span class="source-line-no">697</span><span id="line-697"> c = count.intValue();</span>
-<span class="source-line-no">698</span><span id="line-698"> } else {</span>
-<span class="source-line-no">699</span><span id="line-699"> al.addAndGet(size);</span>
-<span class="source-line-no">700</span><span id="line-700"> }</span>
-<span class="source-line-no">701</span><span id="line-701"></span>
-<span class="source-line-no">702</span><span id="line-702"> filesMap.put(p, ++c);</span>
-<span class="source-line-no">703</span><span id="line-703"> }</span>
-<span class="source-line-no">704</span><span id="line-704"> }</span>
-<span class="source-line-no">705</span><span id="line-705"> });</span>
-<span class="source-line-no">706</span><span id="line-706"> }</span>
-<span class="source-line-no">707</span><span id="line-707"></span>
-<span class="source-line-no">708</span><span id="line-708"> /**</span>
-<span class="source-line-no">709</span><span id="line-709"> * Returns the map of store files based on path for all snapshots</span>
-<span class="source-line-no">710</span><span id="line-710"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">711</span><span id="line-711"> * @param uniqueHFilesArchiveSize pass out the size for store files in archive</span>
-<span class="source-line-no">712</span><span id="line-712"> * @param uniqueHFilesSize pass out the size for store files shared</span>
-<span class="source-line-no">713</span><span id="line-713"> * @param uniqueHFilesMobSize pass out the size for mob store files shared</span>
-<span class="source-line-no">714</span><span id="line-714"> * @return the map of store files</span>
-<span class="source-line-no">715</span><span id="line-715"> */</span>
-<span class="source-line-no">716</span><span id="line-716"> public static Map<Path, Integer> getSnapshotsFilesMap(final Configuration conf,</span>
-<span class="source-line-no">717</span><span id="line-717"> AtomicLong uniqueHFilesArchiveSize, AtomicLong uniqueHFilesSize, AtomicLong uniqueHFilesMobSize)</span>
-<span class="source-line-no">718</span><span id="line-718"> throws IOException {</span>
-<span class="source-line-no">719</span><span id="line-719"> List<SnapshotDescription> snapshotList = getSnapshotList(conf);</span>
-<span class="source-line-no">720</span><span id="line-720"></span>
-<span class="source-line-no">721</span><span id="line-721"> if (snapshotList.isEmpty()) {</span>
-<span class="source-line-no">722</span><span id="line-722"> return Collections.emptyMap();</span>
-<span class="source-line-no">723</span><span id="line-723"> }</span>
-<span class="source-line-no">724</span><span id="line-724"></span>
-<span class="source-line-no">725</span><span id="line-725"> ConcurrentHashMap<Path, Integer> fileMap = new ConcurrentHashMap<>();</span>
-<span class="source-line-no">726</span><span id="line-726"></span>
-<span class="source-line-no">727</span><span id="line-727"> ExecutorService exec = SnapshotManifest.createExecutor(conf, "SnapshotsFilesMapping");</span>
+<span class="source-line-no">580</span><span id="line-580"> @Override</span>
+<span class="source-line-no">581</span><span id="line-581"> protected void processOptions(CommandLine cmd) {</span>
+<span class="source-line-no">582</span><span id="line-582"> snapshotName = cmd.getOptionValue(Options.SNAPSHOT.getLongOpt());</span>
+<span class="source-line-no">583</span><span id="line-583"> showFiles = cmd.hasOption(Options.FILES.getLongOpt());</span>
+<span class="source-line-no">584</span><span id="line-584"> showStats =</span>
+<span class="source-line-no">585</span><span id="line-585"> cmd.hasOption(Options.FILES.getLongOpt()) || cmd.hasOption(Options.STATS.getLongOpt());</span>
+<span class="source-line-no">586</span><span id="line-586"> showSchema = cmd.hasOption(Options.SCHEMA.getLongOpt());</span>
+<span class="source-line-no">587</span><span id="line-587"> listSnapshots = cmd.hasOption(Options.LIST_SNAPSHOTS.getLongOpt());</span>
+<span class="source-line-no">588</span><span id="line-588"> printSizeInBytes = cmd.hasOption(Options.SIZE_IN_BYTES.getLongOpt());</span>
+<span class="source-line-no">589</span><span id="line-589"> if (cmd.hasOption(Options.REMOTE_DIR.getLongOpt())) {</span>
+<span class="source-line-no">590</span><span id="line-590"> remoteDir = new Path(cmd.getOptionValue(Options.REMOTE_DIR.getLongOpt()));</span>
+<span class="source-line-no">591</span><span id="line-591"> }</span>
+<span class="source-line-no">592</span><span id="line-592"> }</span>
+<span class="source-line-no">593</span><span id="line-593"></span>
+<span class="source-line-no">594</span><span id="line-594"> @Override</span>
+<span class="source-line-no">595</span><span id="line-595"> protected void printUsage() {</span>
+<span class="source-line-no">596</span><span id="line-596"> printUsage("hbase snapshot info [options]", "Options:", "");</span>
+<span class="source-line-no">597</span><span id="line-597"> System.err.println("Examples:");</span>
+<span class="source-line-no">598</span><span id="line-598"> System.err.println(" hbase snapshot info --snapshot MySnapshot --files");</span>
+<span class="source-line-no">599</span><span id="line-599"> }</span>
+<span class="source-line-no">600</span><span id="line-600"></span>
+<span class="source-line-no">601</span><span id="line-601"> /**</span>
+<span class="source-line-no">602</span><span id="line-602"> * Returns the snapshot stats</span>
+<span class="source-line-no">603</span><span id="line-603"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">604</span><span id="line-604"> * @param snapshot {@link SnapshotDescription} to get stats from</span>
+<span class="source-line-no">605</span><span id="line-605"> * @return the snapshot stats</span>
+<span class="source-line-no">606</span><span id="line-606"> */</span>
+<span class="source-line-no">607</span><span id="line-607"> public static SnapshotStats getSnapshotStats(final Configuration conf,</span>
+<span class="source-line-no">608</span><span id="line-608"> final SnapshotDescription snapshot) throws IOException {</span>
+<span class="source-line-no">609</span><span id="line-609"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">610</span><span id="line-610"> ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
+<span class="source-line-no">611</span><span id="line-611"> return getSnapshotStats(conf, snapshotDesc, null);</span>
+<span class="source-line-no">612</span><span id="line-612"> }</span>
+<span class="source-line-no">613</span><span id="line-613"></span>
+<span class="source-line-no">614</span><span id="line-614"> /**</span>
+<span class="source-line-no">615</span><span id="line-615"> * Returns the snapshot stats</span>
+<span class="source-line-no">616</span><span id="line-616"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">617</span><span id="line-617"> * @param snapshotDesc HBaseProtos.SnapshotDescription to get stats from</span>
+<span class="source-line-no">618</span><span id="line-618"> * @param filesMap {@link Map} store files map for all snapshots, it may be null</span>
+<span class="source-line-no">619</span><span id="line-619"> * @return the snapshot stats</span>
+<span class="source-line-no">620</span><span id="line-620"> */</span>
+<span class="source-line-no">621</span><span id="line-621"> public static SnapshotStats getSnapshotStats(final Configuration conf,</span>
+<span class="source-line-no">622</span><span id="line-622"> final SnapshotProtos.SnapshotDescription snapshotDesc, final Map<Path, Integer> filesMap)</span>
+<span class="source-line-no">623</span><span id="line-623"> throws IOException {</span>
+<span class="source-line-no">624</span><span id="line-624"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
+<span class="source-line-no">625</span><span id="line-625"> FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
+<span class="source-line-no">626</span><span id="line-626"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotDesc, rootDir);</span>
+<span class="source-line-no">627</span><span id="line-627"> SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);</span>
+<span class="source-line-no">628</span><span id="line-628"> final SnapshotStats stats = new SnapshotStats(conf, fs, snapshotDesc);</span>
+<span class="source-line-no">629</span><span id="line-629"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(conf, fs, manifest,</span>
+<span class="source-line-no">630</span><span id="line-630"> "SnapshotsStatsAggregation", new SnapshotReferenceUtil.SnapshotVisitor() {</span>
+<span class="source-line-no">631</span><span id="line-631"> @Override</span>
+<span class="source-line-no">632</span><span id="line-632"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
+<span class="source-line-no">633</span><span id="line-633"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
+<span class="source-line-no">634</span><span id="line-634"> if (!storeFile.hasReference()) {</span>
+<span class="source-line-no">635</span><span id="line-635"> stats.addStoreFile(regionInfo, family, storeFile, filesMap);</span>
+<span class="source-line-no">636</span><span id="line-636"> }</span>
+<span class="source-line-no">637</span><span id="line-637"> }</span>
+<span class="source-line-no">638</span><span id="line-638"> });</span>
+<span class="source-line-no">639</span><span id="line-639"> return stats;</span>
+<span class="source-line-no">640</span><span id="line-640"> }</span>
+<span class="source-line-no">641</span><span id="line-641"></span>
+<span class="source-line-no">642</span><span id="line-642"> /**</span>
+<span class="source-line-no">643</span><span id="line-643"> * Returns the list of available snapshots in the specified location</span>
+<span class="source-line-no">644</span><span id="line-644"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">645</span><span id="line-645"> * @return the list of snapshots</span>
+<span class="source-line-no">646</span><span id="line-646"> */</span>
+<span class="source-line-no">647</span><span id="line-647"> public static List<SnapshotDescription> getSnapshotList(final Configuration conf)</span>
+<span class="source-line-no">648</span><span id="line-648"> throws IOException {</span>
+<span class="source-line-no">649</span><span id="line-649"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
+<span class="source-line-no">650</span><span id="line-650"> FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
+<span class="source-line-no">651</span><span id="line-651"> Path snapshotDir = SnapshotDescriptionUtils.getSnapshotsDir(rootDir);</span>
+<span class="source-line-no">652</span><span id="line-652"> FileStatus[] snapshots = CommonFSUtils.listStatus(fs, snapshotDir,</span>
+<span class="source-line-no">653</span><span id="line-653"> new SnapshotDescriptionUtils.CompletedSnaphotDirectoriesFilter(fs));</span>
+<span class="source-line-no">654</span><span id="line-654"> if (snapshots == null) {</span>
+<span class="source-line-no">655</span><span id="line-655"> return Collections.emptyList();</span>
+<span class="source-line-no">656</span><span id="line-656"> }</span>
+<span class="source-line-no">657</span><span id="line-657"> List<SnapshotDescription> snapshotLists = new ArrayList<>(snapshots.length);</span>
+<span class="source-line-no">658</span><span id="line-658"> for (FileStatus snapshotDirStat : snapshots) {</span>
+<span class="source-line-no">659</span><span id="line-659"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">660</span><span id="line-660"> SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDirStat.getPath());</span>
+<span class="source-line-no">661</span><span id="line-661"> snapshotLists.add(ProtobufUtil.createSnapshotDesc(snapshotDesc));</span>
+<span class="source-line-no">662</span><span id="line-662"> }</span>
+<span class="source-line-no">663</span><span id="line-663"> return snapshotLists;</span>
+<span class="source-line-no">664</span><span id="line-664"> }</span>
+<span class="source-line-no">665</span><span id="line-665"></span>
+<span class="source-line-no">666</span><span id="line-666"> /**</span>
+<span class="source-line-no">667</span><span id="line-667"> * Gets the store files map for snapshot</span>
+<span class="source-line-no">668</span><span id="line-668"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">669</span><span id="line-669"> * @param snapshot {@link SnapshotDescription} to get stats from</span>
+<span class="source-line-no">670</span><span id="line-670"> * @param exec the {@link ExecutorService} to use</span>
+<span class="source-line-no">671</span><span id="line-671"> * @param filesMap {@link Map} the map to put the mapping entries</span>
+<span class="source-line-no">672</span><span id="line-672"> * @param uniqueHFilesArchiveSize {@link AtomicLong} the accumulated store file size in archive</span>
+<span class="source-line-no">673</span><span id="line-673"> * @param uniqueHFilesSize {@link AtomicLong} the accumulated store file size shared</span>
+<span class="source-line-no">674</span><span id="line-674"> * @param uniqueHFilesMobSize {@link AtomicLong} the accumulated mob store file size shared</span>
+<span class="source-line-no">675</span><span id="line-675"> */</span>
+<span class="source-line-no">676</span><span id="line-676"> private static void getSnapshotFilesMap(final Configuration conf,</span>
+<span class="source-line-no">677</span><span id="line-677"> final SnapshotDescription snapshot, final ExecutorService exec,</span>
+<span class="source-line-no">678</span><span id="line-678"> final ConcurrentHashMap<Path, Integer> filesMap, final AtomicLong uniqueHFilesArchiveSize,</span>
+<span class="source-line-no">679</span><span id="line-679"> final AtomicLong uniqueHFilesSize, final AtomicLong uniqueHFilesMobSize) throws IOException {</span>
+<span class="source-line-no">680</span><span id="line-680"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">681</span><span id="line-681"> ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
+<span class="source-line-no">682</span><span id="line-682"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
+<span class="source-line-no">683</span><span id="line-683"> final FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
+<span class="source-line-no">684</span><span id="line-684"></span>
+<span class="source-line-no">685</span><span id="line-685"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotDesc, rootDir);</span>
+<span class="source-line-no">686</span><span id="line-686"> SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);</span>
+<span class="source-line-no">687</span><span id="line-687"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(conf, fs, manifest, exec,</span>
+<span class="source-line-no">688</span><span id="line-688"> new SnapshotReferenceUtil.SnapshotVisitor() {</span>
+<span class="source-line-no">689</span><span id="line-689"> @Override</span>
+<span class="source-line-no">690</span><span id="line-690"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
+<span class="source-line-no">691</span><span id="line-691"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
+<span class="source-line-no">692</span><span id="line-692"> if (!storeFile.hasReference()) {</span>
+<span class="source-line-no">693</span><span id="line-693"> HFileLink link = HFileLink.build(conf, snapshot.getTableName(),</span>
+<span class="source-line-no">694</span><span id="line-694"> regionInfo.getEncodedName(), family, storeFile.getName());</span>
+<span class="source-line-no">695</span><span id="line-695"> long size;</span>
+<span class="source-line-no">696</span><span id="line-696"> Integer count;</span>
+<span class="source-line-no">697</span><span id="line-697"> Path p;</span>
+<span class="source-line-no">698</span><span id="line-698"> AtomicLong al;</span>
+<span class="source-line-no">699</span><span id="line-699"> int c = 0;</span>
+<span class="source-line-no">700</span><span id="line-700"></span>
+<span class="source-line-no">701</span><span id="line-701"> if (fs.exists(link.getArchivePath())) {</span>
+<span class="source-line-no">702</span><span id="line-702"> p = link.getArchivePath();</span>
+<span class="source-line-no">703</span><span id="line-703"> al = uniqueHFilesArchiveSize;</span>
+<span class="source-line-no">704</span><span id="line-704"> size = fs.getFileStatus(p).getLen();</span>
+<span class="source-line-no">705</span><span id="line-705"> } else if (fs.exists(link.getMobPath())) {</span>
+<span class="source-line-no">706</span><span id="line-706"> p = link.getMobPath();</span>
+<span class="source-line-no">707</span><span id="line-707"> al = uniqueHFilesMobSize;</span>
+<span class="source-line-no">708</span><span id="line-708"> size = fs.getFileStatus(p).getLen();</span>
+<span class="source-line-no">709</span><span id="line-709"> } else {</span>
+<span class="source-line-no">710</span><span id="line-710"> p = link.getOriginPath();</span>
+<span class="source-line-no">711</span><span id="line-711"> al = uniqueHFilesSize;</span>
+<span class="source-line-no">712</span><span id="line-712"> size = link.getFileStatus(fs).getLen();</span>
+<span class="source-line-no">713</span><span id="line-713"> }</span>
+<span class="source-line-no">714</span><span id="line-714"></span>
+<span class="source-line-no">715</span><span id="line-715"> // If it has been counted, do not double count</span>
+<span class="source-line-no">716</span><span id="line-716"> count = filesMap.get(p);</span>
+<span class="source-line-no">717</span><span id="line-717"> if (count != null) {</span>
+<span class="source-line-no">718</span><span id="line-718"> c = count.intValue();</span>
+<span class="source-line-no">719</span><span id="line-719"> } else {</span>
+<span class="source-line-no">720</span><span id="line-720"> al.addAndGet(size);</span>
+<span class="source-line-no">721</span><span id="line-721"> }</span>
+<span class="source-line-no">722</span><span id="line-722"></span>
+<span class="source-line-no">723</span><span id="line-723"> filesMap.put(p, ++c);</span>
+<span class="source-line-no">724</span><span id="line-724"> }</span>
+<span class="source-line-no">725</span><span id="line-725"> }</span>
+<span class="source-line-no">726</span><span id="line-726"> });</span>
+<span class="source-line-no">727</span><span id="line-727"> }</span>
<span class="source-line-no">728</span><span id="line-728"></span>
-<span class="source-line-no">729</span><span id="line-729"> try {</span>
-<span class="source-line-no">730</span><span id="line-730"> for (final SnapshotDescription snapshot : snapshotList) {</span>
-<span class="source-line-no">731</span><span id="line-731"> getSnapshotFilesMap(conf, snapshot, exec, fileMap, uniqueHFilesArchiveSize,</span>
-<span class="source-line-no">732</span><span id="line-732"> uniqueHFilesSize, uniqueHFilesMobSize);</span>
-<span class="source-line-no">733</span><span id="line-733"> }</span>
-<span class="source-line-no">734</span><span id="line-734"> } finally {</span>
-<span class="source-line-no">735</span><span id="line-735"> exec.shutdown();</span>
-<span class="source-line-no">736</span><span id="line-736"> }</span>
-<span class="source-line-no">737</span><span id="line-737"></span>
-<span class="source-line-no">738</span><span id="line-738"> return fileMap;</span>
-<span class="source-line-no">739</span><span id="line-739"> }</span>
-<span class="source-line-no">740</span><span id="line-740"></span>
-<span class="source-line-no">741</span><span id="line-741"> public static void main(String[] args) {</span>
-<span class="source-line-no">742</span><span id="line-742"> new SnapshotInfo().doStaticMain(args);</span>
-<span class="source-line-no">743</span><span id="line-743"> }</span>
-<span class="source-line-no">744</span><span id="line-744">}</span>
+<span class="source-line-no">729</span><span id="line-729"> /**</span>
+<span class="source-line-no">730</span><span id="line-730"> * Returns the map of store files based on path for all snapshots</span>
+<span class="source-line-no">731</span><span id="line-731"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">732</span><span id="line-732"> * @param uniqueHFilesArchiveSize pass out the size for store files in archive</span>
+<span class="source-line-no">733</span><span id="line-733"> * @param uniqueHFilesSize pass out the size for store files shared</span>
+<span class="source-line-no">734</span><span id="line-734"> * @param uniqueHFilesMobSize pass out the size for mob store files shared</span>
+<span class="source-line-no">735</span><span id="line-735"> * @return the map of store files</span>
+<span class="source-line-no">736</span><span id="line-736"> */</span>
+<span class="source-line-no">737</span><span id="line-737"> public static Map<Path, Integer> getSnapshotsFilesMap(final Configuration conf,</span>
+<span class="source-line-no">738</span><span id="line-738"> AtomicLong uniqueHFilesArchiveSize, AtomicLong uniqueHFilesSize, AtomicLong uniqueHFilesMobSize)</span>
+<span class="source-line-no">739</span><span id="line-739"> throws IOException {</span>
+<span class="source-line-no">740</span><span id="line-740"> List<SnapshotDescription> snapshotList = getSnapshotList(conf);</span>
+<span class="source-line-no">741</span><span id="line-741"></span>
+<span class="source-line-no">742</span><span id="line-742"> if (snapshotList.isEmpty()) {</span>
+<span class="source-line-no">743</span><span id="line-743"> return Collections.emptyMap();</span>
+<span class="source-line-no">744</span><span id="line-744"> }</span>
+<span class="source-line-no">745</span><span id="line-745"></span>
+<span class="source-line-no">746</span><span id="line-746"> ConcurrentHashMap<Path, Integer> fileMap = new ConcurrentHashMap<>();</span>
+<span class="source-line-no">747</span><span id="line-747"></span>
+<span class="source-line-no">748</span><span id="line-748"> ExecutorService exec = SnapshotManifest.createExecutor(conf, "SnapshotsFilesMapping");</span>
+<span class="source-line-no">749</span><span id="line-749"></span>
+<span class="source-line-no">750</span><span id="line-750"> try {</span>
+<span class="source-line-no">751</span><span id="line-751"> for (final SnapshotDescription snapshot : snapshotList) {</span>
+<span class="source-line-no">752</span><span id="line-752"> getSnapshotFilesMap(conf, snapshot, exec, fileMap, uniqueHFilesArchiveSize,</span>
+<span class="source-line-no">753</span><span id="line-753"> uniqueHFilesSize, uniqueHFilesMobSize);</span>
+<span class="source-line-no">754</span><span id="line-754"> }</span>
+<span class="source-line-no">755</span><span id="line-755"> } finally {</span>
+<span class="source-line-no">756</span><span id="line-756"> exec.shutdown();</span>
+<span class="source-line-no">757</span><span id="line-757"> }</span>
+<span class="source-line-no">758</span><span id="line-758"></span>
+<span class="source-line-no">759</span><span id="line-759"> return fileMap;</span>
+<span class="source-line-no">760</span><span id="line-760"> }</span>
+<span class="source-line-no">761</span><span id="line-761"></span>
+<span class="source-line-no">762</span><span id="line-762"> public static void main(String[] args) {</span>
+<span class="source-line-no">763</span><span id="line-763"> new SnapshotInfo().doStaticMain(args);</span>
+<span class="source-line-no">764</span><span id="line-764"> }</span>
+<span class="source-line-no">765</span><span id="line-765">}</span>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html b/devapidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html
index 9454cd74764..4958edbf684 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.FileInfo.html
@@ -30,731 +30,752 @@
<span class="source-line-no">017</span><span id="line-17"> */</span>
<span class="source-line-no">018</span><span id="line-18">package org.apache.hadoop.hbase.snapshot;</span>
<span class="source-line-no">019</span><span id="line-19"></span>
-<span class="source-line-no">020</span><span id="line-20">import java.io.FileNotFoundException;</span>
-<span class="source-line-no">021</span><span id="line-21">import java.io.IOException;</span>
-<span class="source-line-no">022</span><span id="line-22">import java.net.URI;</span>
-<span class="source-line-no">023</span><span id="line-23">import java.text.SimpleDateFormat;</span>
-<span class="source-line-no">024</span><span id="line-24">import java.util.ArrayList;</span>
-<span class="source-line-no">025</span><span id="line-25">import java.util.Collections;</span>
-<span class="source-line-no">026</span><span id="line-26">import java.util.Date;</span>
-<span class="source-line-no">027</span><span id="line-27">import java.util.List;</span>
-<span class="source-line-no">028</span><span id="line-28">import java.util.Map;</span>
-<span class="source-line-no">029</span><span id="line-29">import java.util.Properties;</span>
-<span class="source-line-no">030</span><span id="line-30">import java.util.concurrent.ConcurrentHashMap;</span>
-<span class="source-line-no">031</span><span id="line-31">import java.util.concurrent.ExecutorService;</span>
-<span class="source-line-no">032</span><span id="line-32">import java.util.concurrent.atomic.AtomicInteger;</span>
-<span class="source-line-no">033</span><span id="line-33">import java.util.concurrent.atomic.AtomicLong;</span>
-<span class="source-line-no">034</span><span id="line-34">import org.apache.hadoop.conf.Configuration;</span>
-<span class="source-line-no">035</span><span id="line-35">import org.apache.hadoop.fs.FileStatus;</span>
-<span class="source-line-no">036</span><span id="line-36">import org.apache.hadoop.fs.FileSystem;</span>
-<span class="source-line-no">037</span><span id="line-37">import org.apache.hadoop.fs.Path;</span>
-<span class="source-line-no">038</span><span id="line-38">import org.apache.hadoop.hbase.TableName;</span>
-<span class="source-line-no">039</span><span id="line-39">import org.apache.hadoop.hbase.client.RegionInfo;</span>
-<span class="source-line-no">040</span><span id="line-40">import org.apache.hadoop.hbase.client.SnapshotDescription;</span>
-<span class="source-line-no">041</span><span id="line-41">import org.apache.hadoop.hbase.io.HFileLink;</span>
-<span class="source-line-no">042</span><span id="line-42">import org.apache.hadoop.hbase.io.WALLink;</span>
-<span class="source-line-no">043</span><span id="line-43">import org.apache.hadoop.hbase.util.AbstractHBaseTool;</span>
-<span class="source-line-no">044</span><span id="line-44">import org.apache.hadoop.hbase.util.CommonFSUtils;</span>
-<span class="source-line-no">045</span><span id="line-45">import org.apache.hadoop.hbase.util.Strings;</span>
-<span class="source-line-no">046</span><span id="line-46">import org.apache.yetus.audience.InterfaceAudience;</span>
-<span class="source-line-no">047</span><span id="line-47">import org.slf4j.Logger;</span>
-<span class="source-line-no">048</span><span id="line-48">import org.slf4j.LoggerFactory;</span>
-<span class="source-line-no">049</span><span id="line-49"></span>
-<span class="source-line-no">050</span><span id="line-50">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;</span>
-<span class="source-line-no">051</span><span id="line-51">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLineParser;</span>
-<span class="source-line-no">052</span><span id="line-52">import org.apache.hbase.thirdparty.org.apache.commons.cli.DefaultParser;</span>
-<span class="source-line-no">053</span><span id="line-53">import org.apache.hbase.thirdparty.org.apache.commons.cli.Option;</span>
-<span class="source-line-no">054</span><span id="line-54">import org.apache.hbase.thirdparty.org.apache.commons.cli.Options;</span>
-<span class="source-line-no">055</span><span id="line-55">import org.apache.hbase.thirdparty.org.apache.commons.cli.ParseException;</span>
-<span class="source-line-no">056</span><span id="line-56"></span>
-<span class="source-line-no">057</span><span id="line-57">import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;</span>
-<span class="source-line-no">058</span><span id="line-58">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos;</span>
-<span class="source-line-no">059</span><span id="line-59">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;</span>
-<span class="source-line-no">060</span><span id="line-60"></span>
-<span class="source-line-no">061</span><span id="line-61">/**</span>
-<span class="source-line-no">062</span><span id="line-62"> * Tool for dumping snapshot information.</span>
-<span class="source-line-no">063</span><span id="line-63"> * <ol></span>
-<span class="source-line-no">064</span><span id="line-64"> * <li>Table Descriptor</span>
-<span class="source-line-no">065</span><span id="line-65"> * <li>Snapshot creation time, type, format version, ...</span>
-<span class="source-line-no">066</span><span id="line-66"> * <li>List of hfiles and wals</span>
-<span class="source-line-no">067</span><span id="line-67"> * <li>Stats about hfiles and logs sizes, percentage of shared with the source table, ...</span>
-<span class="source-line-no">068</span><span id="line-68"> * </ol></span>
-<span class="source-line-no">069</span><span id="line-69"> */</span>
-<span class="source-line-no">070</span><span id="line-70">@InterfaceAudience.Public</span>
-<span class="source-line-no">071</span><span id="line-71">public final class SnapshotInfo extends AbstractHBaseTool {</span>
-<span class="source-line-no">072</span><span id="line-72"> private static final Logger LOG = LoggerFactory.getLogger(SnapshotInfo.class);</span>
-<span class="source-line-no">073</span><span id="line-73"></span>
-<span class="source-line-no">074</span><span id="line-74"> static final class Options {</span>
-<span class="source-line-no">075</span><span id="line-75"> static final Option SNAPSHOT =</span>
-<span class="source-line-no">076</span><span id="line-76"> new Option(null, "snapshot", true, "The name of the snapshot to be detailed.");</span>
-<span class="source-line-no">077</span><span id="line-77"> static final Option REMOTE_DIR =</span>
-<span class="source-line-no">078</span><span id="line-78"> new Option(null, "remote-dir", true, "A custom root directory where snapshots are stored. "</span>
-<span class="source-line-no">079</span><span id="line-79"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">080</span><span id="line-80"> static final Option LIST_SNAPSHOTS =</span>
-<span class="source-line-no">081</span><span id="line-81"> new Option(null, "list-snapshots", false, "List all the available snapshots and exit.");</span>
-<span class="source-line-no">082</span><span id="line-82"> static final Option FILES =</span>
-<span class="source-line-no">083</span><span id="line-83"> new Option(null, "files", false, "The list of files retained by the specified snapshot. "</span>
-<span class="source-line-no">084</span><span id="line-84"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">085</span><span id="line-85"> static final Option STATS =</span>
-<span class="source-line-no">086</span><span id="line-86"> new Option(null, "stats", false, "Additional information about the specified snapshot. "</span>
-<span class="source-line-no">087</span><span id="line-87"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">088</span><span id="line-88"> static final Option SCHEMA = new Option(null, "schema", false,</span>
-<span class="source-line-no">089</span><span id="line-89"> "Show the descriptor of the table for the specified snapshot. "</span>
+<span class="source-line-no">020</span><span id="line-20">import static org.apache.hadoop.hbase.HConstants.DEFAULT_SNAPSHOT_TTL;</span>
+<span class="source-line-no">021</span><span id="line-21"></span>
+<span class="source-line-no">022</span><span id="line-22">import java.io.FileNotFoundException;</span>
+<span class="source-line-no">023</span><span id="line-23">import java.io.IOException;</span>
+<span class="source-line-no">024</span><span id="line-24">import java.net.URI;</span>
+<span class="source-line-no">025</span><span id="line-25">import java.text.SimpleDateFormat;</span>
+<span class="source-line-no">026</span><span id="line-26">import java.util.ArrayList;</span>
+<span class="source-line-no">027</span><span id="line-27">import java.util.Collections;</span>
+<span class="source-line-no">028</span><span id="line-28">import java.util.Date;</span>
+<span class="source-line-no">029</span><span id="line-29">import java.util.List;</span>
+<span class="source-line-no">030</span><span id="line-30">import java.util.Map;</span>
+<span class="source-line-no">031</span><span id="line-31">import java.util.Properties;</span>
+<span class="source-line-no">032</span><span id="line-32">import java.util.concurrent.ConcurrentHashMap;</span>
+<span class="source-line-no">033</span><span id="line-33">import java.util.concurrent.ExecutorService;</span>
+<span class="source-line-no">034</span><span id="line-34">import java.util.concurrent.atomic.AtomicInteger;</span>
+<span class="source-line-no">035</span><span id="line-35">import java.util.concurrent.atomic.AtomicLong;</span>
+<span class="source-line-no">036</span><span id="line-36">import org.apache.hadoop.conf.Configuration;</span>
+<span class="source-line-no">037</span><span id="line-37">import org.apache.hadoop.fs.FileStatus;</span>
+<span class="source-line-no">038</span><span id="line-38">import org.apache.hadoop.fs.FileSystem;</span>
+<span class="source-line-no">039</span><span id="line-39">import org.apache.hadoop.fs.Path;</span>
+<span class="source-line-no">040</span><span id="line-40">import org.apache.hadoop.hbase.TableName;</span>
+<span class="source-line-no">041</span><span id="line-41">import org.apache.hadoop.hbase.client.RegionInfo;</span>
+<span class="source-line-no">042</span><span id="line-42">import org.apache.hadoop.hbase.client.SnapshotDescription;</span>
+<span class="source-line-no">043</span><span id="line-43">import org.apache.hadoop.hbase.io.HFileLink;</span>
+<span class="source-line-no">044</span><span id="line-44">import org.apache.hadoop.hbase.io.WALLink;</span>
+<span class="source-line-no">045</span><span id="line-45">import org.apache.hadoop.hbase.util.AbstractHBaseTool;</span>
+<span class="source-line-no">046</span><span id="line-46">import org.apache.hadoop.hbase.util.CommonFSUtils;</span>
+<span class="source-line-no">047</span><span id="line-47">import org.apache.hadoop.hbase.util.Strings;</span>
+<span class="source-line-no">048</span><span id="line-48">import org.apache.yetus.audience.InterfaceAudience;</span>
+<span class="source-line-no">049</span><span id="line-49">import org.slf4j.Logger;</span>
+<span class="source-line-no">050</span><span id="line-50">import org.slf4j.LoggerFactory;</span>
+<span class="source-line-no">051</span><span id="line-51"></span>
+<span class="source-line-no">052</span><span id="line-52">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;</span>
+<span class="source-line-no">053</span><span id="line-53">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLineParser;</span>
+<span class="source-line-no">054</span><span id="line-54">import org.apache.hbase.thirdparty.org.apache.commons.cli.DefaultParser;</span>
+<span class="source-line-no">055</span><span id="line-55">import org.apache.hbase.thirdparty.org.apache.commons.cli.Option;</span>
+<span class="source-line-no">056</span><span id="line-56">import org.apache.hbase.thirdparty.org.apache.commons.cli.Options;</span>
+<span class="source-line-no">057</span><span id="line-57">import org.apache.hbase.thirdparty.org.apache.commons.cli.ParseException;</span>
+<span class="source-line-no">058</span><span id="line-58"></span>
+<span class="source-line-no">059</span><span id="line-59">import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;</span>
+<span class="source-line-no">060</span><span id="line-60">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos;</span>
+<span class="source-line-no">061</span><span id="line-61">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;</span>
+<span class="source-line-no">062</span><span id="line-62"></span>
+<span class="source-line-no">063</span><span id="line-63">/**</span>
+<span class="source-line-no">064</span><span id="line-64"> * Tool for dumping snapshot information.</span>
+<span class="source-line-no">065</span><span id="line-65"> * <ol></span>
+<span class="source-line-no">066</span><span id="line-66"> * <li>Table Descriptor</span>
+<span class="source-line-no">067</span><span id="line-67"> * <li>Snapshot creation time, type, format version, ...</span>
+<span class="source-line-no">068</span><span id="line-68"> * <li>List of hfiles and wals</span>
+<span class="source-line-no">069</span><span id="line-69"> * <li>Stats about hfiles and logs sizes, percentage of shared with the source table, ...</span>
+<span class="source-line-no">070</span><span id="line-70"> * </ol></span>
+<span class="source-line-no">071</span><span id="line-71"> */</span>
+<span class="source-line-no">072</span><span id="line-72">@InterfaceAudience.Public</span>
+<span class="source-line-no">073</span><span id="line-73">public final class SnapshotInfo extends AbstractHBaseTool {</span>
+<span class="source-line-no">074</span><span id="line-74"> private static final Logger LOG = LoggerFactory.getLogger(SnapshotInfo.class);</span>
+<span class="source-line-no">075</span><span id="line-75"></span>
+<span class="source-line-no">076</span><span id="line-76"> private static final String EXPIRED_LABEL = "Yes";</span>
+<span class="source-line-no">077</span><span id="line-77"> private static final String NOT_EXPIRED_LABEL = "No";</span>
+<span class="source-line-no">078</span><span id="line-78"> private static final String TTL_FOREVER = "FOREVER";</span>
+<span class="source-line-no">079</span><span id="line-79"></span>
+<span class="source-line-no">080</span><span id="line-80"> static final class Options {</span>
+<span class="source-line-no">081</span><span id="line-81"> static final Option SNAPSHOT =</span>
+<span class="source-line-no">082</span><span id="line-82"> new Option(null, "snapshot", true, "The name of the snapshot to be detailed.");</span>
+<span class="source-line-no">083</span><span id="line-83"> static final Option REMOTE_DIR =</span>
+<span class="source-line-no">084</span><span id="line-84"> new Option(null, "remote-dir", true, "A custom root directory where snapshots are stored. "</span>
+<span class="source-line-no">085</span><span id="line-85"> + "Use it together with the --snapshot option.");</span>
+<span class="source-line-no">086</span><span id="line-86"> static final Option LIST_SNAPSHOTS =</span>
+<span class="source-line-no">087</span><span id="line-87"> new Option(null, "list-snapshots", false, "List all the available snapshots and exit.");</span>
+<span class="source-line-no">088</span><span id="line-88"> static final Option FILES =</span>
+<span class="source-line-no">089</span><span id="line-89"> new Option(null, "files", false, "The list of files retained by the specified snapshot. "</span>
<span class="source-line-no">090</span><span id="line-90"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">091</span><span id="line-91"> static final Option SIZE_IN_BYTES =</span>
-<span class="source-line-no">092</span><span id="line-92"> new Option(null, "size-in-bytes", false, "Print the size of the files in bytes. "</span>
-<span class="source-line-no">093</span><span id="line-93"> + "Use it together with the --snapshot and --files options.");</span>
-<span class="source-line-no">094</span><span id="line-94"> }</span>
-<span class="source-line-no">095</span><span id="line-95"></span>
-<span class="source-line-no">096</span><span id="line-96"> /**</span>
-<span class="source-line-no">097</span><span id="line-97"> * Statistics about the snapshot</span>
-<span class="source-line-no">098</span><span id="line-98"> * <ol></span>
-<span class="source-line-no">099</span><span id="line-99"> * <li>How many store files and logs are in the archive</span>
-<span class="source-line-no">100</span><span id="line-100"> * <li>How many store files and logs are shared with the table</span>
-<span class="source-line-no">101</span><span id="line-101"> * <li>Total store files and logs size and shared amount</span>
-<span class="source-line-no">102</span><span id="line-102"> * </ol></span>
-<span class="source-line-no">103</span><span id="line-103"> */</span>
-<span class="source-line-no">104</span><span id="line-104"> public static class SnapshotStats {</span>
-<span class="source-line-no">105</span><span id="line-105"> /** Information about the file referenced by the snapshot */</span>
-<span class="source-line-no">106</span><span id="line-106"> static class FileInfo {</span>
-<span class="source-line-no">107</span><span id="line-107"> private final boolean corrupted;</span>
-<span class="source-line-no">108</span><span id="line-108"> private final boolean inArchive;</span>
-<span class="source-line-no">109</span><span id="line-109"> private final long size;</span>
-<span class="source-line-no">110</span><span id="line-110"></span>
-<span class="source-line-no">111</span><span id="line-111"> FileInfo(final boolean inArchive, final long size, final boolean corrupted) {</span>
-<span class="source-line-no">112</span><span id="line-112"> this.corrupted = corrupted;</span>
-<span class="source-line-no">113</span><span id="line-113"> this.inArchive = inArchive;</span>
-<span class="source-line-no">114</span><span id="line-114"> this.size = size;</span>
-<span class="source-line-no">115</span><span id="line-115"> }</span>
+<span class="source-line-no">091</span><span id="line-91"> static final Option STATS =</span>
+<span class="source-line-no">092</span><span id="line-92"> new Option(null, "stats", false, "Additional information about the specified snapshot. "</span>
+<span class="source-line-no">093</span><span id="line-93"> + "Use it together with the --snapshot option.");</span>
+<span class="source-line-no">094</span><span id="line-94"> static final Option SCHEMA = new Option(null, "schema", false,</span>
+<span class="source-line-no">095</span><span id="line-95"> "Show the descriptor of the table for the specified snapshot. "</span>
+<span class="source-line-no">096</span><span id="line-96"> + "Use it together with the --snapshot option.");</span>
+<span class="source-line-no">097</span><span id="line-97"> static final Option SIZE_IN_BYTES =</span>
+<span class="source-line-no">098</span><span id="line-98"> new Option(null, "size-in-bytes", false, "Print the size of the files in bytes. "</span>
+<span class="source-line-no">099</span><span id="line-99"> + "Use it together with the --snapshot and --files options.");</span>
+<span class="source-line-no">100</span><span id="line-100"> }</span>
+<span class="source-line-no">101</span><span id="line-101"></span>
+<span class="source-line-no">102</span><span id="line-102"> /**</span>
+<span class="source-line-no">103</span><span id="line-103"> * Statistics about the snapshot</span>
+<span class="source-line-no">104</span><span id="line-104"> * <ol></span>
+<span class="source-line-no">105</span><span id="line-105"> * <li>How many store files and logs are in the archive</span>
+<span class="source-line-no">106</span><span id="line-106"> * <li>How many store files and logs are shared with the table</span>
+<span class="source-line-no">107</span><span id="line-107"> * <li>Total store files and logs size and shared amount</span>
+<span class="source-line-no">108</span><span id="line-108"> * </ol></span>
+<span class="source-line-no">109</span><span id="line-109"> */</span>
+<span class="source-line-no">110</span><span id="line-110"> public static class SnapshotStats {</span>
+<span class="source-line-no">111</span><span id="line-111"> /** Information about the file referenced by the snapshot */</span>
+<span class="source-line-no">112</span><span id="line-112"> static class FileInfo {</span>
+<span class="source-line-no">113</span><span id="line-113"> private final boolean corrupted;</span>
+<span class="source-line-no">114</span><span id="line-114"> private final boolean inArchive;</span>
+<span class="source-line-no">115</span><span id="line-115"> private final long size;</span>
<span class="source-line-no">116</span><span id="line-116"></span>
-<span class="source-line-no">117</span><span id="line-117"> /** Returns true if the file is in the archive */</span>
-<span class="source-line-no">118</span><span id="line-118"> public boolean inArchive() {</span>
-<span class="source-line-no">119</span><span id="line-119"> return this.inArchive;</span>
-<span class="source-line-no">120</span><span id="line-120"> }</span>
-<span class="source-line-no">121</span><span id="line-121"></span>
-<span class="source-line-no">122</span><span id="line-122"> /** Returns true if the file is corrupted */</span>
-<span class="source-line-no">123</span><span id="line-123"> public boolean isCorrupted() {</span>
-<span class="source-line-no">124</span><span id="line-124"> return this.corrupted;</span>
-<span class="source-line-no">125</span><span id="line-125"> }</span>
-<span class="source-line-no">126</span><span id="line-126"></span>
-<span class="source-line-no">127</span><span id="line-127"> /** Returns true if the file is missing */</span>
-<span class="source-line-no">128</span><span id="line-128"> public boolean isMissing() {</span>
-<span class="source-line-no">129</span><span id="line-129"> return this.size < 0;</span>
-<span class="source-line-no">130</span><span id="line-130"> }</span>
-<span class="source-line-no">131</span><span id="line-131"></span>
-<span class="source-line-no">132</span><span id="line-132"> /** Returns the file size */</span>
-<span class="source-line-no">133</span><span id="line-133"> public long getSize() {</span>
-<span class="source-line-no">134</span><span id="line-134"> return this.size;</span>
-<span class="source-line-no">135</span><span id="line-135"> }</span>
-<span class="source-line-no">136</span><span id="line-136"></span>
-<span class="source-line-no">137</span><span id="line-137"> String getStateToString() {</span>
-<span class="source-line-no">138</span><span id="line-138"> if (isCorrupted()) return "CORRUPTED";</span>
-<span class="source-line-no">139</span><span id="line-139"> if (isMissing()) return "NOT FOUND";</span>
-<span class="source-line-no">140</span><span id="line-140"> if (inArchive()) return "archive";</span>
-<span class="source-line-no">141</span><span id="line-141"> return null;</span>
-<span class="source-line-no">142</span><span id="line-142"> }</span>
-<span class="source-line-no">143</span><span id="line-143"> }</span>
-<span class="source-line-no">144</span><span id="line-144"></span>
-<span class="source-line-no">145</span><span id="line-145"> private AtomicInteger hfilesArchiveCount = new AtomicInteger();</span>
-<span class="source-line-no">146</span><span id="line-146"> private AtomicInteger hfilesCorrupted = new AtomicInteger();</span>
-<span class="source-line-no">147</span><span id="line-147"> private AtomicInteger hfilesMissing = new AtomicInteger();</span>
-<span class="source-line-no">148</span><span id="line-148"> private AtomicInteger hfilesCount = new AtomicInteger();</span>
-<span class="source-line-no">149</span><span id="line-149"> private AtomicInteger hfilesMobCount = new AtomicInteger();</span>
-<span class="source-line-no">150</span><span id="line-150"> private AtomicInteger logsMissing = new AtomicInteger();</span>
-<span class="source-line-no">151</span><span id="line-151"> private AtomicInteger logsCount = new AtomicInteger();</span>
-<span class="source-line-no">152</span><span id="line-152"> private AtomicLong hfilesArchiveSize = new AtomicLong();</span>
-<span class="source-line-no">153</span><span id="line-153"> private AtomicLong hfilesSize = new AtomicLong();</span>
-<span class="source-line-no">154</span><span id="line-154"> private AtomicLong hfilesMobSize = new AtomicLong();</span>
-<span class="source-line-no">155</span><span id="line-155"> private AtomicLong nonSharedHfilesArchiveSize = new AtomicLong();</span>
-<span class="source-line-no">156</span><span id="line-156"> private AtomicLong logSize = new AtomicLong();</span>
-<span class="source-line-no">157</span><span id="line-157"></span>
-<span class="source-line-no">158</span><span id="line-158"> private final SnapshotProtos.SnapshotDescription snapshot;</span>
-<span class="source-line-no">159</span><span id="line-159"> private final TableName snapshotTable;</span>
-<span class="source-line-no">160</span><span id="line-160"> private final Configuration conf;</span>
-<span class="source-line-no">161</span><span id="line-161"> private final FileSystem fs;</span>
-<span class="source-line-no">162</span><span id="line-162"></span>
-<span class="source-line-no">163</span><span id="line-163"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
-<span class="source-line-no">164</span><span id="line-164"> final SnapshotDescription snapshot) {</span>
-<span class="source-line-no">165</span><span id="line-165"> this.snapshot = ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
-<span class="source-line-no">166</span><span id="line-166"> this.snapshotTable = snapshot.getTableName();</span>
-<span class="source-line-no">167</span><span id="line-167"> this.conf = conf;</span>
-<span class="source-line-no">168</span><span id="line-168"> this.fs = fs;</span>
-<span class="source-line-no">169</span><span id="line-169"> }</span>
-<span class="source-line-no">170</span><span id="line-170"></span>
-<span class="source-line-no">171</span><span id="line-171"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
-<span class="source-line-no">172</span><span id="line-172"> final SnapshotProtos.SnapshotDescription snapshot) {</span>
-<span class="source-line-no">173</span><span id="line-173"> this.snapshot = snapshot;</span>
-<span class="source-line-no">174</span><span id="line-174"> this.snapshotTable = TableName.valueOf(snapshot.getTable());</span>
-<span class="source-line-no">175</span><span id="line-175"> this.conf = conf;</span>
-<span class="source-line-no">176</span><span id="line-176"> this.fs = fs;</span>
-<span class="source-line-no">177</span><span id="line-177"> }</span>
-<span class="source-line-no">178</span><span id="line-178"></span>
-<span class="source-line-no">179</span><span id="line-179"> /** Returns the snapshot descriptor */</span>
-<span class="source-line-no">180</span><span id="line-180"> public SnapshotDescription getSnapshotDescription() {</span>
-<span class="source-line-no">181</span><span id="line-181"> return ProtobufUtil.createSnapshotDesc(this.snapshot);</span>
-<span class="source-line-no">182</span><span id="line-182"> }</span>
-<span class="source-line-no">183</span><span id="line-183"></span>
-<span class="source-line-no">184</span><span id="line-184"> /** Returns true if the snapshot is corrupted */</span>
-<span class="source-line-no">185</span><span id="line-185"> public boolean isSnapshotCorrupted() {</span>
-<span class="source-line-no">186</span><span id="line-186"> return hfilesMissing.get() > 0 || logsMissing.get() > 0 || hfilesCorrupted.get() > 0;</span>
-<span class="source-line-no">187</span><span id="line-187"> }</span>
-<span class="source-line-no">188</span><span id="line-188"></span>
-<span class="source-line-no">189</span><span id="line-189"> /** Returns the number of available store files */</span>
-<span class="source-line-no">190</span><span id="line-190"> public int getStoreFilesCount() {</span>
-<span class="source-line-no">191</span><span id="line-191"> return hfilesCount.get() + hfilesArchiveCount.get() + hfilesMobCount.get();</span>
-<span class="source-line-no">192</span><span id="line-192"> }</span>
-<span class="source-line-no">193</span><span id="line-193"></span>
-<span class="source-line-no">194</span><span id="line-194"> /** Returns the number of available store files in the archive */</span>
-<span class="source-line-no">195</span><span id="line-195"> public int getArchivedStoreFilesCount() {</span>
-<span class="source-line-no">196</span><span id="line-196"> return hfilesArchiveCount.get();</span>
-<span class="source-line-no">197</span><span id="line-197"> }</span>
-<span class="source-line-no">198</span><span id="line-198"></span>
-<span class="source-line-no">199</span><span id="line-199"> /** Returns the number of available store files in the mob dir */</span>
-<span class="source-line-no">200</span><span id="line-200"> public int getMobStoreFilesCount() {</span>
-<span class="source-line-no">201</span><span id="line-201"> return hfilesMobCount.get();</span>
-<span class="source-line-no">202</span><span id="line-202"> }</span>
-<span class="source-line-no">203</span><span id="line-203"></span>
-<span class="source-line-no">204</span><span id="line-204"> /** Returns the number of available log files */</span>
-<span class="source-line-no">205</span><span id="line-205"> public int getLogsCount() {</span>
-<span class="source-line-no">206</span><span id="line-206"> return logsCount.get();</span>
-<span class="source-line-no">207</span><span id="line-207"> }</span>
-<span class="source-line-no">208</span><span id="line-208"></span>
-<span class="source-line-no">209</span><span id="line-209"> /** Returns the number of missing store files */</span>
-<span class="source-line-no">210</span><span id="line-210"> public int getMissingStoreFilesCount() {</span>
-<span class="source-line-no">211</span><span id="line-211"> return hfilesMissing.get();</span>
-<span class="source-line-no">212</span><span id="line-212"> }</span>
-<span class="source-line-no">213</span><span id="line-213"></span>
-<span class="source-line-no">214</span><span id="line-214"> /** Returns the number of corrupted store files */</span>
-<span class="source-line-no">215</span><span id="line-215"> public int getCorruptedStoreFilesCount() {</span>
-<span class="source-line-no">216</span><span id="line-216"> return hfilesCorrupted.get();</span>
-<span class="source-line-no">217</span><span id="line-217"> }</span>
-<span class="source-line-no">218</span><span id="line-218"></span>
-<span class="source-line-no">219</span><span id="line-219"> /** Returns the number of missing log files */</span>
-<span class="source-line-no">220</span><span id="line-220"> public int getMissingLogsCount() {</span>
-<span class="source-line-no">221</span><span id="line-221"> return logsMissing.get();</span>
-<span class="source-line-no">222</span><span id="line-222"> }</span>
-<span class="source-line-no">223</span><span id="line-223"></span>
-<span class="source-line-no">224</span><span id="line-224"> /** Returns the total size of the store files referenced by the snapshot */</span>
-<span class="source-line-no">225</span><span id="line-225"> public long getStoreFilesSize() {</span>
-<span class="source-line-no">226</span><span id="line-226"> return hfilesSize.get() + hfilesArchiveSize.get() + hfilesMobSize.get();</span>
-<span class="source-line-no">227</span><span id="line-227"> }</span>
-<span class="source-line-no">228</span><span id="line-228"></span>
-<span class="source-line-no">229</span><span id="line-229"> /** Returns the total size of the store files shared */</span>
-<span class="source-line-no">230</span><span id="line-230"> public long getSharedStoreFilesSize() {</span>
-<span class="source-line-no">231</span><span id="line-231"> return hfilesSize.get();</span>
-<span class="source-line-no">232</span><span id="line-232"> }</span>
-<span class="source-line-no">233</span><span id="line-233"></span>
-<span class="source-line-no">234</span><span id="line-234"> /** Returns the total size of the store files in the archive */</span>
-<span class="source-line-no">235</span><span id="line-235"> public long getArchivedStoreFileSize() {</span>
-<span class="source-line-no">236</span><span id="line-236"> return hfilesArchiveSize.get();</span>
-<span class="source-line-no">237</span><span id="line-237"> }</span>
-<span class="source-line-no">238</span><span id="line-238"></span>
-<span class="source-line-no">239</span><span id="line-239"> /** Returns the total size of the store files in the mob store */</span>
-<span class="source-line-no">240</span><span id="line-240"> public long getMobStoreFilesSize() {</span>
-<span class="source-line-no">241</span><span id="line-241"> return hfilesMobSize.get();</span>
-<span class="source-line-no">242</span><span id="line-242"> }</span>
-<span class="source-line-no">243</span><span id="line-243"></span>
-<span class="source-line-no">244</span><span id="line-244"> /**</span>
-<span class="source-line-no">245</span><span id="line-245"> * @return the total size of the store files in the archive which is not shared with other</span>
-<span class="source-line-no">246</span><span id="line-246"> * snapshots and tables This is only calculated when</span>
-<span class="source-line-no">247</span><span id="line-247"> * {@link #getSnapshotStats(Configuration, SnapshotProtos.SnapshotDescription, Map)} is</span>
-<span class="source-line-no">248</span><span id="line-248"> * called with a non-null Map</span>
-<span class="source-line-no">249</span><span id="line-249"> */</span>
-<span class="source-line-no">250</span><span id="line-250"> public long getNonSharedArchivedStoreFilesSize() {</span>
-<span class="source-line-no">251</span><span id="line-251"> return nonSharedHfilesArchiveSize.get();</span>
-<span class="source-line-no">252</span><span id="line-252"> }</span>
-<span class="source-line-no">253</span><span id="line-253"></span>
-<span class="source-line-no">254</span><span id="line-254"> /** Returns the percentage of the shared store files */</span>
-<span class="source-line-no">255</span><span id="line-255"> public float getSharedStoreFilePercentage() {</span>
-<span class="source-line-no">256</span><span id="line-256"> return getStoreFilesSize() == 0</span>
-<span class="source-line-no">257</span><span id="line-257"> ? 0</span>
-<span class="source-line-no">258</span><span id="line-258"> : ((float) hfilesSize.get() / (getStoreFilesSize())) * 100;</span>
-<span class="source-line-no">259</span><span id="line-259"> }</span>
-<span class="source-line-no">260</span><span id="line-260"></span>
-<span class="source-line-no">261</span><span id="line-261"> /** Returns the percentage of the mob store files */</span>
-<span class="source-line-no">262</span><span id="line-262"> public float getMobStoreFilePercentage() {</span>
-<span class="source-line-no">263</span><span id="line-263"> return getStoreFilesSize() == 0</span>
-<span class="source-line-no">264</span><span id="line-264"> ? 0</span>
-<span class="source-line-no">265</span><span id="line-265"> : ((float) hfilesMobSize.get() / (getStoreFilesSize())) * 100;</span>
-<span class="source-line-no">266</span><span id="line-266"> }</span>
-<span class="source-line-no">267</span><span id="line-267"></span>
-<span class="source-line-no">268</span><span id="line-268"> /** Returns the total log size */</span>
-<span class="source-line-no">269</span><span id="line-269"> public long getLogsSize() {</span>
-<span class="source-line-no">270</span><span id="line-270"> return logSize.get();</span>
-<span class="source-line-no">271</span><span id="line-271"> }</span>
-<span class="source-line-no">272</span><span id="line-272"></span>
-<span class="source-line-no">273</span><span id="line-273"> /**</span>
-<span class="source-line-no">274</span><span id="line-274"> * Check if for a give file in archive, if there are other snapshots/tables still reference it.</span>
-<span class="source-line-no">275</span><span id="line-275"> * @param filePath file path in archive</span>
-<span class="source-line-no">276</span><span id="line-276"> * @param snapshotFilesMap a map for store files in snapshots about how many snapshots refer to</span>
-<span class="source-line-no">277</span><span id="line-277"> * it.</span>
-<span class="source-line-no">278</span><span id="line-278"> * @return true or false</span>
-<span class="source-line-no">279</span><span id="line-279"> */</span>
-<span class="source-line-no">280</span><span id="line-280"> private boolean isArchivedFileStillReferenced(final Path filePath,</span>
-<span class="source-line-no">281</span><span id="line-281"> final Map<Path, Integer> snapshotFilesMap) {</span>
-<span class="source-line-no">282</span><span id="line-282"></span>
-<span class="source-line-no">283</span><span id="line-283"> Integer c = snapshotFilesMap.get(filePath);</span>
-<span class="source-line-no">284</span><span id="line-284"></span>
-<span class="source-line-no">285</span><span id="line-285"> // Check if there are other snapshots or table from clone_snapshot() (via back-reference)</span>
-<span class="source-line-no">286</span><span id="line-286"> // still reference to it.</span>
-<span class="source-line-no">287</span><span id="line-287"> if ((c != null) && (c == 1)) {</span>
-<span class="source-line-no">288</span><span id="line-288"> Path parentDir = filePath.getParent();</span>
-<span class="source-line-no">289</span><span id="line-289"> Path backRefDir = HFileLink.getBackReferencesDir(parentDir, filePath.getName());</span>
-<span class="source-line-no">290</span><span id="line-290"> try {</span>
-<span class="source-line-no">291</span><span id="line-291"> if (CommonFSUtils.listStatus(fs, backRefDir) == null) {</span>
-<span class="source-line-no">292</span><span id="line-292"> return false;</span>
-<span class="source-line-no">293</span><span id="line-293"> }</span>
-<span class="source-line-no">294</span><span id="line-294"> } catch (IOException e) {</span>
-<span class="source-line-no">295</span><span id="line-295"> // For the purpose of this function, IOException is ignored and treated as</span>
-<span class="source-line-no">296</span><span id="line-296"> // the file is still being referenced.</span>
-<span class="source-line-no">297</span><span id="line-297"> }</span>
-<span class="source-line-no">298</span><span id="line-298"> }</span>
-<span class="source-line-no">299</span><span id="line-299"> return true;</span>
-<span class="source-line-no">300</span><span id="line-300"> }</span>
-<span class="source-line-no">301</span><span id="line-301"></span>
-<span class="source-line-no">302</span><span id="line-302"> /**</span>
-<span class="source-line-no">303</span><span id="line-303"> * Add the specified store file to the stats</span>
-<span class="source-line-no">304</span><span id="line-304"> * @param region region encoded Name</span>
-<span class="source-line-no">305</span><span id="line-305"> * @param family family name</span>
-<span class="source-line-no">306</span><span id="line-306"> * @param storeFile store file name</span>
-<span class="source-line-no">307</span><span id="line-307"> * @param filesMap store files map for all snapshots, it may be null</span>
-<span class="source-line-no">308</span><span id="line-308"> * @return the store file information</span>
-<span class="source-line-no">309</span><span id="line-309"> */</span>
-<span class="source-line-no">310</span><span id="line-310"> FileInfo addStoreFile(final RegionInfo region, final String family,</span>
-<span class="source-line-no">311</span><span id="line-311"> final SnapshotRegionManifest.StoreFile storeFile, final Map<Path, Integer> filesMap)</span>
-<span class="source-line-no">312</span><span id="line-312"> throws IOException {</span>
-<span class="source-line-no">313</span><span id="line-313"> HFileLink link =</span>
-<span class="source-line-no">314</span><span id="line-314"> HFileLink.build(conf, snapshotTable, region.getEncodedName(), family, storeFile.getName());</span>
-<span class="source-line-no">315</span><span id="line-315"> boolean isCorrupted = false;</span>
-<span class="source-line-no">316</span><span id="line-316"> boolean inArchive = false;</span>
-<span class="source-line-no">317</span><span id="line-317"> long size = -1;</span>
-<span class="source-line-no">318</span><span id="line-318"> try {</span>
-<span class="source-line-no">319</span><span id="line-319"> if (fs.exists(link.getArchivePath())) {</span>
-<span class="source-line-no">320</span><span id="line-320"> inArchive = true;</span>
-<span class="source-line-no">321</span><span id="line-321"> size = fs.getFileStatus(link.getArchivePath()).getLen();</span>
-<span class="source-line-no">322</span><span id="line-322"> hfilesArchiveSize.addAndGet(size);</span>
-<span class="source-line-no">323</span><span id="line-323"> hfilesArchiveCount.incrementAndGet();</span>
-<span class="source-line-no">324</span><span id="line-324"></span>
-<span class="source-line-no">325</span><span id="line-325"> // If store file is not shared with other snapshots and tables,</span>
-<span class="source-line-no">326</span><span id="line-326"> // increase nonSharedHfilesArchiveSize</span>
-<span class="source-line-no">327</span><span id="line-327"> if (</span>
-<span class="source-line-no">328</span><span id="line-328"> (filesMap != null) && !isArchivedFileStillReferenced(link.getArchivePath(), filesMap)</span>
-<span class="source-line-no">329</span><span id="line-329"> ) {</span>
-<span class="source-line-no">330</span><span id="line-330"> nonSharedHfilesArchiveSize.addAndGet(size);</span>
-<span class="source-line-no">331</span><span id="line-331"> }</span>
-<span class="source-line-no">332</span><span id="line-332"> } else if (fs.exists(link.getMobPath())) {</span>
-<span class="source-line-no">333</span><span id="line-333"> inArchive = true;</span>
-<span class="source-line-no">334</span><span id="line-334"> size = fs.getFileStatus(link.getMobPath()).getLen();</span>
-<span class="source-line-no">335</span><span id="line-335"> hfilesMobSize.addAndGet(size);</span>
-<span class="source-line-no">336</span><span id="line-336"> hfilesMobCount.incrementAndGet();</span>
-<span class="source-line-no">337</span><span id="line-337"> } else {</span>
-<span class="source-line-no">338</span><span id="line-338"> size = link.getFileStatus(fs).getLen();</span>
-<span class="source-line-no">339</span><span id="line-339"> hfilesSize.addAndGet(size);</span>
-<span class="source-line-no">340</span><span id="line-340"> hfilesCount.incrementAndGet();</span>
-<span class="source-line-no">341</span><span id="line-341"> }</span>
-<span class="source-line-no">342</span><span id="line-342"> isCorrupted = (storeFile.hasFileSize() && storeFile.getFileSize() != size);</span>
-<span class="source-line-no">343</span><span id="line-343"> if (isCorrupted) hfilesCorrupted.incrementAndGet();</span>
-<span class="source-line-no">344</span><span id="line-344"> } catch (FileNotFoundException e) {</span>
-<span class="source-line-no">345</span><span id="line-345"> hfilesMissing.incrementAndGet();</span>
-<span class="source-line-no">346</span><span id="line-346"> }</span>
-<span class="source-line-no">347</span><span id="line-347"> return new FileInfo(inArchive, size, isCorrupted);</span>
-<span class="source-line-no">348</span><span id="line-348"> }</span>
-<span class="source-line-no">349</span><span id="line-349"></span>
-<span class="source-line-no">350</span><span id="line-350"> /**</span>
-<span class="source-line-no">351</span><span id="line-351"> * Add the specified log file to the stats</span>
-<span class="source-line-no">352</span><span id="line-352"> * @param server server name</span>
-<span class="source-line-no">353</span><span id="line-353"> * @param logfile log file name</span>
-<span class="source-line-no">354</span><span id="line-354"> * @return the log information</span>
-<span class="source-line-no">355</span><span id="line-355"> */</span>
-<span class="source-line-no">356</span><span id="line-356"> FileInfo addLogFile(final String server, final String logfile) throws IOException {</span>
-<span class="source-line-no">357</span><span id="line-357"> WALLink logLink = new WALLink(conf, server, logfile);</span>
-<span class="source-line-no">358</span><span id="line-358"> long size = -1;</span>
-<span class="source-line-no">359</span><span id="line-359"> try {</span>
-<span class="source-line-no">360</span><span id="line-360"> size = logLink.getFileStatus(fs).getLen();</span>
-<span class="source-line-no">361</span><span id="line-361"> logSize.addAndGet(size);</span>
-<span class="source-line-no">362</span><span id="line-362"> logsCount.incrementAndGet();</span>
-<span class="source-line-no">363</span><span id="line-363"> } catch (FileNotFoundException e) {</span>
-<span class="source-line-no">364</span><span id="line-364"> logsMissing.incrementAndGet();</span>
-<span class="source-line-no">365</span><span id="line-365"> }</span>
-<span class="source-line-no">366</span><span id="line-366"> return new FileInfo(false, size, false);</span>
-<span class="source-line-no">367</span><span id="line-367"> }</span>
-<span class="source-line-no">368</span><span id="line-368"> }</span>
-<span class="source-line-no">369</span><span id="line-369"></span>
-<span class="source-line-no">370</span><span id="line-370"> private FileSystem fs;</span>
-<span class="source-line-no">371</span><span id="line-371"> private Path rootDir;</span>
-<span class="source-line-no">372</span><span id="line-372"></span>
-<span class="source-line-no">373</span><span id="line-373"> private SnapshotManifest snapshotManifest;</span>
-<span class="source-line-no">374</span><span id="line-374"></span>
-<span class="source-line-no">375</span><span id="line-375"> private boolean listSnapshots = false;</span>
-<span class="source-line-no">376</span><span id="line-376"> private String snapshotName;</span>
-<span class="source-line-no">377</span><span id="line-377"> private Path remoteDir;</span>
-<span class="source-line-no">378</span><span id="line-378"> private boolean showSchema = false;</span>
-<span class="source-line-no">379</span><span id="line-379"> private boolean showFiles = false;</span>
-<span class="source-line-no">380</span><span id="line-380"> private boolean showStats = false;</span>
-<span class="source-line-no">381</span><span id="line-381"> private boolean printSizeInBytes = false;</span>
-<span class="source-line-no">382</span><span id="line-382"></span>
-<span class="source-line-no">383</span><span id="line-383"> @Override</span>
-<span class="source-line-no">384</span><span id="line-384"> public int doWork() throws IOException, InterruptedException {</span>
-<span class="source-line-no">385</span><span id="line-385"> if (remoteDir != null) {</span>
-<span class="source-line-no">386</span><span id="line-386"> URI defaultFs = remoteDir.getFileSystem(conf).getUri();</span>
-<span class="source-line-no">387</span><span id="line-387"> CommonFSUtils.setFsDefault(conf, new Path(defaultFs));</span>
-<span class="source-line-no">388</span><span id="line-388"> CommonFSUtils.setRootDir(conf, remoteDir);</span>
-<span class="source-line-no">389</span><span id="line-389"> }</span>
-<span class="source-line-no">390</span><span id="line-390"></span>
-<span class="source-line-no">391</span><span id="line-391"> // List Available Snapshots</span>
-<span class="source-line-no">392</span><span id="line-392"> if (listSnapshots) {</span>
-<span class="source-line-no">393</span><span id="line-393"> SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");</span>
-<span class="source-line-no">394</span><span id="line-394"> System.out.printf("%-20s | %-20s | %-20s | %s%n", "SNAPSHOT", "CREATION TIME", "TTL IN SEC",</span>
-<span class="source-line-no">395</span><span id="line-395"> "TABLE NAME");</span>
-<span class="source-line-no">396</span><span id="line-396"> for (SnapshotDescription desc : getSnapshotList(conf)) {</span>
-<span class="source-line-no">397</span><span id="line-397"> System.out.printf("%-20s | %20s | %20s | %s%n", desc.getName(),</span>
-<span class="source-line-no">398</span><span id="line-398"> df.format(new Date(desc.getCreationTime())), desc.getTtl(), desc.getTableNameAsString());</span>
-<span class="source-line-no">399</span><span id="line-399"> }</span>
-<span class="source-line-no">400</span><span id="line-400"> return 0;</span>
-<span class="source-line-no">401</span><span id="line-401"> }</span>
-<span class="source-line-no">402</span><span id="line-402"></span>
-<span class="source-line-no">403</span><span id="line-403"> rootDir = CommonFSUtils.getRootDir(conf);</span>
-<span class="source-line-no">404</span><span id="line-404"> fs = FileSystem.get(rootDir.toUri(), conf);</span>
-<span class="source-line-no">405</span><span id="line-405"> LOG.debug("fs=" + fs.getUri().toString() + " root=" + rootDir);</span>
-<span class="source-line-no">406</span><span id="line-406"></span>
-<span class="source-line-no">407</span><span id="line-407"> // Load snapshot information</span>
-<span class="source-line-no">408</span><span id="line-408"> if (!loadSnapshotInfo(snapshotName)) {</span>
-<span class="source-line-no">409</span><span id="line-409"> System.err.println("Snapshot '" + snapshotName + "' not found!");</span>
-<span class="source-line-no">410</span><span id="line-410"> return 1;</span>
-<span class="source-line-no">411</span><span id="line-411"> }</span>
-<span class="source-line-no">412</span><span id="line-412"></span>
-<span class="source-line-no">413</span><span id="line-413"> printInfo();</span>
-<span class="source-line-no">414</span><span id="line-414"> if (showSchema) {</span>
-<span class="source-line-no">415</span><span id="line-415"> printSchema();</span>
-<span class="source-line-no">416</span><span id="line-416"> }</span>
-<span class="source-line-no">417</span><span id="line-417"> printFiles(showFiles, showStats);</span>
-<span class="source-line-no">418</span><span id="line-418"></span>
-<span class="source-line-no">419</span><span id="line-419"> return 0;</span>
-<span class="source-line-no">420</span><span id="line-420"> }</span>
-<span class="source-line-no">421</span><span id="line-421"></span>
-<span class="source-line-no">422</span><span id="line-422"> /**</span>
-<span class="source-line-no">423</span><span id="line-423"> * Load snapshot info and table descriptor for the specified snapshot</span>
-<span class="source-line-no">424</span><span id="line-424"> * @param snapshotName name of the snapshot to load</span>
-<span class="source-line-no">425</span><span id="line-425"> * @return false if snapshot is not found</span>
-<span class="source-line-no">426</span><span id="line-426"> */</span>
-<span class="source-line-no">427</span><span id="line-427"> private boolean loadSnapshotInfo(final String snapshotName) throws IOException {</span>
-<span class="source-line-no">428</span><span id="line-428"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);</span>
-<span class="source-line-no">429</span><span id="line-429"> if (!fs.exists(snapshotDir)) {</span>
-<span class="source-line-no">430</span><span id="line-430"> LOG.warn("Snapshot '" + snapshotName + "' not found in: " + snapshotDir);</span>
-<span class="source-line-no">431</span><span id="line-431"> return false;</span>
-<span class="source-line-no">432</span><span id="line-432"> }</span>
-<span class="source-line-no">433</span><span id="line-433"></span>
-<span class="source-line-no">434</span><span id="line-434"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">435</span><span id="line-435"> SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);</span>
-<span class="source-line-no">436</span><span id="line-436"> snapshotManifest = SnapshotManifest.open(getConf(), fs, snapshotDir, snapshotDesc);</span>
-<span class="source-line-no">437</span><span id="line-437"> return true;</span>
-<span class="source-line-no">438</span><span id="line-438"> }</span>
-<span class="source-line-no">439</span><span id="line-439"></span>
-<span class="source-line-no">440</span><span id="line-440"> /**</span>
-<span class="source-line-no">441</span><span id="line-441"> * Dump the {@link SnapshotDescription}</span>
-<span class="source-line-no">442</span><span id="line-442"> */</span>
-<span class="source-line-no">443</span><span id="line-443"> private void printInfo() {</span>
-<span class="source-line-no">444</span><span id="line-444"> SnapshotProtos.SnapshotDescription snapshotDesc = snapshotManifest.getSnapshotDescription();</span>
-<span class="source-line-no">445</span><span id="line-445"> SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");</span>
-<span class="source-line-no">446</span><span id="line-446"> System.out.println("Snapshot Info");</span>
-<span class="source-line-no">447</span><span id="line-447"> System.out.println("----------------------------------------");</span>
-<span class="source-line-no">448</span><span id="line-448"> System.out.println(" Name: " + snapshotDesc.getName());</span>
-<span class="source-line-no">449</span><span id="line-449"> System.out.println(" Type: " + snapshotDesc.getType());</span>
-<span class="source-line-no">450</span><span id="line-450"> System.out.println(" Table: " + snapshotDesc.getTable());</span>
-<span class="source-line-no">451</span><span id="line-451"> System.out.println(" Format: " + snapshotDesc.getVersion());</span>
-<span class="source-line-no">452</span><span id="line-452"> System.out.println("Created: " + df.format(new Date(snapshotDesc.getCreationTime())));</span>
-<span class="source-line-no">453</span><span id="line-453"> System.out.println(" Ttl: " + snapshotDesc.getTtl());</span>
-<span class="source-line-no">454</span><span id="line-454"> System.out.println(" Owner: " + snapshotDesc.getOwner());</span>
-<span class="source-line-no">455</span><span id="line-455"> System.out.println();</span>
-<span class="source-line-no">456</span><span id="line-456"> }</span>
-<span class="source-line-no">457</span><span id="line-457"></span>
-<span class="source-line-no">458</span><span id="line-458"> /**</span>
-<span class="source-line-no">459</span><span id="line-459"> * Dump the {@link org.apache.hadoop.hbase.client.TableDescriptor}</span>
-<span class="source-line-no">460</span><span id="line-460"> */</span>
-<span class="source-line-no">461</span><span id="line-461"> private void printSchema() {</span>
-<span class="source-line-no">462</span><span id="line-462"> System.out.println("Table Descriptor");</span>
-<span class="source-line-no">463</span><span id="line-463"> System.out.println("----------------------------------------");</span>
-<span class="source-line-no">464</span><span id="line-464"> System.out.println(snapshotManifest.getTableDescriptor().toString());</span>
-<span class="source-line-no">465</span><span id="line-465"> System.out.println();</span>
-<span class="source-line-no">466</span><span id="line-466"> }</span>
-<span class="source-line-no">467</span><span id="line-467"></span>
-<span class="source-line-no">468</span><span id="line-468"> /**</span>
-<span class="source-line-no">469</span><span id="line-469"> * Collect the hfiles and logs statistics of the snapshot and dump the file list if requested and</span>
-<span class="source-line-no">470</span><span id="line-470"> * the collected information.</span>
-<span class="source-line-no">471</span><span id="line-471"> */</span>
-<span class="source-line-no">472</span><span id="line-472"> private void printFiles(final boolean showFiles, final boolean showStats) throws IOException {</span>
-<span class="source-line-no">473</span><span id="line-473"> if (showFiles) {</span>
-<span class="source-line-no">474</span><span id="line-474"> System.out.println("Snapshot Files");</span>
-<span class="source-line-no">475</span><span id="line-475"> System.out.println("----------------------------------------");</span>
-<span class="source-line-no">476</span><span id="line-476"> }</span>
-<span class="source-line-no">477</span><span id="line-477"></span>
-<span class="source-line-no">478</span><span id="line-478"> // Collect information about hfiles and logs in the snapshot</span>
-<span class="source-line-no">479</span><span id="line-479"> final SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">480</span><span id="line-480"> snapshotManifest.getSnapshotDescription();</span>
-<span class="source-line-no">481</span><span id="line-481"> final String table = snapshotDesc.getTable();</span>
-<span class="source-line-no">482</span><span id="line-482"> final SnapshotDescription desc = ProtobufUtil.createSnapshotDesc(snapshotDesc);</span>
-<span class="source-line-no">483</span><span id="line-483"> final SnapshotStats stats = new SnapshotStats(this.getConf(), this.fs, desc);</span>
-<span class="source-line-no">484</span><span id="line-484"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(getConf(), fs, snapshotManifest,</span>
-<span class="source-line-no">485</span><span id="line-485"> "SnapshotInfo", new SnapshotReferenceUtil.SnapshotVisitor() {</span>
-<span class="source-line-no">486</span><span id="line-486"> @Override</span>
-<span class="source-line-no">487</span><span id="line-487"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
-<span class="source-line-no">488</span><span id="line-488"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
-<span class="source-line-no">489</span><span id="line-489"> if (storeFile.hasReference()) return;</span>
-<span class="source-line-no">490</span><span id="line-490"></span>
-<span class="source-line-no">491</span><span id="line-491"> SnapshotStats.FileInfo info = stats.addStoreFile(regionInfo, family, storeFile, null);</span>
-<span class="source-line-no">492</span><span id="line-492"> if (showFiles) {</span>
-<span class="source-line-no">493</span><span id="line-493"> String state = info.getStateToString();</span>
-<span class="source-line-no">494</span><span id="line-494"> System.out.printf("%8s %s/%s/%s/%s %s%n",</span>
-<span class="source-line-no">495</span><span id="line-495"> (info.isMissing() ? "-" : fileSizeToString(info.getSize())), table,</span>
-<span class="source-line-no">496</span><span id="line-496"> regionInfo.getEncodedName(), family, storeFile.getName(),</span>
-<span class="source-line-no">497</span><span id="line-497"> state == null ? "" : "(" + state + ")");</span>
-<span class="source-line-no">498</span><span id="line-498"> }</span>
-<span class="source-line-no">499</span><span id="line-499"> }</span>
-<span class="source-line-no">500</span><span id="line-500"> });</span>
-<span class="source-line-no">501</span><span id="line-501"></span>
-<span class="source-line-no">502</span><span id="line-502"> // Dump the stats</span>
-<span class="source-line-no">503</span><span id="line-503"> System.out.println();</span>
-<span class="source-line-no">504</span><span id="line-504"> if (stats.isSnapshotCorrupted()) {</span>
-<span class="source-line-no">505</span><span id="line-505"> System.out.println("**************************************************************");</span>
-<span class="source-line-no">506</span><span id="line-506"> System.out.printf("BAD SNAPSHOT: %d hfile(s) and %d log(s) missing.%n",</span>
-<span class="source-line-no">507</span><span id="line-507"> stats.getMissingStoreFilesCount(), stats.getMissingLogsCount());</span>
-<span class="source-line-no">508</span><span id="line-508"> System.out.printf(" %d hfile(s) corrupted.%n",</span>
-<span class="source-line-no">509</span><span id="line-509"> stats.getCorruptedStoreFilesCount());</span>
-<span class="source-line-no">510</span><span id="line-510"> System.out.println("**************************************************************");</span>
-<span class="source-line-no">511</span><span id="line-511"> }</span>
-<span class="source-line-no">512</span><span id="line-512"></span>
-<span class="source-line-no">513</span><span id="line-513"> if (showStats) {</span>
-<span class="source-line-no">514</span><span id="line-514"> System.out.printf(</span>
-<span class="source-line-no">515</span><span id="line-515"> "%d HFiles (%d in archive, %d in mob storage), total size %s "</span>
-<span class="source-line-no">516</span><span id="line-516"> + "(%.2f%% %s shared with the source table, %.2f%% %s in mob dir)%n",</span>
-<span class="source-line-no">517</span><span id="line-517"> stats.getStoreFilesCount(), stats.getArchivedStoreFilesCount(),</span>
-<span class="source-line-no">518</span><span id="line-518"> stats.getMobStoreFilesCount(), fileSizeToString(stats.getStoreFilesSize()),</span>
-<span class="source-line-no">519</span><span id="line-519"> stats.getSharedStoreFilePercentage(), fileSizeToString(stats.getSharedStoreFilesSize()),</span>
-<span class="source-line-no">520</span><span id="line-520"> stats.getMobStoreFilePercentage(), fileSizeToString(stats.getMobStoreFilesSize()));</span>
-<span class="source-line-no">521</span><span id="line-521"> System.out.printf("%d Logs, total size %s%n", stats.getLogsCount(),</span>
-<span class="source-line-no">522</span><span id="line-522"> fileSizeToString(stats.getLogsSize()));</span>
-<span class="source-line-no">523</span><span id="line-523"> System.out.println();</span>
-<span class="source-line-no">524</span><span id="line-524"> }</span>
-<span class="source-line-no">525</span><span id="line-525"> }</span>
-<span class="source-line-no">526</span><span id="line-526"></span>
-<span class="source-line-no">527</span><span id="line-527"> private String fileSizeToString(long size) {</span>
-<span class="source-line-no">528</span><span id="line-528"> return printSizeInBytes ? Long.toString(size) : Strings.humanReadableInt(size);</span>
-<span class="source-line-no">529</span><span id="line-529"> }</span>
-<span class="source-line-no">530</span><span id="line-530"></span>
-<span class="source-line-no">531</span><span id="line-531"> @Override</span>
-<span class="source-line-no">532</span><span id="line-532"> protected void addOptions() {</span>
-<span class="source-line-no">533</span><span id="line-533"> addOption(Options.SNAPSHOT);</span>
-<span class="source-line-no">534</span><span id="line-534"> addOption(Options.REMOTE_DIR);</span>
-<span class="source-line-no">535</span><span id="line-535"> addOption(Options.LIST_SNAPSHOTS);</span>
-<span class="source-line-no">536</span><span id="line-536"> addOption(Options.FILES);</span>
-<span class="source-line-no">537</span><span id="line-537"> addOption(Options.STATS);</span>
-<span class="source-line-no">538</span><span id="line-538"> addOption(Options.SCHEMA);</span>
-<span class="source-line-no">539</span><span id="line-539"> addOption(Options.SIZE_IN_BYTES);</span>
-<span class="source-line-no">540</span><span id="line-540"> }</span>
-<span class="source-line-no">541</span><span id="line-541"></span>
-<span class="source-line-no">542</span><span id="line-542"> @Override</span>
-<span class="source-line-no">543</span><span id="line-543"> protected CommandLineParser newParser() {</span>
-<span class="source-line-no">544</span><span id="line-544"> // Commons-CLI lacks the capability to handle combinations of options, so we do it ourselves</span>
-<span class="source-line-no">545</span><span id="line-545"> // Validate in parse() to get helpful error messages instead of exploding in processOptions()</span>
-<span class="source-line-no">546</span><span id="line-546"> return new DefaultParser() {</span>
-<span class="source-line-no">547</span><span id="line-547"> @Override</span>
-<span class="source-line-no">548</span><span id="line-548"> public CommandLine parse(org.apache.hbase.thirdparty.org.apache.commons.cli.Options opts,</span>
-<span class="source-line-no">549</span><span id="line-549"> String[] args, Properties props, boolean stop) throws ParseException {</span>
-<span class="source-line-no">550</span><span id="line-550"> CommandLine cl = super.parse(opts, args, props, stop);</span>
-<span class="source-line-no">551</span><span id="line-551"> if (!cmd.hasOption(Options.LIST_SNAPSHOTS) && !cmd.hasOption(Options.SNAPSHOT)) {</span>
-<span class="source-line-no">552</span><span id="line-552"> throw new ParseException("Missing required snapshot option!");</span>
-<span class="source-line-no">553</span><span id="line-553"> }</span>
-<span class="source-line-no">554</span><span id="line-554"> return cl;</span>
-<span class="source-line-no">555</span><span id="line-555"> }</span>
-<span class="source-line-no">556</span><span id="line-556"> };</span>
-<span class="source-line-no">557</span><span id="line-557"> }</span>
-<span class="source-line-no">558</span><span id="line-558"></span>
-<span class="source-line-no">559</span><span id="line-559"> @Override</span>
-<span class="source-line-no">560</span><span id="line-560"> protected void processOptions(CommandLine cmd) {</span>
-<span class="source-line-no">561</span><span id="line-561"> snapshotName = cmd.getOptionValue(Options.SNAPSHOT.getLongOpt());</span>
-<span class="source-line-no">562</span><span id="line-562"> showFiles = cmd.hasOption(Options.FILES.getLongOpt());</span>
-<span class="source-line-no">563</span><span id="line-563"> showStats =</span>
-<span class="source-line-no">564</span><span id="line-564"> cmd.hasOption(Options.FILES.getLongOpt()) || cmd.hasOption(Options.STATS.getLongOpt());</span>
-<span class="source-line-no">565</span><span id="line-565"> showSchema = cmd.hasOption(Options.SCHEMA.getLongOpt());</span>
-<span class="source-line-no">566</span><span id="line-566"> listSnapshots = cmd.hasOption(Options.LIST_SNAPSHOTS.getLongOpt());</span>
-<span class="source-line-no">567</span><span id="line-567"> printSizeInBytes = cmd.hasOption(Options.SIZE_IN_BYTES.getLongOpt());</span>
-<span class="source-line-no">568</span><span id="line-568"> if (cmd.hasOption(Options.REMOTE_DIR.getLongOpt())) {</span>
-<span class="source-line-no">569</span><span id="line-569"> remoteDir = new Path(cmd.getOptionValue(Options.REMOTE_DIR.getLongOpt()));</span>
-<span class="source-line-no">570</span><span id="line-570"> }</span>
-<span class="source-line-no">571</span><span id="line-571"> }</span>
-<span class="source-line-no">572</span><span id="line-572"></span>
-<span class="source-line-no">573</span><span id="line-573"> @Override</span>
-<span class="source-line-no">574</span><span id="line-574"> protected void printUsage() {</span>
-<span class="source-line-no">575</span><span id="line-575"> printUsage("hbase snapshot info [options]", "Options:", "");</span>
-<span class="source-line-no">576</span><span id="line-576"> System.err.println("Examples:");</span>
-<span class="source-line-no">577</span><span id="line-577"> System.err.println(" hbase snapshot info --snapshot MySnapshot --files");</span>
+<span class="source-line-no">117</span><span id="line-117"> FileInfo(final boolean inArchive, final long size, final boolean corrupted) {</span>
+<span class="source-line-no">118</span><span id="line-118"> this.corrupted = corrupted;</span>
+<span class="source-line-no">119</span><span id="line-119"> this.inArchive = inArchive;</span>
+<span class="source-line-no">120</span><span id="line-120"> this.size = size;</span>
+<span class="source-line-no">121</span><span id="line-121"> }</span>
+<span class="source-line-no">122</span><span id="line-122"></span>
+<span class="source-line-no">123</span><span id="line-123"> /** Returns true if the file is in the archive */</span>
+<span class="source-line-no">124</span><span id="line-124"> public boolean inArchive() {</span>
+<span class="source-line-no">125</span><span id="line-125"> return this.inArchive;</span>
+<span class="source-line-no">126</span><span id="line-126"> }</span>
+<span class="source-line-no">127</span><span id="line-127"></span>
+<span class="source-line-no">128</span><span id="line-128"> /** Returns true if the file is corrupted */</span>
+<span class="source-line-no">129</span><span id="line-129"> public boolean isCorrupted() {</span>
+<span class="source-line-no">130</span><span id="line-130"> return this.corrupted;</span>
+<span class="source-line-no">131</span><span id="line-131"> }</span>
+<span class="source-line-no">132</span><span id="line-132"></span>
+<span class="source-line-no">133</span><span id="line-133"> /** Returns true if the file is missing */</span>
+<span class="source-line-no">134</span><span id="line-134"> public boolean isMissing() {</span>
+<span class="source-line-no">135</span><span id="line-135"> return this.size < 0;</span>
+<span class="source-line-no">136</span><span id="line-136"> }</span>
+<span class="source-line-no">137</span><span id="line-137"></span>
+<span class="source-line-no">138</span><span id="line-138"> /** Returns the file size */</span>
+<span class="source-line-no">139</span><span id="line-139"> public long getSize() {</span>
+<span class="source-line-no">140</span><span id="line-140"> return this.size;</span>
+<span class="source-line-no">141</span><span id="line-141"> }</span>
+<span class="source-line-no">142</span><span id="line-142"></span>
+<span class="source-line-no">143</span><span id="line-143"> String getStateToString() {</span>
+<span class="source-line-no">144</span><span id="line-144"> if (isCorrupted()) return "CORRUPTED";</span>
+<span class="source-line-no">145</span><span id="line-145"> if (isMissing()) return "NOT FOUND";</span>
+<span class="source-line-no">146</span><span id="line-146"> if (inArchive()) return "archive";</span>
+<span class="source-line-no">147</span><span id="line-147"> return null;</span>
+<span class="source-line-no">148</span><span id="line-148"> }</span>
+<span class="source-line-no">149</span><span id="line-149"> }</span>
+<span class="source-line-no">150</span><span id="line-150"></span>
+<span class="source-line-no">151</span><span id="line-151"> private AtomicInteger hfilesArchiveCount = new AtomicInteger();</span>
+<span class="source-line-no">152</span><span id="line-152"> private AtomicInteger hfilesCorrupted = new AtomicInteger();</span>
+<span class="source-line-no">153</span><span id="line-153"> private AtomicInteger hfilesMissing = new AtomicInteger();</span>
+<span class="source-line-no">154</span><span id="line-154"> private AtomicInteger hfilesCount = new AtomicInteger();</span>
+<span class="source-line-no">155</span><span id="line-155"> private AtomicInteger hfilesMobCount = new AtomicInteger();</span>
+<span class="source-line-no">156</span><span id="line-156"> private AtomicInteger logsMissing = new AtomicInteger();</span>
+<span class="source-line-no">157</span><span id="line-157"> private AtomicInteger logsCount = new AtomicInteger();</span>
+<span class="source-line-no">158</span><span id="line-158"> private AtomicLong hfilesArchiveSize = new AtomicLong();</span>
+<span class="source-line-no">159</span><span id="line-159"> private AtomicLong hfilesSize = new AtomicLong();</span>
+<span class="source-line-no">160</span><span id="line-160"> private AtomicLong hfilesMobSize = new AtomicLong();</span>
+<span class="source-line-no">161</span><span id="line-161"> private AtomicLong nonSharedHfilesArchiveSize = new AtomicLong();</span>
+<span class="source-line-no">162</span><span id="line-162"> private AtomicLong logSize = new AtomicLong();</span>
+<span class="source-line-no">163</span><span id="line-163"></span>
+<span class="source-line-no">164</span><span id="line-164"> private final SnapshotProtos.SnapshotDescription snapshot;</span>
+<span class="source-line-no">165</span><span id="line-165"> private final TableName snapshotTable;</span>
+<span class="source-line-no">166</span><span id="line-166"> private final Configuration conf;</span>
+<span class="source-line-no">167</span><span id="line-167"> private final FileSystem fs;</span>
+<span class="source-line-no">168</span><span id="line-168"></span>
+<span class="source-line-no">169</span><span id="line-169"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
+<span class="source-line-no">170</span><span id="line-170"> final SnapshotDescription snapshot) {</span>
+<span class="source-line-no">171</span><span id="line-171"> this.snapshot = ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
+<span class="source-line-no">172</span><span id="line-172"> this.snapshotTable = snapshot.getTableName();</span>
+<span class="source-line-no">173</span><span id="line-173"> this.conf = conf;</span>
+<span class="source-line-no">174</span><span id="line-174"> this.fs = fs;</span>
+<span class="source-line-no">175</span><span id="line-175"> }</span>
+<span class="source-line-no">176</span><span id="line-176"></span>
+<span class="source-line-no">177</span><span id="line-177"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
+<span class="source-line-no">178</span><span id="line-178"> final SnapshotProtos.SnapshotDescription snapshot) {</span>
+<span class="source-line-no">179</span><span id="line-179"> this.snapshot = snapshot;</span>
+<span class="source-line-no">180</span><span id="line-180"> this.snapshotTable = TableName.valueOf(snapshot.getTable());</span>
+<span class="source-line-no">181</span><span id="line-181"> this.conf = conf;</span>
+<span class="source-line-no">182</span><span id="line-182"> this.fs = fs;</span>
+<span class="source-line-no">183</span><span id="line-183"> }</span>
+<span class="source-line-no">184</span><span id="line-184"></span>
+<span class="source-line-no">185</span><span id="line-185"> /** Returns the snapshot descriptor */</span>
+<span class="source-line-no">186</span><span id="line-186"> public SnapshotDescription getSnapshotDescription() {</span>
+<span class="source-line-no">187</span><span id="line-187"> return ProtobufUtil.createSnapshotDesc(this.snapshot);</span>
+<span class="source-line-no">188</span><span id="line-188"> }</span>
+<span class="source-line-no">189</span><span id="line-189"></span>
+<span class="source-line-no">190</span><span id="line-190"> /** Returns true if the snapshot is corrupted */</span>
+<span class="source-line-no">191</span><span id="line-191"> public boolean isSnapshotCorrupted() {</span>
+<span class="source-line-no">192</span><span id="line-192"> return hfilesMissing.get() > 0 || logsMissing.get() > 0 || hfilesCorrupted.get() > 0;</span>
+<span class="source-line-no">193</span><span id="line-193"> }</span>
+<span class="source-line-no">194</span><span id="line-194"></span>
+<span class="source-line-no">195</span><span id="line-195"> /** Returns the number of available store files */</span>
+<span class="source-line-no">196</span><span id="line-196"> public int getStoreFilesCount() {</span>
+<span class="source-line-no">197</span><span id="line-197"> return hfilesCount.get() + hfilesArchiveCount.get() + hfilesMobCount.get();</span>
+<span class="source-line-no">198</span><span id="line-198"> }</span>
+<span class="source-line-no">199</span><span id="line-199"></span>
+<span class="source-line-no">200</span><span id="line-200"> /** Returns the number of available store files in the archive */</span>
+<span class="source-line-no">201</span><span id="line-201"> public int getArchivedStoreFilesCount() {</span>
+<span class="source-line-no">202</span><span id="line-202"> return hfilesArchiveCount.get();</span>
+<span class="source-line-no">203</span><span id="line-203"> }</span>
+<span class="source-line-no">204</span><span id="line-204"></span>
+<span class="source-line-no">205</span><span id="line-205"> /** Returns the number of available store files in the mob dir */</span>
+<span class="source-line-no">206</span><span id="line-206"> public int getMobStoreFilesCount() {</span>
+<span class="source-line-no">207</span><span id="line-207"> return hfilesMobCount.get();</span>
+<span class="source-line-no">208</span><span id="line-208"> }</span>
+<span class="source-line-no">209</span><span id="line-209"></span>
+<span class="source-line-no">210</span><span id="line-210"> /** Returns the number of available log files */</span>
+<span class="source-line-no">211</span><span id="line-211"> public int getLogsCount() {</span>
+<span class="source-line-no">212</span><span id="line-212"> return logsCount.get();</span>
+<span class="source-line-no">213</span><span id="line-213"> }</span>
+<span class="source-line-no">214</span><span id="line-214"></span>
+<span class="source-line-no">215</span><span id="line-215"> /** Returns the number of missing store files */</span>
+<span class="source-line-no">216</span><span id="line-216"> public int getMissingStoreFilesCount() {</span>
+<span class="source-line-no">217</span><span id="line-217"> return hfilesMissing.get();</span>
+<span class="source-line-no">218</span><span id="line-218"> }</span>
+<span class="source-line-no">219</span><span id="line-219"></span>
+<span class="source-line-no">220</span><span id="line-220"> /** Returns the number of corrupted store files */</span>
+<span class="source-line-no">221</span><span id="line-221"> public int getCorruptedStoreFilesCount() {</span>
+<span class="source-line-no">222</span><span id="line-222"> return hfilesCorrupted.get();</span>
+<span class="source-line-no">223</span><span id="line-223"> }</span>
+<span class="source-line-no">224</span><span id="line-224"></span>
+<span class="source-line-no">225</span><span id="line-225"> /** Returns the number of missing log files */</span>
+<span class="source-line-no">226</span><span id="line-226"> public int getMissingLogsCount() {</span>
+<span class="source-line-no">227</span><span id="line-227"> return logsMissing.get();</span>
+<span class="source-line-no">228</span><span id="line-228"> }</span>
+<span class="source-line-no">229</span><span id="line-229"></span>
+<span class="source-line-no">230</span><span id="line-230"> /** Returns the total size of the store files referenced by the snapshot */</span>
+<span class="source-line-no">231</span><span id="line-231"> public long getStoreFilesSize() {</span>
+<span class="source-line-no">232</span><span id="line-232"> return hfilesSize.get() + hfilesArchiveSize.get() + hfilesMobSize.get();</span>
+<span class="source-line-no">233</span><span id="line-233"> }</span>
+<span class="source-line-no">234</span><span id="line-234"></span>
+<span class="source-line-no">235</span><span id="line-235"> /** Returns the total size of the store files shared */</span>
+<span class="source-line-no">236</span><span id="line-236"> public long getSharedStoreFilesSize() {</span>
+<span class="source-line-no">237</span><span id="line-237"> return hfilesSize.get();</span>
+<span class="source-line-no">238</span><span id="line-238"> }</span>
+<span class="source-line-no">239</span><span id="line-239"></span>
+<span class="source-line-no">240</span><span id="line-240"> /** Returns the total size of the store files in the archive */</span>
+<span class="source-line-no">241</span><span id="line-241"> public long getArchivedStoreFileSize() {</span>
+<span class="source-line-no">242</span><span id="line-242"> return hfilesArchiveSize.get();</span>
+<span class="source-line-no">243</span><span id="line-243"> }</span>
+<span class="source-line-no">244</span><span id="line-244"></span>
+<span class="source-line-no">245</span><span id="line-245"> /** Returns the total size of the store files in the mob store */</span>
+<span class="source-line-no">246</span><span id="line-246"> public long getMobStoreFilesSize() {</span>
+<span class="source-line-no">247</span><span id="line-247"> return hfilesMobSize.get();</span>
+<span class="source-line-no">248</span><span id="line-248"> }</span>
+<span class="source-line-no">249</span><span id="line-249"></span>
+<span class="source-line-no">250</span><span id="line-250"> /**</span>
+<span class="source-line-no">251</span><span id="line-251"> * @return the total size of the store files in the archive which is not shared with other</span>
+<span class="source-line-no">252</span><span id="line-252"> * snapshots and tables This is only calculated when</span>
+<span class="source-line-no">253</span><span id="line-253"> * {@link #getSnapshotStats(Configuration, SnapshotProtos.SnapshotDescription, Map)} is</span>
+<span class="source-line-no">254</span><span id="line-254"> * called with a non-null Map</span>
+<span class="source-line-no">255</span><span id="line-255"> */</span>
+<span class="source-line-no">256</span><span id="line-256"> public long getNonSharedArchivedStoreFilesSize() {</span>
+<span class="source-line-no">257</span><span id="line-257"> return nonSharedHfilesArchiveSize.get();</span>
+<span class="source-line-no">258</span><span id="line-258"> }</span>
+<span class="source-line-no">259</span><span id="line-259"></span>
+<span class="source-line-no">260</span><span id="line-260"> /** Returns the percentage of the shared store files */</span>
+<span class="source-line-no">261</span><span id="line-261"> public float getSharedStoreFilePercentage() {</span>
+<span class="source-line-no">262</span><span id="line-262"> return getStoreFilesSize() == 0</span>
+<span class="source-line-no">263</span><span id="line-263"> ? 0</span>
+<span class="source-line-no">264</span><span id="line-264"> : ((float) hfilesSize.get() / (getStoreFilesSize())) * 100;</span>
+<span class="source-line-no">265</span><span id="line-265"> }</span>
+<span class="source-line-no">266</span><span id="line-266"></span>
+<span class="source-line-no">267</span><span id="line-267"> /** Returns the percentage of the mob store files */</span>
+<span class="source-line-no">268</span><span id="line-268"> public float getMobStoreFilePercentage() {</span>
+<span class="source-line-no">269</span><span id="line-269"> return getStoreFilesSize() == 0</span>
+<span class="source-line-no">270</span><span id="line-270"> ? 0</span>
+<span class="source-line-no">271</span><span id="line-271"> : ((float) hfilesMobSize.get() / (getStoreFilesSize())) * 100;</span>
+<span class="source-line-no">272</span><span id="line-272"> }</span>
+<span class="source-line-no">273</span><span id="line-273"></span>
+<span class="source-line-no">274</span><span id="line-274"> /** Returns the total log size */</span>
+<span class="source-line-no">275</span><span id="line-275"> public long getLogsSize() {</span>
+<span class="source-line-no">276</span><span id="line-276"> return logSize.get();</span>
+<span class="source-line-no">277</span><span id="line-277"> }</span>
+<span class="source-line-no">278</span><span id="line-278"></span>
+<span class="source-line-no">279</span><span id="line-279"> /**</span>
+<span class="source-line-no">280</span><span id="line-280"> * Check if for a give file in archive, if there are other snapshots/tables still reference it.</span>
+<span class="source-line-no">281</span><span id="line-281"> * @param filePath file path in archive</span>
+<span class="source-line-no">282</span><span id="line-282"> * @param snapshotFilesMap a map for store files in snapshots about how many snapshots refer to</span>
+<span class="source-line-no">283</span><span id="line-283"> * it.</span>
+<span class="source-line-no">284</span><span id="line-284"> * @return true or false</span>
+<span class="source-line-no">285</span><span id="line-285"> */</span>
+<span class="source-line-no">286</span><span id="line-286"> private boolean isArchivedFileStillReferenced(final Path filePath,</span>
+<span class="source-line-no">287</span><span id="line-287"> final Map<Path, Integer> snapshotFilesMap) {</span>
+<span class="source-line-no">288</span><span id="line-288"></span>
+<span class="source-line-no">289</span><span id="line-289"> Integer c = snapshotFilesMap.get(filePath);</span>
+<span class="source-line-no">290</span><span id="line-290"></span>
+<span class="source-line-no">291</span><span id="line-291"> // Check if there are other snapshots or table from clone_snapshot() (via back-reference)</span>
+<span class="source-line-no">292</span><span id="line-292"> // still reference to it.</span>
+<span class="source-line-no">293</span><span id="line-293"> if ((c != null) && (c == 1)) {</span>
+<span class="source-line-no">294</span><span id="line-294"> Path parentDir = filePath.getParent();</span>
+<span class="source-line-no">295</span><span id="line-295"> Path backRefDir = HFileLink.getBackReferencesDir(parentDir, filePath.getName());</span>
+<span class="source-line-no">296</span><span id="line-296"> try {</span>
+<span class="source-line-no">297</span><span id="line-297"> if (CommonFSUtils.listStatus(fs, backRefDir) == null) {</span>
+<span class="source-line-no">298</span><span id="line-298"> return false;</span>
+<span class="source-line-no">299</span><span id="line-299"> }</span>
+<span class="source-line-no">300</span><span id="line-300"> } catch (IOException e) {</span>
+<span class="source-line-no">301</span><span id="line-301"> // For the purpose of this function, IOException is ignored and treated as</span>
+<span class="source-line-no">302</span><span id="line-302"> // the file is still being referenced.</span>
+<span class="source-line-no">303</span><span id="line-303"> }</span>
+<span class="source-line-no">304</span><span id="line-304"> }</span>
+<span class="source-line-no">305</span><span id="line-305"> return true;</span>
+<span class="source-line-no">306</span><span id="line-306"> }</span>
+<span class="source-line-no">307</span><span id="line-307"></span>
+<span class="source-line-no">308</span><span id="line-308"> /**</span>
+<span class="source-line-no">309</span><span id="line-309"> * Add the specified store file to the stats</span>
+<span class="source-line-no">310</span><span id="line-310"> * @param region region encoded Name</span>
+<span class="source-line-no">311</span><span id="line-311"> * @param family family name</span>
+<span class="source-line-no">312</span><span id="line-312"> * @param storeFile store file name</span>
+<span class="source-line-no">313</span><span id="line-313"> * @param filesMap store files map for all snapshots, it may be null</span>
+<span class="source-line-no">314</span><span id="line-314"> * @return the store file information</span>
+<span class="source-line-no">315</span><span id="line-315"> */</span>
+<span class="source-line-no">316</span><span id="line-316"> FileInfo addStoreFile(final RegionInfo region, final String family,</span>
+<span class="source-line-no">317</span><span id="line-317"> final SnapshotRegionManifest.StoreFile storeFile, final Map<Path, Integer> filesMap)</span>
+<span class="source-line-no">318</span><span id="line-318"> throws IOException {</span>
+<span class="source-line-no">319</span><span id="line-319"> HFileLink link =</span>
+<span class="source-line-no">320</span><span id="line-320"> HFileLink.build(conf, snapshotTable, region.getEncodedName(), family, storeFile.getName());</span>
+<span class="source-line-no">321</span><span id="line-321"> boolean isCorrupted = false;</span>
+<span class="source-line-no">322</span><span id="line-322"> boolean inArchive = false;</span>
+<span class="source-line-no">323</span><span id="line-323"> long size = -1;</span>
+<span class="source-line-no">324</span><span id="line-324"> try {</span>
+<span class="source-line-no">325</span><span id="line-325"> if (fs.exists(link.getArchivePath())) {</span>
+<span class="source-line-no">326</span><span id="line-326"> inArchive = true;</span>
+<span class="source-line-no">327</span><span id="line-327"> size = fs.getFileStatus(link.getArchivePath()).getLen();</span>
+<span class="source-line-no">328</span><span id="line-328"> hfilesArchiveSize.addAndGet(size);</span>
+<span class="source-line-no">329</span><span id="line-329"> hfilesArchiveCount.incrementAndGet();</span>
+<span class="source-line-no">330</span><span id="line-330"></span>
+<span class="source-line-no">331</span><span id="line-331"> // If store file is not shared with other snapshots and tables,</span>
+<span class="source-line-no">332</span><span id="line-332"> // increase nonSharedHfilesArchiveSize</span>
+<span class="source-line-no">333</span><span id="line-333"> if (</span>
+<span class="source-line-no">334</span><span id="line-334"> (filesMap != null) && !isArchivedFileStillReferenced(link.getArchivePath(), filesMap)</span>
+<span class="source-line-no">335</span><span id="line-335"> ) {</span>
+<span class="source-line-no">336</span><span id="line-336"> nonSharedHfilesArchiveSize.addAndGet(size);</span>
+<span class="source-line-no">337</span><span id="line-337"> }</span>
+<span class="source-line-no">338</span><span id="line-338"> } else if (fs.exists(link.getMobPath())) {</span>
+<span class="source-line-no">339</span><span id="line-339"> inArchive = true;</span>
+<span class="source-line-no">340</span><span id="line-340"> size = fs.getFileStatus(link.getMobPath()).getLen();</span>
+<span class="source-line-no">341</span><span id="line-341"> hfilesMobSize.addAndGet(size);</span>
+<span class="source-line-no">342</span><span id="line-342"> hfilesMobCount.incrementAndGet();</span>
+<span class="source-line-no">343</span><span id="line-343"> } else {</span>
+<span class="source-line-no">344</span><span id="line-344"> size = link.getFileStatus(fs).getLen();</span>
+<span class="source-line-no">345</span><span id="line-345"> hfilesSize.addAndGet(size);</span>
+<span class="source-line-no">346</span><span id="line-346"> hfilesCount.incrementAndGet();</span>
+<span class="source-line-no">347</span><span id="line-347"> }</span>
+<span class="source-line-no">348</span><span id="line-348"> isCorrupted = (storeFile.hasFileSize() && storeFile.getFileSize() != size);</span>
+<span class="source-line-no">349</span><span id="line-349"> if (isCorrupted) hfilesCorrupted.incrementAndGet();</span>
+<span class="source-line-no">350</span><span id="line-350"> } catch (FileNotFoundException e) {</span>
+<span class="source-line-no">351</span><span id="line-351"> hfilesMissing.incrementAndGet();</span>
+<span class="source-line-no">352</span><span id="line-352"> }</span>
+<span class="source-line-no">353</span><span id="line-353"> return new FileInfo(inArchive, size, isCorrupted);</span>
+<span class="source-line-no">354</span><span id="line-354"> }</span>
+<span class="source-line-no">355</span><span id="line-355"></span>
+<span class="source-line-no">356</span><span id="line-356"> /**</span>
+<span class="source-line-no">357</span><span id="line-357"> * Add the specified log file to the stats</span>
+<span class="source-line-no">358</span><span id="line-358"> * @param server server name</span>
+<span class="source-line-no">359</span><span id="line-359"> * @param logfile log file name</span>
+<span class="source-line-no">360</span><span id="line-360"> * @return the log information</span>
+<span class="source-line-no">361</span><span id="line-361"> */</span>
+<span class="source-line-no">362</span><span id="line-362"> FileInfo addLogFile(final String server, final String logfile) throws IOException {</span>
+<span class="source-line-no">363</span><span id="line-363"> WALLink logLink = new WALLink(conf, server, logfile);</span>
+<span class="source-line-no">364</span><span id="line-364"> long size = -1;</span>
+<span class="source-line-no">365</span><span id="line-365"> try {</span>
+<span class="source-line-no">366</span><span id="line-366"> size = logLink.getFileStatus(fs).getLen();</span>
+<span class="source-line-no">367</span><span id="line-367"> logSize.addAndGet(size);</span>
+<span class="source-line-no">368</span><span id="line-368"> logsCount.incrementAndGet();</span>
+<span class="source-line-no">369</span><span id="line-369"> } catch (FileNotFoundException e) {</span>
+<span class="source-line-no">370</span><span id="line-370"> logsMissing.incrementAndGet();</span>
+<span class="source-line-no">371</span><span id="line-371"> }</span>
+<span class="source-line-no">372</span><span id="line-372"> return new FileInfo(false, size, false);</span>
+<span class="source-line-no">373</span><span id="line-373"> }</span>
+<span class="source-line-no">374</span><span id="line-374"> }</span>
+<span class="source-line-no">375</span><span id="line-375"></span>
+<span class="source-line-no">376</span><span id="line-376"> private FileSystem fs;</span>
+<span class="source-line-no">377</span><span id="line-377"> private Path rootDir;</span>
+<span class="source-line-no">378</span><span id="line-378"></span>
+<span class="source-line-no">379</span><span id="line-379"> private SnapshotManifest snapshotManifest;</span>
+<span class="source-line-no">380</span><span id="line-380"></span>
+<span class="source-line-no">381</span><span id="line-381"> private boolean listSnapshots = false;</span>
+<span class="source-line-no">382</span><span id="line-382"> private String snapshotName;</span>
+<span class="source-line-no">383</span><span id="line-383"> private Path remoteDir;</span>
+<span class="source-line-no">384</span><span id="line-384"> private boolean showSchema = false;</span>
+<span class="source-line-no">385</span><span id="line-385"> private boolean showFiles = false;</span>
+<span class="source-line-no">386</span><span id="line-386"> private boolean showStats = false;</span>
+<span class="source-line-no">387</span><span id="line-387"> private boolean printSizeInBytes = false;</span>
+<span class="source-line-no">388</span><span id="line-388"></span>
+<span class="source-line-no">389</span><span id="line-389"> @Override</span>
+<span class="source-line-no">390</span><span id="line-390"> public int doWork() throws IOException, InterruptedException {</span>
+<span class="source-line-no">391</span><span id="line-391"> if (remoteDir != null) {</span>
+<span class="source-line-no">392</span><span id="line-392"> URI defaultFs = remoteDir.getFileSystem(conf).getUri();</span>
+<span class="source-line-no">393</span><span id="line-393"> CommonFSUtils.setFsDefault(conf, new Path(defaultFs));</span>
+<span class="source-line-no">394</span><span id="line-394"> CommonFSUtils.setRootDir(conf, remoteDir);</span>
+<span class="source-line-no">395</span><span id="line-395"> }</span>
+<span class="source-line-no">396</span><span id="line-396"></span>
+<span class="source-line-no">397</span><span id="line-397"> // List Available Snapshots</span>
+<span class="source-line-no">398</span><span id="line-398"> if (listSnapshots) {</span>
+<span class="source-line-no">399</span><span id="line-399"> SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");</span>
+<span class="source-line-no">400</span><span id="line-400"> List<SnapshotDescription> snapshotDescriptions = getSnapshotList(conf);</span>
+<span class="source-line-no">401</span><span id="line-401"> System.out.printf("%-20s | %-20s | %-20s | %-20s | %s%n", "SNAPSHOT", "CREATION TIME",</span>
+<span class="source-line-no">402</span><span id="line-402"> "TTL(Sec)", "EXPIRED", "TABLE NAME");</span>
+<span class="source-line-no">403</span><span id="line-403"> long currentTime = System.currentTimeMillis();</span>
+<span class="source-line-no">404</span><span id="line-404"> for (SnapshotDescription desc : snapshotDescriptions) {</span>
+<span class="source-line-no">405</span><span id="line-405"> String ttlInfo =</span>
+<span class="source-line-no">406</span><span id="line-406"> desc.getTtl() == DEFAULT_SNAPSHOT_TTL ? TTL_FOREVER : String.valueOf(desc.getTtl());</span>
+<span class="source-line-no">407</span><span id="line-407"> String expired = SnapshotDescriptionUtils.isExpiredSnapshot(desc.getTtl(),</span>
+<span class="source-line-no">408</span><span id="line-408"> desc.getCreationTime(), currentTime) ? EXPIRED_LABEL : NOT_EXPIRED_LABEL;</span>
+<span class="source-line-no">409</span><span id="line-409"> System.out.printf("%-20s | %20s | %20s | %20s | %s%n", desc.getName(),</span>
+<span class="source-line-no">410</span><span id="line-410"> df.format(new Date(desc.getCreationTime())), ttlInfo, expired,</span>
+<span class="source-line-no">411</span><span id="line-411"> desc.getTableNameAsString());</span>
+<span class="source-line-no">412</span><span id="line-412"> }</span>
+<span class="source-line-no">413</span><span id="line-413"> return 0;</span>
+<span class="source-line-no">414</span><span id="line-414"> }</span>
+<span class="source-line-no">415</span><span id="line-415"></span>
+<span class="source-line-no">416</span><span id="line-416"> rootDir = CommonFSUtils.getRootDir(conf);</span>
+<span class="source-line-no">417</span><span id="line-417"> fs = FileSystem.get(rootDir.toUri(), conf);</span>
+<span class="source-line-no">418</span><span id="line-418"> LOG.debug("fs=" + fs.getUri().toString() + " root=" + rootDir);</span>
+<span class="source-line-no">419</span><span id="line-419"></span>
+<span class="source-line-no">420</span><span id="line-420"> // Load snapshot information</span>
+<span class="source-line-no">421</span><span id="line-421"> if (!loadSnapshotInfo(snapshotName)) {</span>
+<span class="source-line-no">422</span><span id="line-422"> System.err.println("Snapshot '" + snapshotName + "' not found!");</span>
+<span class="source-line-no">423</span><span id="line-423"> return 1;</span>
+<span class="source-line-no">424</span><span id="line-424"> }</span>
+<span class="source-line-no">425</span><span id="line-425"></span>
+<span class="source-line-no">426</span><span id="line-426"> printInfo();</span>
+<span class="source-line-no">427</span><span id="line-427"> if (showSchema) {</span>
+<span class="source-line-no">428</span><span id="line-428"> printSchema();</span>
+<span class="source-line-no">429</span><span id="line-429"> }</span>
+<span class="source-line-no">430</span><span id="line-430"> printFiles(showFiles, showStats);</span>
+<span class="source-line-no">431</span><span id="line-431"></span>
+<span class="source-line-no">432</span><span id="line-432"> return 0;</span>
+<span class="source-line-no">433</span><span id="line-433"> }</span>
+<span class="source-line-no">434</span><span id="line-434"></span>
+<span class="source-line-no">435</span><span id="line-435"> /**</span>
+<span class="source-line-no">436</span><span id="line-436"> * Load snapshot info and table descriptor for the specified snapshot</span>
+<span class="source-line-no">437</span><span id="line-437"> * @param snapshotName name of the snapshot to load</span>
+<span class="source-line-no">438</span><span id="line-438"> * @return false if snapshot is not found</span>
+<span class="source-line-no">439</span><span id="line-439"> */</span>
+<span class="source-line-no">440</span><span id="line-440"> private boolean loadSnapshotInfo(final String snapshotName) throws IOException {</span>
+<span class="source-line-no">441</span><span id="line-441"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);</span>
+<span class="source-line-no">442</span><span id="line-442"> if (!fs.exists(snapshotDir)) {</span>
+<span class="source-line-no">443</span><span id="line-443"> LOG.warn("Snapshot '" + snapshotName + "' not found in: " + snapshotDir);</span>
+<span class="source-line-no">444</span><span id="line-444"> return false;</span>
+<span class="source-line-no">445</span><span id="line-445"> }</span>
+<span class="source-line-no">446</span><span id="line-446"></span>
+<span class="source-line-no">447</span><span id="line-447"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">448</span><span id="line-448"> SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);</span>
+<span class="source-line-no">449</span><span id="line-449"> snapshotManifest = SnapshotManifest.open(getConf(), fs, snapshotDir, snapshotDesc);</span>
+<span class="source-line-no">450</span><span id="line-450"> return true;</span>
+<span class="source-line-no">451</span><span id="line-451"> }</span>
+<span class="source-line-no">452</span><span id="line-452"></span>
+<span class="source-line-no">453</span><span id="line-453"> /**</span>
+<span class="source-line-no">454</span><span id="line-454"> * Dump the {@link SnapshotDescription}</span>
+<span class="source-line-no">455</span><span id="line-455"> */</span>
+<span class="source-line-no">456</span><span id="line-456"> private void printInfo() {</span>
+<span class="source-line-no">457</span><span id="line-457"> SnapshotProtos.SnapshotDescription snapshotDesc = snapshotManifest.getSnapshotDescription();</span>
+<span class="source-line-no">458</span><span id="line-458"> SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");</span>
+<span class="source-line-no">459</span><span id="line-459"> String ttlInfo = snapshotDesc.getTtl() == DEFAULT_SNAPSHOT_TTL</span>
+<span class="source-line-no">460</span><span id="line-460"> ? TTL_FOREVER</span>
+<span class="source-line-no">461</span><span id="line-461"> : String.valueOf(snapshotDesc.getTtl());</span>
+<span class="source-line-no">462</span><span id="line-462"> String expired = SnapshotDescriptionUtils.isExpiredSnapshot(snapshotDesc.getTtl(),</span>
+<span class="source-line-no">463</span><span id="line-463"> snapshotDesc.getCreationTime(), System.currentTimeMillis())</span>
+<span class="source-line-no">464</span><span id="line-464"> ? EXPIRED_LABEL</span>
+<span class="source-line-no">465</span><span id="line-465"> : NOT_EXPIRED_LABEL;</span>
+<span class="source-line-no">466</span><span id="line-466"> System.out.println("Snapshot Info");</span>
+<span class="source-line-no">467</span><span id="line-467"> System.out.println("-----------------------------------------");</span>
+<span class="source-line-no">468</span><span id="line-468"> System.out.println(" Name: " + snapshotDesc.getName());</span>
+<span class="source-line-no">469</span><span id="line-469"> System.out.println(" Type: " + snapshotDesc.getType());</span>
+<span class="source-line-no">470</span><span id="line-470"> System.out.println(" Table: " + snapshotDesc.getTable());</span>
+<span class="source-line-no">471</span><span id="line-471"> System.out.println(" Format: " + snapshotDesc.getVersion());</span>
+<span class="source-line-no">472</span><span id="line-472"> System.out.println(" Created: " + df.format(new Date(snapshotDesc.getCreationTime())));</span>
+<span class="source-line-no">473</span><span id="line-473"> System.out.println("Ttl(Sec): " + ttlInfo);</span>
+<span class="source-line-no">474</span><span id="line-474"> System.out.println(" Expired: " + expired);</span>
+<span class="source-line-no">475</span><span id="line-475"> System.out.println(" Owner: " + snapshotDesc.getOwner());</span>
+<span class="source-line-no">476</span><span id="line-476"> System.out.println();</span>
+<span class="source-line-no">477</span><span id="line-477"> }</span>
+<span class="source-line-no">478</span><span id="line-478"></span>
+<span class="source-line-no">479</span><span id="line-479"> /**</span>
+<span class="source-line-no">480</span><span id="line-480"> * Dump the {@link org.apache.hadoop.hbase.client.TableDescriptor}</span>
+<span class="source-line-no">481</span><span id="line-481"> */</span>
+<span class="source-line-no">482</span><span id="line-482"> private void printSchema() {</span>
+<span class="source-line-no">483</span><span id="line-483"> System.out.println("Table Descriptor");</span>
+<span class="source-line-no">484</span><span id="line-484"> System.out.println("----------------------------------------");</span>
+<span class="source-line-no">485</span><span id="line-485"> System.out.println(snapshotManifest.getTableDescriptor().toString());</span>
+<span class="source-line-no">486</span><span id="line-486"> System.out.println();</span>
+<span class="source-line-no">487</span><span id="line-487"> }</span>
+<span class="source-line-no">488</span><span id="line-488"></span>
+<span class="source-line-no">489</span><span id="line-489"> /**</span>
+<span class="source-line-no">490</span><span id="line-490"> * Collect the hfiles and logs statistics of the snapshot and dump the file list if requested and</span>
+<span class="source-line-no">491</span><span id="line-491"> * the collected information.</span>
+<span class="source-line-no">492</span><span id="line-492"> */</span>
+<span class="source-line-no">493</span><span id="line-493"> private void printFiles(final boolean showFiles, final boolean showStats) throws IOException {</span>
+<span class="source-line-no">494</span><span id="line-494"> if (showFiles) {</span>
+<span class="source-line-no">495</span><span id="line-495"> System.out.println("Snapshot Files");</span>
+<span class="source-line-no">496</span><span id="line-496"> System.out.println("----------------------------------------");</span>
+<span class="source-line-no">497</span><span id="line-497"> }</span>
+<span class="source-line-no">498</span><span id="line-498"></span>
+<span class="source-line-no">499</span><span id="line-499"> // Collect information about hfiles and logs in the snapshot</span>
+<span class="source-line-no">500</span><span id="line-500"> final SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">501</span><span id="line-501"> snapshotManifest.getSnapshotDescription();</span>
+<span class="source-line-no">502</span><span id="line-502"> final String table = snapshotDesc.getTable();</span>
+<span class="source-line-no">503</span><span id="line-503"> final SnapshotDescription desc = ProtobufUtil.createSnapshotDesc(snapshotDesc);</span>
+<span class="source-line-no">504</span><span id="line-504"> final SnapshotStats stats = new SnapshotStats(this.getConf(), this.fs, desc);</span>
+<span class="source-line-no">505</span><span id="line-505"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(getConf(), fs, snapshotManifest,</span>
+<span class="source-line-no">506</span><span id="line-506"> "SnapshotInfo", new SnapshotReferenceUtil.SnapshotVisitor() {</span>
+<span class="source-line-no">507</span><span id="line-507"> @Override</span>
+<span class="source-line-no">508</span><span id="line-508"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
+<span class="source-line-no">509</span><span id="line-509"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
+<span class="source-line-no">510</span><span id="line-510"> if (storeFile.hasReference()) return;</span>
+<span class="source-line-no">511</span><span id="line-511"></span>
+<span class="source-line-no">512</span><span id="line-512"> SnapshotStats.FileInfo info = stats.addStoreFile(regionInfo, family, storeFile, null);</span>
+<span class="source-line-no">513</span><span id="line-513"> if (showFiles) {</span>
+<span class="source-line-no">514</span><span id="line-514"> String state = info.getStateToString();</span>
+<span class="source-line-no">515</span><span id="line-515"> System.out.printf("%8s %s/%s/%s/%s %s%n",</span>
+<span class="source-line-no">516</span><span id="line-516"> (info.isMissing() ? "-" : fileSizeToString(info.getSize())), table,</span>
+<span class="source-line-no">517</span><span id="line-517"> regionInfo.getEncodedName(), family, storeFile.getName(),</span>
+<span class="source-line-no">518</span><span id="line-518"> state == null ? "" : "(" + state + ")");</span>
+<span class="source-line-no">519</span><span id="line-519"> }</span>
+<span class="source-line-no">520</span><span id="line-520"> }</span>
+<span class="source-line-no">521</span><span id="line-521"> });</span>
+<span class="source-line-no">522</span><span id="line-522"></span>
+<span class="source-line-no">523</span><span id="line-523"> // Dump the stats</span>
+<span class="source-line-no">524</span><span id="line-524"> System.out.println();</span>
+<span class="source-line-no">525</span><span id="line-525"> if (stats.isSnapshotCorrupted()) {</span>
+<span class="source-line-no">526</span><span id="line-526"> System.out.println("**************************************************************");</span>
+<span class="source-line-no">527</span><span id="line-527"> System.out.printf("BAD SNAPSHOT: %d hfile(s) and %d log(s) missing.%n",</span>
+<span class="source-line-no">528</span><span id="line-528"> stats.getMissingStoreFilesCount(), stats.getMissingLogsCount());</span>
+<span class="source-line-no">529</span><span id="line-529"> System.out.printf(" %d hfile(s) corrupted.%n",</span>
+<span class="source-line-no">530</span><span id="line-530"> stats.getCorruptedStoreFilesCount());</span>
+<span class="source-line-no">531</span><span id="line-531"> System.out.println("**************************************************************");</span>
+<span class="source-line-no">532</span><span id="line-532"> }</span>
+<span class="source-line-no">533</span><span id="line-533"></span>
+<span class="source-line-no">534</span><span id="line-534"> if (showStats) {</span>
+<span class="source-line-no">535</span><span id="line-535"> System.out.printf(</span>
+<span class="source-line-no">536</span><span id="line-536"> "%d HFiles (%d in archive, %d in mob storage), total size %s "</span>
+<span class="source-line-no">537</span><span id="line-537"> + "(%.2f%% %s shared with the source table, %.2f%% %s in mob dir)%n",</span>
+<span class="source-line-no">538</span><span id="line-538"> stats.getStoreFilesCount(), stats.getArchivedStoreFilesCount(),</span>
+<span class="source-line-no">539</span><span id="line-539"> stats.getMobStoreFilesCount(), fileSizeToString(stats.getStoreFilesSize()),</span>
+<span class="source-line-no">540</span><span id="line-540"> stats.getSharedStoreFilePercentage(), fileSizeToString(stats.getSharedStoreFilesSize()),</span>
+<span class="source-line-no">541</span><span id="line-541"> stats.getMobStoreFilePercentage(), fileSizeToString(stats.getMobStoreFilesSize()));</span>
+<span class="source-line-no">542</span><span id="line-542"> System.out.printf("%d Logs, total size %s%n", stats.getLogsCount(),</span>
+<span class="source-line-no">543</span><span id="line-543"> fileSizeToString(stats.getLogsSize()));</span>
+<span class="source-line-no">544</span><span id="line-544"> System.out.println();</span>
+<span class="source-line-no">545</span><span id="line-545"> }</span>
+<span class="source-line-no">546</span><span id="line-546"> }</span>
+<span class="source-line-no">547</span><span id="line-547"></span>
+<span class="source-line-no">548</span><span id="line-548"> private String fileSizeToString(long size) {</span>
+<span class="source-line-no">549</span><span id="line-549"> return printSizeInBytes ? Long.toString(size) : Strings.humanReadableInt(size);</span>
+<span class="source-line-no">550</span><span id="line-550"> }</span>
+<span class="source-line-no">551</span><span id="line-551"></span>
+<span class="source-line-no">552</span><span id="line-552"> @Override</span>
+<span class="source-line-no">553</span><span id="line-553"> protected void addOptions() {</span>
+<span class="source-line-no">554</span><span id="line-554"> addOption(Options.SNAPSHOT);</span>
+<span class="source-line-no">555</span><span id="line-555"> addOption(Options.REMOTE_DIR);</span>
+<span class="source-line-no">556</span><span id="line-556"> addOption(Options.LIST_SNAPSHOTS);</span>
+<span class="source-line-no">557</span><span id="line-557"> addOption(Options.FILES);</span>
+<span class="source-line-no">558</span><span id="line-558"> addOption(Options.STATS);</span>
+<span class="source-line-no">559</span><span id="line-559"> addOption(Options.SCHEMA);</span>
+<span class="source-line-no">560</span><span id="line-560"> addOption(Options.SIZE_IN_BYTES);</span>
+<span class="source-line-no">561</span><span id="line-561"> }</span>
+<span class="source-line-no">562</span><span id="line-562"></span>
+<span class="source-line-no">563</span><span id="line-563"> @Override</span>
+<span class="source-line-no">564</span><span id="line-564"> protected CommandLineParser newParser() {</span>
+<span class="source-line-no">565</span><span id="line-565"> // Commons-CLI lacks the capability to handle combinations of options, so we do it ourselves</span>
+<span class="source-line-no">566</span><span id="line-566"> // Validate in parse() to get helpful error messages instead of exploding in processOptions()</span>
+<span class="source-line-no">567</span><span id="line-567"> return new DefaultParser() {</span>
+<span class="source-line-no">568</span><span id="line-568"> @Override</span>
+<span class="source-line-no">569</span><span id="line-569"> public CommandLine parse(org.apache.hbase.thirdparty.org.apache.commons.cli.Options opts,</span>
+<span class="source-line-no">570</span><span id="line-570"> String[] args, Properties props, boolean stop) throws ParseException {</span>
+<span class="source-line-no">571</span><span id="line-571"> CommandLine cl = super.parse(opts, args, props, stop);</span>
+<span class="source-line-no">572</span><span id="line-572"> if (!cmd.hasOption(Options.LIST_SNAPSHOTS) && !cmd.hasOption(Options.SNAPSHOT)) {</span>
+<span class="source-line-no">573</span><span id="line-573"> throw new ParseException("Missing required snapshot option!");</span>
+<span class="source-line-no">574</span><span id="line-574"> }</span>
+<span class="source-line-no">575</span><span id="line-575"> return cl;</span>
+<span class="source-line-no">576</span><span id="line-576"> }</span>
+<span class="source-line-no">577</span><span id="line-577"> };</span>
<span class="source-line-no">578</span><span id="line-578"> }</span>
<span class="source-line-no">579</span><span id="line-579"></span>
-<span class="source-line-no">580</span><span id="line-580"> /**</span>
-<span class="source-line-no">581</span><span id="line-581"> * Returns the snapshot stats</span>
-<span class="source-line-no">582</span><span id="line-582"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">583</span><span id="line-583"> * @param snapshot {@link SnapshotDescription} to get stats from</span>
-<span class="source-line-no">584</span><span id="line-584"> * @return the snapshot stats</span>
-<span class="source-line-no">585</span><span id="line-585"> */</span>
-<span class="source-line-no">586</span><span id="line-586"> public static SnapshotStats getSnapshotStats(final Configuration conf,</span>
-<span class="source-line-no">587</span><span id="line-587"> final SnapshotDescription snapshot) throws IOException {</span>
-<span class="source-line-no">588</span><span id="line-588"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">589</span><span id="line-589"> ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
-<span class="source-line-no">590</span><span id="line-590"> return getSnapshotStats(conf, snapshotDesc, null);</span>
-<span class="source-line-no">591</span><span id="line-591"> }</span>
-<span class="source-line-no">592</span><span id="line-592"></span>
-<span class="source-line-no">593</span><span id="line-593"> /**</span>
-<span class="source-line-no">594</span><span id="line-594"> * Returns the snapshot stats</span>
-<span class="source-line-no">595</span><span id="line-595"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">596</span><span id="line-596"> * @param snapshotDesc HBaseProtos.SnapshotDescription to get stats from</span>
-<span class="source-line-no">597</span><span id="line-597"> * @param filesMap {@link Map} store files map for all snapshots, it may be null</span>
-<span class="source-line-no">598</span><span id="line-598"> * @return the snapshot stats</span>
-<span class="source-line-no">599</span><span id="line-599"> */</span>
-<span class="source-line-no">600</span><span id="line-600"> public static SnapshotStats getSnapshotStats(final Configuration conf,</span>
-<span class="source-line-no">601</span><span id="line-601"> final SnapshotProtos.SnapshotDescription snapshotDesc, final Map<Path, Integer> filesMap)</span>
-<span class="source-line-no">602</span><span id="line-602"> throws IOException {</span>
-<span class="source-line-no">603</span><span id="line-603"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
-<span class="source-line-no">604</span><span id="line-604"> FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
-<span class="source-line-no">605</span><span id="line-605"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotDesc, rootDir);</span>
-<span class="source-line-no">606</span><span id="line-606"> SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);</span>
-<span class="source-line-no">607</span><span id="line-607"> final SnapshotStats stats = new SnapshotStats(conf, fs, snapshotDesc);</span>
-<span class="source-line-no">608</span><span id="line-608"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(conf, fs, manifest,</span>
-<span class="source-line-no">609</span><span id="line-609"> "SnapshotsStatsAggregation", new SnapshotReferenceUtil.SnapshotVisitor() {</span>
-<span class="source-line-no">610</span><span id="line-610"> @Override</span>
-<span class="source-line-no">611</span><span id="line-611"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
-<span class="source-line-no">612</span><span id="line-612"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
-<span class="source-line-no">613</span><span id="line-613"> if (!storeFile.hasReference()) {</span>
-<span class="source-line-no">614</span><span id="line-614"> stats.addStoreFile(regionInfo, family, storeFile, filesMap);</span>
-<span class="source-line-no">615</span><span id="line-615"> }</span>
-<span class="source-line-no">616</span><span id="line-616"> }</span>
-<span class="source-line-no">617</span><span id="line-617"> });</span>
-<span class="source-line-no">618</span><span id="line-618"> return stats;</span>
-<span class="source-line-no">619</span><span id="line-619"> }</span>
-<span class="source-line-no">620</span><span id="line-620"></span>
-<span class="source-line-no">621</span><span id="line-621"> /**</span>
-<span class="source-line-no">622</span><span id="line-622"> * Returns the list of available snapshots in the specified location</span>
-<span class="source-line-no">623</span><span id="line-623"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">624</span><span id="line-624"> * @return the list of snapshots</span>
-<span class="source-line-no">625</span><span id="line-625"> */</span>
-<span class="source-line-no">626</span><span id="line-626"> public static List<SnapshotDescription> getSnapshotList(final Configuration conf)</span>
-<span class="source-line-no">627</span><span id="line-627"> throws IOException {</span>
-<span class="source-line-no">628</span><span id="line-628"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
-<span class="source-line-no">629</span><span id="line-629"> FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
-<span class="source-line-no">630</span><span id="line-630"> Path snapshotDir = SnapshotDescriptionUtils.getSnapshotsDir(rootDir);</span>
-<span class="source-line-no">631</span><span id="line-631"> FileStatus[] snapshots = CommonFSUtils.listStatus(fs, snapshotDir,</span>
-<span class="source-line-no">632</span><span id="line-632"> new SnapshotDescriptionUtils.CompletedSnaphotDirectoriesFilter(fs));</span>
-<span class="source-line-no">633</span><span id="line-633"> if (snapshots == null) {</span>
-<span class="source-line-no">634</span><span id="line-634"> return Collections.emptyList();</span>
-<span class="source-line-no">635</span><span id="line-635"> }</span>
-<span class="source-line-no">636</span><span id="line-636"> List<SnapshotDescription> snapshotLists = new ArrayList<>(snapshots.length);</span>
-<span class="source-line-no">637</span><span id="line-637"> for (FileStatus snapshotDirStat : snapshots) {</span>
-<span class="source-line-no">638</span><span id="line-638"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">639</span><span id="line-639"> SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDirStat.getPath());</span>
-<span class="source-line-no">640</span><span id="line-640"> snapshotLists.add(ProtobufUtil.createSnapshotDesc(snapshotDesc));</span>
-<span class="source-line-no">641</span><span id="line-641"> }</span>
-<span class="source-line-no">642</span><span id="line-642"> return snapshotLists;</span>
-<span class="source-line-no">643</span><span id="line-643"> }</span>
-<span class="source-line-no">644</span><span id="line-644"></span>
-<span class="source-line-no">645</span><span id="line-645"> /**</span>
-<span class="source-line-no">646</span><span id="line-646"> * Gets the store files map for snapshot</span>
-<span class="source-line-no">647</span><span id="line-647"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">648</span><span id="line-648"> * @param snapshot {@link SnapshotDescription} to get stats from</span>
-<span class="source-line-no">649</span><span id="line-649"> * @param exec the {@link ExecutorService} to use</span>
-<span class="source-line-no">650</span><span id="line-650"> * @param filesMap {@link Map} the map to put the mapping entries</span>
-<span class="source-line-no">651</span><span id="line-651"> * @param uniqueHFilesArchiveSize {@link AtomicLong} the accumulated store file size in archive</span>
-<span class="source-line-no">652</span><span id="line-652"> * @param uniqueHFilesSize {@link AtomicLong} the accumulated store file size shared</span>
-<span class="source-line-no">653</span><span id="line-653"> * @param uniqueHFilesMobSize {@link AtomicLong} the accumulated mob store file size shared</span>
-<span class="source-line-no">654</span><span id="line-654"> */</span>
-<span class="source-line-no">655</span><span id="line-655"> private static void getSnapshotFilesMap(final Configuration conf,</span>
-<span class="source-line-no">656</span><span id="line-656"> final SnapshotDescription snapshot, final ExecutorService exec,</span>
-<span class="source-line-no">657</span><span id="line-657"> final ConcurrentHashMap<Path, Integer> filesMap, final AtomicLong uniqueHFilesArchiveSize,</span>
-<span class="source-line-no">658</span><span id="line-658"> final AtomicLong uniqueHFilesSize, final AtomicLong uniqueHFilesMobSize) throws IOException {</span>
-<span class="source-line-no">659</span><span id="line-659"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
-<span class="source-line-no">660</span><span id="line-660"> ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
-<span class="source-line-no">661</span><span id="line-661"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
-<span class="source-line-no">662</span><span id="line-662"> final FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
-<span class="source-line-no">663</span><span id="line-663"></span>
-<span class="source-line-no">664</span><span id="line-664"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotDesc, rootDir);</span>
-<span class="source-line-no">665</span><span id="line-665"> SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);</span>
-<span class="source-line-no">666</span><span id="line-666"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(conf, fs, manifest, exec,</span>
-<span class="source-line-no">667</span><span id="line-667"> new SnapshotReferenceUtil.SnapshotVisitor() {</span>
-<span class="source-line-no">668</span><span id="line-668"> @Override</span>
-<span class="source-line-no">669</span><span id="line-669"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
-<span class="source-line-no">670</span><span id="line-670"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
-<span class="source-line-no">671</span><span id="line-671"> if (!storeFile.hasReference()) {</span>
-<span class="source-line-no">672</span><span id="line-672"> HFileLink link = HFileLink.build(conf, snapshot.getTableName(),</span>
-<span class="source-line-no">673</span><span id="line-673"> regionInfo.getEncodedName(), family, storeFile.getName());</span>
-<span class="source-line-no">674</span><span id="line-674"> long size;</span>
-<span class="source-line-no">675</span><span id="line-675"> Integer count;</span>
-<span class="source-line-no">676</span><span id="line-676"> Path p;</span>
-<span class="source-line-no">677</span><span id="line-677"> AtomicLong al;</span>
-<span class="source-line-no">678</span><span id="line-678"> int c = 0;</span>
-<span class="source-line-no">679</span><span id="line-679"></span>
-<span class="source-line-no">680</span><span id="line-680"> if (fs.exists(link.getArchivePath())) {</span>
-<span class="source-line-no">681</span><span id="line-681"> p = link.getArchivePath();</span>
-<span class="source-line-no">682</span><span id="line-682"> al = uniqueHFilesArchiveSize;</span>
-<span class="source-line-no">683</span><span id="line-683"> size = fs.getFileStatus(p).getLen();</span>
-<span class="source-line-no">684</span><span id="line-684"> } else if (fs.exists(link.getMobPath())) {</span>
-<span class="source-line-no">685</span><span id="line-685"> p = link.getMobPath();</span>
-<span class="source-line-no">686</span><span id="line-686"> al = uniqueHFilesMobSize;</span>
-<span class="source-line-no">687</span><span id="line-687"> size = fs.getFileStatus(p).getLen();</span>
-<span class="source-line-no">688</span><span id="line-688"> } else {</span>
-<span class="source-line-no">689</span><span id="line-689"> p = link.getOriginPath();</span>
-<span class="source-line-no">690</span><span id="line-690"> al = uniqueHFilesSize;</span>
-<span class="source-line-no">691</span><span id="line-691"> size = link.getFileStatus(fs).getLen();</span>
-<span class="source-line-no">692</span><span id="line-692"> }</span>
-<span class="source-line-no">693</span><span id="line-693"></span>
-<span class="source-line-no">694</span><span id="line-694"> // If it has been counted, do not double count</span>
-<span class="source-line-no">695</span><span id="line-695"> count = filesMap.get(p);</span>
-<span class="source-line-no">696</span><span id="line-696"> if (count != null) {</span>
-<span class="source-line-no">697</span><span id="line-697"> c = count.intValue();</span>
-<span class="source-line-no">698</span><span id="line-698"> } else {</span>
-<span class="source-line-no">699</span><span id="line-699"> al.addAndGet(size);</span>
-<span class="source-line-no">700</span><span id="line-700"> }</span>
-<span class="source-line-no">701</span><span id="line-701"></span>
-<span class="source-line-no">702</span><span id="line-702"> filesMap.put(p, ++c);</span>
-<span class="source-line-no">703</span><span id="line-703"> }</span>
-<span class="source-line-no">704</span><span id="line-704"> }</span>
-<span class="source-line-no">705</span><span id="line-705"> });</span>
-<span class="source-line-no">706</span><span id="line-706"> }</span>
-<span class="source-line-no">707</span><span id="line-707"></span>
-<span class="source-line-no">708</span><span id="line-708"> /**</span>
-<span class="source-line-no">709</span><span id="line-709"> * Returns the map of store files based on path for all snapshots</span>
-<span class="source-line-no">710</span><span id="line-710"> * @param conf the {@link Configuration} to use</span>
-<span class="source-line-no">711</span><span id="line-711"> * @param uniqueHFilesArchiveSize pass out the size for store files in archive</span>
-<span class="source-line-no">712</span><span id="line-712"> * @param uniqueHFilesSize pass out the size for store files shared</span>
-<span class="source-line-no">713</span><span id="line-713"> * @param uniqueHFilesMobSize pass out the size for mob store files shared</span>
-<span class="source-line-no">714</span><span id="line-714"> * @return the map of store files</span>
-<span class="source-line-no">715</span><span id="line-715"> */</span>
-<span class="source-line-no">716</span><span id="line-716"> public static Map<Path, Integer> getSnapshotsFilesMap(final Configuration conf,</span>
-<span class="source-line-no">717</span><span id="line-717"> AtomicLong uniqueHFilesArchiveSize, AtomicLong uniqueHFilesSize, AtomicLong uniqueHFilesMobSize)</span>
-<span class="source-line-no">718</span><span id="line-718"> throws IOException {</span>
-<span class="source-line-no">719</span><span id="line-719"> List<SnapshotDescription> snapshotList = getSnapshotList(conf);</span>
-<span class="source-line-no">720</span><span id="line-720"></span>
-<span class="source-line-no">721</span><span id="line-721"> if (snapshotList.isEmpty()) {</span>
-<span class="source-line-no">722</span><span id="line-722"> return Collections.emptyMap();</span>
-<span class="source-line-no">723</span><span id="line-723"> }</span>
-<span class="source-line-no">724</span><span id="line-724"></span>
-<span class="source-line-no">725</span><span id="line-725"> ConcurrentHashMap<Path, Integer> fileMap = new ConcurrentHashMap<>();</span>
-<span class="source-line-no">726</span><span id="line-726"></span>
-<span class="source-line-no">727</span><span id="line-727"> ExecutorService exec = SnapshotManifest.createExecutor(conf, "SnapshotsFilesMapping");</span>
+<span class="source-line-no">580</span><span id="line-580"> @Override</span>
+<span class="source-line-no">581</span><span id="line-581"> protected void processOptions(CommandLine cmd) {</span>
+<span class="source-line-no">582</span><span id="line-582"> snapshotName = cmd.getOptionValue(Options.SNAPSHOT.getLongOpt());</span>
+<span class="source-line-no">583</span><span id="line-583"> showFiles = cmd.hasOption(Options.FILES.getLongOpt());</span>
+<span class="source-line-no">584</span><span id="line-584"> showStats =</span>
+<span class="source-line-no">585</span><span id="line-585"> cmd.hasOption(Options.FILES.getLongOpt()) || cmd.hasOption(Options.STATS.getLongOpt());</span>
+<span class="source-line-no">586</span><span id="line-586"> showSchema = cmd.hasOption(Options.SCHEMA.getLongOpt());</span>
+<span class="source-line-no">587</span><span id="line-587"> listSnapshots = cmd.hasOption(Options.LIST_SNAPSHOTS.getLongOpt());</span>
+<span class="source-line-no">588</span><span id="line-588"> printSizeInBytes = cmd.hasOption(Options.SIZE_IN_BYTES.getLongOpt());</span>
+<span class="source-line-no">589</span><span id="line-589"> if (cmd.hasOption(Options.REMOTE_DIR.getLongOpt())) {</span>
+<span class="source-line-no">590</span><span id="line-590"> remoteDir = new Path(cmd.getOptionValue(Options.REMOTE_DIR.getLongOpt()));</span>
+<span class="source-line-no">591</span><span id="line-591"> }</span>
+<span class="source-line-no">592</span><span id="line-592"> }</span>
+<span class="source-line-no">593</span><span id="line-593"></span>
+<span class="source-line-no">594</span><span id="line-594"> @Override</span>
+<span class="source-line-no">595</span><span id="line-595"> protected void printUsage() {</span>
+<span class="source-line-no">596</span><span id="line-596"> printUsage("hbase snapshot info [options]", "Options:", "");</span>
+<span class="source-line-no">597</span><span id="line-597"> System.err.println("Examples:");</span>
+<span class="source-line-no">598</span><span id="line-598"> System.err.println(" hbase snapshot info --snapshot MySnapshot --files");</span>
+<span class="source-line-no">599</span><span id="line-599"> }</span>
+<span class="source-line-no">600</span><span id="line-600"></span>
+<span class="source-line-no">601</span><span id="line-601"> /**</span>
+<span class="source-line-no">602</span><span id="line-602"> * Returns the snapshot stats</span>
+<span class="source-line-no">603</span><span id="line-603"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">604</span><span id="line-604"> * @param snapshot {@link SnapshotDescription} to get stats from</span>
+<span class="source-line-no">605</span><span id="line-605"> * @return the snapshot stats</span>
+<span class="source-line-no">606</span><span id="line-606"> */</span>
+<span class="source-line-no">607</span><span id="line-607"> public static SnapshotStats getSnapshotStats(final Configuration conf,</span>
+<span class="source-line-no">608</span><span id="line-608"> final SnapshotDescription snapshot) throws IOException {</span>
+<span class="source-line-no">609</span><span id="line-609"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">610</span><span id="line-610"> ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
+<span class="source-line-no">611</span><span id="line-611"> return getSnapshotStats(conf, snapshotDesc, null);</span>
+<span class="source-line-no">612</span><span id="line-612"> }</span>
+<span class="source-line-no">613</span><span id="line-613"></span>
+<span class="source-line-no">614</span><span id="line-614"> /**</span>
+<span class="source-line-no">615</span><span id="line-615"> * Returns the snapshot stats</span>
+<span class="source-line-no">616</span><span id="line-616"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">617</span><span id="line-617"> * @param snapshotDesc HBaseProtos.SnapshotDescription to get stats from</span>
+<span class="source-line-no">618</span><span id="line-618"> * @param filesMap {@link Map} store files map for all snapshots, it may be null</span>
+<span class="source-line-no">619</span><span id="line-619"> * @return the snapshot stats</span>
+<span class="source-line-no">620</span><span id="line-620"> */</span>
+<span class="source-line-no">621</span><span id="line-621"> public static SnapshotStats getSnapshotStats(final Configuration conf,</span>
+<span class="source-line-no">622</span><span id="line-622"> final SnapshotProtos.SnapshotDescription snapshotDesc, final Map<Path, Integer> filesMap)</span>
+<span class="source-line-no">623</span><span id="line-623"> throws IOException {</span>
+<span class="source-line-no">624</span><span id="line-624"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
+<span class="source-line-no">625</span><span id="line-625"> FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
+<span class="source-line-no">626</span><span id="line-626"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotDesc, rootDir);</span>
+<span class="source-line-no">627</span><span id="line-627"> SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);</span>
+<span class="source-line-no">628</span><span id="line-628"> final SnapshotStats stats = new SnapshotStats(conf, fs, snapshotDesc);</span>
+<span class="source-line-no">629</span><span id="line-629"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(conf, fs, manifest,</span>
+<span class="source-line-no">630</span><span id="line-630"> "SnapshotsStatsAggregation", new SnapshotReferenceUtil.SnapshotVisitor() {</span>
+<span class="source-line-no">631</span><span id="line-631"> @Override</span>
+<span class="source-line-no">632</span><span id="line-632"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
+<span class="source-line-no">633</span><span id="line-633"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
+<span class="source-line-no">634</span><span id="line-634"> if (!storeFile.hasReference()) {</span>
+<span class="source-line-no">635</span><span id="line-635"> stats.addStoreFile(regionInfo, family, storeFile, filesMap);</span>
+<span class="source-line-no">636</span><span id="line-636"> }</span>
+<span class="source-line-no">637</span><span id="line-637"> }</span>
+<span class="source-line-no">638</span><span id="line-638"> });</span>
+<span class="source-line-no">639</span><span id="line-639"> return stats;</span>
+<span class="source-line-no">640</span><span id="line-640"> }</span>
+<span class="source-line-no">641</span><span id="line-641"></span>
+<span class="source-line-no">642</span><span id="line-642"> /**</span>
+<span class="source-line-no">643</span><span id="line-643"> * Returns the list of available snapshots in the specified location</span>
+<span class="source-line-no">644</span><span id="line-644"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">645</span><span id="line-645"> * @return the list of snapshots</span>
+<span class="source-line-no">646</span><span id="line-646"> */</span>
+<span class="source-line-no">647</span><span id="line-647"> public static List<SnapshotDescription> getSnapshotList(final Configuration conf)</span>
+<span class="source-line-no">648</span><span id="line-648"> throws IOException {</span>
+<span class="source-line-no">649</span><span id="line-649"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
+<span class="source-line-no">650</span><span id="line-650"> FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
+<span class="source-line-no">651</span><span id="line-651"> Path snapshotDir = SnapshotDescriptionUtils.getSnapshotsDir(rootDir);</span>
+<span class="source-line-no">652</span><span id="line-652"> FileStatus[] snapshots = CommonFSUtils.listStatus(fs, snapshotDir,</span>
+<span class="source-line-no">653</span><span id="line-653"> new SnapshotDescriptionUtils.CompletedSnaphotDirectoriesFilter(fs));</span>
+<span class="source-line-no">654</span><span id="line-654"> if (snapshots == null) {</span>
+<span class="source-line-no">655</span><span id="line-655"> return Collections.emptyList();</span>
+<span class="source-line-no">656</span><span id="line-656"> }</span>
+<span class="source-line-no">657</span><span id="line-657"> List<SnapshotDescription> snapshotLists = new ArrayList<>(snapshots.length);</span>
+<span class="source-line-no">658</span><span id="line-658"> for (FileStatus snapshotDirStat : snapshots) {</span>
+<span class="source-line-no">659</span><span id="line-659"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">660</span><span id="line-660"> SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDirStat.getPath());</span>
+<span class="source-line-no">661</span><span id="line-661"> snapshotLists.add(ProtobufUtil.createSnapshotDesc(snapshotDesc));</span>
+<span class="source-line-no">662</span><span id="line-662"> }</span>
+<span class="source-line-no">663</span><span id="line-663"> return snapshotLists;</span>
+<span class="source-line-no">664</span><span id="line-664"> }</span>
+<span class="source-line-no">665</span><span id="line-665"></span>
+<span class="source-line-no">666</span><span id="line-666"> /**</span>
+<span class="source-line-no">667</span><span id="line-667"> * Gets the store files map for snapshot</span>
+<span class="source-line-no">668</span><span id="line-668"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">669</span><span id="line-669"> * @param snapshot {@link SnapshotDescription} to get stats from</span>
+<span class="source-line-no">670</span><span id="line-670"> * @param exec the {@link ExecutorService} to use</span>
+<span class="source-line-no">671</span><span id="line-671"> * @param filesMap {@link Map} the map to put the mapping entries</span>
+<span class="source-line-no">672</span><span id="line-672"> * @param uniqueHFilesArchiveSize {@link AtomicLong} the accumulated store file size in archive</span>
+<span class="source-line-no">673</span><span id="line-673"> * @param uniqueHFilesSize {@link AtomicLong} the accumulated store file size shared</span>
+<span class="source-line-no">674</span><span id="line-674"> * @param uniqueHFilesMobSize {@link AtomicLong} the accumulated mob store file size shared</span>
+<span class="source-line-no">675</span><span id="line-675"> */</span>
+<span class="source-line-no">676</span><span id="line-676"> private static void getSnapshotFilesMap(final Configuration conf,</span>
+<span class="source-line-no">677</span><span id="line-677"> final SnapshotDescription snapshot, final ExecutorService exec,</span>
+<span class="source-line-no">678</span><span id="line-678"> final ConcurrentHashMap<Path, Integer> filesMap, final AtomicLong uniqueHFilesArchiveSize,</span>
+<span class="source-line-no">679</span><span id="line-679"> final AtomicLong uniqueHFilesSize, final AtomicLong uniqueHFilesMobSize) throws IOException {</span>
+<span class="source-line-no">680</span><span id="line-680"> SnapshotProtos.SnapshotDescription snapshotDesc =</span>
+<span class="source-line-no">681</span><span id="line-681"> ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
+<span class="source-line-no">682</span><span id="line-682"> Path rootDir = CommonFSUtils.getRootDir(conf);</span>
+<span class="source-line-no">683</span><span id="line-683"> final FileSystem fs = FileSystem.get(rootDir.toUri(), conf);</span>
+<span class="source-line-no">684</span><span id="line-684"></span>
+<span class="source-line-no">685</span><span id="line-685"> Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotDesc, rootDir);</span>
+<span class="source-line-no">686</span><span id="line-686"> SnapshotManifest manifest = SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);</span>
+<span class="source-line-no">687</span><span id="line-687"> SnapshotReferenceUtil.concurrentVisitReferencedFiles(conf, fs, manifest, exec,</span>
+<span class="source-line-no">688</span><span id="line-688"> new SnapshotReferenceUtil.SnapshotVisitor() {</span>
+<span class="source-line-no">689</span><span id="line-689"> @Override</span>
+<span class="source-line-no">690</span><span id="line-690"> public void storeFile(final RegionInfo regionInfo, final String family,</span>
+<span class="source-line-no">691</span><span id="line-691"> final SnapshotRegionManifest.StoreFile storeFile) throws IOException {</span>
+<span class="source-line-no">692</span><span id="line-692"> if (!storeFile.hasReference()) {</span>
+<span class="source-line-no">693</span><span id="line-693"> HFileLink link = HFileLink.build(conf, snapshot.getTableName(),</span>
+<span class="source-line-no">694</span><span id="line-694"> regionInfo.getEncodedName(), family, storeFile.getName());</span>
+<span class="source-line-no">695</span><span id="line-695"> long size;</span>
+<span class="source-line-no">696</span><span id="line-696"> Integer count;</span>
+<span class="source-line-no">697</span><span id="line-697"> Path p;</span>
+<span class="source-line-no">698</span><span id="line-698"> AtomicLong al;</span>
+<span class="source-line-no">699</span><span id="line-699"> int c = 0;</span>
+<span class="source-line-no">700</span><span id="line-700"></span>
+<span class="source-line-no">701</span><span id="line-701"> if (fs.exists(link.getArchivePath())) {</span>
+<span class="source-line-no">702</span><span id="line-702"> p = link.getArchivePath();</span>
+<span class="source-line-no">703</span><span id="line-703"> al = uniqueHFilesArchiveSize;</span>
+<span class="source-line-no">704</span><span id="line-704"> size = fs.getFileStatus(p).getLen();</span>
+<span class="source-line-no">705</span><span id="line-705"> } else if (fs.exists(link.getMobPath())) {</span>
+<span class="source-line-no">706</span><span id="line-706"> p = link.getMobPath();</span>
+<span class="source-line-no">707</span><span id="line-707"> al = uniqueHFilesMobSize;</span>
+<span class="source-line-no">708</span><span id="line-708"> size = fs.getFileStatus(p).getLen();</span>
+<span class="source-line-no">709</span><span id="line-709"> } else {</span>
+<span class="source-line-no">710</span><span id="line-710"> p = link.getOriginPath();</span>
+<span class="source-line-no">711</span><span id="line-711"> al = uniqueHFilesSize;</span>
+<span class="source-line-no">712</span><span id="line-712"> size = link.getFileStatus(fs).getLen();</span>
+<span class="source-line-no">713</span><span id="line-713"> }</span>
+<span class="source-line-no">714</span><span id="line-714"></span>
+<span class="source-line-no">715</span><span id="line-715"> // If it has been counted, do not double count</span>
+<span class="source-line-no">716</span><span id="line-716"> count = filesMap.get(p);</span>
+<span class="source-line-no">717</span><span id="line-717"> if (count != null) {</span>
+<span class="source-line-no">718</span><span id="line-718"> c = count.intValue();</span>
+<span class="source-line-no">719</span><span id="line-719"> } else {</span>
+<span class="source-line-no">720</span><span id="line-720"> al.addAndGet(size);</span>
+<span class="source-line-no">721</span><span id="line-721"> }</span>
+<span class="source-line-no">722</span><span id="line-722"></span>
+<span class="source-line-no">723</span><span id="line-723"> filesMap.put(p, ++c);</span>
+<span class="source-line-no">724</span><span id="line-724"> }</span>
+<span class="source-line-no">725</span><span id="line-725"> }</span>
+<span class="source-line-no">726</span><span id="line-726"> });</span>
+<span class="source-line-no">727</span><span id="line-727"> }</span>
<span class="source-line-no">728</span><span id="line-728"></span>
-<span class="source-line-no">729</span><span id="line-729"> try {</span>
-<span class="source-line-no">730</span><span id="line-730"> for (final SnapshotDescription snapshot : snapshotList) {</span>
-<span class="source-line-no">731</span><span id="line-731"> getSnapshotFilesMap(conf, snapshot, exec, fileMap, uniqueHFilesArchiveSize,</span>
-<span class="source-line-no">732</span><span id="line-732"> uniqueHFilesSize, uniqueHFilesMobSize);</span>
-<span class="source-line-no">733</span><span id="line-733"> }</span>
-<span class="source-line-no">734</span><span id="line-734"> } finally {</span>
-<span class="source-line-no">735</span><span id="line-735"> exec.shutdown();</span>
-<span class="source-line-no">736</span><span id="line-736"> }</span>
-<span class="source-line-no">737</span><span id="line-737"></span>
-<span class="source-line-no">738</span><span id="line-738"> return fileMap;</span>
-<span class="source-line-no">739</span><span id="line-739"> }</span>
-<span class="source-line-no">740</span><span id="line-740"></span>
-<span class="source-line-no">741</span><span id="line-741"> public static void main(String[] args) {</span>
-<span class="source-line-no">742</span><span id="line-742"> new SnapshotInfo().doStaticMain(args);</span>
-<span class="source-line-no">743</span><span id="line-743"> }</span>
-<span class="source-line-no">744</span><span id="line-744">}</span>
+<span class="source-line-no">729</span><span id="line-729"> /**</span>
+<span class="source-line-no">730</span><span id="line-730"> * Returns the map of store files based on path for all snapshots</span>
+<span class="source-line-no">731</span><span id="line-731"> * @param conf the {@link Configuration} to use</span>
+<span class="source-line-no">732</span><span id="line-732"> * @param uniqueHFilesArchiveSize pass out the size for store files in archive</span>
+<span class="source-line-no">733</span><span id="line-733"> * @param uniqueHFilesSize pass out the size for store files shared</span>
+<span class="source-line-no">734</span><span id="line-734"> * @param uniqueHFilesMobSize pass out the size for mob store files shared</span>
+<span class="source-line-no">735</span><span id="line-735"> * @return the map of store files</span>
+<span class="source-line-no">736</span><span id="line-736"> */</span>
+<span class="source-line-no">737</span><span id="line-737"> public static Map<Path, Integer> getSnapshotsFilesMap(final Configuration conf,</span>
+<span class="source-line-no">738</span><span id="line-738"> AtomicLong uniqueHFilesArchiveSize, AtomicLong uniqueHFilesSize, AtomicLong uniqueHFilesMobSize)</span>
+<span class="source-line-no">739</span><span id="line-739"> throws IOException {</span>
+<span class="source-line-no">740</span><span id="line-740"> List<SnapshotDescription> snapshotList = getSnapshotList(conf);</span>
+<span class="source-line-no">741</span><span id="line-741"></span>
+<span class="source-line-no">742</span><span id="line-742"> if (snapshotList.isEmpty()) {</span>
+<span class="source-line-no">743</span><span id="line-743"> return Collections.emptyMap();</span>
+<span class="source-line-no">744</span><span id="line-744"> }</span>
+<span class="source-line-no">745</span><span id="line-745"></span>
+<span class="source-line-no">746</span><span id="line-746"> ConcurrentHashMap<Path, Integer> fileMap = new ConcurrentHashMap<>();</span>
+<span class="source-line-no">747</span><span id="line-747"></span>
+<span class="source-line-no">748</span><span id="line-748"> ExecutorService exec = SnapshotManifest.createExecutor(conf, "SnapshotsFilesMapping");</span>
+<span class="source-line-no">749</span><span id="line-749"></span>
+<span class="source-line-no">750</span><span id="line-750"> try {</span>
+<span class="source-line-no">751</span><span id="line-751"> for (final SnapshotDescription snapshot : snapshotList) {</span>
+<span class="source-line-no">752</span><span id="line-752"> getSnapshotFilesMap(conf, snapshot, exec, fileMap, uniqueHFilesArchiveSize,</span>
+<span class="source-line-no">753</span><span id="line-753"> uniqueHFilesSize, uniqueHFilesMobSize);</span>
+<span class="source-line-no">754</span><span id="line-754"> }</span>
+<span class="source-line-no">755</span><span id="line-755"> } finally {</span>
+<span class="source-line-no">756</span><span id="line-756"> exec.shutdown();</span>
+<span class="source-line-no">757</span><span id="line-757"> }</span>
+<span class="source-line-no">758</span><span id="line-758"></span>
+<span class="source-line-no">759</span><span id="line-759"> return fileMap;</span>
+<span class="source-line-no">760</span><span id="line-760"> }</span>
+<span class="source-line-no">761</span><span id="line-761"></span>
+<span class="source-line-no">762</span><span id="line-762"> public static void main(String[] args) {</span>
+<span class="source-line-no">763</span><span id="line-763"> new SnapshotInfo().doStaticMain(args);</span>
+<span class="source-line-no">764</span><span id="line-764"> }</span>
+<span class="source-line-no">765</span><span id="line-765">}</span>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html b/devapidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html
index e8578d2d279..5999aee5723 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/snapshot/SnapshotInfo.SnapshotStats.html
@@ -30,731 +30,752 @@
<span class="source-line-no">017</span><span id="line-17"> */</span>
<span class="source-line-no">018</span><span id="line-18">package org.apache.hadoop.hbase.snapshot;</span>
<span class="source-line-no">019</span><span id="line-19"></span>
-<span class="source-line-no">020</span><span id="line-20">import java.io.FileNotFoundException;</span>
-<span class="source-line-no">021</span><span id="line-21">import java.io.IOException;</span>
-<span class="source-line-no">022</span><span id="line-22">import java.net.URI;</span>
-<span class="source-line-no">023</span><span id="line-23">import java.text.SimpleDateFormat;</span>
-<span class="source-line-no">024</span><span id="line-24">import java.util.ArrayList;</span>
-<span class="source-line-no">025</span><span id="line-25">import java.util.Collections;</span>
-<span class="source-line-no">026</span><span id="line-26">import java.util.Date;</span>
-<span class="source-line-no">027</span><span id="line-27">import java.util.List;</span>
-<span class="source-line-no">028</span><span id="line-28">import java.util.Map;</span>
-<span class="source-line-no">029</span><span id="line-29">import java.util.Properties;</span>
-<span class="source-line-no">030</span><span id="line-30">import java.util.concurrent.ConcurrentHashMap;</span>
-<span class="source-line-no">031</span><span id="line-31">import java.util.concurrent.ExecutorService;</span>
-<span class="source-line-no">032</span><span id="line-32">import java.util.concurrent.atomic.AtomicInteger;</span>
-<span class="source-line-no">033</span><span id="line-33">import java.util.concurrent.atomic.AtomicLong;</span>
-<span class="source-line-no">034</span><span id="line-34">import org.apache.hadoop.conf.Configuration;</span>
-<span class="source-line-no">035</span><span id="line-35">import org.apache.hadoop.fs.FileStatus;</span>
-<span class="source-line-no">036</span><span id="line-36">import org.apache.hadoop.fs.FileSystem;</span>
-<span class="source-line-no">037</span><span id="line-37">import org.apache.hadoop.fs.Path;</span>
-<span class="source-line-no">038</span><span id="line-38">import org.apache.hadoop.hbase.TableName;</span>
-<span class="source-line-no">039</span><span id="line-39">import org.apache.hadoop.hbase.client.RegionInfo;</span>
-<span class="source-line-no">040</span><span id="line-40">import org.apache.hadoop.hbase.client.SnapshotDescription;</span>
-<span class="source-line-no">041</span><span id="line-41">import org.apache.hadoop.hbase.io.HFileLink;</span>
-<span class="source-line-no">042</span><span id="line-42">import org.apache.hadoop.hbase.io.WALLink;</span>
-<span class="source-line-no">043</span><span id="line-43">import org.apache.hadoop.hbase.util.AbstractHBaseTool;</span>
-<span class="source-line-no">044</span><span id="line-44">import org.apache.hadoop.hbase.util.CommonFSUtils;</span>
-<span class="source-line-no">045</span><span id="line-45">import org.apache.hadoop.hbase.util.Strings;</span>
-<span class="source-line-no">046</span><span id="line-46">import org.apache.yetus.audience.InterfaceAudience;</span>
-<span class="source-line-no">047</span><span id="line-47">import org.slf4j.Logger;</span>
-<span class="source-line-no">048</span><span id="line-48">import org.slf4j.LoggerFactory;</span>
-<span class="source-line-no">049</span><span id="line-49"></span>
-<span class="source-line-no">050</span><span id="line-50">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;</span>
-<span class="source-line-no">051</span><span id="line-51">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLineParser;</span>
-<span class="source-line-no">052</span><span id="line-52">import org.apache.hbase.thirdparty.org.apache.commons.cli.DefaultParser;</span>
-<span class="source-line-no">053</span><span id="line-53">import org.apache.hbase.thirdparty.org.apache.commons.cli.Option;</span>
-<span class="source-line-no">054</span><span id="line-54">import org.apache.hbase.thirdparty.org.apache.commons.cli.Options;</span>
-<span class="source-line-no">055</span><span id="line-55">import org.apache.hbase.thirdparty.org.apache.commons.cli.ParseException;</span>
-<span class="source-line-no">056</span><span id="line-56"></span>
-<span class="source-line-no">057</span><span id="line-57">import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;</span>
-<span class="source-line-no">058</span><span id="line-58">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos;</span>
-<span class="source-line-no">059</span><span id="line-59">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;</span>
-<span class="source-line-no">060</span><span id="line-60"></span>
-<span class="source-line-no">061</span><span id="line-61">/**</span>
-<span class="source-line-no">062</span><span id="line-62"> * Tool for dumping snapshot information.</span>
-<span class="source-line-no">063</span><span id="line-63"> * <ol></span>
-<span class="source-line-no">064</span><span id="line-64"> * <li>Table Descriptor</span>
-<span class="source-line-no">065</span><span id="line-65"> * <li>Snapshot creation time, type, format version, ...</span>
-<span class="source-line-no">066</span><span id="line-66"> * <li>List of hfiles and wals</span>
-<span class="source-line-no">067</span><span id="line-67"> * <li>Stats about hfiles and logs sizes, percentage of shared with the source table, ...</span>
-<span class="source-line-no">068</span><span id="line-68"> * </ol></span>
-<span class="source-line-no">069</span><span id="line-69"> */</span>
-<span class="source-line-no">070</span><span id="line-70">@InterfaceAudience.Public</span>
-<span class="source-line-no">071</span><span id="line-71">public final class SnapshotInfo extends AbstractHBaseTool {</span>
-<span class="source-line-no">072</span><span id="line-72"> private static final Logger LOG = LoggerFactory.getLogger(SnapshotInfo.class);</span>
-<span class="source-line-no">073</span><span id="line-73"></span>
-<span class="source-line-no">074</span><span id="line-74"> static final class Options {</span>
-<span class="source-line-no">075</span><span id="line-75"> static final Option SNAPSHOT =</span>
-<span class="source-line-no">076</span><span id="line-76"> new Option(null, "snapshot", true, "The name of the snapshot to be detailed.");</span>
-<span class="source-line-no">077</span><span id="line-77"> static final Option REMOTE_DIR =</span>
-<span class="source-line-no">078</span><span id="line-78"> new Option(null, "remote-dir", true, "A custom root directory where snapshots are stored. "</span>
-<span class="source-line-no">079</span><span id="line-79"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">080</span><span id="line-80"> static final Option LIST_SNAPSHOTS =</span>
-<span class="source-line-no">081</span><span id="line-81"> new Option(null, "list-snapshots", false, "List all the available snapshots and exit.");</span>
-<span class="source-line-no">082</span><span id="line-82"> static final Option FILES =</span>
-<span class="source-line-no">083</span><span id="line-83"> new Option(null, "files", false, "The list of files retained by the specified snapshot. "</span>
-<span class="source-line-no">084</span><span id="line-84"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">085</span><span id="line-85"> static final Option STATS =</span>
-<span class="source-line-no">086</span><span id="line-86"> new Option(null, "stats", false, "Additional information about the specified snapshot. "</span>
-<span class="source-line-no">087</span><span id="line-87"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">088</span><span id="line-88"> static final Option SCHEMA = new Option(null, "schema", false,</span>
-<span class="source-line-no">089</span><span id="line-89"> "Show the descriptor of the table for the specified snapshot. "</span>
+<span class="source-line-no">020</span><span id="line-20">import static org.apache.hadoop.hbase.HConstants.DEFAULT_SNAPSHOT_TTL;</span>
+<span class="source-line-no">021</span><span id="line-21"></span>
+<span class="source-line-no">022</span><span id="line-22">import java.io.FileNotFoundException;</span>
+<span class="source-line-no">023</span><span id="line-23">import java.io.IOException;</span>
+<span class="source-line-no">024</span><span id="line-24">import java.net.URI;</span>
+<span class="source-line-no">025</span><span id="line-25">import java.text.SimpleDateFormat;</span>
+<span class="source-line-no">026</span><span id="line-26">import java.util.ArrayList;</span>
+<span class="source-line-no">027</span><span id="line-27">import java.util.Collections;</span>
+<span class="source-line-no">028</span><span id="line-28">import java.util.Date;</span>
+<span class="source-line-no">029</span><span id="line-29">import java.util.List;</span>
+<span class="source-line-no">030</span><span id="line-30">import java.util.Map;</span>
+<span class="source-line-no">031</span><span id="line-31">import java.util.Properties;</span>
+<span class="source-line-no">032</span><span id="line-32">import java.util.concurrent.ConcurrentHashMap;</span>
+<span class="source-line-no">033</span><span id="line-33">import java.util.concurrent.ExecutorService;</span>
+<span class="source-line-no">034</span><span id="line-34">import java.util.concurrent.atomic.AtomicInteger;</span>
+<span class="source-line-no">035</span><span id="line-35">import java.util.concurrent.atomic.AtomicLong;</span>
+<span class="source-line-no">036</span><span id="line-36">import org.apache.hadoop.conf.Configuration;</span>
+<span class="source-line-no">037</span><span id="line-37">import org.apache.hadoop.fs.FileStatus;</span>
+<span class="source-line-no">038</span><span id="line-38">import org.apache.hadoop.fs.FileSystem;</span>
+<span class="source-line-no">039</span><span id="line-39">import org.apache.hadoop.fs.Path;</span>
+<span class="source-line-no">040</span><span id="line-40">import org.apache.hadoop.hbase.TableName;</span>
+<span class="source-line-no">041</span><span id="line-41">import org.apache.hadoop.hbase.client.RegionInfo;</span>
+<span class="source-line-no">042</span><span id="line-42">import org.apache.hadoop.hbase.client.SnapshotDescription;</span>
+<span class="source-line-no">043</span><span id="line-43">import org.apache.hadoop.hbase.io.HFileLink;</span>
+<span class="source-line-no">044</span><span id="line-44">import org.apache.hadoop.hbase.io.WALLink;</span>
+<span class="source-line-no">045</span><span id="line-45">import org.apache.hadoop.hbase.util.AbstractHBaseTool;</span>
+<span class="source-line-no">046</span><span id="line-46">import org.apache.hadoop.hbase.util.CommonFSUtils;</span>
+<span class="source-line-no">047</span><span id="line-47">import org.apache.hadoop.hbase.util.Strings;</span>
+<span class="source-line-no">048</span><span id="line-48">import org.apache.yetus.audience.InterfaceAudience;</span>
+<span class="source-line-no">049</span><span id="line-49">import org.slf4j.Logger;</span>
+<span class="source-line-no">050</span><span id="line-50">import org.slf4j.LoggerFactory;</span>
+<span class="source-line-no">051</span><span id="line-51"></span>
+<span class="source-line-no">052</span><span id="line-52">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine;</span>
+<span class="source-line-no">053</span><span id="line-53">import org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLineParser;</span>
+<span class="source-line-no">054</span><span id="line-54">import org.apache.hbase.thirdparty.org.apache.commons.cli.DefaultParser;</span>
+<span class="source-line-no">055</span><span id="line-55">import org.apache.hbase.thirdparty.org.apache.commons.cli.Option;</span>
+<span class="source-line-no">056</span><span id="line-56">import org.apache.hbase.thirdparty.org.apache.commons.cli.Options;</span>
+<span class="source-line-no">057</span><span id="line-57">import org.apache.hbase.thirdparty.org.apache.commons.cli.ParseException;</span>
+<span class="source-line-no">058</span><span id="line-58"></span>
+<span class="source-line-no">059</span><span id="line-59">import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;</span>
+<span class="source-line-no">060</span><span id="line-60">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos;</span>
+<span class="source-line-no">061</span><span id="line-61">import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;</span>
+<span class="source-line-no">062</span><span id="line-62"></span>
+<span class="source-line-no">063</span><span id="line-63">/**</span>
+<span class="source-line-no">064</span><span id="line-64"> * Tool for dumping snapshot information.</span>
+<span class="source-line-no">065</span><span id="line-65"> * <ol></span>
+<span class="source-line-no">066</span><span id="line-66"> * <li>Table Descriptor</span>
+<span class="source-line-no">067</span><span id="line-67"> * <li>Snapshot creation time, type, format version, ...</span>
+<span class="source-line-no">068</span><span id="line-68"> * <li>List of hfiles and wals</span>
+<span class="source-line-no">069</span><span id="line-69"> * <li>Stats about hfiles and logs sizes, percentage of shared with the source table, ...</span>
+<span class="source-line-no">070</span><span id="line-70"> * </ol></span>
+<span class="source-line-no">071</span><span id="line-71"> */</span>
+<span class="source-line-no">072</span><span id="line-72">@InterfaceAudience.Public</span>
+<span class="source-line-no">073</span><span id="line-73">public final class SnapshotInfo extends AbstractHBaseTool {</span>
+<span class="source-line-no">074</span><span id="line-74"> private static final Logger LOG = LoggerFactory.getLogger(SnapshotInfo.class);</span>
+<span class="source-line-no">075</span><span id="line-75"></span>
+<span class="source-line-no">076</span><span id="line-76"> private static final String EXPIRED_LABEL = "Yes";</span>
+<span class="source-line-no">077</span><span id="line-77"> private static final String NOT_EXPIRED_LABEL = "No";</span>
+<span class="source-line-no">078</span><span id="line-78"> private static final String TTL_FOREVER = "FOREVER";</span>
+<span class="source-line-no">079</span><span id="line-79"></span>
+<span class="source-line-no">080</span><span id="line-80"> static final class Options {</span>
+<span class="source-line-no">081</span><span id="line-81"> static final Option SNAPSHOT =</span>
+<span class="source-line-no">082</span><span id="line-82"> new Option(null, "snapshot", true, "The name of the snapshot to be detailed.");</span>
+<span class="source-line-no">083</span><span id="line-83"> static final Option REMOTE_DIR =</span>
+<span class="source-line-no">084</span><span id="line-84"> new Option(null, "remote-dir", true, "A custom root directory where snapshots are stored. "</span>
+<span class="source-line-no">085</span><span id="line-85"> + "Use it together with the --snapshot option.");</span>
+<span class="source-line-no">086</span><span id="line-86"> static final Option LIST_SNAPSHOTS =</span>
+<span class="source-line-no">087</span><span id="line-87"> new Option(null, "list-snapshots", false, "List all the available snapshots and exit.");</span>
+<span class="source-line-no">088</span><span id="line-88"> static final Option FILES =</span>
+<span class="source-line-no">089</span><span id="line-89"> new Option(null, "files", false, "The list of files retained by the specified snapshot. "</span>
<span class="source-line-no">090</span><span id="line-90"> + "Use it together with the --snapshot option.");</span>
-<span class="source-line-no">091</span><span id="line-91"> static final Option SIZE_IN_BYTES =</span>
-<span class="source-line-no">092</span><span id="line-92"> new Option(null, "size-in-bytes", false, "Print the size of the files in bytes. "</span>
-<span class="source-line-no">093</span><span id="line-93"> + "Use it together with the --snapshot and --files options.");</span>
-<span class="source-line-no">094</span><span id="line-94"> }</span>
-<span class="source-line-no">095</span><span id="line-95"></span>
-<span class="source-line-no">096</span><span id="line-96"> /**</span>
-<span class="source-line-no">097</span><span id="line-97"> * Statistics about the snapshot</span>
-<span class="source-line-no">098</span><span id="line-98"> * <ol></span>
-<span class="source-line-no">099</span><span id="line-99"> * <li>How many store files and logs are in the archive</span>
-<span class="source-line-no">100</span><span id="line-100"> * <li>How many store files and logs are shared with the table</span>
-<span class="source-line-no">101</span><span id="line-101"> * <li>Total store files and logs size and shared amount</span>
-<span class="source-line-no">102</span><span id="line-102"> * </ol></span>
-<span class="source-line-no">103</span><span id="line-103"> */</span>
-<span class="source-line-no">104</span><span id="line-104"> public static class SnapshotStats {</span>
-<span class="source-line-no">105</span><span id="line-105"> /** Information about the file referenced by the snapshot */</span>
-<span class="source-line-no">106</span><span id="line-106"> static class FileInfo {</span>
-<span class="source-line-no">107</span><span id="line-107"> private final boolean corrupted;</span>
-<span class="source-line-no">108</span><span id="line-108"> private final boolean inArchive;</span>
-<span class="source-line-no">109</span><span id="line-109"> private final long size;</span>
-<span class="source-line-no">110</span><span id="line-110"></span>
-<span class="source-line-no">111</span><span id="line-111"> FileInfo(final boolean inArchive, final long size, final boolean corrupted) {</span>
-<span class="source-line-no">112</span><span id="line-112"> this.corrupted = corrupted;</span>
-<span class="source-line-no">113</span><span id="line-113"> this.inArchive = inArchive;</span>
-<span class="source-line-no">114</span><span id="line-114"> this.size = size;</span>
-<span class="source-line-no">115</span><span id="line-115"> }</span>
+<span class="source-line-no">091</span><span id="line-91"> static final Option STATS =</span>
+<span class="source-line-no">092</span><span id="line-92"> new Option(null, "stats", false, "Additional information about the specified snapshot. "</span>
+<span class="source-line-no">093</span><span id="line-93"> + "Use it together with the --snapshot option.");</span>
+<span class="source-line-no">094</span><span id="line-94"> static final Option SCHEMA = new Option(null, "schema", false,</span>
+<span class="source-line-no">095</span><span id="line-95"> "Show the descriptor of the table for the specified snapshot. "</span>
+<span class="source-line-no">096</span><span id="line-96"> + "Use it together with the --snapshot option.");</span>
+<span class="source-line-no">097</span><span id="line-97"> static final Option SIZE_IN_BYTES =</span>
+<span class="source-line-no">098</span><span id="line-98"> new Option(null, "size-in-bytes", false, "Print the size of the files in bytes. "</span>
+<span class="source-line-no">099</span><span id="line-99"> + "Use it together with the --snapshot and --files options.");</span>
+<span class="source-line-no">100</span><span id="line-100"> }</span>
+<span class="source-line-no">101</span><span id="line-101"></span>
+<span class="source-line-no">102</span><span id="line-102"> /**</span>
+<span class="source-line-no">103</span><span id="line-103"> * Statistics about the snapshot</span>
+<span class="source-line-no">104</span><span id="line-104"> * <ol></span>
+<span class="source-line-no">105</span><span id="line-105"> * <li>How many store files and logs are in the archive</span>
+<span class="source-line-no">106</span><span id="line-106"> * <li>How many store files and logs are shared with the table</span>
+<span class="source-line-no">107</span><span id="line-107"> * <li>Total store files and logs size and shared amount</span>
+<span class="source-line-no">108</span><span id="line-108"> * </ol></span>
+<span class="source-line-no">109</span><span id="line-109"> */</span>
+<span class="source-line-no">110</span><span id="line-110"> public static class SnapshotStats {</span>
+<span class="source-line-no">111</span><span id="line-111"> /** Information about the file referenced by the snapshot */</span>
+<span class="source-line-no">112</span><span id="line-112"> static class FileInfo {</span>
+<span class="source-line-no">113</span><span id="line-113"> private final boolean corrupted;</span>
+<span class="source-line-no">114</span><span id="line-114"> private final boolean inArchive;</span>
+<span class="source-line-no">115</span><span id="line-115"> private final long size;</span>
<span class="source-line-no">116</span><span id="line-116"></span>
-<span class="source-line-no">117</span><span id="line-117"> /** Returns true if the file is in the archive */</span>
-<span class="source-line-no">118</span><span id="line-118"> public boolean inArchive() {</span>
-<span class="source-line-no">119</span><span id="line-119"> return this.inArchive;</span>
-<span class="source-line-no">120</span><span id="line-120"> }</span>
-<span class="source-line-no">121</span><span id="line-121"></span>
-<span class="source-line-no">122</span><span id="line-122"> /** Returns true if the file is corrupted */</span>
-<span class="source-line-no">123</span><span id="line-123"> public boolean isCorrupted() {</span>
-<span class="source-line-no">124</span><span id="line-124"> return this.corrupted;</span>
-<span class="source-line-no">125</span><span id="line-125"> }</span>
-<span class="source-line-no">126</span><span id="line-126"></span>
-<span class="source-line-no">127</span><span id="line-127"> /** Returns true if the file is missing */</span>
-<span class="source-line-no">128</span><span id="line-128"> public boolean isMissing() {</span>
-<span class="source-line-no">129</span><span id="line-129"> return this.size < 0;</span>
-<span class="source-line-no">130</span><span id="line-130"> }</span>
-<span class="source-line-no">131</span><span id="line-131"></span>
-<span class="source-line-no">132</span><span id="line-132"> /** Returns the file size */</span>
-<span class="source-line-no">133</span><span id="line-133"> public long getSize() {</span>
-<span class="source-line-no">134</span><span id="line-134"> return this.size;</span>
-<span class="source-line-no">135</span><span id="line-135"> }</span>
-<span class="source-line-no">136</span><span id="line-136"></span>
-<span class="source-line-no">137</span><span id="line-137"> String getStateToString() {</span>
-<span class="source-line-no">138</span><span id="line-138"> if (isCorrupted()) return "CORRUPTED";</span>
-<span class="source-line-no">139</span><span id="line-139"> if (isMissing()) return "NOT FOUND";</span>
-<span class="source-line-no">140</span><span id="line-140"> if (inArchive()) return "archive";</span>
-<span class="source-line-no">141</span><span id="line-141"> return null;</span>
-<span class="source-line-no">142</span><span id="line-142"> }</span>
-<span class="source-line-no">143</span><span id="line-143"> }</span>
-<span class="source-line-no">144</span><span id="line-144"></span>
-<span class="source-line-no">145</span><span id="line-145"> private AtomicInteger hfilesArchiveCount = new AtomicInteger();</span>
-<span class="source-line-no">146</span><span id="line-146"> private AtomicInteger hfilesCorrupted = new AtomicInteger();</span>
-<span class="source-line-no">147</span><span id="line-147"> private AtomicInteger hfilesMissing = new AtomicInteger();</span>
-<span class="source-line-no">148</span><span id="line-148"> private AtomicInteger hfilesCount = new AtomicInteger();</span>
-<span class="source-line-no">149</span><span id="line-149"> private AtomicInteger hfilesMobCount = new AtomicInteger();</span>
-<span class="source-line-no">150</span><span id="line-150"> private AtomicInteger logsMissing = new AtomicInteger();</span>
-<span class="source-line-no">151</span><span id="line-151"> private AtomicInteger logsCount = new AtomicInteger();</span>
-<span class="source-line-no">152</span><span id="line-152"> private AtomicLong hfilesArchiveSize = new AtomicLong();</span>
-<span class="source-line-no">153</span><span id="line-153"> private AtomicLong hfilesSize = new AtomicLong();</span>
-<span class="source-line-no">154</span><span id="line-154"> private AtomicLong hfilesMobSize = new AtomicLong();</span>
-<span class="source-line-no">155</span><span id="line-155"> private AtomicLong nonSharedHfilesArchiveSize = new AtomicLong();</span>
-<span class="source-line-no">156</span><span id="line-156"> private AtomicLong logSize = new AtomicLong();</span>
-<span class="source-line-no">157</span><span id="line-157"></span>
-<span class="source-line-no">158</span><span id="line-158"> private final SnapshotProtos.SnapshotDescription snapshot;</span>
-<span class="source-line-no">159</span><span id="line-159"> private final TableName snapshotTable;</span>
-<span class="source-line-no">160</span><span id="line-160"> private final Configuration conf;</span>
-<span class="source-line-no">161</span><span id="line-161"> private final FileSystem fs;</span>
-<span class="source-line-no">162</span><span id="line-162"></span>
-<span class="source-line-no">163</span><span id="line-163"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
-<span class="source-line-no">164</span><span id="line-164"> final SnapshotDescription snapshot) {</span>
-<span class="source-line-no">165</span><span id="line-165"> this.snapshot = ProtobufUtil.createHBaseProtosSnapshotDesc(snapshot);</span>
-<span class="source-line-no">166</span><span id="line-166"> this.snapshotTable = snapshot.getTableName();</span>
-<span class="source-line-no">167</span><span id="line-167"> this.conf = conf;</span>
-<span class="source-line-no">168</span><span id="line-168"> this.fs = fs;</span>
-<span class="source-line-no">169</span><span id="line-169"> }</span>
-<span class="source-line-no">170</span><span id="line-170"></span>
-<span class="source-line-no">171</span><span id="line-171"> SnapshotStats(final Configuration conf, final FileSystem fs,</span>
-<span class="source-line-no">172</span><span id="line-172"> final SnapshotProtos.SnapshotDescription snapshot) {</span>
-<span class="source-line-no">173</span><span id="line-173"> this.snapshot = snapshot;</span>
-<span class="source-line-no">174</span><span id="line-174"> this.snapshotTable = TableName.valueOf(snapshot.getTable());</span>
-<span class="source-line-no">175</span><span id="line-175"> this.conf = conf;</span>
-<span class="source-line-no">176</span><span id="line-176"> this.fs = fs;</span>
-<span class="source-line-no">177</span><span id="line-177"> }</span>
-<span class="source-line-no">178</span><span id="line-178"></span>
-<span class="source-line-no">179</span><span id="line-179"> /** Returns the snapshot descriptor */</span>
-<span class="source-line-no">180</span><span id="line-180"> public SnapshotDescription getSnapshotDescription() {</span>
-<span class="source-line-no">181</span><span id="line-181"> return ProtobufUtil.createSnapshotDesc(this.snapshot);</span>
-<span class="source-line-no">182</span><span id="line-182"> }</span>
-<span class="source-line-no">183</span><span id="line-183"></span>
-<span class="source-line-no">184</span><span id="line-184"> /** Returns true if the snapshot is corrupted */</span>
-<span class="source-line-no">185</span><span id="line-185"> public boolean isSnapshotCorrupted() {</span>
-<span class="source-line-no">186</span><span id="line-186"> return hfilesMissing.get() > 0 || logsMissing.get() > 0 || hfilesCorrupted.get() > 0;</span>
-<span class="source-line-no">187</span><span id="line-187"> }</span>
-<span class="source-line-no">188</span><span id="line-188"></span>
-<span class="source-line-no">189</span><span id="line-189"> /** Returns the number of available store files */</span>
-<span class="source-line-no">190</span><span id="line-190"> public int getStoreFilesCount() {</span>
-<span class="source-line-no">191</span><span id="line-191"> return hfilesCount.get() + hfilesArchiveCount.get() + hfilesMobCount.get();</span>
-<span class="source-line-no">192</span><span id="line-192"> }</span>
-<span class="source-line-no">193</span><span id="line-193"></span>
-<span class="source-line-no">194</span><span id="line-194"> /** Returns the number of available store files in the archive */</span>
-<span class="source-line-no">195</span><span id="line-195"> public int getArchivedStoreFilesCount() {</span>
-<span class="source-line-no">196</span><span id="line-196"> return hfilesArchiveCount.get();</span>
-<span class="source-line-no">197</span><span id="line-197"> }</span>
-<span class="source-line-no">198</span><span id="line-198"></span>
-<span class="source-line-no">199</span><span id="line-199"> /** Returns the number of available store files in the mob dir */</span>
-<span class="source-line-no">200</span><span id="line-200"> public int getMobStoreFilesCount() {</span>
-<span class="source-line-no">201</span><span id="line-201"> return hfilesMobCount.get();</span>
-<span class="source-line-no">202</span><span id="line-202"> }</span>
-<span class="source-line-no">203</span><span id="line-203"></span>
-<span class="source-line-no">204</span><span id="line-204"> /** Returns the number of available log files */</span>
-<span class="source-line-no">205</span><span id="line-205"> public int getLogsCount() {</span>
-<span class="source-line-no">206</span><span id="line-206"> return logsCount.get();</span>
-<span class="source-line-no">207</span><span id="line-207"> }</span>
-<span class="source-line-no">208</span><span id="line-208"></span>
-<span class="source-line-no">209</span><span id="line-209"> /** Returns the number of missing store files */</span>
-<span class="source-line-no">210</span><span id="line-210"> public int getMissingStoreFilesCount() {</span>
-<span class="source-line-no">211</span><span id="line-211"> return hfilesMissing.get();</span>
-<span class="source-line-no">212</span><span id="line-212"> }</span>
-<span class="source-line-no">213</span><span id="line-213"></span>
-<span class="source-line-no">214</span><span id="line-214"> /** Returns the number of corrupted store files */</span>
-<span class="source-line-no">215</span><span id="line-215"> public int getCorruptedStoreFilesCount() {</span>
-<span class="source-line-no">216</span><span id="line-216"> return hfilesCorrupted.get();</span>
-<span class="source-line-no">217</span><span id="line-217"> }</span>
-<span class="source-line-no">218</span><span id="line-218"></span>
-<span class="source-line-no">219</span><span id="line-219"> /** Returns the number of missing log files */</span>
-<span class="source-line-no">220</span><span id="line-220"> public int getMissingLogsCount() {</span>
-<span class="source-line-no">221</span><span id="line-221"> return logsMissing.get();</span>
-<span class="source-line-no">222</span><span id="line-222"> }</span>
-<span class="source-line-no">223</span><span id="line-223"></span>
-<span class="source-line-no">224</span><span id="line-224"> /** Returns the total size of the store files referenced by the snapshot */</span>
-<span class="source-line-no">225</span><span id="line-225"> public long getStoreFilesSize() {</span>
-<span class="source-line-no">226</span><span id="line-226"> return hfilesSize.get() + hfilesArchiveSize.get() + hfilesMobSize.get();</span>
-<span class="source-line-no">227</span><span id="line-227"> }</span>
-<span class="source-line-no">228</span><span id="line-228"></span>
-<span class="source-line-no">229</span><span id="line-229"> /** Returns the total size of the store files shared */</span>
-<span class="source-line-no">230</span><span id="line-230"> public long getSharedStoreFilesSize() {</span>
-<span class="source-line-no">231</span><span id="line-231"> return hfilesSize.get();</span>
-<span class="source-line-no">232</span><span id="line-232"> }</span>
-<span class="source-line-no">233</span><span id="line-233"></span>
-<span class="source-line-no">234</span><span id="line-234"> /** Returns the total size of the store files in the archive */</span>
-<span class="source-line-no">235</span><span id="line-235"> public long getArchivedStoreFileSize() {</span>
-<span class="source-line-no">236</span><span id="line-236"> return hfilesArchiveSize.get();</span>
-<span class="source-line-no">237</span><span id="line-237"> }</span>
-<span class="source-line-no">238</span><span id="line-238"></span>
-<span class="source-line-no">239</span><span id="line-239"> /** Returns the total size of the store files in the mob store */</span>
-<span class="source-line-no">240</span><span id="line-240"> public long getMobStoreFilesSize() {</span>
-<span class="source-line-no">241</span><span id="line-241"> return hfilesMobSize.get();</span>
-<span class="source-line-no">242</span><span id="line-242"> }</span>
-<span class="source-line-no">243</span><span id="line-243"></span>
-<span class="source-line-no">244</span><span id="line-244"> /**</span>
-<span class="source-line-no">245</span><span id="line-245"> * @return the total size of the store files in the archive which is not shared with other</span>
... 34114 lines suppressed ...