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 2022/03/30 14:55:44 UTC
[hbase-site] branch asf-site updated: Published site at 7adccd2a19afdb5e3e5e6f679fa288f6d9c9046c.
This is an automated email from the ASF dual-hosted git repository.
git-site-role 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 abc395f Published site at 7adccd2a19afdb5e3e5e6f679fa288f6d9c9046c.
abc395f is described below
commit abc395f37655e634f881fb5706db5a7dca3fbcbf
Author: jenkins <bu...@apache.org>
AuthorDate: Wed Mar 30 14:55:14 2022 +0000
Published site at 7adccd2a19afdb5e3e5e6f679fa288f6d9c9046c.
---
acid-semantics.html | 2 +-
apache_hbase_reference_guide.pdf | 4 +-
book.html | 2 +-
bulk-loads.html | 2 +-
checkstyle-aggregate.html | 28 +-
coc.html | 2 +-
dependencies.html | 2 +-
dependency-convergence.html | 2 +-
dependency-info.html | 2 +-
dependency-management.html | 4 +-
.../hadoop/hbase/backup/HFileArchiver.File.html | 24 +-
.../hbase/backup/HFileArchiver.FileConverter.html | 6 +-
.../backup/HFileArchiver.FileStatusConverter.html | 6 +-
.../hbase/backup/HFileArchiver.FileablePath.html | 20 +-
.../backup/HFileArchiver.FileableStoreFile.html | 18 +-
.../hbase/backup/HFileArchiver.StoreToFile.html | 6 +-
.../apache/hadoop/hbase/backup/HFileArchiver.html | 4 +-
...TransitRegionStateProcedure.TransitionType.html | 14 +-
.../assignment/TransitRegionStateProcedure.html | 88 +-
.../hadoop/hbase/backup/HFileArchiver.File.html | 629 +++++----
.../hbase/backup/HFileArchiver.FileConverter.html | 629 +++++----
.../backup/HFileArchiver.FileStatusConverter.html | 629 +++++----
.../hbase/backup/HFileArchiver.FileablePath.html | 629 +++++----
.../backup/HFileArchiver.FileableStoreFile.html | 629 +++++----
.../hbase/backup/HFileArchiver.StoreToFile.html | 629 +++++----
.../apache/hadoop/hbase/backup/HFileArchiver.html | 629 +++++----
...TransitRegionStateProcedure.TransitionType.html | 1130 ++++++++--------
.../assignment/TransitRegionStateProcedure.html | 1130 ++++++++--------
downloads.html | 2 +-
export_control.html | 2 +-
index.html | 2 +-
issue-management.html | 2 +-
licenses.html | 2 +-
mailing-lists.html | 2 +-
metrics.html | 2 +-
old_news.html | 2 +-
plugin-management.html | 2 +-
plugins.html | 2 +-
poweredbyhbase.html | 2 +-
project-info.html | 2 +-
project-reports.html | 2 +-
pseudo-distributed.html | 2 +-
replication.html | 2 +-
resources.html | 2 +-
scm.html | 2 +-
sponsors.html | 2 +-
summary.html | 2 +-
supportingprojects.html | 2 +-
team.html | 2 +-
testdevapidocs/index-all.html | 8 +
.../TestHFileArchiving.ArchivingFunction.html | 4 +-
.../hadoop/hbase/backup/TestHFileArchiving.html | 170 ++-
.../TestHFileArchiving.ArchivingFunction.html | 9 +
.../org/apache/hadoop/hbase/package-tree.html | 10 +-
.../hadoop/hbase/procedure2/package-tree.html | 4 +-
.../hadoop/hbase/regionserver/package-tree.html | 4 +-
.../org/apache/hadoop/hbase/test/package-tree.html | 6 +-
.../org/apache/hadoop/hbase/wal/package-tree.html | 2 +-
.../TestHFileArchiving.ArchivingFunction.html | 1431 ++++++++++----------
.../hadoop/hbase/backup/TestHFileArchiving.html | 1431 ++++++++++----------
60 files changed, 5229 insertions(+), 4791 deletions(-)
diff --git a/acid-semantics.html b/acid-semantics.html
index 7a9655b..21dc087 100644
--- a/acid-semantics.html
+++ b/acid-semantics.html
@@ -455,7 +455,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/apache_hbase_reference_guide.pdf b/apache_hbase_reference_guide.pdf
index ed64c2b..072c5bd 100644
--- a/apache_hbase_reference_guide.pdf
+++ b/apache_hbase_reference_guide.pdf
@@ -5,8 +5,8 @@
/Author (Apache HBase Team)
/Creator (Asciidoctor PDF 1.5.3, based on Prawn 2.2.2)
/Producer (Apache HBase Team)
-/ModDate (D:20220328165934+00'00')
-/CreationDate (D:20220328171258+00'00')
+/ModDate (D:20220330143941+00'00')
+/CreationDate (D:20220330145318+00'00')
>>
endobj
2 0 obj
diff --git a/book.html b/book.html
index dc5e410..259dce5 100644
--- a/book.html
+++ b/book.html
@@ -46555,7 +46555,7 @@ org/apache/hadoop/hbase/security/access/AccessControlClient.revoke:(Lorg/apache/
<div id="footer">
<div id="footer-text">
Version 3.0.0-alpha-3-SNAPSHOT<br>
-Last updated 2022-03-28 16:59:34 UTC
+Last updated 2022-03-30 14:39:41 UTC
</div>
</div>
<link rel="stylesheet" href="./coderay-asciidoctor.css">
diff --git a/bulk-loads.html b/bulk-loads.html
index 38e34c9..28cae8a 100644
--- a/bulk-loads.html
+++ b/bulk-loads.html
@@ -160,7 +160,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/checkstyle-aggregate.html b/checkstyle-aggregate.html
index cf7351f..99c1185 100644
--- a/checkstyle-aggregate.html
+++ b/checkstyle-aggregate.html
@@ -7307,7 +7307,7 @@
<tr class="a">
<td>annotation</td>
<td><a class="externalLink" href="http://checkstyle.sourceforge.net/config_annotation.html#MissingDeprecated">MissingDeprecated</a></td>
-<td>9</td>
+<td>6</td>
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td></tr>
<tr class="b">
<td>blocks</td>
@@ -7411,7 +7411,7 @@
<tr class="b">
<td></td>
<td><a class="externalLink" href="http://checkstyle.sourceforge.net/config_javadoc.html#NonEmptyAtclauseDescription">NonEmptyAtclauseDescription</a></td>
-<td>2046</td>
+<td>2049</td>
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td></tr>
<tr class="a">
<td>misc</td>
@@ -12606,31 +12606,31 @@
<td>javadoc</td>
<td>NonEmptyAtclauseDescription</td>
<td>At-clause should have a non-empty description.</td>
-<td>666</td></tr>
+<td>697</td></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>javadoc</td>
<td>NonEmptyAtclauseDescription</td>
<td>At-clause should have a non-empty description.</td>
-<td>672</td></tr>
+<td>703</td></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>javadoc</td>
<td>NonEmptyAtclauseDescription</td>
<td>At-clause should have a non-empty description.</td>
-<td>689</td></tr>
+<td>720</td></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>javadoc</td>
<td>NonEmptyAtclauseDescription</td>
<td>At-clause should have a non-empty description.</td>
-<td>691</td></tr>
+<td>722</td></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
<td>blocks</td>
<td>NeedBraces</td>
<td>'if' construct must use '{}'s.</td>
-<td>727</td></tr></table></div>
+<td>758</td></tr></table></div>
<div class="section">
<h3 id="org.apache.hadoop.hbase.backup.regionserver.LogRollBackupSubprocedurePool.java">org/apache/hadoop/hbase/backup/regionserver/LogRollBackupSubprocedurePool.java</h3>
<table border="0" class="table table-striped">
@@ -34875,8 +34875,8 @@
<th>Line</th></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
-<td>annotation</td>
-<td>MissingDeprecated</td>
+<td>javadoc</td>
+<td>NonEmptyAtclauseDescription</td>
<td>Javadoc comment at column 14 has parse error. Details: mismatched input ':' expecting <EOF> while parsing JAVADOC</td>
<td>46</td></tr></table></div>
<div class="section">
@@ -49392,8 +49392,8 @@
<th>Line</th></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
-<td>annotation</td>
-<td>MissingDeprecated</td>
+<td>javadoc</td>
+<td>NonEmptyAtclauseDescription</td>
<td>Javadoc comment at column 54 has parse error. Details: no viable alternative at input '(' while parsing JAVADOC_INLINE_TAG</td>
<td>59</td></tr>
<tr class="a">
@@ -68973,8 +68973,8 @@
<td>598</td></tr>
<tr class="b">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
-<td>annotation</td>
-<td>MissingDeprecated</td>
+<td>javadoc</td>
+<td>NonEmptyAtclauseDescription</td>
<td>Javadoc comment at column 0 has parse error. Details: mismatched input ' *' expecting JAVADOC_INLINE_TAG_END while parsing JAVADOC_INLINE_TAG</td>
<td>747</td></tr>
<tr class="a">
@@ -71799,7 +71799,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/coc.html b/coc.html
index 4e15cfb..04eb3bf 100644
--- a/coc.html
+++ b/coc.html
@@ -229,7 +229,7 @@ email to <a class="externalLink" href="mailto:private@hbase.apache.org">the priv
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/dependencies.html b/dependencies.html
index 6ed678c..8f5b8b5 100644
--- a/dependencies.html
+++ b/dependencies.html
@@ -301,7 +301,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/dependency-convergence.html b/dependency-convergence.html
index 396b035..7b4239e 100644
--- a/dependency-convergence.html
+++ b/dependency-convergence.html
@@ -961,7 +961,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/dependency-info.html b/dependency-info.html
index 76dcad2..65cf187 100644
--- a/dependency-info.html
+++ b/dependency-info.html
@@ -182,7 +182,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/dependency-management.html b/dependency-management.html
index ed1e292..58ea8f2 100644
--- a/dependency-management.html
+++ b/dependency-management.html
@@ -1254,7 +1254,7 @@
<tr class="a">
<td>org.bouncycastle</td>
<td><a class="externalLink" href="http://www.bouncycastle.org/java.html">bcprov-jdk15on</a></td>
-<td>1.60</td>
+<td>1.67</td>
<td>-</td>
<td>jar</td>
<td><a class="externalLink" href="http://www.bouncycastle.org/licence.html">Bouncy Castle Licence</a></td></tr>
@@ -1273,7 +1273,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.File.html b/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.File.html
index 666b764..dce43c9 100644
--- a/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.File.html
+++ b/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.File.html
@@ -117,7 +117,7 @@ var activeTableTab = "activeTableTab";
</dl>
<hr>
<br>
-<pre>private abstract static class <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html#line.643">HFileArchiver.File</a>
+<pre>private abstract static class <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html#line.674">HFileArchiver.File</a>
extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a></pre>
<div class="block">Wrapper to handle file operations uniformly</div>
</li>
@@ -246,7 +246,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>fs</h4>
-<pre>protected final org.apache.hadoop.fs.FileSystem <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.644">fs</a></pre>
+<pre>protected final org.apache.hadoop.fs.FileSystem <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.675">fs</a></pre>
</li>
</ul>
</li>
@@ -263,7 +263,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>File</h4>
-<pre>public <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.646">File</a>(org.apache.hadoop.fs.FileSystem fs)</pre>
+<pre>public <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.677">File</a>(org.apache.hadoop.fs.FileSystem fs)</pre>
</li>
</ul>
</li>
@@ -280,7 +280,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>delete</h4>
-<pre>abstract void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.654">delete</a>()
+<pre>abstract void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.685">delete</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<div class="block">Delete the file</div>
<dl>
@@ -295,7 +295,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>isFile</h4>
-<pre>abstract boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.661">isFile</a>()
+<pre>abstract boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.692">isFile</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<div class="block">Check to see if this is a file or a directory</div>
<dl>
@@ -312,7 +312,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getChildren</h4>
-<pre>abstract <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html?is-external=true" title="class or interface in java.util">Collection</a><<a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a>> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.668">getChildren</a>()
+<pre>abstract <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html?is-external=true" title="class or interface in java.util">Collection</a><<a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a>> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.699">getChildren</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<dl>
<dt><span class="returnLabel">Returns:</span></dt>
@@ -329,7 +329,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>close</h4>
-<pre>abstract void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.674">close</a>()
+<pre>abstract void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.705">close</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<div class="block">close any outside readers of the file</div>
<dl>
@@ -344,7 +344,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getName</h4>
-<pre>abstract <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.680">getName</a>()</pre>
+<pre>abstract <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.711">getName</a>()</pre>
<dl>
<dt><span class="returnLabel">Returns:</span></dt>
<dd>the name of the file (not the full fs path, just the individual
@@ -358,7 +358,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getPath</h4>
-<pre>abstract org.apache.hadoop.fs.Path <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.685">getPath</a>()</pre>
+<pre>abstract org.apache.hadoop.fs.Path <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.716">getPath</a>()</pre>
<dl>
<dt><span class="returnLabel">Returns:</span></dt>
<dd>the path to this file</dd>
@@ -371,7 +371,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>moveAndClose</h4>
-<pre>public boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.693">moveAndClose</a>(org.apache.hadoop.fs.Path dest)
+<pre>public boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.724">moveAndClose</a>(org.apache.hadoop.fs.Path dest)
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<div class="block">Move the file to the given destination</div>
<dl>
@@ -390,7 +390,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getFileSystem</h4>
-<pre>public org.apache.hadoop.fs.FileSystem <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.702">getFileSystem</a>()</pre>
+<pre>public org.apache.hadoop.fs.FileSystem <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.733">getFileSystem</a>()</pre>
<dl>
<dt><span class="returnLabel">Returns:</span></dt>
<dd>the <code>FileSystem</code> on which this file resides</dd>
@@ -403,7 +403,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>toString</h4>
-<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.707">toString</a>()</pre>
+<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html#line.738">toString</a>()</pre>
<dl>
<dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true#toString--" title="class or interface in java.lang">toString</a></code> in class <code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a></code></dd>
diff --git a/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.FileConverter.html b/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.FileConverter.html
index d9294e1..2fe01fa 100644
--- a/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.FileConverter.html
+++ b/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.FileConverter.html
@@ -119,7 +119,7 @@
</dl>
<hr>
<br>
-<pre>private abstract static class <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html#line.603">HFileArchiver.FileConverter</a><T>
+<pre>private abstract static class <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html#line.634">HFileArchiver.FileConverter</a><T>
extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a>
implements <a href="https://docs.oracle.com/javase/8/docs/api/java/util/function/Function.html?is-external=true" title="class or interface in java.util.function">Function</a><T,<a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a>></pre>
<div class="block">Adapt a type to match the <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup"><code>HFileArchiver.File</code></a> interface, which is used internally for handling
@@ -206,7 +206,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/util/function
<ul class="blockListLast">
<li class="blockList">
<h4>fs</h4>
-<pre>protected final org.apache.hadoop.fs.FileSystem <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileConverter.html#line.604">fs</a></pre>
+<pre>protected final org.apache.hadoop.fs.FileSystem <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileConverter.html#line.635">fs</a></pre>
</li>
</ul>
</li>
@@ -223,7 +223,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/util/function
<ul class="blockListLast">
<li class="blockList">
<h4>FileConverter</h4>
-<pre>public <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileConverter.html#line.606">FileConverter</a>(org.apache.hadoop.fs.FileSystem fs)</pre>
+<pre>public <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileConverter.html#line.637">FileConverter</a>(org.apache.hadoop.fs.FileSystem fs)</pre>
</li>
</ul>
</li>
diff --git a/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.FileStatusConverter.html b/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.FileStatusConverter.html
index 9e03b4f..8c85c64 100644
--- a/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.FileStatusConverter.html
+++ b/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.FileStatusConverter.html
@@ -122,7 +122,7 @@ var activeTableTab = "activeTableTab";
</dl>
<hr>
<br>
-<pre>private static class <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html#line.614">HFileArchiver.FileStatusConverter</a>
+<pre>private static class <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html#line.645">HFileArchiver.FileStatusConverter</a>
extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.FileConverter.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.FileConverter</a><org.apache.hadoop.fs.FileStatus></pre>
<div class="block">Convert a FileStatus to something we can manage in the archiving</div>
</li>
@@ -214,7 +214,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockListLast">
<li class="blockList">
<h4>FileStatusConverter</h4>
-<pre>public <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileStatusConverter.html#line.615">FileStatusConverter</a>(org.apache.hadoop.fs.FileSystem fs)</pre>
+<pre>public <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileStatusConverter.html#line.646">FileStatusConverter</a>(org.apache.hadoop.fs.FileSystem fs)</pre>
</li>
</ul>
</li>
@@ -231,7 +231,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockListLast">
<li class="blockList">
<h4>apply</h4>
-<pre>public <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileStatusConverter.html#line.620">apply</a>(org.apache.hadoop.fs.FileStatus input)</pre>
+<pre>public <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileStatusConverter.html#line.651">apply</a>(org.apache.hadoop.fs.FileStatus input)</pre>
</li>
</ul>
</li>
diff --git a/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html b/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html
index c033314..0b4ca27 100644
--- a/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html
+++ b/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html
@@ -118,7 +118,7 @@ var activeTableTab = "activeTableTab";
</dl>
<hr>
<br>
-<pre>private static class <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html#line.715">HFileArchiver.FileablePath</a>
+<pre>private static class <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html#line.746">HFileArchiver.FileablePath</a>
extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a></pre>
<div class="block">A <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup"><code>HFileArchiver.File</code></a> that wraps a simple <code>Path</code> on a <code>FileSystem</code>.</div>
</li>
@@ -252,7 +252,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockList">
<li class="blockList">
<h4>file</h4>
-<pre>private final org.apache.hadoop.fs.Path <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.716">file</a></pre>
+<pre>private final org.apache.hadoop.fs.Path <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.747">file</a></pre>
</li>
</ul>
<a name="getAsFile">
@@ -261,7 +261,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockListLast">
<li class="blockList">
<h4>getAsFile</h4>
-<pre>private final <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.FileStatusConverter.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.FileStatusConverter</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.717">getAsFile</a></pre>
+<pre>private final <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.FileStatusConverter.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.FileStatusConverter</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.748">getAsFile</a></pre>
</li>
</ul>
</li>
@@ -278,7 +278,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockListLast">
<li class="blockList">
<h4>FileablePath</h4>
-<pre>public <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.719">FileablePath</a>(org.apache.hadoop.fs.FileSystem fs,
+<pre>public <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.750">FileablePath</a>(org.apache.hadoop.fs.FileSystem fs,
org.apache.hadoop.fs.Path file)</pre>
</li>
</ul>
@@ -296,7 +296,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockList">
<li class="blockList">
<h4>delete</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.726">delete</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.757">delete</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<div class="block"><span class="descfrmTypeLabel">Description copied from class: <code><a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html#delete--">HFileArchiver.File</a></code></span></div>
<div class="block">Delete the file</div>
@@ -314,7 +314,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockList">
<li class="blockList">
<h4>getName</h4>
-<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.731">getName</a>()</pre>
+<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.762">getName</a>()</pre>
<dl>
<dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
<dd><code><a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html#getName--">getName</a></code> in class <code><a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a></code></dd>
@@ -330,7 +330,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockList">
<li class="blockList">
<h4>getChildren</h4>
-<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html?is-external=true" title="class or interface in java.util">Collection</a><<a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a>> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.736">getChildren</a>()
+<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html?is-external=true" title="class or interface in java.util">Collection</a><<a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a>> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.767">getChildren</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<dl>
<dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
@@ -349,7 +349,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockList">
<li class="blockList">
<h4>isFile</h4>
-<pre>public boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.744">isFile</a>()
+<pre>public boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.775">isFile</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<div class="block"><span class="descfrmTypeLabel">Description copied from class: <code><a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html#isFile--">HFileArchiver.File</a></code></span></div>
<div class="block">Check to see if this is a file or a directory</div>
@@ -369,7 +369,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockList">
<li class="blockList">
<h4>close</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.749">close</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.780">close</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<div class="block"><span class="descfrmTypeLabel">Description copied from class: <code><a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html#close--">HFileArchiver.File</a></code></span></div>
<div class="block">close any outside readers of the file</div>
@@ -387,7 +387,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockListLast">
<li class="blockList">
<h4>getPath</h4>
-<pre>org.apache.hadoop.fs.Path <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.754">getPath</a>()</pre>
+<pre>org.apache.hadoop.fs.Path <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html#line.785">getPath</a>()</pre>
<dl>
<dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
<dd><code><a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html#getPath--">getPath</a></code> in class <code><a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a></code></dd>
diff --git a/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html b/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html
index 916a83a..5d42afc 100644
--- a/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html
+++ b/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html
@@ -118,7 +118,7 @@ var activeTableTab = "activeTableTab";
</dl>
<hr>
<br>
-<pre>private static class <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html#line.763">HFileArchiver.FileableStoreFile</a>
+<pre>private static class <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html#line.794">HFileArchiver.FileableStoreFile</a>
extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a></pre>
<div class="block"><a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup"><code>HFileArchiver.File</code></a> adapter for a <a href="../../../../../org/apache/hadoop/hbase/regionserver/HStoreFile.html" title="class in org.apache.hadoop.hbase.regionserver"><code>HStoreFile</code></a> living on a <code>FileSystem</code>
.</div>
@@ -249,7 +249,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockListLast">
<li class="blockList">
<h4>file</h4>
-<pre><a href="../../../../../org/apache/hadoop/hbase/regionserver/HStoreFile.html" title="class in org.apache.hadoop.hbase.regionserver">HStoreFile</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html#line.764">file</a></pre>
+<pre><a href="../../../../../org/apache/hadoop/hbase/regionserver/HStoreFile.html" title="class in org.apache.hadoop.hbase.regionserver">HStoreFile</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html#line.795">file</a></pre>
</li>
</ul>
</li>
@@ -266,7 +266,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockListLast">
<li class="blockList">
<h4>FileableStoreFile</h4>
-<pre>public <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html#line.766">FileableStoreFile</a>(org.apache.hadoop.fs.FileSystem fs,
+<pre>public <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html#line.797">FileableStoreFile</a>(org.apache.hadoop.fs.FileSystem fs,
<a href="../../../../../org/apache/hadoop/hbase/regionserver/HStoreFile.html" title="class in org.apache.hadoop.hbase.regionserver">HStoreFile</a> store)</pre>
</li>
</ul>
@@ -284,7 +284,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockList">
<li class="blockList">
<h4>delete</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html#line.772">delete</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html#line.803">delete</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<div class="block"><span class="descfrmTypeLabel">Description copied from class: <code><a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html#delete--">HFileArchiver.File</a></code></span></div>
<div class="block">Delete the file</div>
@@ -302,7 +302,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockList">
<li class="blockList">
<h4>getName</h4>
-<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html#line.777">getName</a>()</pre>
+<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html#line.808">getName</a>()</pre>
<dl>
<dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
<dd><code><a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html#getName--">getName</a></code> in class <code><a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a></code></dd>
@@ -318,7 +318,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockList">
<li class="blockList">
<h4>isFile</h4>
-<pre>public boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html#line.782">isFile</a>()</pre>
+<pre>public boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html#line.813">isFile</a>()</pre>
<div class="block"><span class="descfrmTypeLabel">Description copied from class: <code><a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html#isFile--">HFileArchiver.File</a></code></span></div>
<div class="block">Check to see if this is a file or a directory</div>
<dl>
@@ -335,7 +335,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockList">
<li class="blockList">
<h4>getChildren</h4>
-<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html?is-external=true" title="class or interface in java.util">Collection</a><<a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a>> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html#line.787">getChildren</a>()
+<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html?is-external=true" title="class or interface in java.util">Collection</a><<a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a>> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html#line.818">getChildren</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<dl>
<dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
@@ -354,7 +354,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockList">
<li class="blockList">
<h4>close</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html#line.793">close</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html#line.824">close</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<div class="block"><span class="descfrmTypeLabel">Description copied from class: <code><a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html#close--">HFileArchiver.File</a></code></span></div>
<div class="block">close any outside readers of the file</div>
@@ -372,7 +372,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockListLast">
<li class="blockList">
<h4>getPath</h4>
-<pre>org.apache.hadoop.fs.Path <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html#line.798">getPath</a>()</pre>
+<pre>org.apache.hadoop.fs.Path <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html#line.829">getPath</a>()</pre>
<dl>
<dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
<dd><code><a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html#getPath--">getPath</a></code> in class <code><a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a></code></dd>
diff --git a/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.StoreToFile.html b/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.StoreToFile.html
index e5b5b40..955331a 100644
--- a/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.StoreToFile.html
+++ b/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.StoreToFile.html
@@ -122,7 +122,7 @@ var activeTableTab = "activeTableTab";
</dl>
<hr>
<br>
-<pre>private static class <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html#line.629">HFileArchiver.StoreToFile</a>
+<pre>private static class <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html#line.660">HFileArchiver.StoreToFile</a>
extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.FileConverter.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.FileConverter</a><<a href="../../../../../org/apache/hadoop/hbase/regionserver/HStoreFile.html" title="class in org.apache.hadoop.hbase.regionserver">HStoreFile</a>></pre>
<div class="block">Convert the <a href="../../../../../org/apache/hadoop/hbase/regionserver/HStoreFile.html" title="class in org.apache.hadoop.hbase.regionserver"><code>HStoreFile</code></a> into something we can manage in the archive
methods</div>
@@ -215,7 +215,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockListLast">
<li class="blockList">
<h4>StoreToFile</h4>
-<pre>public <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.StoreToFile.html#line.630">StoreToFile</a>(org.apache.hadoop.fs.FileSystem fs)</pre>
+<pre>public <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.StoreToFile.html#line.661">StoreToFile</a>(org.apache.hadoop.fs.FileSystem fs)</pre>
</li>
</ul>
</li>
@@ -232,7 +232,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.Fil
<ul class="blockListLast">
<li class="blockList">
<h4>apply</h4>
-<pre>public <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.StoreToFile.html#line.635">apply</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/HStoreFile.html" title="class in org.apache.hadoop.hbase.regionserver">HStoreFile</a> input)</pre>
+<pre>public <a href="../../../../../org/apache/hadoop/hbase/backup/HFileArchiver.File.html" title="class in org.apache.hadoop.hbase.backup">HFileArchiver.File</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.StoreToFile.html#line.666">apply</a>(<a href="../../../../../org/apache/hadoop/hbase/regionserver/HStoreFile.html" title="class in org.apache.hadoop.hbase.regionserver">HStoreFile</a> input)</pre>
</li>
</ul>
</li>
diff --git a/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.html b/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.html
index 33232a7..0679512 100644
--- a/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.html
+++ b/devapidocs/org/apache/hadoop/hbase/backup/HFileArchiver.html
@@ -807,7 +807,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>deleteRegionWithoutArchiving</h4>
-<pre>private static boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html#line.562">deleteRegionWithoutArchiving</a>(org.apache.hadoop.fs.FileSystem fs,
+<pre>private static boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html#line.593">deleteRegionWithoutArchiving</a>(org.apache.hadoop.fs.FileSystem fs,
org.apache.hadoop.fs.Path regionDir)
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<div class="block">Without regard for backup, delete a region. Should be used with caution.</div>
@@ -828,7 +828,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>deleteStoreFilesWithoutArchiving</h4>
-<pre>private static void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html#line.581">deleteStoreFilesWithoutArchiving</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html?is-external=true" title="class or interface in java.util">Collection</a><<a href="../../../../../org/apache/hadoop/hbase/regionserver/HStoreFile.html" title="class in org.apache.hadoop.hbase.regionserver">HStoreFile</a>> compactedFiles)
+<pre>private static void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html#line.612">deleteStoreFilesWithoutArchiving</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html?is-external=true" title="class or interface in java.util">Collection</a><<a href="../../../../../org/apache/hadoop/hbase/regionserver/HStoreFile.html" title="class in org.apache.hadoop.hbase.regionserver">HStoreFile</a>> compactedFiles)
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<div class="block">Just do a simple delete of the given store files
<p>
diff --git a/devapidocs/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html b/devapidocs/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html
index 32af20f..5e66e87 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html
@@ -122,7 +122,7 @@ var activeTableTab = "activeTableTab";
</dl>
<hr>
<br>
-<pre>public static enum <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.557">TransitRegionStateProcedure.TransitionType</a>
+<pre>public static enum <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.559">TransitRegionStateProcedure.TransitionType</a>
extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang">Enum</a><<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a>></pre>
</li>
</ul>
@@ -216,7 +216,7 @@ the order they are declared.</div>
<ul class="blockList">
<li class="blockList">
<h4>ASSIGN</h4>
-<pre>public static final <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html#line.558">ASSIGN</a></pre>
+<pre>public static final <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html#line.560">ASSIGN</a></pre>
</li>
</ul>
<a name="UNASSIGN">
@@ -225,7 +225,7 @@ the order they are declared.</div>
<ul class="blockList">
<li class="blockList">
<h4>UNASSIGN</h4>
-<pre>public static final <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html#line.558">UNASSIGN</a></pre>
+<pre>public static final <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html#line.560">UNASSIGN</a></pre>
</li>
</ul>
<a name="MOVE">
@@ -234,7 +234,7 @@ the order they are declared.</div>
<ul class="blockList">
<li class="blockList">
<h4>MOVE</h4>
-<pre>public static final <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html#line.558">MOVE</a></pre>
+<pre>public static final <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html#line.560">MOVE</a></pre>
</li>
</ul>
<a name="REOPEN">
@@ -243,7 +243,7 @@ the order they are declared.</div>
<ul class="blockListLast">
<li class="blockList">
<h4>REOPEN</h4>
-<pre>public static final <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html#line.558">REOPEN</a></pre>
+<pre>public static final <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html#line.560">REOPEN</a></pre>
</li>
</ul>
</li>
@@ -260,7 +260,7 @@ the order they are declared.</div>
<ul class="blockList">
<li class="blockList">
<h4>values</h4>
-<pre>public static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a>[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html#line.590">values</a>()</pre>
+<pre>public static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a>[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html#line.592">values</a>()</pre>
<div class="block">Returns an array containing the constants of this enum type, in
the order they are declared. This method may be used to iterate
over the constants as follows:
@@ -280,7 +280,7 @@ for (TransitRegionStateProcedure.TransitionType c : TransitRegionStateProcedure.
<ul class="blockListLast">
<li class="blockList">
<h4>valueOf</h4>
-<pre>public static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html#line.590">valueOf</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" t [...]
+<pre>public static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html#line.592">valueOf</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" t [...]
<div class="block">Returns the enum constant of this type with the specified name.
The string must match <i>exactly</i> an identifier used to declare an
enum constant in this type. (Extraneous whitespace characters are
diff --git a/devapidocs/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html b/devapidocs/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html
index 4a760c2..b90fc1f 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html
@@ -134,7 +134,7 @@ var activeTableTab = "activeTableTab";
<hr>
<br>
<pre>@InterfaceAudience.Private
-public class <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.101">TransitRegionStateProcedure</a>
+public class <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.103">TransitRegionStateProcedure</a>
extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/AbstractStateMachineRegionProcedure.html" title="class in org.apache.hadoop.hbase.master.procedure">AbstractStateMachineRegionProcedure</a><org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState></pre>
<div class="block">The procedure to deal with the state transition of a region. A region with a TRSP in place is
called RIT, i.e, RegionInTransition.
@@ -582,7 +582,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>LOG</h4>
-<pre>private static final org.slf4j.Logger <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.104">LOG</a></pre>
+<pre>private static final org.slf4j.Logger <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.106">LOG</a></pre>
</li>
</ul>
<a name="type">
@@ -591,7 +591,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>type</h4>
-<pre>private <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.106">type</a></pre>
+<pre>private <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.108">type</a></pre>
</li>
</ul>
<a name="initialState">
@@ -600,7 +600,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>initialState</h4>
-<pre>private org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.108">initialState</a></pre>
+<pre>private org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.110">initialState</a></pre>
</li>
</ul>
<a name="lastState">
@@ -609,7 +609,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>lastState</h4>
-<pre>private org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.110">lastState</a></pre>
+<pre>private org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.112">lastState</a></pre>
</li>
</ul>
<a name="assignCandidate">
@@ -618,7 +618,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>assignCandidate</h4>
-<pre>private <a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.113">assignCandidate</a></pre>
+<pre>private <a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.115">assignCandidate</a></pre>
</li>
</ul>
<a name="forceNewPlan">
@@ -627,7 +627,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>forceNewPlan</h4>
-<pre>private boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.115">forceNewPlan</a></pre>
+<pre>private boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.117">forceNewPlan</a></pre>
</li>
</ul>
<a name="retryCounter">
@@ -636,7 +636,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>retryCounter</h4>
-<pre>private <a href="../../../../../../org/apache/hadoop/hbase/util/RetryCounter.html" title="class in org.apache.hadoop.hbase.util">RetryCounter</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.117">retryCounter</a></pre>
+<pre>private <a href="../../../../../../org/apache/hadoop/hbase/util/RetryCounter.html" title="class in org.apache.hadoop.hbase.util">RetryCounter</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.119">retryCounter</a></pre>
</li>
</ul>
<a name="remoteProc">
@@ -645,7 +645,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockListLast">
<li class="blockList">
<h4>remoteProc</h4>
-<pre>private <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionRemoteProcedureBase.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionRemoteProcedureBase</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.119">remoteProc</a></pre>
+<pre>private <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionRemoteProcedureBase.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionRemoteProcedureBase</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.121">remoteProc</a></pre>
</li>
</ul>
</li>
@@ -662,7 +662,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>TransitRegionStateProcedure</h4>
-<pre>public <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.121">TransitRegionStateProcedure</a>()</pre>
+<pre>public <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.123">TransitRegionStateProcedure</a>()</pre>
</li>
</ul>
<a name="TransitRegionStateProcedure-org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv-org.apache.hadoop.hbase.client.RegionInfo-org.apache.hadoop.hbase.ServerName-boolean-org.apache.hadoop.hbase.master.assignment.TransitRegionStateProcedure.TransitionType-">
@@ -671,7 +671,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockListLast">
<li class="blockList">
<h4>TransitRegionStateProcedure</h4>
-<pre>protected <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.144">TransitRegionStateProcedure</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env,
+<pre>protected <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.146">TransitRegionStateProcedure</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env,
<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> hri,
<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> assignCandidate,
boolean forceNewPlan,
@@ -692,7 +692,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>setInitialAndLastState</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.124">setInitialAndLastState</a>()</pre>
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.126">setInitialAndLastState</a>()</pre>
</li>
</ul>
<a name="getTableOperationType--">
@@ -701,7 +701,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>getTableOperationType</h4>
-<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/TableProcedureInterface.TableOperationType.html" title="enum in org.apache.hadoop.hbase.master.procedure">TableProcedureInterface.TableOperationType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.159">getTableOperationType</a>()</pre>
+<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/TableProcedureInterface.TableOperationType.html" title="enum in org.apache.hadoop.hbase.master.procedure">TableProcedureInterface.TableOperationType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.161">getTableOperationType</a>()</pre>
<div class="block"><span class="descfrmTypeLabel">Description copied from interface: <code><a href="../../../../../../org/apache/hadoop/hbase/master/procedure/TableProcedureInterface.html#getTableOperationType--">TableProcedureInterface</a></code></span></div>
<div class="block">Given an operation type we can take decisions about what to do with pending operations.
e.g. if we get a delete and we have some table operation pending (e.g. add column)
@@ -722,7 +722,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>waitInitialized</h4>
-<pre>protected boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.165">waitInitialized</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env)</pre>
+<pre>protected boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.167">waitInitialized</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env)</pre>
<div class="block"><span class="descfrmTypeLabel">Description copied from class: <code><a href="../../../../../../org/apache/hadoop/hbase/procedure2/Procedure.html#waitInitialized-TEnvironment-">Procedure</a></code></span></div>
<div class="block">The <a href="../../../../../../org/apache/hadoop/hbase/procedure2/Procedure.html#doAcquireLock-TEnvironment-org.apache.hadoop.hbase.procedure2.store.ProcedureStore-"><code>Procedure.doAcquireLock(Object, ProcedureStore)</code></a> will be split into two steps, first, it will
call us to determine whether we need to wait for initialization, second, it will call
@@ -747,7 +747,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>queueAssign</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.175">queueAssign</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env,
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.177">queueAssign</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env,
<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode)
throws <a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureSuspendedException.html" title="class in org.apache.hadoop.hbase.procedure2">ProcedureSuspendedException</a></pre>
<dl>
@@ -762,7 +762,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>openRegion</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.200">openRegion</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env,
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.202">openRegion</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env,
<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode)
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<dl>
@@ -777,7 +777,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>confirmOpened</h4>
-<pre>private <a href="../../../../../../org/apache/hadoop/hbase/procedure2/StateMachineProcedure.Flow.html" title="enum in org.apache.hadoop.hbase.procedure2">StateMachineProcedure.Flow</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.213">confirmOpened</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">Ma [...]
+<pre>private <a href="../../../../../../org/apache/hadoop/hbase/procedure2/StateMachineProcedure.Flow.html" title="enum in org.apache.hadoop.hbase.procedure2">StateMachineProcedure.Flow</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.215">confirmOpened</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">Ma [...]
<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode)
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<dl>
@@ -792,7 +792,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>closeRegion</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.261">closeRegion</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env,
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.263">closeRegion</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env,
<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode)
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<dl>
@@ -807,7 +807,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>confirmClosed</h4>
-<pre>private <a href="../../../../../../org/apache/hadoop/hbase/procedure2/StateMachineProcedure.Flow.html" title="enum in org.apache.hadoop.hbase.procedure2">StateMachineProcedure.Flow</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.275">confirmClosed</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">Ma [...]
+<pre>private <a href="../../../../../../org/apache/hadoop/hbase/procedure2/StateMachineProcedure.Flow.html" title="enum in org.apache.hadoop.hbase.procedure2">StateMachineProcedure.Flow</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.277">confirmClosed</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">Ma [...]
<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode)
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<dl>
@@ -822,7 +822,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>execute</h4>
-<pre>protected <a href="../../../../../../org/apache/hadoop/hbase/procedure2/Procedure.html" title="class in org.apache.hadoop.hbase.procedure2">Procedure</a>[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.315">execute</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env)
+<pre>protected <a href="../../../../../../org/apache/hadoop/hbase/procedure2/Procedure.html" title="class in org.apache.hadoop.hbase.procedure2">Procedure</a>[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.317">execute</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env)
throws <a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureSuspendedException.html" title="class in org.apache.hadoop.hbase.procedure2">ProcedureSuspendedException</a>,
<a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureYieldException.html" title="class in org.apache.hadoop.hbase.procedure2">ProcedureYieldException</a>,
<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InterruptedException.html?is-external=true" title="class or interface in java.lang">InterruptedException</a></pre>
@@ -853,7 +853,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>getRegionStateNode</h4>
-<pre>private <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.327">getRegionStateNode</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">Mast [...]
+<pre>private <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.329">getRegionStateNode</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">Mast [...]
</li>
</ul>
<a name="executeFromState-org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv-org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState-">
@@ -862,7 +862,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>executeFromState</h4>
-<pre>protected <a href="../../../../../../org/apache/hadoop/hbase/procedure2/StateMachineProcedure.Flow.html" title="enum in org.apache.hadoop.hbase.procedure2">StateMachineProcedure.Flow</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.332">executeFromState</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedur [...]
+<pre>protected <a href="../../../../../../org/apache/hadoop/hbase/procedure2/StateMachineProcedure.Flow.html" title="enum in org.apache.hadoop.hbase.procedure2">StateMachineProcedure.Flow</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.334">executeFromState</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedur [...]
org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState state)
throws <a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureSuspendedException.html" title="class in org.apache.hadoop.hbase.procedure2">ProcedureSuspendedException</a>,
<a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureYieldException.html" title="class in org.apache.hadoop.hbase.procedure2">ProcedureYieldException</a>,
@@ -889,7 +889,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>setTimeoutFailure</h4>
-<pre>protected boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.387">setTimeoutFailure</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env)</pre>
+<pre>protected boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.389">setTimeoutFailure</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env)</pre>
<div class="block">At end of timeout, wake ourselves up so we run again.</div>
<dl>
<dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
@@ -906,7 +906,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>reportTransition</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.394">reportTransition</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env,
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.396">reportTransition</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env,
<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode,
<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName,
org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionStateTransition.TransitionCode code,
@@ -925,7 +925,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>serverCrashed</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.416">serverCrashed</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env,
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.418">serverCrashed</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env,
<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode,
<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName,
boolean forceNewPlan)
@@ -942,7 +942,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>attachRemoteProc</h4>
-<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.428">attachRemoteProc</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionRemoteProcedureBase.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionRemoteProcedureBase</a> proc)</pre>
+<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.430">attachRemoteProc</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionRemoteProcedureBase.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionRemoteProcedureBase</a> proc)</pre>
</li>
</ul>
<a name="unattachRemoteProc-org.apache.hadoop.hbase.master.assignment.RegionRemoteProcedureBase-">
@@ -951,7 +951,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>unattachRemoteProc</h4>
-<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.432">unattachRemoteProc</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionRemoteProcedureBase.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionRemoteProcedureBase</a> proc)</pre>
+<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.434">unattachRemoteProc</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionRemoteProcedureBase.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionRemoteProcedureBase</a> proc)</pre>
</li>
</ul>
<a name="stateLoaded-org.apache.hadoop.hbase.master.assignment.AssignmentManager-org.apache.hadoop.hbase.master.assignment.RegionStateNode-">
@@ -960,7 +960,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>stateLoaded</h4>
-<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.440">stateLoaded</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/AssignmentManager.html" title="class in org.apache.hadoop.hbase.master.assignment">AssignmentManager</a> am,
+<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.442">stateLoaded</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/AssignmentManager.html" title="class in org.apache.hadoop.hbase.master.assignment">AssignmentManager</a> am,
<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode)</pre>
</li>
</ul>
@@ -970,7 +970,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>rollbackState</h4>
-<pre>protected void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.447">rollbackState</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env,
+<pre>protected void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.449">rollbackState</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env,
org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState state)
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a>,
<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InterruptedException.html?is-external=true" title="class or interface in java.lang">InterruptedException</a></pre>
@@ -992,7 +992,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>getState</h4>
-<pre>protected org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.454">getState</a>(int stateId)</pre>
+<pre>protected org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.456">getState</a>(int stateId)</pre>
<div class="block"><span class="descfrmTypeLabel">Description copied from class: <code><a href="../../../../../../org/apache/hadoop/hbase/procedure2/StateMachineProcedure.html#getState-int-">StateMachineProcedure</a></code></span></div>
<div class="block">Convert an ordinal (or state id) to an Enum (or more descriptive) state object.</div>
<dl>
@@ -1011,7 +1011,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>getStateId</h4>
-<pre>protected int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.459">getStateId</a>(org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState state)</pre>
+<pre>protected int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.461">getStateId</a>(org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState state)</pre>
<div class="block"><span class="descfrmTypeLabel">Description copied from class: <code><a href="../../../../../../org/apache/hadoop/hbase/procedure2/StateMachineProcedure.html#getStateId-TState-">StateMachineProcedure</a></code></span></div>
<div class="block">Convert the Enum (or more descriptive) state object to an ordinal (or state id).</div>
<dl>
@@ -1030,7 +1030,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>getInitialState</h4>
-<pre>protected org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.464">getInitialState</a>()</pre>
+<pre>protected org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.466">getInitialState</a>()</pre>
<div class="block"><span class="descfrmTypeLabel">Description copied from class: <code><a href="../../../../../../org/apache/hadoop/hbase/procedure2/StateMachineProcedure.html#getInitialState--">StateMachineProcedure</a></code></span></div>
<div class="block">Return the initial state object that will be used for the first call to executeFromState().</div>
<dl>
@@ -1047,7 +1047,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>convert</h4>
-<pre>private static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.468">convert</a>(org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionTransitionType type)</pre>
+<pre>private static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.470">convert</a>(org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionTransitionType type)</pre>
</li>
</ul>
<a name="convert-org.apache.hadoop.hbase.master.assignment.TransitRegionStateProcedure.TransitionType-">
@@ -1056,7 +1056,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>convert</h4>
-<pre>private static org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionTransitionType <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.483">convert</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a> type)</pre>
+<pre>private static org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionTransitionType <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.485">convert</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure.TransitionType</a> type)</pre>
</li>
</ul>
<a name="serializeStateData-org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer-">
@@ -1065,7 +1065,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>serializeStateData</h4>
-<pre>protected void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.499">serializeStateData</a>(<a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureStateSerializer.html" title="interface in org.apache.hadoop.hbase.procedure2">ProcedureStateSerializer</a> serializer)
+<pre>protected void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.501">serializeStateData</a>(<a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureStateSerializer.html" title="interface in org.apache.hadoop.hbase.procedure2">ProcedureStateSerializer</a> serializer)
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<div class="block"><span class="descfrmTypeLabel">Description copied from class: <code><a href="../../../../../../org/apache/hadoop/hbase/procedure2/Procedure.html#serializeStateData-org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer-">Procedure</a></code></span></div>
<div class="block">The user-level code of the procedure may have some state to
@@ -1087,7 +1087,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>deserializeStateData</h4>
-<pre>protected void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.510">deserializeStateData</a>(<a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureStateSerializer.html" title="interface in org.apache.hadoop.hbase.procedure2">ProcedureStateSerializer</a> serializer)
+<pre>protected void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.512">deserializeStateData</a>(<a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureStateSerializer.html" title="interface in org.apache.hadoop.hbase.procedure2">ProcedureStateSerializer</a> serializer)
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<div class="block"><span class="descfrmTypeLabel">Description copied from class: <code><a href="../../../../../../org/apache/hadoop/hbase/procedure2/Procedure.html#deserializeStateData-org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer-">Procedure</a></code></span></div>
<div class="block">Called on store load to allow the user to decode the previously serialized
@@ -1108,7 +1108,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>getProcedureMetrics</h4>
-<pre>protected <a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureMetrics.html" title="interface in org.apache.hadoop.hbase.procedure2">ProcedureMetrics</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.523">getProcedureMetrics</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterPro [...]
+<pre>protected <a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureMetrics.html" title="interface in org.apache.hadoop.hbase.procedure2">ProcedureMetrics</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.525">getProcedureMetrics</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterPro [...]
<div class="block"><span class="descfrmTypeLabel">Description copied from class: <code><a href="../../../../../../org/apache/hadoop/hbase/procedure2/Procedure.html#getProcedureMetrics-TEnvironment-">Procedure</a></code></span></div>
<div class="block">Override this method to provide procedure specific counters for submitted count, failed
count and time histogram.</div>
@@ -1128,7 +1128,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>toStringClassDetails</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.540">toStringClassDetails</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html?is-external=true" title="class or interface in java.lang">StringBuilder</a> sb)</pre>
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.542">toStringClassDetails</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/StringBuilder.html?is-external=true" title="class or interface in java.lang">StringBuilder</a> sb)</pre>
<div class="block"><span class="descfrmTypeLabel">Description copied from class: <code><a href="../../../../../../org/apache/hadoop/hbase/procedure2/Procedure.html#toStringClassDetails-java.lang.StringBuilder-">Procedure</a></code></span></div>
<div class="block">Extend the toString() information with the procedure details
e.g. className and parameters</div>
@@ -1146,7 +1146,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>setOwner</h4>
-<pre>private static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html" title="class in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.551">setOwner</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.m [...]
+<pre>private static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html" title="class in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.553">setOwner</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.m [...]
<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html" title="class in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure</a> proc)</pre>
</li>
</ul>
@@ -1156,7 +1156,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>assign</h4>
-<pre>public static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html" title="class in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.564">assign</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.mast [...]
+<pre>public static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html" title="class in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.566">assign</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.mast [...]
<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> region,
@Nullable
<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> targetServer)</pre>
@@ -1168,7 +1168,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>assign</h4>
-<pre>public static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html" title="class in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.569">assign</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.mast [...]
+<pre>public static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html" title="class in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.571">assign</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.mast [...]
<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> region,
boolean forceNewPlan,
@Nullable
@@ -1181,7 +1181,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>unassign</h4>
-<pre>public static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html" title="class in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.575">unassign</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.ma [...]
+<pre>public static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html" title="class in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.577">unassign</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.ma [...]
<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> region)</pre>
</li>
</ul>
@@ -1191,7 +1191,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockList">
<li class="blockList">
<h4>reopen</h4>
-<pre>public static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html" title="class in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.580">reopen</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.mast [...]
+<pre>public static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html" title="class in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.582">reopen</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.mast [...]
<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> region)</pre>
</li>
</ul>
@@ -1201,7 +1201,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/procedure/Abst
<ul class="blockListLast">
<li class="blockList">
<h4>move</h4>
-<pre>public static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html" title="class in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.585">move</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master [...]
+<pre>public static <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html" title="class in org.apache.hadoop.hbase.master.assignment">TransitRegionStateProcedure</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html#line.587">move</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master [...]
<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> region,
@Nullable
<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> targetServer)</pre>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html b/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html
index 22ea136..ee79f25 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.File.html
@@ -496,318 +496,349 @@
<span class="sourceLineNo">488</span> Path archiveFile = new Path(archiveDir, filename);<a name="line.488"></a>
<span class="sourceLineNo">489</span> FileSystem fs = currentFile.getFileSystem();<a name="line.489"></a>
<span class="sourceLineNo">490</span><a name="line.490"></a>
-<span class="sourceLineNo">491</span> // if the file already exists in the archive, move that one to a timestamped backup. This is a<a name="line.491"></a>
-<span class="sourceLineNo">492</span> // really, really unlikely situtation, where we get the same name for the existing file, but<a name="line.492"></a>
-<span class="sourceLineNo">493</span> // is included just for that 1 in trillion chance.<a name="line.493"></a>
-<span class="sourceLineNo">494</span> if (fs.exists(archiveFile)) {<a name="line.494"></a>
-<span class="sourceLineNo">495</span> LOG.debug("{} already exists in archive, moving to timestamped backup and " +<a name="line.495"></a>
-<span class="sourceLineNo">496</span> "overwriting current.", archiveFile);<a name="line.496"></a>
-<span class="sourceLineNo">497</span><a name="line.497"></a>
-<span class="sourceLineNo">498</span> // move the archive file to the stamped backup<a name="line.498"></a>
-<span class="sourceLineNo">499</span> Path backedupArchiveFile = new Path(archiveDir, filename + SEPARATOR + archiveStartTime);<a name="line.499"></a>
-<span class="sourceLineNo">500</span> if (!fs.rename(archiveFile, backedupArchiveFile)) {<a name="line.500"></a>
-<span class="sourceLineNo">501</span> LOG.error("Could not rename archive file to backup: " + backedupArchiveFile<a name="line.501"></a>
-<span class="sourceLineNo">502</span> + ", deleting existing file in favor of newer.");<a name="line.502"></a>
-<span class="sourceLineNo">503</span> // try to delete the exisiting file, if we can't rename it<a name="line.503"></a>
-<span class="sourceLineNo">504</span> if (!fs.delete(archiveFile, false)) {<a name="line.504"></a>
-<span class="sourceLineNo">505</span> throw new IOException("Couldn't delete existing archive file (" + archiveFile<a name="line.505"></a>
-<span class="sourceLineNo">506</span> + ") or rename it to the backup file (" + backedupArchiveFile<a name="line.506"></a>
-<span class="sourceLineNo">507</span> + ") to make room for similarly named file.");<a name="line.507"></a>
-<span class="sourceLineNo">508</span> }<a name="line.508"></a>
-<span class="sourceLineNo">509</span> }<a name="line.509"></a>
-<span class="sourceLineNo">510</span> LOG.debug("Backed up archive file from " + archiveFile);<a name="line.510"></a>
-<span class="sourceLineNo">511</span> }<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span> LOG.trace("No existing file in archive for {}, free to archive original file.", archiveFile);<a name="line.513"></a>
-<span class="sourceLineNo">514</span><a name="line.514"></a>
-<span class="sourceLineNo">515</span> // at this point, we should have a free spot for the archive file<a name="line.515"></a>
-<span class="sourceLineNo">516</span> boolean success = false;<a name="line.516"></a>
-<span class="sourceLineNo">517</span> for (int i = 0; !success && i < DEFAULT_RETRIES_NUMBER; ++i) {<a name="line.517"></a>
-<span class="sourceLineNo">518</span> if (i > 0) {<a name="line.518"></a>
-<span class="sourceLineNo">519</span> // Ensure that the archive directory exists.<a name="line.519"></a>
-<span class="sourceLineNo">520</span> // The previous "move to archive" operation has failed probably because<a name="line.520"></a>
-<span class="sourceLineNo">521</span> // the cleaner has removed our archive directory (HBASE-7643).<a name="line.521"></a>
-<span class="sourceLineNo">522</span> // (we're in a retry loop, so don't worry too much about the exception)<a name="line.522"></a>
-<span class="sourceLineNo">523</span> try {<a name="line.523"></a>
-<span class="sourceLineNo">524</span> if (!fs.exists(archiveDir)) {<a name="line.524"></a>
-<span class="sourceLineNo">525</span> if (fs.mkdirs(archiveDir)) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span> LOG.debug("Created archive directory {}", archiveDir);<a name="line.526"></a>
-<span class="sourceLineNo">527</span> }<a name="line.527"></a>
-<span class="sourceLineNo">528</span> }<a name="line.528"></a>
-<span class="sourceLineNo">529</span> } catch (IOException e) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span> LOG.warn("Failed to create directory {}", archiveDir, e);<a name="line.530"></a>
-<span class="sourceLineNo">531</span> }<a name="line.531"></a>
-<span class="sourceLineNo">532</span> }<a name="line.532"></a>
-<span class="sourceLineNo">533</span><a name="line.533"></a>
-<span class="sourceLineNo">534</span> try {<a name="line.534"></a>
-<span class="sourceLineNo">535</span> success = currentFile.moveAndClose(archiveFile);<a name="line.535"></a>
-<span class="sourceLineNo">536</span> } catch (FileNotFoundException fnfe) {<a name="line.536"></a>
-<span class="sourceLineNo">537</span> LOG.warn("Failed to archive " + currentFile +<a name="line.537"></a>
-<span class="sourceLineNo">538</span> " because it does not exist! Skipping and continuing on.", fnfe);<a name="line.538"></a>
-<span class="sourceLineNo">539</span> success = true;<a name="line.539"></a>
-<span class="sourceLineNo">540</span> } catch (IOException e) {<a name="line.540"></a>
-<span class="sourceLineNo">541</span> LOG.warn("Failed to archive " + currentFile + " on try #" + i, e);<a name="line.541"></a>
-<span class="sourceLineNo">542</span> success = false;<a name="line.542"></a>
-<span class="sourceLineNo">543</span> }<a name="line.543"></a>
-<span class="sourceLineNo">544</span> }<a name="line.544"></a>
+<span class="sourceLineNo">491</span> // An existing destination file in the archive is unexpected, but we handle it here.<a name="line.491"></a>
+<span class="sourceLineNo">492</span> if (fs.exists(archiveFile)) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span> if (!fs.exists(currentFile.getPath())) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span> // If the file already exists in the archive, and there is no current file to archive, then<a name="line.494"></a>
+<span class="sourceLineNo">495</span> // assume that the file in archive is correct. This is an unexpected situation, suggesting a<a name="line.495"></a>
+<span class="sourceLineNo">496</span> // race condition or split brain.<a name="line.496"></a>
+<span class="sourceLineNo">497</span> // In HBASE-26718 this was found when compaction incorrectly happened during warmupRegion.<a name="line.497"></a>
+<span class="sourceLineNo">498</span> LOG.warn("{} exists in archive. Attempted to archive nonexistent file {}.", archiveFile,<a name="line.498"></a>
+<span class="sourceLineNo">499</span> currentFile);<a name="line.499"></a>
+<span class="sourceLineNo">500</span> // We return success to match existing behavior in this method, where FileNotFoundException<a name="line.500"></a>
+<span class="sourceLineNo">501</span> // in moveAndClose is ignored.<a name="line.501"></a>
+<span class="sourceLineNo">502</span> return true;<a name="line.502"></a>
+<span class="sourceLineNo">503</span> }<a name="line.503"></a>
+<span class="sourceLineNo">504</span> // There is a conflict between the current file and the already existing archived file.<a name="line.504"></a>
+<span class="sourceLineNo">505</span> // Move the archived file to a timestamped backup. This is a really, really unlikely<a name="line.505"></a>
+<span class="sourceLineNo">506</span> // situation, where we get the same name for the existing file, but is included just for that<a name="line.506"></a>
+<span class="sourceLineNo">507</span> // 1 in trillion chance. We are potentially incurring data loss in the archive directory if<a name="line.507"></a>
+<span class="sourceLineNo">508</span> // the files are not identical. The timestamped backup will be cleaned by HFileCleaner as it<a name="line.508"></a>
+<span class="sourceLineNo">509</span> // has no references.<a name="line.509"></a>
+<span class="sourceLineNo">510</span> FileStatus curStatus = fs.getFileStatus(currentFile.getPath());<a name="line.510"></a>
+<span class="sourceLineNo">511</span> FileStatus archiveStatus = fs.getFileStatus(archiveFile);<a name="line.511"></a>
+<span class="sourceLineNo">512</span> long curLen = curStatus.getLen();<a name="line.512"></a>
+<span class="sourceLineNo">513</span> long archiveLen = archiveStatus.getLen();<a name="line.513"></a>
+<span class="sourceLineNo">514</span> long curMtime = curStatus.getModificationTime();<a name="line.514"></a>
+<span class="sourceLineNo">515</span> long archiveMtime = archiveStatus.getModificationTime();<a name="line.515"></a>
+<span class="sourceLineNo">516</span> if (curLen != archiveLen) {<a name="line.516"></a>
+<span class="sourceLineNo">517</span> LOG.error("{} already exists in archive with different size than current {}."<a name="line.517"></a>
+<span class="sourceLineNo">518</span> + " archiveLen: {} currentLen: {} archiveMtime: {} currentMtime: {}",<a name="line.518"></a>
+<span class="sourceLineNo">519</span> archiveFile, currentFile, archiveLen, curLen, archiveMtime, curMtime);<a name="line.519"></a>
+<span class="sourceLineNo">520</span> throw new IOException(archiveFile + " already exists in archive with different size" +<a name="line.520"></a>
+<span class="sourceLineNo">521</span> " than " + currentFile);<a name="line.521"></a>
+<span class="sourceLineNo">522</span> }<a name="line.522"></a>
+<span class="sourceLineNo">523</span><a name="line.523"></a>
+<span class="sourceLineNo">524</span> LOG.error("{} already exists in archive, moving to timestamped backup and overwriting"<a name="line.524"></a>
+<span class="sourceLineNo">525</span> + " current {}. archiveLen: {} currentLen: {} archiveMtime: {} currentMtime: {}",<a name="line.525"></a>
+<span class="sourceLineNo">526</span> archiveFile, currentFile, archiveLen, curLen, archiveMtime, curMtime);<a name="line.526"></a>
+<span class="sourceLineNo">527</span><a name="line.527"></a>
+<span class="sourceLineNo">528</span> // move the archive file to the stamped backup<a name="line.528"></a>
+<span class="sourceLineNo">529</span> Path backedupArchiveFile = new Path(archiveDir, filename + SEPARATOR + archiveStartTime);<a name="line.529"></a>
+<span class="sourceLineNo">530</span> if (!fs.rename(archiveFile, backedupArchiveFile)) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span> LOG.error("Could not rename archive file to backup: " + backedupArchiveFile<a name="line.531"></a>
+<span class="sourceLineNo">532</span> + ", deleting existing file in favor of newer.");<a name="line.532"></a>
+<span class="sourceLineNo">533</span> // try to delete the existing file, if we can't rename it<a name="line.533"></a>
+<span class="sourceLineNo">534</span> if (!fs.delete(archiveFile, false)) {<a name="line.534"></a>
+<span class="sourceLineNo">535</span> throw new IOException("Couldn't delete existing archive file (" + archiveFile<a name="line.535"></a>
+<span class="sourceLineNo">536</span> + ") or rename it to the backup file (" + backedupArchiveFile<a name="line.536"></a>
+<span class="sourceLineNo">537</span> + ") to make room for similarly named file.");<a name="line.537"></a>
+<span class="sourceLineNo">538</span> }<a name="line.538"></a>
+<span class="sourceLineNo">539</span> } else {<a name="line.539"></a>
+<span class="sourceLineNo">540</span> LOG.info("Backed up archive file from {} to {}.", archiveFile, backedupArchiveFile);<a name="line.540"></a>
+<span class="sourceLineNo">541</span> }<a name="line.541"></a>
+<span class="sourceLineNo">542</span> }<a name="line.542"></a>
+<span class="sourceLineNo">543</span><a name="line.543"></a>
+<span class="sourceLineNo">544</span> LOG.trace("No existing file in archive for {}, free to archive original file.", archiveFile);<a name="line.544"></a>
<span class="sourceLineNo">545</span><a name="line.545"></a>
-<span class="sourceLineNo">546</span> if (!success) {<a name="line.546"></a>
-<span class="sourceLineNo">547</span> LOG.error("Failed to archive " + currentFile);<a name="line.547"></a>
-<span class="sourceLineNo">548</span> return false;<a name="line.548"></a>
-<span class="sourceLineNo">549</span> }<a name="line.549"></a>
-<span class="sourceLineNo">550</span><a name="line.550"></a>
-<span class="sourceLineNo">551</span> LOG.debug("Archived from {} to {}", currentFile, archiveFile);<a name="line.551"></a>
-<span class="sourceLineNo">552</span> return true;<a name="line.552"></a>
-<span class="sourceLineNo">553</span> }<a name="line.553"></a>
-<span class="sourceLineNo">554</span><a name="line.554"></a>
-<span class="sourceLineNo">555</span> /**<a name="line.555"></a>
-<span class="sourceLineNo">556</span> * Without regard for backup, delete a region. Should be used with caution.<a name="line.556"></a>
-<span class="sourceLineNo">557</span> * @param regionDir {@link Path} to the region to be deleted.<a name="line.557"></a>
-<span class="sourceLineNo">558</span> * @param fs FileSystem from which to delete the region<a name="line.558"></a>
-<span class="sourceLineNo">559</span> * @return <tt>true</tt> on successful deletion, <tt>false</tt> otherwise<a name="line.559"></a>
-<span class="sourceLineNo">560</span> * @throws IOException on filesystem operation failure<a name="line.560"></a>
-<span class="sourceLineNo">561</span> */<a name="line.561"></a>
-<span class="sourceLineNo">562</span> private static boolean deleteRegionWithoutArchiving(FileSystem fs, Path regionDir)<a name="line.562"></a>
-<span class="sourceLineNo">563</span> throws IOException {<a name="line.563"></a>
-<span class="sourceLineNo">564</span> if (fs.delete(regionDir, true)) {<a name="line.564"></a>
-<span class="sourceLineNo">565</span> LOG.debug("Deleted {}", regionDir);<a name="line.565"></a>
-<span class="sourceLineNo">566</span> return true;<a name="line.566"></a>
-<span class="sourceLineNo">567</span> }<a name="line.567"></a>
-<span class="sourceLineNo">568</span> LOG.debug("Failed to delete directory {}", regionDir);<a name="line.568"></a>
-<span class="sourceLineNo">569</span> return false;<a name="line.569"></a>
-<span class="sourceLineNo">570</span> }<a name="line.570"></a>
-<span class="sourceLineNo">571</span><a name="line.571"></a>
-<span class="sourceLineNo">572</span> /**<a name="line.572"></a>
-<span class="sourceLineNo">573</span> * Just do a simple delete of the given store files<a name="line.573"></a>
-<span class="sourceLineNo">574</span> * <p><a name="line.574"></a>
-<span class="sourceLineNo">575</span> * A best effort is made to delete each of the files, rather than bailing on the first failure.<a name="line.575"></a>
-<span class="sourceLineNo">576</span> * <p><a name="line.576"></a>
-<span class="sourceLineNo">577</span> * @param compactedFiles store files to delete from the file system.<a name="line.577"></a>
-<span class="sourceLineNo">578</span> * @throws IOException if a file cannot be deleted. All files will be attempted to deleted before<a name="line.578"></a>
-<span class="sourceLineNo">579</span> * throwing the exception, rather than failing at the first file.<a name="line.579"></a>
-<span class="sourceLineNo">580</span> */<a name="line.580"></a>
-<span class="sourceLineNo">581</span> private static void deleteStoreFilesWithoutArchiving(Collection<HStoreFile> compactedFiles)<a name="line.581"></a>
-<span class="sourceLineNo">582</span> throws IOException {<a name="line.582"></a>
-<span class="sourceLineNo">583</span> LOG.debug("Deleting files without archiving.");<a name="line.583"></a>
-<span class="sourceLineNo">584</span> List<IOException> errors = new ArrayList<>(0);<a name="line.584"></a>
-<span class="sourceLineNo">585</span> for (HStoreFile hsf : compactedFiles) {<a name="line.585"></a>
-<span class="sourceLineNo">586</span> try {<a name="line.586"></a>
-<span class="sourceLineNo">587</span> hsf.deleteStoreFile();<a name="line.587"></a>
-<span class="sourceLineNo">588</span> } catch (IOException e) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span> LOG.error("Failed to delete {}", hsf.getPath());<a name="line.589"></a>
-<span class="sourceLineNo">590</span> errors.add(e);<a name="line.590"></a>
-<span class="sourceLineNo">591</span> }<a name="line.591"></a>
-<span class="sourceLineNo">592</span> }<a name="line.592"></a>
-<span class="sourceLineNo">593</span> if (errors.size() > 0) {<a name="line.593"></a>
-<span class="sourceLineNo">594</span> throw MultipleIOException.createIOException(errors);<a name="line.594"></a>
-<span class="sourceLineNo">595</span> }<a name="line.595"></a>
-<span class="sourceLineNo">596</span> }<a name="line.596"></a>
-<span class="sourceLineNo">597</span><a name="line.597"></a>
-<span class="sourceLineNo">598</span> /**<a name="line.598"></a>
-<span class="sourceLineNo">599</span> * Adapt a type to match the {@link File} interface, which is used internally for handling<a name="line.599"></a>
-<span class="sourceLineNo">600</span> * archival/removal of files<a name="line.600"></a>
-<span class="sourceLineNo">601</span> * @param <T> type to adapt to the {@link File} interface<a name="line.601"></a>
-<span class="sourceLineNo">602</span> */<a name="line.602"></a>
-<span class="sourceLineNo">603</span> private static abstract class FileConverter<T> implements Function<T, File> {<a name="line.603"></a>
-<span class="sourceLineNo">604</span> protected final FileSystem fs;<a name="line.604"></a>
-<span class="sourceLineNo">605</span><a name="line.605"></a>
-<span class="sourceLineNo">606</span> public FileConverter(FileSystem fs) {<a name="line.606"></a>
-<span class="sourceLineNo">607</span> this.fs = fs;<a name="line.607"></a>
-<span class="sourceLineNo">608</span> }<a name="line.608"></a>
-<span class="sourceLineNo">609</span> }<a name="line.609"></a>
-<span class="sourceLineNo">610</span><a name="line.610"></a>
-<span class="sourceLineNo">611</span> /**<a name="line.611"></a>
-<span class="sourceLineNo">612</span> * Convert a FileStatus to something we can manage in the archiving<a name="line.612"></a>
-<span class="sourceLineNo">613</span> */<a name="line.613"></a>
-<span class="sourceLineNo">614</span> private static class FileStatusConverter extends FileConverter<FileStatus> {<a name="line.614"></a>
-<span class="sourceLineNo">615</span> public FileStatusConverter(FileSystem fs) {<a name="line.615"></a>
-<span class="sourceLineNo">616</span> super(fs);<a name="line.616"></a>
-<span class="sourceLineNo">617</span> }<a name="line.617"></a>
-<span class="sourceLineNo">618</span><a name="line.618"></a>
-<span class="sourceLineNo">619</span> @Override<a name="line.619"></a>
-<span class="sourceLineNo">620</span> public File apply(FileStatus input) {<a name="line.620"></a>
-<span class="sourceLineNo">621</span> return new FileablePath(fs, input.getPath());<a name="line.621"></a>
-<span class="sourceLineNo">622</span> }<a name="line.622"></a>
-<span class="sourceLineNo">623</span> }<a name="line.623"></a>
-<span class="sourceLineNo">624</span><a name="line.624"></a>
-<span class="sourceLineNo">625</span> /**<a name="line.625"></a>
-<span class="sourceLineNo">626</span> * Convert the {@link HStoreFile} into something we can manage in the archive<a name="line.626"></a>
-<span class="sourceLineNo">627</span> * methods<a name="line.627"></a>
-<span class="sourceLineNo">628</span> */<a name="line.628"></a>
-<span class="sourceLineNo">629</span> private static class StoreToFile extends FileConverter<HStoreFile> {<a name="line.629"></a>
-<span class="sourceLineNo">630</span> public StoreToFile(FileSystem fs) {<a name="line.630"></a>
-<span class="sourceLineNo">631</span> super(fs);<a name="line.631"></a>
-<span class="sourceLineNo">632</span> }<a name="line.632"></a>
-<span class="sourceLineNo">633</span><a name="line.633"></a>
-<span class="sourceLineNo">634</span> @Override<a name="line.634"></a>
-<span class="sourceLineNo">635</span> public File apply(HStoreFile input) {<a name="line.635"></a>
-<span class="sourceLineNo">636</span> return new FileableStoreFile(fs, input);<a name="line.636"></a>
-<span class="sourceLineNo">637</span> }<a name="line.637"></a>
-<span class="sourceLineNo">638</span> }<a name="line.638"></a>
-<span class="sourceLineNo">639</span><a name="line.639"></a>
-<span class="sourceLineNo">640</span> /**<a name="line.640"></a>
-<span class="sourceLineNo">641</span> * Wrapper to handle file operations uniformly<a name="line.641"></a>
-<span class="sourceLineNo">642</span> */<a name="line.642"></a>
-<span class="sourceLineNo">643</span> private static abstract class File {<a name="line.643"></a>
-<span class="sourceLineNo">644</span> protected final FileSystem fs;<a name="line.644"></a>
-<span class="sourceLineNo">645</span><a name="line.645"></a>
-<span class="sourceLineNo">646</span> public File(FileSystem fs) {<a name="line.646"></a>
-<span class="sourceLineNo">647</span> this.fs = fs;<a name="line.647"></a>
+<span class="sourceLineNo">546</span> // at this point, we should have a free spot for the archive file<a name="line.546"></a>
+<span class="sourceLineNo">547</span> boolean success = false;<a name="line.547"></a>
+<span class="sourceLineNo">548</span> for (int i = 0; !success && i < DEFAULT_RETRIES_NUMBER; ++i) {<a name="line.548"></a>
+<span class="sourceLineNo">549</span> if (i > 0) {<a name="line.549"></a>
+<span class="sourceLineNo">550</span> // Ensure that the archive directory exists.<a name="line.550"></a>
+<span class="sourceLineNo">551</span> // The previous "move to archive" operation has failed probably because<a name="line.551"></a>
+<span class="sourceLineNo">552</span> // the cleaner has removed our archive directory (HBASE-7643).<a name="line.552"></a>
+<span class="sourceLineNo">553</span> // (we're in a retry loop, so don't worry too much about the exception)<a name="line.553"></a>
+<span class="sourceLineNo">554</span> try {<a name="line.554"></a>
+<span class="sourceLineNo">555</span> if (!fs.exists(archiveDir)) {<a name="line.555"></a>
+<span class="sourceLineNo">556</span> if (fs.mkdirs(archiveDir)) {<a name="line.556"></a>
+<span class="sourceLineNo">557</span> LOG.debug("Created archive directory {}", archiveDir);<a name="line.557"></a>
+<span class="sourceLineNo">558</span> }<a name="line.558"></a>
+<span class="sourceLineNo">559</span> }<a name="line.559"></a>
+<span class="sourceLineNo">560</span> } catch (IOException e) {<a name="line.560"></a>
+<span class="sourceLineNo">561</span> LOG.warn("Failed to create directory {}", archiveDir, e);<a name="line.561"></a>
+<span class="sourceLineNo">562</span> }<a name="line.562"></a>
+<span class="sourceLineNo">563</span> }<a name="line.563"></a>
+<span class="sourceLineNo">564</span><a name="line.564"></a>
+<span class="sourceLineNo">565</span> try {<a name="line.565"></a>
+<span class="sourceLineNo">566</span> success = currentFile.moveAndClose(archiveFile);<a name="line.566"></a>
+<span class="sourceLineNo">567</span> } catch (FileNotFoundException fnfe) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span> LOG.warn("Failed to archive " + currentFile +<a name="line.568"></a>
+<span class="sourceLineNo">569</span> " because it does not exist! Skipping and continuing on.", fnfe);<a name="line.569"></a>
+<span class="sourceLineNo">570</span> success = true;<a name="line.570"></a>
+<span class="sourceLineNo">571</span> } catch (IOException e) {<a name="line.571"></a>
+<span class="sourceLineNo">572</span> LOG.warn("Failed to archive " + currentFile + " on try #" + i, e);<a name="line.572"></a>
+<span class="sourceLineNo">573</span> success = false;<a name="line.573"></a>
+<span class="sourceLineNo">574</span> }<a name="line.574"></a>
+<span class="sourceLineNo">575</span> }<a name="line.575"></a>
+<span class="sourceLineNo">576</span><a name="line.576"></a>
+<span class="sourceLineNo">577</span> if (!success) {<a name="line.577"></a>
+<span class="sourceLineNo">578</span> LOG.error("Failed to archive " + currentFile);<a name="line.578"></a>
+<span class="sourceLineNo">579</span> return false;<a name="line.579"></a>
+<span class="sourceLineNo">580</span> }<a name="line.580"></a>
+<span class="sourceLineNo">581</span><a name="line.581"></a>
+<span class="sourceLineNo">582</span> LOG.debug("Archived from {} to {}", currentFile, archiveFile);<a name="line.582"></a>
+<span class="sourceLineNo">583</span> return true;<a name="line.583"></a>
+<span class="sourceLineNo">584</span> }<a name="line.584"></a>
+<span class="sourceLineNo">585</span><a name="line.585"></a>
+<span class="sourceLineNo">586</span> /**<a name="line.586"></a>
+<span class="sourceLineNo">587</span> * Without regard for backup, delete a region. Should be used with caution.<a name="line.587"></a>
+<span class="sourceLineNo">588</span> * @param regionDir {@link Path} to the region to be deleted.<a name="line.588"></a>
+<span class="sourceLineNo">589</span> * @param fs FileSystem from which to delete the region<a name="line.589"></a>
+<span class="sourceLineNo">590</span> * @return <tt>true</tt> on successful deletion, <tt>false</tt> otherwise<a name="line.590"></a>
+<span class="sourceLineNo">591</span> * @throws IOException on filesystem operation failure<a name="line.591"></a>
+<span class="sourceLineNo">592</span> */<a name="line.592"></a>
+<span class="sourceLineNo">593</span> private static boolean deleteRegionWithoutArchiving(FileSystem fs, Path regionDir)<a name="line.593"></a>
+<span class="sourceLineNo">594</span> throws IOException {<a name="line.594"></a>
+<span class="sourceLineNo">595</span> if (fs.delete(regionDir, true)) {<a name="line.595"></a>
+<span class="sourceLineNo">596</span> LOG.debug("Deleted {}", regionDir);<a name="line.596"></a>
+<span class="sourceLineNo">597</span> return true;<a name="line.597"></a>
+<span class="sourceLineNo">598</span> }<a name="line.598"></a>
+<span class="sourceLineNo">599</span> LOG.debug("Failed to delete directory {}", regionDir);<a name="line.599"></a>
+<span class="sourceLineNo">600</span> return false;<a name="line.600"></a>
+<span class="sourceLineNo">601</span> }<a name="line.601"></a>
+<span class="sourceLineNo">602</span><a name="line.602"></a>
+<span class="sourceLineNo">603</span> /**<a name="line.603"></a>
+<span class="sourceLineNo">604</span> * Just do a simple delete of the given store files<a name="line.604"></a>
+<span class="sourceLineNo">605</span> * <p><a name="line.605"></a>
+<span class="sourceLineNo">606</span> * A best effort is made to delete each of the files, rather than bailing on the first failure.<a name="line.606"></a>
+<span class="sourceLineNo">607</span> * <p><a name="line.607"></a>
+<span class="sourceLineNo">608</span> * @param compactedFiles store files to delete from the file system.<a name="line.608"></a>
+<span class="sourceLineNo">609</span> * @throws IOException if a file cannot be deleted. All files will be attempted to deleted before<a name="line.609"></a>
+<span class="sourceLineNo">610</span> * throwing the exception, rather than failing at the first file.<a name="line.610"></a>
+<span class="sourceLineNo">611</span> */<a name="line.611"></a>
+<span class="sourceLineNo">612</span> private static void deleteStoreFilesWithoutArchiving(Collection<HStoreFile> compactedFiles)<a name="line.612"></a>
+<span class="sourceLineNo">613</span> throws IOException {<a name="line.613"></a>
+<span class="sourceLineNo">614</span> LOG.debug("Deleting files without archiving.");<a name="line.614"></a>
+<span class="sourceLineNo">615</span> List<IOException> errors = new ArrayList<>(0);<a name="line.615"></a>
+<span class="sourceLineNo">616</span> for (HStoreFile hsf : compactedFiles) {<a name="line.616"></a>
+<span class="sourceLineNo">617</span> try {<a name="line.617"></a>
+<span class="sourceLineNo">618</span> hsf.deleteStoreFile();<a name="line.618"></a>
+<span class="sourceLineNo">619</span> } catch (IOException e) {<a name="line.619"></a>
+<span class="sourceLineNo">620</span> LOG.error("Failed to delete {}", hsf.getPath());<a name="line.620"></a>
+<span class="sourceLineNo">621</span> errors.add(e);<a name="line.621"></a>
+<span class="sourceLineNo">622</span> }<a name="line.622"></a>
+<span class="sourceLineNo">623</span> }<a name="line.623"></a>
+<span class="sourceLineNo">624</span> if (errors.size() > 0) {<a name="line.624"></a>
+<span class="sourceLineNo">625</span> throw MultipleIOException.createIOException(errors);<a name="line.625"></a>
+<span class="sourceLineNo">626</span> }<a name="line.626"></a>
+<span class="sourceLineNo">627</span> }<a name="line.627"></a>
+<span class="sourceLineNo">628</span><a name="line.628"></a>
+<span class="sourceLineNo">629</span> /**<a name="line.629"></a>
+<span class="sourceLineNo">630</span> * Adapt a type to match the {@link File} interface, which is used internally for handling<a name="line.630"></a>
+<span class="sourceLineNo">631</span> * archival/removal of files<a name="line.631"></a>
+<span class="sourceLineNo">632</span> * @param <T> type to adapt to the {@link File} interface<a name="line.632"></a>
+<span class="sourceLineNo">633</span> */<a name="line.633"></a>
+<span class="sourceLineNo">634</span> private static abstract class FileConverter<T> implements Function<T, File> {<a name="line.634"></a>
+<span class="sourceLineNo">635</span> protected final FileSystem fs;<a name="line.635"></a>
+<span class="sourceLineNo">636</span><a name="line.636"></a>
+<span class="sourceLineNo">637</span> public FileConverter(FileSystem fs) {<a name="line.637"></a>
+<span class="sourceLineNo">638</span> this.fs = fs;<a name="line.638"></a>
+<span class="sourceLineNo">639</span> }<a name="line.639"></a>
+<span class="sourceLineNo">640</span> }<a name="line.640"></a>
+<span class="sourceLineNo">641</span><a name="line.641"></a>
+<span class="sourceLineNo">642</span> /**<a name="line.642"></a>
+<span class="sourceLineNo">643</span> * Convert a FileStatus to something we can manage in the archiving<a name="line.643"></a>
+<span class="sourceLineNo">644</span> */<a name="line.644"></a>
+<span class="sourceLineNo">645</span> private static class FileStatusConverter extends FileConverter<FileStatus> {<a name="line.645"></a>
+<span class="sourceLineNo">646</span> public FileStatusConverter(FileSystem fs) {<a name="line.646"></a>
+<span class="sourceLineNo">647</span> super(fs);<a name="line.647"></a>
<span class="sourceLineNo">648</span> }<a name="line.648"></a>
<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span> /**<a name="line.650"></a>
-<span class="sourceLineNo">651</span> * Delete the file<a name="line.651"></a>
-<span class="sourceLineNo">652</span> * @throws IOException on failure<a name="line.652"></a>
-<span class="sourceLineNo">653</span> */<a name="line.653"></a>
-<span class="sourceLineNo">654</span> abstract void delete() throws IOException;<a name="line.654"></a>
+<span class="sourceLineNo">650</span> @Override<a name="line.650"></a>
+<span class="sourceLineNo">651</span> public File apply(FileStatus input) {<a name="line.651"></a>
+<span class="sourceLineNo">652</span> return new FileablePath(fs, input.getPath());<a name="line.652"></a>
+<span class="sourceLineNo">653</span> }<a name="line.653"></a>
+<span class="sourceLineNo">654</span> }<a name="line.654"></a>
<span class="sourceLineNo">655</span><a name="line.655"></a>
-<span class="sourceLineNo">656</span> /**<a name="line.656"></a>
-<span class="sourceLineNo">657</span> * Check to see if this is a file or a directory<a name="line.657"></a>
-<span class="sourceLineNo">658</span> * @return <tt>true</tt> if it is a file, <tt>false</tt> otherwise<a name="line.658"></a>
-<span class="sourceLineNo">659</span> * @throws IOException on {@link FileSystem} connection error<a name="line.659"></a>
-<span class="sourceLineNo">660</span> */<a name="line.660"></a>
-<span class="sourceLineNo">661</span> abstract boolean isFile() throws IOException;<a name="line.661"></a>
-<span class="sourceLineNo">662</span><a name="line.662"></a>
-<span class="sourceLineNo">663</span> /**<a name="line.663"></a>
-<span class="sourceLineNo">664</span> * @return if this is a directory, returns all the children in the<a name="line.664"></a>
-<span class="sourceLineNo">665</span> * directory, otherwise returns an empty list<a name="line.665"></a>
-<span class="sourceLineNo">666</span> * @throws IOException<a name="line.666"></a>
-<span class="sourceLineNo">667</span> */<a name="line.667"></a>
-<span class="sourceLineNo">668</span> abstract Collection<File> getChildren() throws IOException;<a name="line.668"></a>
-<span class="sourceLineNo">669</span><a name="line.669"></a>
-<span class="sourceLineNo">670</span> /**<a name="line.670"></a>
-<span class="sourceLineNo">671</span> * close any outside readers of the file<a name="line.671"></a>
-<span class="sourceLineNo">672</span> * @throws IOException<a name="line.672"></a>
-<span class="sourceLineNo">673</span> */<a name="line.673"></a>
-<span class="sourceLineNo">674</span> abstract void close() throws IOException;<a name="line.674"></a>
-<span class="sourceLineNo">675</span><a name="line.675"></a>
-<span class="sourceLineNo">676</span> /**<a name="line.676"></a>
-<span class="sourceLineNo">677</span> * @return the name of the file (not the full fs path, just the individual<a name="line.677"></a>
-<span class="sourceLineNo">678</span> * file name)<a name="line.678"></a>
-<span class="sourceLineNo">679</span> */<a name="line.679"></a>
-<span class="sourceLineNo">680</span> abstract String getName();<a name="line.680"></a>
-<span class="sourceLineNo">681</span><a name="line.681"></a>
-<span class="sourceLineNo">682</span> /**<a name="line.682"></a>
-<span class="sourceLineNo">683</span> * @return the path to this file<a name="line.683"></a>
+<span class="sourceLineNo">656</span> /**<a name="line.656"></a>
+<span class="sourceLineNo">657</span> * Convert the {@link HStoreFile} into something we can manage in the archive<a name="line.657"></a>
+<span class="sourceLineNo">658</span> * methods<a name="line.658"></a>
+<span class="sourceLineNo">659</span> */<a name="line.659"></a>
+<span class="sourceLineNo">660</span> private static class StoreToFile extends FileConverter<HStoreFile> {<a name="line.660"></a>
+<span class="sourceLineNo">661</span> public StoreToFile(FileSystem fs) {<a name="line.661"></a>
+<span class="sourceLineNo">662</span> super(fs);<a name="line.662"></a>
+<span class="sourceLineNo">663</span> }<a name="line.663"></a>
+<span class="sourceLineNo">664</span><a name="line.664"></a>
+<span class="sourceLineNo">665</span> @Override<a name="line.665"></a>
+<span class="sourceLineNo">666</span> public File apply(HStoreFile input) {<a name="line.666"></a>
+<span class="sourceLineNo">667</span> return new FileableStoreFile(fs, input);<a name="line.667"></a>
+<span class="sourceLineNo">668</span> }<a name="line.668"></a>
+<span class="sourceLineNo">669</span> }<a name="line.669"></a>
+<span class="sourceLineNo">670</span><a name="line.670"></a>
+<span class="sourceLineNo">671</span> /**<a name="line.671"></a>
+<span class="sourceLineNo">672</span> * Wrapper to handle file operations uniformly<a name="line.672"></a>
+<span class="sourceLineNo">673</span> */<a name="line.673"></a>
+<span class="sourceLineNo">674</span> private static abstract class File {<a name="line.674"></a>
+<span class="sourceLineNo">675</span> protected final FileSystem fs;<a name="line.675"></a>
+<span class="sourceLineNo">676</span><a name="line.676"></a>
+<span class="sourceLineNo">677</span> public File(FileSystem fs) {<a name="line.677"></a>
+<span class="sourceLineNo">678</span> this.fs = fs;<a name="line.678"></a>
+<span class="sourceLineNo">679</span> }<a name="line.679"></a>
+<span class="sourceLineNo">680</span><a name="line.680"></a>
+<span class="sourceLineNo">681</span> /**<a name="line.681"></a>
+<span class="sourceLineNo">682</span> * Delete the file<a name="line.682"></a>
+<span class="sourceLineNo">683</span> * @throws IOException on failure<a name="line.683"></a>
<span class="sourceLineNo">684</span> */<a name="line.684"></a>
-<span class="sourceLineNo">685</span> abstract Path getPath();<a name="line.685"></a>
+<span class="sourceLineNo">685</span> abstract void delete() throws IOException;<a name="line.685"></a>
<span class="sourceLineNo">686</span><a name="line.686"></a>
<span class="sourceLineNo">687</span> /**<a name="line.687"></a>
-<span class="sourceLineNo">688</span> * Move the file to the given destination<a name="line.688"></a>
-<span class="sourceLineNo">689</span> * @param dest<a name="line.689"></a>
-<span class="sourceLineNo">690</span> * @return <tt>true</tt> on success<a name="line.690"></a>
-<span class="sourceLineNo">691</span> * @throws IOException<a name="line.691"></a>
-<span class="sourceLineNo">692</span> */<a name="line.692"></a>
-<span class="sourceLineNo">693</span> public boolean moveAndClose(Path dest) throws IOException {<a name="line.693"></a>
-<span class="sourceLineNo">694</span> this.close();<a name="line.694"></a>
-<span class="sourceLineNo">695</span> Path p = this.getPath();<a name="line.695"></a>
-<span class="sourceLineNo">696</span> return CommonFSUtils.renameAndSetModifyTime(fs, p, dest);<a name="line.696"></a>
-<span class="sourceLineNo">697</span> }<a name="line.697"></a>
-<span class="sourceLineNo">698</span><a name="line.698"></a>
-<span class="sourceLineNo">699</span> /**<a name="line.699"></a>
-<span class="sourceLineNo">700</span> * @return the {@link FileSystem} on which this file resides<a name="line.700"></a>
-<span class="sourceLineNo">701</span> */<a name="line.701"></a>
-<span class="sourceLineNo">702</span> public FileSystem getFileSystem() {<a name="line.702"></a>
-<span class="sourceLineNo">703</span> return this.fs;<a name="line.703"></a>
-<span class="sourceLineNo">704</span> }<a name="line.704"></a>
-<span class="sourceLineNo">705</span><a name="line.705"></a>
-<span class="sourceLineNo">706</span> @Override<a name="line.706"></a>
-<span class="sourceLineNo">707</span> public String toString() {<a name="line.707"></a>
-<span class="sourceLineNo">708</span> return this.getClass().getSimpleName() + ", " + getPath().toString();<a name="line.708"></a>
-<span class="sourceLineNo">709</span> }<a name="line.709"></a>
-<span class="sourceLineNo">710</span> }<a name="line.710"></a>
-<span class="sourceLineNo">711</span><a name="line.711"></a>
-<span class="sourceLineNo">712</span> /**<a name="line.712"></a>
-<span class="sourceLineNo">713</span> * A {@link File} that wraps a simple {@link Path} on a {@link FileSystem}.<a name="line.713"></a>
-<span class="sourceLineNo">714</span> */<a name="line.714"></a>
-<span class="sourceLineNo">715</span> private static class FileablePath extends File {<a name="line.715"></a>
-<span class="sourceLineNo">716</span> private final Path file;<a name="line.716"></a>
-<span class="sourceLineNo">717</span> private final FileStatusConverter getAsFile;<a name="line.717"></a>
-<span class="sourceLineNo">718</span><a name="line.718"></a>
-<span class="sourceLineNo">719</span> public FileablePath(FileSystem fs, Path file) {<a name="line.719"></a>
-<span class="sourceLineNo">720</span> super(fs);<a name="line.720"></a>
-<span class="sourceLineNo">721</span> this.file = file;<a name="line.721"></a>
-<span class="sourceLineNo">722</span> this.getAsFile = new FileStatusConverter(fs);<a name="line.722"></a>
-<span class="sourceLineNo">723</span> }<a name="line.723"></a>
-<span class="sourceLineNo">724</span><a name="line.724"></a>
-<span class="sourceLineNo">725</span> @Override<a name="line.725"></a>
-<span class="sourceLineNo">726</span> public void delete() throws IOException {<a name="line.726"></a>
-<span class="sourceLineNo">727</span> if (!fs.delete(file, true)) throw new IOException("Failed to delete:" + this.file);<a name="line.727"></a>
+<span class="sourceLineNo">688</span> * Check to see if this is a file or a directory<a name="line.688"></a>
+<span class="sourceLineNo">689</span> * @return <tt>true</tt> if it is a file, <tt>false</tt> otherwise<a name="line.689"></a>
+<span class="sourceLineNo">690</span> * @throws IOException on {@link FileSystem} connection error<a name="line.690"></a>
+<span class="sourceLineNo">691</span> */<a name="line.691"></a>
+<span class="sourceLineNo">692</span> abstract boolean isFile() throws IOException;<a name="line.692"></a>
+<span class="sourceLineNo">693</span><a name="line.693"></a>
+<span class="sourceLineNo">694</span> /**<a name="line.694"></a>
+<span class="sourceLineNo">695</span> * @return if this is a directory, returns all the children in the<a name="line.695"></a>
+<span class="sourceLineNo">696</span> * directory, otherwise returns an empty list<a name="line.696"></a>
+<span class="sourceLineNo">697</span> * @throws IOException<a name="line.697"></a>
+<span class="sourceLineNo">698</span> */<a name="line.698"></a>
+<span class="sourceLineNo">699</span> abstract Collection<File> getChildren() throws IOException;<a name="line.699"></a>
+<span class="sourceLineNo">700</span><a name="line.700"></a>
+<span class="sourceLineNo">701</span> /**<a name="line.701"></a>
+<span class="sourceLineNo">702</span> * close any outside readers of the file<a name="line.702"></a>
+<span class="sourceLineNo">703</span> * @throws IOException<a name="line.703"></a>
+<span class="sourceLineNo">704</span> */<a name="line.704"></a>
+<span class="sourceLineNo">705</span> abstract void close() throws IOException;<a name="line.705"></a>
+<span class="sourceLineNo">706</span><a name="line.706"></a>
+<span class="sourceLineNo">707</span> /**<a name="line.707"></a>
+<span class="sourceLineNo">708</span> * @return the name of the file (not the full fs path, just the individual<a name="line.708"></a>
+<span class="sourceLineNo">709</span> * file name)<a name="line.709"></a>
+<span class="sourceLineNo">710</span> */<a name="line.710"></a>
+<span class="sourceLineNo">711</span> abstract String getName();<a name="line.711"></a>
+<span class="sourceLineNo">712</span><a name="line.712"></a>
+<span class="sourceLineNo">713</span> /**<a name="line.713"></a>
+<span class="sourceLineNo">714</span> * @return the path to this file<a name="line.714"></a>
+<span class="sourceLineNo">715</span> */<a name="line.715"></a>
+<span class="sourceLineNo">716</span> abstract Path getPath();<a name="line.716"></a>
+<span class="sourceLineNo">717</span><a name="line.717"></a>
+<span class="sourceLineNo">718</span> /**<a name="line.718"></a>
+<span class="sourceLineNo">719</span> * Move the file to the given destination<a name="line.719"></a>
+<span class="sourceLineNo">720</span> * @param dest<a name="line.720"></a>
+<span class="sourceLineNo">721</span> * @return <tt>true</tt> on success<a name="line.721"></a>
+<span class="sourceLineNo">722</span> * @throws IOException<a name="line.722"></a>
+<span class="sourceLineNo">723</span> */<a name="line.723"></a>
+<span class="sourceLineNo">724</span> public boolean moveAndClose(Path dest) throws IOException {<a name="line.724"></a>
+<span class="sourceLineNo">725</span> this.close();<a name="line.725"></a>
+<span class="sourceLineNo">726</span> Path p = this.getPath();<a name="line.726"></a>
+<span class="sourceLineNo">727</span> return CommonFSUtils.renameAndSetModifyTime(fs, p, dest);<a name="line.727"></a>
<span class="sourceLineNo">728</span> }<a name="line.728"></a>
<span class="sourceLineNo">729</span><a name="line.729"></a>
-<span class="sourceLineNo">730</span> @Override<a name="line.730"></a>
-<span class="sourceLineNo">731</span> public String getName() {<a name="line.731"></a>
-<span class="sourceLineNo">732</span> return file.getName();<a name="line.732"></a>
-<span class="sourceLineNo">733</span> }<a name="line.733"></a>
-<span class="sourceLineNo">734</span><a name="line.734"></a>
-<span class="sourceLineNo">735</span> @Override<a name="line.735"></a>
-<span class="sourceLineNo">736</span> public Collection<File> getChildren() throws IOException {<a name="line.736"></a>
-<span class="sourceLineNo">737</span> if (fs.isFile(file)) {<a name="line.737"></a>
-<span class="sourceLineNo">738</span> return Collections.emptyList();<a name="line.738"></a>
-<span class="sourceLineNo">739</span> }<a name="line.739"></a>
-<span class="sourceLineNo">740</span> return Stream.of(fs.listStatus(file)).map(getAsFile).collect(Collectors.toList());<a name="line.740"></a>
-<span class="sourceLineNo">741</span> }<a name="line.741"></a>
+<span class="sourceLineNo">730</span> /**<a name="line.730"></a>
+<span class="sourceLineNo">731</span> * @return the {@link FileSystem} on which this file resides<a name="line.731"></a>
+<span class="sourceLineNo">732</span> */<a name="line.732"></a>
+<span class="sourceLineNo">733</span> public FileSystem getFileSystem() {<a name="line.733"></a>
+<span class="sourceLineNo">734</span> return this.fs;<a name="line.734"></a>
+<span class="sourceLineNo">735</span> }<a name="line.735"></a>
+<span class="sourceLineNo">736</span><a name="line.736"></a>
+<span class="sourceLineNo">737</span> @Override<a name="line.737"></a>
+<span class="sourceLineNo">738</span> public String toString() {<a name="line.738"></a>
+<span class="sourceLineNo">739</span> return this.getClass().getSimpleName() + ", " + getPath().toString();<a name="line.739"></a>
+<span class="sourceLineNo">740</span> }<a name="line.740"></a>
+<span class="sourceLineNo">741</span> }<a name="line.741"></a>
<span class="sourceLineNo">742</span><a name="line.742"></a>
-<span class="sourceLineNo">743</span> @Override<a name="line.743"></a>
-<span class="sourceLineNo">744</span> public boolean isFile() throws IOException {<a name="line.744"></a>
-<span class="sourceLineNo">745</span> return fs.isFile(file);<a name="line.745"></a>
-<span class="sourceLineNo">746</span> }<a name="line.746"></a>
-<span class="sourceLineNo">747</span><a name="line.747"></a>
-<span class="sourceLineNo">748</span> @Override<a name="line.748"></a>
-<span class="sourceLineNo">749</span> public void close() throws IOException {<a name="line.749"></a>
-<span class="sourceLineNo">750</span> // NOOP - files are implicitly closed on removal<a name="line.750"></a>
-<span class="sourceLineNo">751</span> }<a name="line.751"></a>
-<span class="sourceLineNo">752</span><a name="line.752"></a>
-<span class="sourceLineNo">753</span> @Override<a name="line.753"></a>
-<span class="sourceLineNo">754</span> Path getPath() {<a name="line.754"></a>
-<span class="sourceLineNo">755</span> return file;<a name="line.755"></a>
-<span class="sourceLineNo">756</span> }<a name="line.756"></a>
-<span class="sourceLineNo">757</span> }<a name="line.757"></a>
-<span class="sourceLineNo">758</span><a name="line.758"></a>
-<span class="sourceLineNo">759</span> /**<a name="line.759"></a>
-<span class="sourceLineNo">760</span> * {@link File} adapter for a {@link HStoreFile} living on a {@link FileSystem}<a name="line.760"></a>
-<span class="sourceLineNo">761</span> * .<a name="line.761"></a>
-<span class="sourceLineNo">762</span> */<a name="line.762"></a>
-<span class="sourceLineNo">763</span> private static class FileableStoreFile extends File {<a name="line.763"></a>
-<span class="sourceLineNo">764</span> HStoreFile file;<a name="line.764"></a>
+<span class="sourceLineNo">743</span> /**<a name="line.743"></a>
+<span class="sourceLineNo">744</span> * A {@link File} that wraps a simple {@link Path} on a {@link FileSystem}.<a name="line.744"></a>
+<span class="sourceLineNo">745</span> */<a name="line.745"></a>
+<span class="sourceLineNo">746</span> private static class FileablePath extends File {<a name="line.746"></a>
+<span class="sourceLineNo">747</span> private final Path file;<a name="line.747"></a>
+<span class="sourceLineNo">748</span> private final FileStatusConverter getAsFile;<a name="line.748"></a>
+<span class="sourceLineNo">749</span><a name="line.749"></a>
+<span class="sourceLineNo">750</span> public FileablePath(FileSystem fs, Path file) {<a name="line.750"></a>
+<span class="sourceLineNo">751</span> super(fs);<a name="line.751"></a>
+<span class="sourceLineNo">752</span> this.file = file;<a name="line.752"></a>
+<span class="sourceLineNo">753</span> this.getAsFile = new FileStatusConverter(fs);<a name="line.753"></a>
+<span class="sourceLineNo">754</span> }<a name="line.754"></a>
+<span class="sourceLineNo">755</span><a name="line.755"></a>
+<span class="sourceLineNo">756</span> @Override<a name="line.756"></a>
+<span class="sourceLineNo">757</span> public void delete() throws IOException {<a name="line.757"></a>
+<span class="sourceLineNo">758</span> if (!fs.delete(file, true)) throw new IOException("Failed to delete:" + this.file);<a name="line.758"></a>
+<span class="sourceLineNo">759</span> }<a name="line.759"></a>
+<span class="sourceLineNo">760</span><a name="line.760"></a>
+<span class="sourceLineNo">761</span> @Override<a name="line.761"></a>
+<span class="sourceLineNo">762</span> public String getName() {<a name="line.762"></a>
+<span class="sourceLineNo">763</span> return file.getName();<a name="line.763"></a>
+<span class="sourceLineNo">764</span> }<a name="line.764"></a>
<span class="sourceLineNo">765</span><a name="line.765"></a>
-<span class="sourceLineNo">766</span> public FileableStoreFile(FileSystem fs, HStoreFile store) {<a name="line.766"></a>
-<span class="sourceLineNo">767</span> super(fs);<a name="line.767"></a>
-<span class="sourceLineNo">768</span> this.file = store;<a name="line.768"></a>
-<span class="sourceLineNo">769</span> }<a name="line.769"></a>
-<span class="sourceLineNo">770</span><a name="line.770"></a>
-<span class="sourceLineNo">771</span> @Override<a name="line.771"></a>
-<span class="sourceLineNo">772</span> public void delete() throws IOException {<a name="line.772"></a>
-<span class="sourceLineNo">773</span> file.deleteStoreFile();<a name="line.773"></a>
-<span class="sourceLineNo">774</span> }<a name="line.774"></a>
-<span class="sourceLineNo">775</span><a name="line.775"></a>
-<span class="sourceLineNo">776</span> @Override<a name="line.776"></a>
-<span class="sourceLineNo">777</span> public String getName() {<a name="line.777"></a>
-<span class="sourceLineNo">778</span> return file.getPath().getName();<a name="line.778"></a>
-<span class="sourceLineNo">779</span> }<a name="line.779"></a>
-<span class="sourceLineNo">780</span><a name="line.780"></a>
-<span class="sourceLineNo">781</span> @Override<a name="line.781"></a>
-<span class="sourceLineNo">782</span> public boolean isFile() {<a name="line.782"></a>
-<span class="sourceLineNo">783</span> return true;<a name="line.783"></a>
-<span class="sourceLineNo">784</span> }<a name="line.784"></a>
-<span class="sourceLineNo">785</span><a name="line.785"></a>
-<span class="sourceLineNo">786</span> @Override<a name="line.786"></a>
-<span class="sourceLineNo">787</span> public Collection<File> getChildren() throws IOException {<a name="line.787"></a>
-<span class="sourceLineNo">788</span> // storefiles don't have children<a name="line.788"></a>
-<span class="sourceLineNo">789</span> return Collections.emptyList();<a name="line.789"></a>
-<span class="sourceLineNo">790</span> }<a name="line.790"></a>
-<span class="sourceLineNo">791</span><a name="line.791"></a>
-<span class="sourceLineNo">792</span> @Override<a name="line.792"></a>
-<span class="sourceLineNo">793</span> public void close() throws IOException {<a name="line.793"></a>
-<span class="sourceLineNo">794</span> file.closeStoreFile(true);<a name="line.794"></a>
-<span class="sourceLineNo">795</span> }<a name="line.795"></a>
+<span class="sourceLineNo">766</span> @Override<a name="line.766"></a>
+<span class="sourceLineNo">767</span> public Collection<File> getChildren() throws IOException {<a name="line.767"></a>
+<span class="sourceLineNo">768</span> if (fs.isFile(file)) {<a name="line.768"></a>
+<span class="sourceLineNo">769</span> return Collections.emptyList();<a name="line.769"></a>
+<span class="sourceLineNo">770</span> }<a name="line.770"></a>
+<span class="sourceLineNo">771</span> return Stream.of(fs.listStatus(file)).map(getAsFile).collect(Collectors.toList());<a name="line.771"></a>
+<span class="sourceLineNo">772</span> }<a name="line.772"></a>
+<span class="sourceLineNo">773</span><a name="line.773"></a>
+<span class="sourceLineNo">774</span> @Override<a name="line.774"></a>
+<span class="sourceLineNo">775</span> public boolean isFile() throws IOException {<a name="line.775"></a>
+<span class="sourceLineNo">776</span> return fs.isFile(file);<a name="line.776"></a>
+<span class="sourceLineNo">777</span> }<a name="line.777"></a>
+<span class="sourceLineNo">778</span><a name="line.778"></a>
+<span class="sourceLineNo">779</span> @Override<a name="line.779"></a>
+<span class="sourceLineNo">780</span> public void close() throws IOException {<a name="line.780"></a>
+<span class="sourceLineNo">781</span> // NOOP - files are implicitly closed on removal<a name="line.781"></a>
+<span class="sourceLineNo">782</span> }<a name="line.782"></a>
+<span class="sourceLineNo">783</span><a name="line.783"></a>
+<span class="sourceLineNo">784</span> @Override<a name="line.784"></a>
+<span class="sourceLineNo">785</span> Path getPath() {<a name="line.785"></a>
+<span class="sourceLineNo">786</span> return file;<a name="line.786"></a>
+<span class="sourceLineNo">787</span> }<a name="line.787"></a>
+<span class="sourceLineNo">788</span> }<a name="line.788"></a>
+<span class="sourceLineNo">789</span><a name="line.789"></a>
+<span class="sourceLineNo">790</span> /**<a name="line.790"></a>
+<span class="sourceLineNo">791</span> * {@link File} adapter for a {@link HStoreFile} living on a {@link FileSystem}<a name="line.791"></a>
+<span class="sourceLineNo">792</span> * .<a name="line.792"></a>
+<span class="sourceLineNo">793</span> */<a name="line.793"></a>
+<span class="sourceLineNo">794</span> private static class FileableStoreFile extends File {<a name="line.794"></a>
+<span class="sourceLineNo">795</span> HStoreFile file;<a name="line.795"></a>
<span class="sourceLineNo">796</span><a name="line.796"></a>
-<span class="sourceLineNo">797</span> @Override<a name="line.797"></a>
-<span class="sourceLineNo">798</span> Path getPath() {<a name="line.798"></a>
-<span class="sourceLineNo">799</span> return file.getPath();<a name="line.799"></a>
+<span class="sourceLineNo">797</span> public FileableStoreFile(FileSystem fs, HStoreFile store) {<a name="line.797"></a>
+<span class="sourceLineNo">798</span> super(fs);<a name="line.798"></a>
+<span class="sourceLineNo">799</span> this.file = store;<a name="line.799"></a>
<span class="sourceLineNo">800</span> }<a name="line.800"></a>
-<span class="sourceLineNo">801</span> }<a name="line.801"></a>
-<span class="sourceLineNo">802</span>}<a name="line.802"></a>
+<span class="sourceLineNo">801</span><a name="line.801"></a>
+<span class="sourceLineNo">802</span> @Override<a name="line.802"></a>
+<span class="sourceLineNo">803</span> public void delete() throws IOException {<a name="line.803"></a>
+<span class="sourceLineNo">804</span> file.deleteStoreFile();<a name="line.804"></a>
+<span class="sourceLineNo">805</span> }<a name="line.805"></a>
+<span class="sourceLineNo">806</span><a name="line.806"></a>
+<span class="sourceLineNo">807</span> @Override<a name="line.807"></a>
+<span class="sourceLineNo">808</span> public String getName() {<a name="line.808"></a>
+<span class="sourceLineNo">809</span> return file.getPath().getName();<a name="line.809"></a>
+<span class="sourceLineNo">810</span> }<a name="line.810"></a>
+<span class="sourceLineNo">811</span><a name="line.811"></a>
+<span class="sourceLineNo">812</span> @Override<a name="line.812"></a>
+<span class="sourceLineNo">813</span> public boolean isFile() {<a name="line.813"></a>
+<span class="sourceLineNo">814</span> return true;<a name="line.814"></a>
+<span class="sourceLineNo">815</span> }<a name="line.815"></a>
+<span class="sourceLineNo">816</span><a name="line.816"></a>
+<span class="sourceLineNo">817</span> @Override<a name="line.817"></a>
+<span class="sourceLineNo">818</span> public Collection<File> getChildren() throws IOException {<a name="line.818"></a>
+<span class="sourceLineNo">819</span> // storefiles don't have children<a name="line.819"></a>
+<span class="sourceLineNo">820</span> return Collections.emptyList();<a name="line.820"></a>
+<span class="sourceLineNo">821</span> }<a name="line.821"></a>
+<span class="sourceLineNo">822</span><a name="line.822"></a>
+<span class="sourceLineNo">823</span> @Override<a name="line.823"></a>
+<span class="sourceLineNo">824</span> public void close() throws IOException {<a name="line.824"></a>
+<span class="sourceLineNo">825</span> file.closeStoreFile(true);<a name="line.825"></a>
+<span class="sourceLineNo">826</span> }<a name="line.826"></a>
+<span class="sourceLineNo">827</span><a name="line.827"></a>
+<span class="sourceLineNo">828</span> @Override<a name="line.828"></a>
+<span class="sourceLineNo">829</span> Path getPath() {<a name="line.829"></a>
+<span class="sourceLineNo">830</span> return file.getPath();<a name="line.830"></a>
+<span class="sourceLineNo">831</span> }<a name="line.831"></a>
+<span class="sourceLineNo">832</span> }<a name="line.832"></a>
+<span class="sourceLineNo">833</span>}<a name="line.833"></a>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileConverter.html b/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileConverter.html
index 22ea136..ee79f25 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileConverter.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileConverter.html
@@ -496,318 +496,349 @@
<span class="sourceLineNo">488</span> Path archiveFile = new Path(archiveDir, filename);<a name="line.488"></a>
<span class="sourceLineNo">489</span> FileSystem fs = currentFile.getFileSystem();<a name="line.489"></a>
<span class="sourceLineNo">490</span><a name="line.490"></a>
-<span class="sourceLineNo">491</span> // if the file already exists in the archive, move that one to a timestamped backup. This is a<a name="line.491"></a>
-<span class="sourceLineNo">492</span> // really, really unlikely situtation, where we get the same name for the existing file, but<a name="line.492"></a>
-<span class="sourceLineNo">493</span> // is included just for that 1 in trillion chance.<a name="line.493"></a>
-<span class="sourceLineNo">494</span> if (fs.exists(archiveFile)) {<a name="line.494"></a>
-<span class="sourceLineNo">495</span> LOG.debug("{} already exists in archive, moving to timestamped backup and " +<a name="line.495"></a>
-<span class="sourceLineNo">496</span> "overwriting current.", archiveFile);<a name="line.496"></a>
-<span class="sourceLineNo">497</span><a name="line.497"></a>
-<span class="sourceLineNo">498</span> // move the archive file to the stamped backup<a name="line.498"></a>
-<span class="sourceLineNo">499</span> Path backedupArchiveFile = new Path(archiveDir, filename + SEPARATOR + archiveStartTime);<a name="line.499"></a>
-<span class="sourceLineNo">500</span> if (!fs.rename(archiveFile, backedupArchiveFile)) {<a name="line.500"></a>
-<span class="sourceLineNo">501</span> LOG.error("Could not rename archive file to backup: " + backedupArchiveFile<a name="line.501"></a>
-<span class="sourceLineNo">502</span> + ", deleting existing file in favor of newer.");<a name="line.502"></a>
-<span class="sourceLineNo">503</span> // try to delete the exisiting file, if we can't rename it<a name="line.503"></a>
-<span class="sourceLineNo">504</span> if (!fs.delete(archiveFile, false)) {<a name="line.504"></a>
-<span class="sourceLineNo">505</span> throw new IOException("Couldn't delete existing archive file (" + archiveFile<a name="line.505"></a>
-<span class="sourceLineNo">506</span> + ") or rename it to the backup file (" + backedupArchiveFile<a name="line.506"></a>
-<span class="sourceLineNo">507</span> + ") to make room for similarly named file.");<a name="line.507"></a>
-<span class="sourceLineNo">508</span> }<a name="line.508"></a>
-<span class="sourceLineNo">509</span> }<a name="line.509"></a>
-<span class="sourceLineNo">510</span> LOG.debug("Backed up archive file from " + archiveFile);<a name="line.510"></a>
-<span class="sourceLineNo">511</span> }<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span> LOG.trace("No existing file in archive for {}, free to archive original file.", archiveFile);<a name="line.513"></a>
-<span class="sourceLineNo">514</span><a name="line.514"></a>
-<span class="sourceLineNo">515</span> // at this point, we should have a free spot for the archive file<a name="line.515"></a>
-<span class="sourceLineNo">516</span> boolean success = false;<a name="line.516"></a>
-<span class="sourceLineNo">517</span> for (int i = 0; !success && i < DEFAULT_RETRIES_NUMBER; ++i) {<a name="line.517"></a>
-<span class="sourceLineNo">518</span> if (i > 0) {<a name="line.518"></a>
-<span class="sourceLineNo">519</span> // Ensure that the archive directory exists.<a name="line.519"></a>
-<span class="sourceLineNo">520</span> // The previous "move to archive" operation has failed probably because<a name="line.520"></a>
-<span class="sourceLineNo">521</span> // the cleaner has removed our archive directory (HBASE-7643).<a name="line.521"></a>
-<span class="sourceLineNo">522</span> // (we're in a retry loop, so don't worry too much about the exception)<a name="line.522"></a>
-<span class="sourceLineNo">523</span> try {<a name="line.523"></a>
-<span class="sourceLineNo">524</span> if (!fs.exists(archiveDir)) {<a name="line.524"></a>
-<span class="sourceLineNo">525</span> if (fs.mkdirs(archiveDir)) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span> LOG.debug("Created archive directory {}", archiveDir);<a name="line.526"></a>
-<span class="sourceLineNo">527</span> }<a name="line.527"></a>
-<span class="sourceLineNo">528</span> }<a name="line.528"></a>
-<span class="sourceLineNo">529</span> } catch (IOException e) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span> LOG.warn("Failed to create directory {}", archiveDir, e);<a name="line.530"></a>
-<span class="sourceLineNo">531</span> }<a name="line.531"></a>
-<span class="sourceLineNo">532</span> }<a name="line.532"></a>
-<span class="sourceLineNo">533</span><a name="line.533"></a>
-<span class="sourceLineNo">534</span> try {<a name="line.534"></a>
-<span class="sourceLineNo">535</span> success = currentFile.moveAndClose(archiveFile);<a name="line.535"></a>
-<span class="sourceLineNo">536</span> } catch (FileNotFoundException fnfe) {<a name="line.536"></a>
-<span class="sourceLineNo">537</span> LOG.warn("Failed to archive " + currentFile +<a name="line.537"></a>
-<span class="sourceLineNo">538</span> " because it does not exist! Skipping and continuing on.", fnfe);<a name="line.538"></a>
-<span class="sourceLineNo">539</span> success = true;<a name="line.539"></a>
-<span class="sourceLineNo">540</span> } catch (IOException e) {<a name="line.540"></a>
-<span class="sourceLineNo">541</span> LOG.warn("Failed to archive " + currentFile + " on try #" + i, e);<a name="line.541"></a>
-<span class="sourceLineNo">542</span> success = false;<a name="line.542"></a>
-<span class="sourceLineNo">543</span> }<a name="line.543"></a>
-<span class="sourceLineNo">544</span> }<a name="line.544"></a>
+<span class="sourceLineNo">491</span> // An existing destination file in the archive is unexpected, but we handle it here.<a name="line.491"></a>
+<span class="sourceLineNo">492</span> if (fs.exists(archiveFile)) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span> if (!fs.exists(currentFile.getPath())) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span> // If the file already exists in the archive, and there is no current file to archive, then<a name="line.494"></a>
+<span class="sourceLineNo">495</span> // assume that the file in archive is correct. This is an unexpected situation, suggesting a<a name="line.495"></a>
+<span class="sourceLineNo">496</span> // race condition or split brain.<a name="line.496"></a>
+<span class="sourceLineNo">497</span> // In HBASE-26718 this was found when compaction incorrectly happened during warmupRegion.<a name="line.497"></a>
+<span class="sourceLineNo">498</span> LOG.warn("{} exists in archive. Attempted to archive nonexistent file {}.", archiveFile,<a name="line.498"></a>
+<span class="sourceLineNo">499</span> currentFile);<a name="line.499"></a>
+<span class="sourceLineNo">500</span> // We return success to match existing behavior in this method, where FileNotFoundException<a name="line.500"></a>
+<span class="sourceLineNo">501</span> // in moveAndClose is ignored.<a name="line.501"></a>
+<span class="sourceLineNo">502</span> return true;<a name="line.502"></a>
+<span class="sourceLineNo">503</span> }<a name="line.503"></a>
+<span class="sourceLineNo">504</span> // There is a conflict between the current file and the already existing archived file.<a name="line.504"></a>
+<span class="sourceLineNo">505</span> // Move the archived file to a timestamped backup. This is a really, really unlikely<a name="line.505"></a>
+<span class="sourceLineNo">506</span> // situation, where we get the same name for the existing file, but is included just for that<a name="line.506"></a>
+<span class="sourceLineNo">507</span> // 1 in trillion chance. We are potentially incurring data loss in the archive directory if<a name="line.507"></a>
+<span class="sourceLineNo">508</span> // the files are not identical. The timestamped backup will be cleaned by HFileCleaner as it<a name="line.508"></a>
+<span class="sourceLineNo">509</span> // has no references.<a name="line.509"></a>
+<span class="sourceLineNo">510</span> FileStatus curStatus = fs.getFileStatus(currentFile.getPath());<a name="line.510"></a>
+<span class="sourceLineNo">511</span> FileStatus archiveStatus = fs.getFileStatus(archiveFile);<a name="line.511"></a>
+<span class="sourceLineNo">512</span> long curLen = curStatus.getLen();<a name="line.512"></a>
+<span class="sourceLineNo">513</span> long archiveLen = archiveStatus.getLen();<a name="line.513"></a>
+<span class="sourceLineNo">514</span> long curMtime = curStatus.getModificationTime();<a name="line.514"></a>
+<span class="sourceLineNo">515</span> long archiveMtime = archiveStatus.getModificationTime();<a name="line.515"></a>
+<span class="sourceLineNo">516</span> if (curLen != archiveLen) {<a name="line.516"></a>
+<span class="sourceLineNo">517</span> LOG.error("{} already exists in archive with different size than current {}."<a name="line.517"></a>
+<span class="sourceLineNo">518</span> + " archiveLen: {} currentLen: {} archiveMtime: {} currentMtime: {}",<a name="line.518"></a>
+<span class="sourceLineNo">519</span> archiveFile, currentFile, archiveLen, curLen, archiveMtime, curMtime);<a name="line.519"></a>
+<span class="sourceLineNo">520</span> throw new IOException(archiveFile + " already exists in archive with different size" +<a name="line.520"></a>
+<span class="sourceLineNo">521</span> " than " + currentFile);<a name="line.521"></a>
+<span class="sourceLineNo">522</span> }<a name="line.522"></a>
+<span class="sourceLineNo">523</span><a name="line.523"></a>
+<span class="sourceLineNo">524</span> LOG.error("{} already exists in archive, moving to timestamped backup and overwriting"<a name="line.524"></a>
+<span class="sourceLineNo">525</span> + " current {}. archiveLen: {} currentLen: {} archiveMtime: {} currentMtime: {}",<a name="line.525"></a>
+<span class="sourceLineNo">526</span> archiveFile, currentFile, archiveLen, curLen, archiveMtime, curMtime);<a name="line.526"></a>
+<span class="sourceLineNo">527</span><a name="line.527"></a>
+<span class="sourceLineNo">528</span> // move the archive file to the stamped backup<a name="line.528"></a>
+<span class="sourceLineNo">529</span> Path backedupArchiveFile = new Path(archiveDir, filename + SEPARATOR + archiveStartTime);<a name="line.529"></a>
+<span class="sourceLineNo">530</span> if (!fs.rename(archiveFile, backedupArchiveFile)) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span> LOG.error("Could not rename archive file to backup: " + backedupArchiveFile<a name="line.531"></a>
+<span class="sourceLineNo">532</span> + ", deleting existing file in favor of newer.");<a name="line.532"></a>
+<span class="sourceLineNo">533</span> // try to delete the existing file, if we can't rename it<a name="line.533"></a>
+<span class="sourceLineNo">534</span> if (!fs.delete(archiveFile, false)) {<a name="line.534"></a>
+<span class="sourceLineNo">535</span> throw new IOException("Couldn't delete existing archive file (" + archiveFile<a name="line.535"></a>
+<span class="sourceLineNo">536</span> + ") or rename it to the backup file (" + backedupArchiveFile<a name="line.536"></a>
+<span class="sourceLineNo">537</span> + ") to make room for similarly named file.");<a name="line.537"></a>
+<span class="sourceLineNo">538</span> }<a name="line.538"></a>
+<span class="sourceLineNo">539</span> } else {<a name="line.539"></a>
+<span class="sourceLineNo">540</span> LOG.info("Backed up archive file from {} to {}.", archiveFile, backedupArchiveFile);<a name="line.540"></a>
+<span class="sourceLineNo">541</span> }<a name="line.541"></a>
+<span class="sourceLineNo">542</span> }<a name="line.542"></a>
+<span class="sourceLineNo">543</span><a name="line.543"></a>
+<span class="sourceLineNo">544</span> LOG.trace("No existing file in archive for {}, free to archive original file.", archiveFile);<a name="line.544"></a>
<span class="sourceLineNo">545</span><a name="line.545"></a>
-<span class="sourceLineNo">546</span> if (!success) {<a name="line.546"></a>
-<span class="sourceLineNo">547</span> LOG.error("Failed to archive " + currentFile);<a name="line.547"></a>
-<span class="sourceLineNo">548</span> return false;<a name="line.548"></a>
-<span class="sourceLineNo">549</span> }<a name="line.549"></a>
-<span class="sourceLineNo">550</span><a name="line.550"></a>
-<span class="sourceLineNo">551</span> LOG.debug("Archived from {} to {}", currentFile, archiveFile);<a name="line.551"></a>
-<span class="sourceLineNo">552</span> return true;<a name="line.552"></a>
-<span class="sourceLineNo">553</span> }<a name="line.553"></a>
-<span class="sourceLineNo">554</span><a name="line.554"></a>
-<span class="sourceLineNo">555</span> /**<a name="line.555"></a>
-<span class="sourceLineNo">556</span> * Without regard for backup, delete a region. Should be used with caution.<a name="line.556"></a>
-<span class="sourceLineNo">557</span> * @param regionDir {@link Path} to the region to be deleted.<a name="line.557"></a>
-<span class="sourceLineNo">558</span> * @param fs FileSystem from which to delete the region<a name="line.558"></a>
-<span class="sourceLineNo">559</span> * @return <tt>true</tt> on successful deletion, <tt>false</tt> otherwise<a name="line.559"></a>
-<span class="sourceLineNo">560</span> * @throws IOException on filesystem operation failure<a name="line.560"></a>
-<span class="sourceLineNo">561</span> */<a name="line.561"></a>
-<span class="sourceLineNo">562</span> private static boolean deleteRegionWithoutArchiving(FileSystem fs, Path regionDir)<a name="line.562"></a>
-<span class="sourceLineNo">563</span> throws IOException {<a name="line.563"></a>
-<span class="sourceLineNo">564</span> if (fs.delete(regionDir, true)) {<a name="line.564"></a>
-<span class="sourceLineNo">565</span> LOG.debug("Deleted {}", regionDir);<a name="line.565"></a>
-<span class="sourceLineNo">566</span> return true;<a name="line.566"></a>
-<span class="sourceLineNo">567</span> }<a name="line.567"></a>
-<span class="sourceLineNo">568</span> LOG.debug("Failed to delete directory {}", regionDir);<a name="line.568"></a>
-<span class="sourceLineNo">569</span> return false;<a name="line.569"></a>
-<span class="sourceLineNo">570</span> }<a name="line.570"></a>
-<span class="sourceLineNo">571</span><a name="line.571"></a>
-<span class="sourceLineNo">572</span> /**<a name="line.572"></a>
-<span class="sourceLineNo">573</span> * Just do a simple delete of the given store files<a name="line.573"></a>
-<span class="sourceLineNo">574</span> * <p><a name="line.574"></a>
-<span class="sourceLineNo">575</span> * A best effort is made to delete each of the files, rather than bailing on the first failure.<a name="line.575"></a>
-<span class="sourceLineNo">576</span> * <p><a name="line.576"></a>
-<span class="sourceLineNo">577</span> * @param compactedFiles store files to delete from the file system.<a name="line.577"></a>
-<span class="sourceLineNo">578</span> * @throws IOException if a file cannot be deleted. All files will be attempted to deleted before<a name="line.578"></a>
-<span class="sourceLineNo">579</span> * throwing the exception, rather than failing at the first file.<a name="line.579"></a>
-<span class="sourceLineNo">580</span> */<a name="line.580"></a>
-<span class="sourceLineNo">581</span> private static void deleteStoreFilesWithoutArchiving(Collection<HStoreFile> compactedFiles)<a name="line.581"></a>
-<span class="sourceLineNo">582</span> throws IOException {<a name="line.582"></a>
-<span class="sourceLineNo">583</span> LOG.debug("Deleting files without archiving.");<a name="line.583"></a>
-<span class="sourceLineNo">584</span> List<IOException> errors = new ArrayList<>(0);<a name="line.584"></a>
-<span class="sourceLineNo">585</span> for (HStoreFile hsf : compactedFiles) {<a name="line.585"></a>
-<span class="sourceLineNo">586</span> try {<a name="line.586"></a>
-<span class="sourceLineNo">587</span> hsf.deleteStoreFile();<a name="line.587"></a>
-<span class="sourceLineNo">588</span> } catch (IOException e) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span> LOG.error("Failed to delete {}", hsf.getPath());<a name="line.589"></a>
-<span class="sourceLineNo">590</span> errors.add(e);<a name="line.590"></a>
-<span class="sourceLineNo">591</span> }<a name="line.591"></a>
-<span class="sourceLineNo">592</span> }<a name="line.592"></a>
-<span class="sourceLineNo">593</span> if (errors.size() > 0) {<a name="line.593"></a>
-<span class="sourceLineNo">594</span> throw MultipleIOException.createIOException(errors);<a name="line.594"></a>
-<span class="sourceLineNo">595</span> }<a name="line.595"></a>
-<span class="sourceLineNo">596</span> }<a name="line.596"></a>
-<span class="sourceLineNo">597</span><a name="line.597"></a>
-<span class="sourceLineNo">598</span> /**<a name="line.598"></a>
-<span class="sourceLineNo">599</span> * Adapt a type to match the {@link File} interface, which is used internally for handling<a name="line.599"></a>
-<span class="sourceLineNo">600</span> * archival/removal of files<a name="line.600"></a>
-<span class="sourceLineNo">601</span> * @param <T> type to adapt to the {@link File} interface<a name="line.601"></a>
-<span class="sourceLineNo">602</span> */<a name="line.602"></a>
-<span class="sourceLineNo">603</span> private static abstract class FileConverter<T> implements Function<T, File> {<a name="line.603"></a>
-<span class="sourceLineNo">604</span> protected final FileSystem fs;<a name="line.604"></a>
-<span class="sourceLineNo">605</span><a name="line.605"></a>
-<span class="sourceLineNo">606</span> public FileConverter(FileSystem fs) {<a name="line.606"></a>
-<span class="sourceLineNo">607</span> this.fs = fs;<a name="line.607"></a>
-<span class="sourceLineNo">608</span> }<a name="line.608"></a>
-<span class="sourceLineNo">609</span> }<a name="line.609"></a>
-<span class="sourceLineNo">610</span><a name="line.610"></a>
-<span class="sourceLineNo">611</span> /**<a name="line.611"></a>
-<span class="sourceLineNo">612</span> * Convert a FileStatus to something we can manage in the archiving<a name="line.612"></a>
-<span class="sourceLineNo">613</span> */<a name="line.613"></a>
-<span class="sourceLineNo">614</span> private static class FileStatusConverter extends FileConverter<FileStatus> {<a name="line.614"></a>
-<span class="sourceLineNo">615</span> public FileStatusConverter(FileSystem fs) {<a name="line.615"></a>
-<span class="sourceLineNo">616</span> super(fs);<a name="line.616"></a>
-<span class="sourceLineNo">617</span> }<a name="line.617"></a>
-<span class="sourceLineNo">618</span><a name="line.618"></a>
-<span class="sourceLineNo">619</span> @Override<a name="line.619"></a>
-<span class="sourceLineNo">620</span> public File apply(FileStatus input) {<a name="line.620"></a>
-<span class="sourceLineNo">621</span> return new FileablePath(fs, input.getPath());<a name="line.621"></a>
-<span class="sourceLineNo">622</span> }<a name="line.622"></a>
-<span class="sourceLineNo">623</span> }<a name="line.623"></a>
-<span class="sourceLineNo">624</span><a name="line.624"></a>
-<span class="sourceLineNo">625</span> /**<a name="line.625"></a>
-<span class="sourceLineNo">626</span> * Convert the {@link HStoreFile} into something we can manage in the archive<a name="line.626"></a>
-<span class="sourceLineNo">627</span> * methods<a name="line.627"></a>
-<span class="sourceLineNo">628</span> */<a name="line.628"></a>
-<span class="sourceLineNo">629</span> private static class StoreToFile extends FileConverter<HStoreFile> {<a name="line.629"></a>
-<span class="sourceLineNo">630</span> public StoreToFile(FileSystem fs) {<a name="line.630"></a>
-<span class="sourceLineNo">631</span> super(fs);<a name="line.631"></a>
-<span class="sourceLineNo">632</span> }<a name="line.632"></a>
-<span class="sourceLineNo">633</span><a name="line.633"></a>
-<span class="sourceLineNo">634</span> @Override<a name="line.634"></a>
-<span class="sourceLineNo">635</span> public File apply(HStoreFile input) {<a name="line.635"></a>
-<span class="sourceLineNo">636</span> return new FileableStoreFile(fs, input);<a name="line.636"></a>
-<span class="sourceLineNo">637</span> }<a name="line.637"></a>
-<span class="sourceLineNo">638</span> }<a name="line.638"></a>
-<span class="sourceLineNo">639</span><a name="line.639"></a>
-<span class="sourceLineNo">640</span> /**<a name="line.640"></a>
-<span class="sourceLineNo">641</span> * Wrapper to handle file operations uniformly<a name="line.641"></a>
-<span class="sourceLineNo">642</span> */<a name="line.642"></a>
-<span class="sourceLineNo">643</span> private static abstract class File {<a name="line.643"></a>
-<span class="sourceLineNo">644</span> protected final FileSystem fs;<a name="line.644"></a>
-<span class="sourceLineNo">645</span><a name="line.645"></a>
-<span class="sourceLineNo">646</span> public File(FileSystem fs) {<a name="line.646"></a>
-<span class="sourceLineNo">647</span> this.fs = fs;<a name="line.647"></a>
+<span class="sourceLineNo">546</span> // at this point, we should have a free spot for the archive file<a name="line.546"></a>
+<span class="sourceLineNo">547</span> boolean success = false;<a name="line.547"></a>
+<span class="sourceLineNo">548</span> for (int i = 0; !success && i < DEFAULT_RETRIES_NUMBER; ++i) {<a name="line.548"></a>
+<span class="sourceLineNo">549</span> if (i > 0) {<a name="line.549"></a>
+<span class="sourceLineNo">550</span> // Ensure that the archive directory exists.<a name="line.550"></a>
+<span class="sourceLineNo">551</span> // The previous "move to archive" operation has failed probably because<a name="line.551"></a>
+<span class="sourceLineNo">552</span> // the cleaner has removed our archive directory (HBASE-7643).<a name="line.552"></a>
+<span class="sourceLineNo">553</span> // (we're in a retry loop, so don't worry too much about the exception)<a name="line.553"></a>
+<span class="sourceLineNo">554</span> try {<a name="line.554"></a>
+<span class="sourceLineNo">555</span> if (!fs.exists(archiveDir)) {<a name="line.555"></a>
+<span class="sourceLineNo">556</span> if (fs.mkdirs(archiveDir)) {<a name="line.556"></a>
+<span class="sourceLineNo">557</span> LOG.debug("Created archive directory {}", archiveDir);<a name="line.557"></a>
+<span class="sourceLineNo">558</span> }<a name="line.558"></a>
+<span class="sourceLineNo">559</span> }<a name="line.559"></a>
+<span class="sourceLineNo">560</span> } catch (IOException e) {<a name="line.560"></a>
+<span class="sourceLineNo">561</span> LOG.warn("Failed to create directory {}", archiveDir, e);<a name="line.561"></a>
+<span class="sourceLineNo">562</span> }<a name="line.562"></a>
+<span class="sourceLineNo">563</span> }<a name="line.563"></a>
+<span class="sourceLineNo">564</span><a name="line.564"></a>
+<span class="sourceLineNo">565</span> try {<a name="line.565"></a>
+<span class="sourceLineNo">566</span> success = currentFile.moveAndClose(archiveFile);<a name="line.566"></a>
+<span class="sourceLineNo">567</span> } catch (FileNotFoundException fnfe) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span> LOG.warn("Failed to archive " + currentFile +<a name="line.568"></a>
+<span class="sourceLineNo">569</span> " because it does not exist! Skipping and continuing on.", fnfe);<a name="line.569"></a>
+<span class="sourceLineNo">570</span> success = true;<a name="line.570"></a>
+<span class="sourceLineNo">571</span> } catch (IOException e) {<a name="line.571"></a>
+<span class="sourceLineNo">572</span> LOG.warn("Failed to archive " + currentFile + " on try #" + i, e);<a name="line.572"></a>
+<span class="sourceLineNo">573</span> success = false;<a name="line.573"></a>
+<span class="sourceLineNo">574</span> }<a name="line.574"></a>
+<span class="sourceLineNo">575</span> }<a name="line.575"></a>
+<span class="sourceLineNo">576</span><a name="line.576"></a>
+<span class="sourceLineNo">577</span> if (!success) {<a name="line.577"></a>
+<span class="sourceLineNo">578</span> LOG.error("Failed to archive " + currentFile);<a name="line.578"></a>
+<span class="sourceLineNo">579</span> return false;<a name="line.579"></a>
+<span class="sourceLineNo">580</span> }<a name="line.580"></a>
+<span class="sourceLineNo">581</span><a name="line.581"></a>
+<span class="sourceLineNo">582</span> LOG.debug("Archived from {} to {}", currentFile, archiveFile);<a name="line.582"></a>
+<span class="sourceLineNo">583</span> return true;<a name="line.583"></a>
+<span class="sourceLineNo">584</span> }<a name="line.584"></a>
+<span class="sourceLineNo">585</span><a name="line.585"></a>
+<span class="sourceLineNo">586</span> /**<a name="line.586"></a>
+<span class="sourceLineNo">587</span> * Without regard for backup, delete a region. Should be used with caution.<a name="line.587"></a>
+<span class="sourceLineNo">588</span> * @param regionDir {@link Path} to the region to be deleted.<a name="line.588"></a>
+<span class="sourceLineNo">589</span> * @param fs FileSystem from which to delete the region<a name="line.589"></a>
+<span class="sourceLineNo">590</span> * @return <tt>true</tt> on successful deletion, <tt>false</tt> otherwise<a name="line.590"></a>
+<span class="sourceLineNo">591</span> * @throws IOException on filesystem operation failure<a name="line.591"></a>
+<span class="sourceLineNo">592</span> */<a name="line.592"></a>
+<span class="sourceLineNo">593</span> private static boolean deleteRegionWithoutArchiving(FileSystem fs, Path regionDir)<a name="line.593"></a>
+<span class="sourceLineNo">594</span> throws IOException {<a name="line.594"></a>
+<span class="sourceLineNo">595</span> if (fs.delete(regionDir, true)) {<a name="line.595"></a>
+<span class="sourceLineNo">596</span> LOG.debug("Deleted {}", regionDir);<a name="line.596"></a>
+<span class="sourceLineNo">597</span> return true;<a name="line.597"></a>
+<span class="sourceLineNo">598</span> }<a name="line.598"></a>
+<span class="sourceLineNo">599</span> LOG.debug("Failed to delete directory {}", regionDir);<a name="line.599"></a>
+<span class="sourceLineNo">600</span> return false;<a name="line.600"></a>
+<span class="sourceLineNo">601</span> }<a name="line.601"></a>
+<span class="sourceLineNo">602</span><a name="line.602"></a>
+<span class="sourceLineNo">603</span> /**<a name="line.603"></a>
+<span class="sourceLineNo">604</span> * Just do a simple delete of the given store files<a name="line.604"></a>
+<span class="sourceLineNo">605</span> * <p><a name="line.605"></a>
+<span class="sourceLineNo">606</span> * A best effort is made to delete each of the files, rather than bailing on the first failure.<a name="line.606"></a>
+<span class="sourceLineNo">607</span> * <p><a name="line.607"></a>
+<span class="sourceLineNo">608</span> * @param compactedFiles store files to delete from the file system.<a name="line.608"></a>
+<span class="sourceLineNo">609</span> * @throws IOException if a file cannot be deleted. All files will be attempted to deleted before<a name="line.609"></a>
+<span class="sourceLineNo">610</span> * throwing the exception, rather than failing at the first file.<a name="line.610"></a>
+<span class="sourceLineNo">611</span> */<a name="line.611"></a>
+<span class="sourceLineNo">612</span> private static void deleteStoreFilesWithoutArchiving(Collection<HStoreFile> compactedFiles)<a name="line.612"></a>
+<span class="sourceLineNo">613</span> throws IOException {<a name="line.613"></a>
+<span class="sourceLineNo">614</span> LOG.debug("Deleting files without archiving.");<a name="line.614"></a>
+<span class="sourceLineNo">615</span> List<IOException> errors = new ArrayList<>(0);<a name="line.615"></a>
+<span class="sourceLineNo">616</span> for (HStoreFile hsf : compactedFiles) {<a name="line.616"></a>
+<span class="sourceLineNo">617</span> try {<a name="line.617"></a>
+<span class="sourceLineNo">618</span> hsf.deleteStoreFile();<a name="line.618"></a>
+<span class="sourceLineNo">619</span> } catch (IOException e) {<a name="line.619"></a>
+<span class="sourceLineNo">620</span> LOG.error("Failed to delete {}", hsf.getPath());<a name="line.620"></a>
+<span class="sourceLineNo">621</span> errors.add(e);<a name="line.621"></a>
+<span class="sourceLineNo">622</span> }<a name="line.622"></a>
+<span class="sourceLineNo">623</span> }<a name="line.623"></a>
+<span class="sourceLineNo">624</span> if (errors.size() > 0) {<a name="line.624"></a>
+<span class="sourceLineNo">625</span> throw MultipleIOException.createIOException(errors);<a name="line.625"></a>
+<span class="sourceLineNo">626</span> }<a name="line.626"></a>
+<span class="sourceLineNo">627</span> }<a name="line.627"></a>
+<span class="sourceLineNo">628</span><a name="line.628"></a>
+<span class="sourceLineNo">629</span> /**<a name="line.629"></a>
+<span class="sourceLineNo">630</span> * Adapt a type to match the {@link File} interface, which is used internally for handling<a name="line.630"></a>
+<span class="sourceLineNo">631</span> * archival/removal of files<a name="line.631"></a>
+<span class="sourceLineNo">632</span> * @param <T> type to adapt to the {@link File} interface<a name="line.632"></a>
+<span class="sourceLineNo">633</span> */<a name="line.633"></a>
+<span class="sourceLineNo">634</span> private static abstract class FileConverter<T> implements Function<T, File> {<a name="line.634"></a>
+<span class="sourceLineNo">635</span> protected final FileSystem fs;<a name="line.635"></a>
+<span class="sourceLineNo">636</span><a name="line.636"></a>
+<span class="sourceLineNo">637</span> public FileConverter(FileSystem fs) {<a name="line.637"></a>
+<span class="sourceLineNo">638</span> this.fs = fs;<a name="line.638"></a>
+<span class="sourceLineNo">639</span> }<a name="line.639"></a>
+<span class="sourceLineNo">640</span> }<a name="line.640"></a>
+<span class="sourceLineNo">641</span><a name="line.641"></a>
+<span class="sourceLineNo">642</span> /**<a name="line.642"></a>
+<span class="sourceLineNo">643</span> * Convert a FileStatus to something we can manage in the archiving<a name="line.643"></a>
+<span class="sourceLineNo">644</span> */<a name="line.644"></a>
+<span class="sourceLineNo">645</span> private static class FileStatusConverter extends FileConverter<FileStatus> {<a name="line.645"></a>
+<span class="sourceLineNo">646</span> public FileStatusConverter(FileSystem fs) {<a name="line.646"></a>
+<span class="sourceLineNo">647</span> super(fs);<a name="line.647"></a>
<span class="sourceLineNo">648</span> }<a name="line.648"></a>
<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span> /**<a name="line.650"></a>
-<span class="sourceLineNo">651</span> * Delete the file<a name="line.651"></a>
-<span class="sourceLineNo">652</span> * @throws IOException on failure<a name="line.652"></a>
-<span class="sourceLineNo">653</span> */<a name="line.653"></a>
-<span class="sourceLineNo">654</span> abstract void delete() throws IOException;<a name="line.654"></a>
+<span class="sourceLineNo">650</span> @Override<a name="line.650"></a>
+<span class="sourceLineNo">651</span> public File apply(FileStatus input) {<a name="line.651"></a>
+<span class="sourceLineNo">652</span> return new FileablePath(fs, input.getPath());<a name="line.652"></a>
+<span class="sourceLineNo">653</span> }<a name="line.653"></a>
+<span class="sourceLineNo">654</span> }<a name="line.654"></a>
<span class="sourceLineNo">655</span><a name="line.655"></a>
-<span class="sourceLineNo">656</span> /**<a name="line.656"></a>
-<span class="sourceLineNo">657</span> * Check to see if this is a file or a directory<a name="line.657"></a>
-<span class="sourceLineNo">658</span> * @return <tt>true</tt> if it is a file, <tt>false</tt> otherwise<a name="line.658"></a>
-<span class="sourceLineNo">659</span> * @throws IOException on {@link FileSystem} connection error<a name="line.659"></a>
-<span class="sourceLineNo">660</span> */<a name="line.660"></a>
-<span class="sourceLineNo">661</span> abstract boolean isFile() throws IOException;<a name="line.661"></a>
-<span class="sourceLineNo">662</span><a name="line.662"></a>
-<span class="sourceLineNo">663</span> /**<a name="line.663"></a>
-<span class="sourceLineNo">664</span> * @return if this is a directory, returns all the children in the<a name="line.664"></a>
-<span class="sourceLineNo">665</span> * directory, otherwise returns an empty list<a name="line.665"></a>
-<span class="sourceLineNo">666</span> * @throws IOException<a name="line.666"></a>
-<span class="sourceLineNo">667</span> */<a name="line.667"></a>
-<span class="sourceLineNo">668</span> abstract Collection<File> getChildren() throws IOException;<a name="line.668"></a>
-<span class="sourceLineNo">669</span><a name="line.669"></a>
-<span class="sourceLineNo">670</span> /**<a name="line.670"></a>
-<span class="sourceLineNo">671</span> * close any outside readers of the file<a name="line.671"></a>
-<span class="sourceLineNo">672</span> * @throws IOException<a name="line.672"></a>
-<span class="sourceLineNo">673</span> */<a name="line.673"></a>
-<span class="sourceLineNo">674</span> abstract void close() throws IOException;<a name="line.674"></a>
-<span class="sourceLineNo">675</span><a name="line.675"></a>
-<span class="sourceLineNo">676</span> /**<a name="line.676"></a>
-<span class="sourceLineNo">677</span> * @return the name of the file (not the full fs path, just the individual<a name="line.677"></a>
-<span class="sourceLineNo">678</span> * file name)<a name="line.678"></a>
-<span class="sourceLineNo">679</span> */<a name="line.679"></a>
-<span class="sourceLineNo">680</span> abstract String getName();<a name="line.680"></a>
-<span class="sourceLineNo">681</span><a name="line.681"></a>
-<span class="sourceLineNo">682</span> /**<a name="line.682"></a>
-<span class="sourceLineNo">683</span> * @return the path to this file<a name="line.683"></a>
+<span class="sourceLineNo">656</span> /**<a name="line.656"></a>
+<span class="sourceLineNo">657</span> * Convert the {@link HStoreFile} into something we can manage in the archive<a name="line.657"></a>
+<span class="sourceLineNo">658</span> * methods<a name="line.658"></a>
+<span class="sourceLineNo">659</span> */<a name="line.659"></a>
+<span class="sourceLineNo">660</span> private static class StoreToFile extends FileConverter<HStoreFile> {<a name="line.660"></a>
+<span class="sourceLineNo">661</span> public StoreToFile(FileSystem fs) {<a name="line.661"></a>
+<span class="sourceLineNo">662</span> super(fs);<a name="line.662"></a>
+<span class="sourceLineNo">663</span> }<a name="line.663"></a>
+<span class="sourceLineNo">664</span><a name="line.664"></a>
+<span class="sourceLineNo">665</span> @Override<a name="line.665"></a>
+<span class="sourceLineNo">666</span> public File apply(HStoreFile input) {<a name="line.666"></a>
+<span class="sourceLineNo">667</span> return new FileableStoreFile(fs, input);<a name="line.667"></a>
+<span class="sourceLineNo">668</span> }<a name="line.668"></a>
+<span class="sourceLineNo">669</span> }<a name="line.669"></a>
+<span class="sourceLineNo">670</span><a name="line.670"></a>
+<span class="sourceLineNo">671</span> /**<a name="line.671"></a>
+<span class="sourceLineNo">672</span> * Wrapper to handle file operations uniformly<a name="line.672"></a>
+<span class="sourceLineNo">673</span> */<a name="line.673"></a>
+<span class="sourceLineNo">674</span> private static abstract class File {<a name="line.674"></a>
+<span class="sourceLineNo">675</span> protected final FileSystem fs;<a name="line.675"></a>
+<span class="sourceLineNo">676</span><a name="line.676"></a>
+<span class="sourceLineNo">677</span> public File(FileSystem fs) {<a name="line.677"></a>
+<span class="sourceLineNo">678</span> this.fs = fs;<a name="line.678"></a>
+<span class="sourceLineNo">679</span> }<a name="line.679"></a>
+<span class="sourceLineNo">680</span><a name="line.680"></a>
+<span class="sourceLineNo">681</span> /**<a name="line.681"></a>
+<span class="sourceLineNo">682</span> * Delete the file<a name="line.682"></a>
+<span class="sourceLineNo">683</span> * @throws IOException on failure<a name="line.683"></a>
<span class="sourceLineNo">684</span> */<a name="line.684"></a>
-<span class="sourceLineNo">685</span> abstract Path getPath();<a name="line.685"></a>
+<span class="sourceLineNo">685</span> abstract void delete() throws IOException;<a name="line.685"></a>
<span class="sourceLineNo">686</span><a name="line.686"></a>
<span class="sourceLineNo">687</span> /**<a name="line.687"></a>
-<span class="sourceLineNo">688</span> * Move the file to the given destination<a name="line.688"></a>
-<span class="sourceLineNo">689</span> * @param dest<a name="line.689"></a>
-<span class="sourceLineNo">690</span> * @return <tt>true</tt> on success<a name="line.690"></a>
-<span class="sourceLineNo">691</span> * @throws IOException<a name="line.691"></a>
-<span class="sourceLineNo">692</span> */<a name="line.692"></a>
-<span class="sourceLineNo">693</span> public boolean moveAndClose(Path dest) throws IOException {<a name="line.693"></a>
-<span class="sourceLineNo">694</span> this.close();<a name="line.694"></a>
-<span class="sourceLineNo">695</span> Path p = this.getPath();<a name="line.695"></a>
-<span class="sourceLineNo">696</span> return CommonFSUtils.renameAndSetModifyTime(fs, p, dest);<a name="line.696"></a>
-<span class="sourceLineNo">697</span> }<a name="line.697"></a>
-<span class="sourceLineNo">698</span><a name="line.698"></a>
-<span class="sourceLineNo">699</span> /**<a name="line.699"></a>
-<span class="sourceLineNo">700</span> * @return the {@link FileSystem} on which this file resides<a name="line.700"></a>
-<span class="sourceLineNo">701</span> */<a name="line.701"></a>
-<span class="sourceLineNo">702</span> public FileSystem getFileSystem() {<a name="line.702"></a>
-<span class="sourceLineNo">703</span> return this.fs;<a name="line.703"></a>
-<span class="sourceLineNo">704</span> }<a name="line.704"></a>
-<span class="sourceLineNo">705</span><a name="line.705"></a>
-<span class="sourceLineNo">706</span> @Override<a name="line.706"></a>
-<span class="sourceLineNo">707</span> public String toString() {<a name="line.707"></a>
-<span class="sourceLineNo">708</span> return this.getClass().getSimpleName() + ", " + getPath().toString();<a name="line.708"></a>
-<span class="sourceLineNo">709</span> }<a name="line.709"></a>
-<span class="sourceLineNo">710</span> }<a name="line.710"></a>
-<span class="sourceLineNo">711</span><a name="line.711"></a>
-<span class="sourceLineNo">712</span> /**<a name="line.712"></a>
-<span class="sourceLineNo">713</span> * A {@link File} that wraps a simple {@link Path} on a {@link FileSystem}.<a name="line.713"></a>
-<span class="sourceLineNo">714</span> */<a name="line.714"></a>
-<span class="sourceLineNo">715</span> private static class FileablePath extends File {<a name="line.715"></a>
-<span class="sourceLineNo">716</span> private final Path file;<a name="line.716"></a>
-<span class="sourceLineNo">717</span> private final FileStatusConverter getAsFile;<a name="line.717"></a>
-<span class="sourceLineNo">718</span><a name="line.718"></a>
-<span class="sourceLineNo">719</span> public FileablePath(FileSystem fs, Path file) {<a name="line.719"></a>
-<span class="sourceLineNo">720</span> super(fs);<a name="line.720"></a>
-<span class="sourceLineNo">721</span> this.file = file;<a name="line.721"></a>
-<span class="sourceLineNo">722</span> this.getAsFile = new FileStatusConverter(fs);<a name="line.722"></a>
-<span class="sourceLineNo">723</span> }<a name="line.723"></a>
-<span class="sourceLineNo">724</span><a name="line.724"></a>
-<span class="sourceLineNo">725</span> @Override<a name="line.725"></a>
-<span class="sourceLineNo">726</span> public void delete() throws IOException {<a name="line.726"></a>
-<span class="sourceLineNo">727</span> if (!fs.delete(file, true)) throw new IOException("Failed to delete:" + this.file);<a name="line.727"></a>
+<span class="sourceLineNo">688</span> * Check to see if this is a file or a directory<a name="line.688"></a>
+<span class="sourceLineNo">689</span> * @return <tt>true</tt> if it is a file, <tt>false</tt> otherwise<a name="line.689"></a>
+<span class="sourceLineNo">690</span> * @throws IOException on {@link FileSystem} connection error<a name="line.690"></a>
+<span class="sourceLineNo">691</span> */<a name="line.691"></a>
+<span class="sourceLineNo">692</span> abstract boolean isFile() throws IOException;<a name="line.692"></a>
+<span class="sourceLineNo">693</span><a name="line.693"></a>
+<span class="sourceLineNo">694</span> /**<a name="line.694"></a>
+<span class="sourceLineNo">695</span> * @return if this is a directory, returns all the children in the<a name="line.695"></a>
+<span class="sourceLineNo">696</span> * directory, otherwise returns an empty list<a name="line.696"></a>
+<span class="sourceLineNo">697</span> * @throws IOException<a name="line.697"></a>
+<span class="sourceLineNo">698</span> */<a name="line.698"></a>
+<span class="sourceLineNo">699</span> abstract Collection<File> getChildren() throws IOException;<a name="line.699"></a>
+<span class="sourceLineNo">700</span><a name="line.700"></a>
+<span class="sourceLineNo">701</span> /**<a name="line.701"></a>
+<span class="sourceLineNo">702</span> * close any outside readers of the file<a name="line.702"></a>
+<span class="sourceLineNo">703</span> * @throws IOException<a name="line.703"></a>
+<span class="sourceLineNo">704</span> */<a name="line.704"></a>
+<span class="sourceLineNo">705</span> abstract void close() throws IOException;<a name="line.705"></a>
+<span class="sourceLineNo">706</span><a name="line.706"></a>
+<span class="sourceLineNo">707</span> /**<a name="line.707"></a>
+<span class="sourceLineNo">708</span> * @return the name of the file (not the full fs path, just the individual<a name="line.708"></a>
+<span class="sourceLineNo">709</span> * file name)<a name="line.709"></a>
+<span class="sourceLineNo">710</span> */<a name="line.710"></a>
+<span class="sourceLineNo">711</span> abstract String getName();<a name="line.711"></a>
+<span class="sourceLineNo">712</span><a name="line.712"></a>
+<span class="sourceLineNo">713</span> /**<a name="line.713"></a>
+<span class="sourceLineNo">714</span> * @return the path to this file<a name="line.714"></a>
+<span class="sourceLineNo">715</span> */<a name="line.715"></a>
+<span class="sourceLineNo">716</span> abstract Path getPath();<a name="line.716"></a>
+<span class="sourceLineNo">717</span><a name="line.717"></a>
+<span class="sourceLineNo">718</span> /**<a name="line.718"></a>
+<span class="sourceLineNo">719</span> * Move the file to the given destination<a name="line.719"></a>
+<span class="sourceLineNo">720</span> * @param dest<a name="line.720"></a>
+<span class="sourceLineNo">721</span> * @return <tt>true</tt> on success<a name="line.721"></a>
+<span class="sourceLineNo">722</span> * @throws IOException<a name="line.722"></a>
+<span class="sourceLineNo">723</span> */<a name="line.723"></a>
+<span class="sourceLineNo">724</span> public boolean moveAndClose(Path dest) throws IOException {<a name="line.724"></a>
+<span class="sourceLineNo">725</span> this.close();<a name="line.725"></a>
+<span class="sourceLineNo">726</span> Path p = this.getPath();<a name="line.726"></a>
+<span class="sourceLineNo">727</span> return CommonFSUtils.renameAndSetModifyTime(fs, p, dest);<a name="line.727"></a>
<span class="sourceLineNo">728</span> }<a name="line.728"></a>
<span class="sourceLineNo">729</span><a name="line.729"></a>
-<span class="sourceLineNo">730</span> @Override<a name="line.730"></a>
-<span class="sourceLineNo">731</span> public String getName() {<a name="line.731"></a>
-<span class="sourceLineNo">732</span> return file.getName();<a name="line.732"></a>
-<span class="sourceLineNo">733</span> }<a name="line.733"></a>
-<span class="sourceLineNo">734</span><a name="line.734"></a>
-<span class="sourceLineNo">735</span> @Override<a name="line.735"></a>
-<span class="sourceLineNo">736</span> public Collection<File> getChildren() throws IOException {<a name="line.736"></a>
-<span class="sourceLineNo">737</span> if (fs.isFile(file)) {<a name="line.737"></a>
-<span class="sourceLineNo">738</span> return Collections.emptyList();<a name="line.738"></a>
-<span class="sourceLineNo">739</span> }<a name="line.739"></a>
-<span class="sourceLineNo">740</span> return Stream.of(fs.listStatus(file)).map(getAsFile).collect(Collectors.toList());<a name="line.740"></a>
-<span class="sourceLineNo">741</span> }<a name="line.741"></a>
+<span class="sourceLineNo">730</span> /**<a name="line.730"></a>
+<span class="sourceLineNo">731</span> * @return the {@link FileSystem} on which this file resides<a name="line.731"></a>
+<span class="sourceLineNo">732</span> */<a name="line.732"></a>
+<span class="sourceLineNo">733</span> public FileSystem getFileSystem() {<a name="line.733"></a>
+<span class="sourceLineNo">734</span> return this.fs;<a name="line.734"></a>
+<span class="sourceLineNo">735</span> }<a name="line.735"></a>
+<span class="sourceLineNo">736</span><a name="line.736"></a>
+<span class="sourceLineNo">737</span> @Override<a name="line.737"></a>
+<span class="sourceLineNo">738</span> public String toString() {<a name="line.738"></a>
+<span class="sourceLineNo">739</span> return this.getClass().getSimpleName() + ", " + getPath().toString();<a name="line.739"></a>
+<span class="sourceLineNo">740</span> }<a name="line.740"></a>
+<span class="sourceLineNo">741</span> }<a name="line.741"></a>
<span class="sourceLineNo">742</span><a name="line.742"></a>
-<span class="sourceLineNo">743</span> @Override<a name="line.743"></a>
-<span class="sourceLineNo">744</span> public boolean isFile() throws IOException {<a name="line.744"></a>
-<span class="sourceLineNo">745</span> return fs.isFile(file);<a name="line.745"></a>
-<span class="sourceLineNo">746</span> }<a name="line.746"></a>
-<span class="sourceLineNo">747</span><a name="line.747"></a>
-<span class="sourceLineNo">748</span> @Override<a name="line.748"></a>
-<span class="sourceLineNo">749</span> public void close() throws IOException {<a name="line.749"></a>
-<span class="sourceLineNo">750</span> // NOOP - files are implicitly closed on removal<a name="line.750"></a>
-<span class="sourceLineNo">751</span> }<a name="line.751"></a>
-<span class="sourceLineNo">752</span><a name="line.752"></a>
-<span class="sourceLineNo">753</span> @Override<a name="line.753"></a>
-<span class="sourceLineNo">754</span> Path getPath() {<a name="line.754"></a>
-<span class="sourceLineNo">755</span> return file;<a name="line.755"></a>
-<span class="sourceLineNo">756</span> }<a name="line.756"></a>
-<span class="sourceLineNo">757</span> }<a name="line.757"></a>
-<span class="sourceLineNo">758</span><a name="line.758"></a>
-<span class="sourceLineNo">759</span> /**<a name="line.759"></a>
-<span class="sourceLineNo">760</span> * {@link File} adapter for a {@link HStoreFile} living on a {@link FileSystem}<a name="line.760"></a>
-<span class="sourceLineNo">761</span> * .<a name="line.761"></a>
-<span class="sourceLineNo">762</span> */<a name="line.762"></a>
-<span class="sourceLineNo">763</span> private static class FileableStoreFile extends File {<a name="line.763"></a>
-<span class="sourceLineNo">764</span> HStoreFile file;<a name="line.764"></a>
+<span class="sourceLineNo">743</span> /**<a name="line.743"></a>
+<span class="sourceLineNo">744</span> * A {@link File} that wraps a simple {@link Path} on a {@link FileSystem}.<a name="line.744"></a>
+<span class="sourceLineNo">745</span> */<a name="line.745"></a>
+<span class="sourceLineNo">746</span> private static class FileablePath extends File {<a name="line.746"></a>
+<span class="sourceLineNo">747</span> private final Path file;<a name="line.747"></a>
+<span class="sourceLineNo">748</span> private final FileStatusConverter getAsFile;<a name="line.748"></a>
+<span class="sourceLineNo">749</span><a name="line.749"></a>
+<span class="sourceLineNo">750</span> public FileablePath(FileSystem fs, Path file) {<a name="line.750"></a>
+<span class="sourceLineNo">751</span> super(fs);<a name="line.751"></a>
+<span class="sourceLineNo">752</span> this.file = file;<a name="line.752"></a>
+<span class="sourceLineNo">753</span> this.getAsFile = new FileStatusConverter(fs);<a name="line.753"></a>
+<span class="sourceLineNo">754</span> }<a name="line.754"></a>
+<span class="sourceLineNo">755</span><a name="line.755"></a>
+<span class="sourceLineNo">756</span> @Override<a name="line.756"></a>
+<span class="sourceLineNo">757</span> public void delete() throws IOException {<a name="line.757"></a>
+<span class="sourceLineNo">758</span> if (!fs.delete(file, true)) throw new IOException("Failed to delete:" + this.file);<a name="line.758"></a>
+<span class="sourceLineNo">759</span> }<a name="line.759"></a>
+<span class="sourceLineNo">760</span><a name="line.760"></a>
+<span class="sourceLineNo">761</span> @Override<a name="line.761"></a>
+<span class="sourceLineNo">762</span> public String getName() {<a name="line.762"></a>
+<span class="sourceLineNo">763</span> return file.getName();<a name="line.763"></a>
+<span class="sourceLineNo">764</span> }<a name="line.764"></a>
<span class="sourceLineNo">765</span><a name="line.765"></a>
-<span class="sourceLineNo">766</span> public FileableStoreFile(FileSystem fs, HStoreFile store) {<a name="line.766"></a>
-<span class="sourceLineNo">767</span> super(fs);<a name="line.767"></a>
-<span class="sourceLineNo">768</span> this.file = store;<a name="line.768"></a>
-<span class="sourceLineNo">769</span> }<a name="line.769"></a>
-<span class="sourceLineNo">770</span><a name="line.770"></a>
-<span class="sourceLineNo">771</span> @Override<a name="line.771"></a>
-<span class="sourceLineNo">772</span> public void delete() throws IOException {<a name="line.772"></a>
-<span class="sourceLineNo">773</span> file.deleteStoreFile();<a name="line.773"></a>
-<span class="sourceLineNo">774</span> }<a name="line.774"></a>
-<span class="sourceLineNo">775</span><a name="line.775"></a>
-<span class="sourceLineNo">776</span> @Override<a name="line.776"></a>
-<span class="sourceLineNo">777</span> public String getName() {<a name="line.777"></a>
-<span class="sourceLineNo">778</span> return file.getPath().getName();<a name="line.778"></a>
-<span class="sourceLineNo">779</span> }<a name="line.779"></a>
-<span class="sourceLineNo">780</span><a name="line.780"></a>
-<span class="sourceLineNo">781</span> @Override<a name="line.781"></a>
-<span class="sourceLineNo">782</span> public boolean isFile() {<a name="line.782"></a>
-<span class="sourceLineNo">783</span> return true;<a name="line.783"></a>
-<span class="sourceLineNo">784</span> }<a name="line.784"></a>
-<span class="sourceLineNo">785</span><a name="line.785"></a>
-<span class="sourceLineNo">786</span> @Override<a name="line.786"></a>
-<span class="sourceLineNo">787</span> public Collection<File> getChildren() throws IOException {<a name="line.787"></a>
-<span class="sourceLineNo">788</span> // storefiles don't have children<a name="line.788"></a>
-<span class="sourceLineNo">789</span> return Collections.emptyList();<a name="line.789"></a>
-<span class="sourceLineNo">790</span> }<a name="line.790"></a>
-<span class="sourceLineNo">791</span><a name="line.791"></a>
-<span class="sourceLineNo">792</span> @Override<a name="line.792"></a>
-<span class="sourceLineNo">793</span> public void close() throws IOException {<a name="line.793"></a>
-<span class="sourceLineNo">794</span> file.closeStoreFile(true);<a name="line.794"></a>
-<span class="sourceLineNo">795</span> }<a name="line.795"></a>
+<span class="sourceLineNo">766</span> @Override<a name="line.766"></a>
+<span class="sourceLineNo">767</span> public Collection<File> getChildren() throws IOException {<a name="line.767"></a>
+<span class="sourceLineNo">768</span> if (fs.isFile(file)) {<a name="line.768"></a>
+<span class="sourceLineNo">769</span> return Collections.emptyList();<a name="line.769"></a>
+<span class="sourceLineNo">770</span> }<a name="line.770"></a>
+<span class="sourceLineNo">771</span> return Stream.of(fs.listStatus(file)).map(getAsFile).collect(Collectors.toList());<a name="line.771"></a>
+<span class="sourceLineNo">772</span> }<a name="line.772"></a>
+<span class="sourceLineNo">773</span><a name="line.773"></a>
+<span class="sourceLineNo">774</span> @Override<a name="line.774"></a>
+<span class="sourceLineNo">775</span> public boolean isFile() throws IOException {<a name="line.775"></a>
+<span class="sourceLineNo">776</span> return fs.isFile(file);<a name="line.776"></a>
+<span class="sourceLineNo">777</span> }<a name="line.777"></a>
+<span class="sourceLineNo">778</span><a name="line.778"></a>
+<span class="sourceLineNo">779</span> @Override<a name="line.779"></a>
+<span class="sourceLineNo">780</span> public void close() throws IOException {<a name="line.780"></a>
+<span class="sourceLineNo">781</span> // NOOP - files are implicitly closed on removal<a name="line.781"></a>
+<span class="sourceLineNo">782</span> }<a name="line.782"></a>
+<span class="sourceLineNo">783</span><a name="line.783"></a>
+<span class="sourceLineNo">784</span> @Override<a name="line.784"></a>
+<span class="sourceLineNo">785</span> Path getPath() {<a name="line.785"></a>
+<span class="sourceLineNo">786</span> return file;<a name="line.786"></a>
+<span class="sourceLineNo">787</span> }<a name="line.787"></a>
+<span class="sourceLineNo">788</span> }<a name="line.788"></a>
+<span class="sourceLineNo">789</span><a name="line.789"></a>
+<span class="sourceLineNo">790</span> /**<a name="line.790"></a>
+<span class="sourceLineNo">791</span> * {@link File} adapter for a {@link HStoreFile} living on a {@link FileSystem}<a name="line.791"></a>
+<span class="sourceLineNo">792</span> * .<a name="line.792"></a>
+<span class="sourceLineNo">793</span> */<a name="line.793"></a>
+<span class="sourceLineNo">794</span> private static class FileableStoreFile extends File {<a name="line.794"></a>
+<span class="sourceLineNo">795</span> HStoreFile file;<a name="line.795"></a>
<span class="sourceLineNo">796</span><a name="line.796"></a>
-<span class="sourceLineNo">797</span> @Override<a name="line.797"></a>
-<span class="sourceLineNo">798</span> Path getPath() {<a name="line.798"></a>
-<span class="sourceLineNo">799</span> return file.getPath();<a name="line.799"></a>
+<span class="sourceLineNo">797</span> public FileableStoreFile(FileSystem fs, HStoreFile store) {<a name="line.797"></a>
+<span class="sourceLineNo">798</span> super(fs);<a name="line.798"></a>
+<span class="sourceLineNo">799</span> this.file = store;<a name="line.799"></a>
<span class="sourceLineNo">800</span> }<a name="line.800"></a>
-<span class="sourceLineNo">801</span> }<a name="line.801"></a>
-<span class="sourceLineNo">802</span>}<a name="line.802"></a>
+<span class="sourceLineNo">801</span><a name="line.801"></a>
+<span class="sourceLineNo">802</span> @Override<a name="line.802"></a>
+<span class="sourceLineNo">803</span> public void delete() throws IOException {<a name="line.803"></a>
+<span class="sourceLineNo">804</span> file.deleteStoreFile();<a name="line.804"></a>
+<span class="sourceLineNo">805</span> }<a name="line.805"></a>
+<span class="sourceLineNo">806</span><a name="line.806"></a>
+<span class="sourceLineNo">807</span> @Override<a name="line.807"></a>
+<span class="sourceLineNo">808</span> public String getName() {<a name="line.808"></a>
+<span class="sourceLineNo">809</span> return file.getPath().getName();<a name="line.809"></a>
+<span class="sourceLineNo">810</span> }<a name="line.810"></a>
+<span class="sourceLineNo">811</span><a name="line.811"></a>
+<span class="sourceLineNo">812</span> @Override<a name="line.812"></a>
+<span class="sourceLineNo">813</span> public boolean isFile() {<a name="line.813"></a>
+<span class="sourceLineNo">814</span> return true;<a name="line.814"></a>
+<span class="sourceLineNo">815</span> }<a name="line.815"></a>
+<span class="sourceLineNo">816</span><a name="line.816"></a>
+<span class="sourceLineNo">817</span> @Override<a name="line.817"></a>
+<span class="sourceLineNo">818</span> public Collection<File> getChildren() throws IOException {<a name="line.818"></a>
+<span class="sourceLineNo">819</span> // storefiles don't have children<a name="line.819"></a>
+<span class="sourceLineNo">820</span> return Collections.emptyList();<a name="line.820"></a>
+<span class="sourceLineNo">821</span> }<a name="line.821"></a>
+<span class="sourceLineNo">822</span><a name="line.822"></a>
+<span class="sourceLineNo">823</span> @Override<a name="line.823"></a>
+<span class="sourceLineNo">824</span> public void close() throws IOException {<a name="line.824"></a>
+<span class="sourceLineNo">825</span> file.closeStoreFile(true);<a name="line.825"></a>
+<span class="sourceLineNo">826</span> }<a name="line.826"></a>
+<span class="sourceLineNo">827</span><a name="line.827"></a>
+<span class="sourceLineNo">828</span> @Override<a name="line.828"></a>
+<span class="sourceLineNo">829</span> Path getPath() {<a name="line.829"></a>
+<span class="sourceLineNo">830</span> return file.getPath();<a name="line.830"></a>
+<span class="sourceLineNo">831</span> }<a name="line.831"></a>
+<span class="sourceLineNo">832</span> }<a name="line.832"></a>
+<span class="sourceLineNo">833</span>}<a name="line.833"></a>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileStatusConverter.html b/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileStatusConverter.html
index 22ea136..ee79f25 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileStatusConverter.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileStatusConverter.html
@@ -496,318 +496,349 @@
<span class="sourceLineNo">488</span> Path archiveFile = new Path(archiveDir, filename);<a name="line.488"></a>
<span class="sourceLineNo">489</span> FileSystem fs = currentFile.getFileSystem();<a name="line.489"></a>
<span class="sourceLineNo">490</span><a name="line.490"></a>
-<span class="sourceLineNo">491</span> // if the file already exists in the archive, move that one to a timestamped backup. This is a<a name="line.491"></a>
-<span class="sourceLineNo">492</span> // really, really unlikely situtation, where we get the same name for the existing file, but<a name="line.492"></a>
-<span class="sourceLineNo">493</span> // is included just for that 1 in trillion chance.<a name="line.493"></a>
-<span class="sourceLineNo">494</span> if (fs.exists(archiveFile)) {<a name="line.494"></a>
-<span class="sourceLineNo">495</span> LOG.debug("{} already exists in archive, moving to timestamped backup and " +<a name="line.495"></a>
-<span class="sourceLineNo">496</span> "overwriting current.", archiveFile);<a name="line.496"></a>
-<span class="sourceLineNo">497</span><a name="line.497"></a>
-<span class="sourceLineNo">498</span> // move the archive file to the stamped backup<a name="line.498"></a>
-<span class="sourceLineNo">499</span> Path backedupArchiveFile = new Path(archiveDir, filename + SEPARATOR + archiveStartTime);<a name="line.499"></a>
-<span class="sourceLineNo">500</span> if (!fs.rename(archiveFile, backedupArchiveFile)) {<a name="line.500"></a>
-<span class="sourceLineNo">501</span> LOG.error("Could not rename archive file to backup: " + backedupArchiveFile<a name="line.501"></a>
-<span class="sourceLineNo">502</span> + ", deleting existing file in favor of newer.");<a name="line.502"></a>
-<span class="sourceLineNo">503</span> // try to delete the exisiting file, if we can't rename it<a name="line.503"></a>
-<span class="sourceLineNo">504</span> if (!fs.delete(archiveFile, false)) {<a name="line.504"></a>
-<span class="sourceLineNo">505</span> throw new IOException("Couldn't delete existing archive file (" + archiveFile<a name="line.505"></a>
-<span class="sourceLineNo">506</span> + ") or rename it to the backup file (" + backedupArchiveFile<a name="line.506"></a>
-<span class="sourceLineNo">507</span> + ") to make room for similarly named file.");<a name="line.507"></a>
-<span class="sourceLineNo">508</span> }<a name="line.508"></a>
-<span class="sourceLineNo">509</span> }<a name="line.509"></a>
-<span class="sourceLineNo">510</span> LOG.debug("Backed up archive file from " + archiveFile);<a name="line.510"></a>
-<span class="sourceLineNo">511</span> }<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span> LOG.trace("No existing file in archive for {}, free to archive original file.", archiveFile);<a name="line.513"></a>
-<span class="sourceLineNo">514</span><a name="line.514"></a>
-<span class="sourceLineNo">515</span> // at this point, we should have a free spot for the archive file<a name="line.515"></a>
-<span class="sourceLineNo">516</span> boolean success = false;<a name="line.516"></a>
-<span class="sourceLineNo">517</span> for (int i = 0; !success && i < DEFAULT_RETRIES_NUMBER; ++i) {<a name="line.517"></a>
-<span class="sourceLineNo">518</span> if (i > 0) {<a name="line.518"></a>
-<span class="sourceLineNo">519</span> // Ensure that the archive directory exists.<a name="line.519"></a>
-<span class="sourceLineNo">520</span> // The previous "move to archive" operation has failed probably because<a name="line.520"></a>
-<span class="sourceLineNo">521</span> // the cleaner has removed our archive directory (HBASE-7643).<a name="line.521"></a>
-<span class="sourceLineNo">522</span> // (we're in a retry loop, so don't worry too much about the exception)<a name="line.522"></a>
-<span class="sourceLineNo">523</span> try {<a name="line.523"></a>
-<span class="sourceLineNo">524</span> if (!fs.exists(archiveDir)) {<a name="line.524"></a>
-<span class="sourceLineNo">525</span> if (fs.mkdirs(archiveDir)) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span> LOG.debug("Created archive directory {}", archiveDir);<a name="line.526"></a>
-<span class="sourceLineNo">527</span> }<a name="line.527"></a>
-<span class="sourceLineNo">528</span> }<a name="line.528"></a>
-<span class="sourceLineNo">529</span> } catch (IOException e) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span> LOG.warn("Failed to create directory {}", archiveDir, e);<a name="line.530"></a>
-<span class="sourceLineNo">531</span> }<a name="line.531"></a>
-<span class="sourceLineNo">532</span> }<a name="line.532"></a>
-<span class="sourceLineNo">533</span><a name="line.533"></a>
-<span class="sourceLineNo">534</span> try {<a name="line.534"></a>
-<span class="sourceLineNo">535</span> success = currentFile.moveAndClose(archiveFile);<a name="line.535"></a>
-<span class="sourceLineNo">536</span> } catch (FileNotFoundException fnfe) {<a name="line.536"></a>
-<span class="sourceLineNo">537</span> LOG.warn("Failed to archive " + currentFile +<a name="line.537"></a>
-<span class="sourceLineNo">538</span> " because it does not exist! Skipping and continuing on.", fnfe);<a name="line.538"></a>
-<span class="sourceLineNo">539</span> success = true;<a name="line.539"></a>
-<span class="sourceLineNo">540</span> } catch (IOException e) {<a name="line.540"></a>
-<span class="sourceLineNo">541</span> LOG.warn("Failed to archive " + currentFile + " on try #" + i, e);<a name="line.541"></a>
-<span class="sourceLineNo">542</span> success = false;<a name="line.542"></a>
-<span class="sourceLineNo">543</span> }<a name="line.543"></a>
-<span class="sourceLineNo">544</span> }<a name="line.544"></a>
+<span class="sourceLineNo">491</span> // An existing destination file in the archive is unexpected, but we handle it here.<a name="line.491"></a>
+<span class="sourceLineNo">492</span> if (fs.exists(archiveFile)) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span> if (!fs.exists(currentFile.getPath())) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span> // If the file already exists in the archive, and there is no current file to archive, then<a name="line.494"></a>
+<span class="sourceLineNo">495</span> // assume that the file in archive is correct. This is an unexpected situation, suggesting a<a name="line.495"></a>
+<span class="sourceLineNo">496</span> // race condition or split brain.<a name="line.496"></a>
+<span class="sourceLineNo">497</span> // In HBASE-26718 this was found when compaction incorrectly happened during warmupRegion.<a name="line.497"></a>
+<span class="sourceLineNo">498</span> LOG.warn("{} exists in archive. Attempted to archive nonexistent file {}.", archiveFile,<a name="line.498"></a>
+<span class="sourceLineNo">499</span> currentFile);<a name="line.499"></a>
+<span class="sourceLineNo">500</span> // We return success to match existing behavior in this method, where FileNotFoundException<a name="line.500"></a>
+<span class="sourceLineNo">501</span> // in moveAndClose is ignored.<a name="line.501"></a>
+<span class="sourceLineNo">502</span> return true;<a name="line.502"></a>
+<span class="sourceLineNo">503</span> }<a name="line.503"></a>
+<span class="sourceLineNo">504</span> // There is a conflict between the current file and the already existing archived file.<a name="line.504"></a>
+<span class="sourceLineNo">505</span> // Move the archived file to a timestamped backup. This is a really, really unlikely<a name="line.505"></a>
+<span class="sourceLineNo">506</span> // situation, where we get the same name for the existing file, but is included just for that<a name="line.506"></a>
+<span class="sourceLineNo">507</span> // 1 in trillion chance. We are potentially incurring data loss in the archive directory if<a name="line.507"></a>
+<span class="sourceLineNo">508</span> // the files are not identical. The timestamped backup will be cleaned by HFileCleaner as it<a name="line.508"></a>
+<span class="sourceLineNo">509</span> // has no references.<a name="line.509"></a>
+<span class="sourceLineNo">510</span> FileStatus curStatus = fs.getFileStatus(currentFile.getPath());<a name="line.510"></a>
+<span class="sourceLineNo">511</span> FileStatus archiveStatus = fs.getFileStatus(archiveFile);<a name="line.511"></a>
+<span class="sourceLineNo">512</span> long curLen = curStatus.getLen();<a name="line.512"></a>
+<span class="sourceLineNo">513</span> long archiveLen = archiveStatus.getLen();<a name="line.513"></a>
+<span class="sourceLineNo">514</span> long curMtime = curStatus.getModificationTime();<a name="line.514"></a>
+<span class="sourceLineNo">515</span> long archiveMtime = archiveStatus.getModificationTime();<a name="line.515"></a>
+<span class="sourceLineNo">516</span> if (curLen != archiveLen) {<a name="line.516"></a>
+<span class="sourceLineNo">517</span> LOG.error("{} already exists in archive with different size than current {}."<a name="line.517"></a>
+<span class="sourceLineNo">518</span> + " archiveLen: {} currentLen: {} archiveMtime: {} currentMtime: {}",<a name="line.518"></a>
+<span class="sourceLineNo">519</span> archiveFile, currentFile, archiveLen, curLen, archiveMtime, curMtime);<a name="line.519"></a>
+<span class="sourceLineNo">520</span> throw new IOException(archiveFile + " already exists in archive with different size" +<a name="line.520"></a>
+<span class="sourceLineNo">521</span> " than " + currentFile);<a name="line.521"></a>
+<span class="sourceLineNo">522</span> }<a name="line.522"></a>
+<span class="sourceLineNo">523</span><a name="line.523"></a>
+<span class="sourceLineNo">524</span> LOG.error("{} already exists in archive, moving to timestamped backup and overwriting"<a name="line.524"></a>
+<span class="sourceLineNo">525</span> + " current {}. archiveLen: {} currentLen: {} archiveMtime: {} currentMtime: {}",<a name="line.525"></a>
+<span class="sourceLineNo">526</span> archiveFile, currentFile, archiveLen, curLen, archiveMtime, curMtime);<a name="line.526"></a>
+<span class="sourceLineNo">527</span><a name="line.527"></a>
+<span class="sourceLineNo">528</span> // move the archive file to the stamped backup<a name="line.528"></a>
+<span class="sourceLineNo">529</span> Path backedupArchiveFile = new Path(archiveDir, filename + SEPARATOR + archiveStartTime);<a name="line.529"></a>
+<span class="sourceLineNo">530</span> if (!fs.rename(archiveFile, backedupArchiveFile)) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span> LOG.error("Could not rename archive file to backup: " + backedupArchiveFile<a name="line.531"></a>
+<span class="sourceLineNo">532</span> + ", deleting existing file in favor of newer.");<a name="line.532"></a>
+<span class="sourceLineNo">533</span> // try to delete the existing file, if we can't rename it<a name="line.533"></a>
+<span class="sourceLineNo">534</span> if (!fs.delete(archiveFile, false)) {<a name="line.534"></a>
+<span class="sourceLineNo">535</span> throw new IOException("Couldn't delete existing archive file (" + archiveFile<a name="line.535"></a>
+<span class="sourceLineNo">536</span> + ") or rename it to the backup file (" + backedupArchiveFile<a name="line.536"></a>
+<span class="sourceLineNo">537</span> + ") to make room for similarly named file.");<a name="line.537"></a>
+<span class="sourceLineNo">538</span> }<a name="line.538"></a>
+<span class="sourceLineNo">539</span> } else {<a name="line.539"></a>
+<span class="sourceLineNo">540</span> LOG.info("Backed up archive file from {} to {}.", archiveFile, backedupArchiveFile);<a name="line.540"></a>
+<span class="sourceLineNo">541</span> }<a name="line.541"></a>
+<span class="sourceLineNo">542</span> }<a name="line.542"></a>
+<span class="sourceLineNo">543</span><a name="line.543"></a>
+<span class="sourceLineNo">544</span> LOG.trace("No existing file in archive for {}, free to archive original file.", archiveFile);<a name="line.544"></a>
<span class="sourceLineNo">545</span><a name="line.545"></a>
-<span class="sourceLineNo">546</span> if (!success) {<a name="line.546"></a>
-<span class="sourceLineNo">547</span> LOG.error("Failed to archive " + currentFile);<a name="line.547"></a>
-<span class="sourceLineNo">548</span> return false;<a name="line.548"></a>
-<span class="sourceLineNo">549</span> }<a name="line.549"></a>
-<span class="sourceLineNo">550</span><a name="line.550"></a>
-<span class="sourceLineNo">551</span> LOG.debug("Archived from {} to {}", currentFile, archiveFile);<a name="line.551"></a>
-<span class="sourceLineNo">552</span> return true;<a name="line.552"></a>
-<span class="sourceLineNo">553</span> }<a name="line.553"></a>
-<span class="sourceLineNo">554</span><a name="line.554"></a>
-<span class="sourceLineNo">555</span> /**<a name="line.555"></a>
-<span class="sourceLineNo">556</span> * Without regard for backup, delete a region. Should be used with caution.<a name="line.556"></a>
-<span class="sourceLineNo">557</span> * @param regionDir {@link Path} to the region to be deleted.<a name="line.557"></a>
-<span class="sourceLineNo">558</span> * @param fs FileSystem from which to delete the region<a name="line.558"></a>
-<span class="sourceLineNo">559</span> * @return <tt>true</tt> on successful deletion, <tt>false</tt> otherwise<a name="line.559"></a>
-<span class="sourceLineNo">560</span> * @throws IOException on filesystem operation failure<a name="line.560"></a>
-<span class="sourceLineNo">561</span> */<a name="line.561"></a>
-<span class="sourceLineNo">562</span> private static boolean deleteRegionWithoutArchiving(FileSystem fs, Path regionDir)<a name="line.562"></a>
-<span class="sourceLineNo">563</span> throws IOException {<a name="line.563"></a>
-<span class="sourceLineNo">564</span> if (fs.delete(regionDir, true)) {<a name="line.564"></a>
-<span class="sourceLineNo">565</span> LOG.debug("Deleted {}", regionDir);<a name="line.565"></a>
-<span class="sourceLineNo">566</span> return true;<a name="line.566"></a>
-<span class="sourceLineNo">567</span> }<a name="line.567"></a>
-<span class="sourceLineNo">568</span> LOG.debug("Failed to delete directory {}", regionDir);<a name="line.568"></a>
-<span class="sourceLineNo">569</span> return false;<a name="line.569"></a>
-<span class="sourceLineNo">570</span> }<a name="line.570"></a>
-<span class="sourceLineNo">571</span><a name="line.571"></a>
-<span class="sourceLineNo">572</span> /**<a name="line.572"></a>
-<span class="sourceLineNo">573</span> * Just do a simple delete of the given store files<a name="line.573"></a>
-<span class="sourceLineNo">574</span> * <p><a name="line.574"></a>
-<span class="sourceLineNo">575</span> * A best effort is made to delete each of the files, rather than bailing on the first failure.<a name="line.575"></a>
-<span class="sourceLineNo">576</span> * <p><a name="line.576"></a>
-<span class="sourceLineNo">577</span> * @param compactedFiles store files to delete from the file system.<a name="line.577"></a>
-<span class="sourceLineNo">578</span> * @throws IOException if a file cannot be deleted. All files will be attempted to deleted before<a name="line.578"></a>
-<span class="sourceLineNo">579</span> * throwing the exception, rather than failing at the first file.<a name="line.579"></a>
-<span class="sourceLineNo">580</span> */<a name="line.580"></a>
-<span class="sourceLineNo">581</span> private static void deleteStoreFilesWithoutArchiving(Collection<HStoreFile> compactedFiles)<a name="line.581"></a>
-<span class="sourceLineNo">582</span> throws IOException {<a name="line.582"></a>
-<span class="sourceLineNo">583</span> LOG.debug("Deleting files without archiving.");<a name="line.583"></a>
-<span class="sourceLineNo">584</span> List<IOException> errors = new ArrayList<>(0);<a name="line.584"></a>
-<span class="sourceLineNo">585</span> for (HStoreFile hsf : compactedFiles) {<a name="line.585"></a>
-<span class="sourceLineNo">586</span> try {<a name="line.586"></a>
-<span class="sourceLineNo">587</span> hsf.deleteStoreFile();<a name="line.587"></a>
-<span class="sourceLineNo">588</span> } catch (IOException e) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span> LOG.error("Failed to delete {}", hsf.getPath());<a name="line.589"></a>
-<span class="sourceLineNo">590</span> errors.add(e);<a name="line.590"></a>
-<span class="sourceLineNo">591</span> }<a name="line.591"></a>
-<span class="sourceLineNo">592</span> }<a name="line.592"></a>
-<span class="sourceLineNo">593</span> if (errors.size() > 0) {<a name="line.593"></a>
-<span class="sourceLineNo">594</span> throw MultipleIOException.createIOException(errors);<a name="line.594"></a>
-<span class="sourceLineNo">595</span> }<a name="line.595"></a>
-<span class="sourceLineNo">596</span> }<a name="line.596"></a>
-<span class="sourceLineNo">597</span><a name="line.597"></a>
-<span class="sourceLineNo">598</span> /**<a name="line.598"></a>
-<span class="sourceLineNo">599</span> * Adapt a type to match the {@link File} interface, which is used internally for handling<a name="line.599"></a>
-<span class="sourceLineNo">600</span> * archival/removal of files<a name="line.600"></a>
-<span class="sourceLineNo">601</span> * @param <T> type to adapt to the {@link File} interface<a name="line.601"></a>
-<span class="sourceLineNo">602</span> */<a name="line.602"></a>
-<span class="sourceLineNo">603</span> private static abstract class FileConverter<T> implements Function<T, File> {<a name="line.603"></a>
-<span class="sourceLineNo">604</span> protected final FileSystem fs;<a name="line.604"></a>
-<span class="sourceLineNo">605</span><a name="line.605"></a>
-<span class="sourceLineNo">606</span> public FileConverter(FileSystem fs) {<a name="line.606"></a>
-<span class="sourceLineNo">607</span> this.fs = fs;<a name="line.607"></a>
-<span class="sourceLineNo">608</span> }<a name="line.608"></a>
-<span class="sourceLineNo">609</span> }<a name="line.609"></a>
-<span class="sourceLineNo">610</span><a name="line.610"></a>
-<span class="sourceLineNo">611</span> /**<a name="line.611"></a>
-<span class="sourceLineNo">612</span> * Convert a FileStatus to something we can manage in the archiving<a name="line.612"></a>
-<span class="sourceLineNo">613</span> */<a name="line.613"></a>
-<span class="sourceLineNo">614</span> private static class FileStatusConverter extends FileConverter<FileStatus> {<a name="line.614"></a>
-<span class="sourceLineNo">615</span> public FileStatusConverter(FileSystem fs) {<a name="line.615"></a>
-<span class="sourceLineNo">616</span> super(fs);<a name="line.616"></a>
-<span class="sourceLineNo">617</span> }<a name="line.617"></a>
-<span class="sourceLineNo">618</span><a name="line.618"></a>
-<span class="sourceLineNo">619</span> @Override<a name="line.619"></a>
-<span class="sourceLineNo">620</span> public File apply(FileStatus input) {<a name="line.620"></a>
-<span class="sourceLineNo">621</span> return new FileablePath(fs, input.getPath());<a name="line.621"></a>
-<span class="sourceLineNo">622</span> }<a name="line.622"></a>
-<span class="sourceLineNo">623</span> }<a name="line.623"></a>
-<span class="sourceLineNo">624</span><a name="line.624"></a>
-<span class="sourceLineNo">625</span> /**<a name="line.625"></a>
-<span class="sourceLineNo">626</span> * Convert the {@link HStoreFile} into something we can manage in the archive<a name="line.626"></a>
-<span class="sourceLineNo">627</span> * methods<a name="line.627"></a>
-<span class="sourceLineNo">628</span> */<a name="line.628"></a>
-<span class="sourceLineNo">629</span> private static class StoreToFile extends FileConverter<HStoreFile> {<a name="line.629"></a>
-<span class="sourceLineNo">630</span> public StoreToFile(FileSystem fs) {<a name="line.630"></a>
-<span class="sourceLineNo">631</span> super(fs);<a name="line.631"></a>
-<span class="sourceLineNo">632</span> }<a name="line.632"></a>
-<span class="sourceLineNo">633</span><a name="line.633"></a>
-<span class="sourceLineNo">634</span> @Override<a name="line.634"></a>
-<span class="sourceLineNo">635</span> public File apply(HStoreFile input) {<a name="line.635"></a>
-<span class="sourceLineNo">636</span> return new FileableStoreFile(fs, input);<a name="line.636"></a>
-<span class="sourceLineNo">637</span> }<a name="line.637"></a>
-<span class="sourceLineNo">638</span> }<a name="line.638"></a>
-<span class="sourceLineNo">639</span><a name="line.639"></a>
-<span class="sourceLineNo">640</span> /**<a name="line.640"></a>
-<span class="sourceLineNo">641</span> * Wrapper to handle file operations uniformly<a name="line.641"></a>
-<span class="sourceLineNo">642</span> */<a name="line.642"></a>
-<span class="sourceLineNo">643</span> private static abstract class File {<a name="line.643"></a>
-<span class="sourceLineNo">644</span> protected final FileSystem fs;<a name="line.644"></a>
-<span class="sourceLineNo">645</span><a name="line.645"></a>
-<span class="sourceLineNo">646</span> public File(FileSystem fs) {<a name="line.646"></a>
-<span class="sourceLineNo">647</span> this.fs = fs;<a name="line.647"></a>
+<span class="sourceLineNo">546</span> // at this point, we should have a free spot for the archive file<a name="line.546"></a>
+<span class="sourceLineNo">547</span> boolean success = false;<a name="line.547"></a>
+<span class="sourceLineNo">548</span> for (int i = 0; !success && i < DEFAULT_RETRIES_NUMBER; ++i) {<a name="line.548"></a>
+<span class="sourceLineNo">549</span> if (i > 0) {<a name="line.549"></a>
+<span class="sourceLineNo">550</span> // Ensure that the archive directory exists.<a name="line.550"></a>
+<span class="sourceLineNo">551</span> // The previous "move to archive" operation has failed probably because<a name="line.551"></a>
+<span class="sourceLineNo">552</span> // the cleaner has removed our archive directory (HBASE-7643).<a name="line.552"></a>
+<span class="sourceLineNo">553</span> // (we're in a retry loop, so don't worry too much about the exception)<a name="line.553"></a>
+<span class="sourceLineNo">554</span> try {<a name="line.554"></a>
+<span class="sourceLineNo">555</span> if (!fs.exists(archiveDir)) {<a name="line.555"></a>
+<span class="sourceLineNo">556</span> if (fs.mkdirs(archiveDir)) {<a name="line.556"></a>
+<span class="sourceLineNo">557</span> LOG.debug("Created archive directory {}", archiveDir);<a name="line.557"></a>
+<span class="sourceLineNo">558</span> }<a name="line.558"></a>
+<span class="sourceLineNo">559</span> }<a name="line.559"></a>
+<span class="sourceLineNo">560</span> } catch (IOException e) {<a name="line.560"></a>
+<span class="sourceLineNo">561</span> LOG.warn("Failed to create directory {}", archiveDir, e);<a name="line.561"></a>
+<span class="sourceLineNo">562</span> }<a name="line.562"></a>
+<span class="sourceLineNo">563</span> }<a name="line.563"></a>
+<span class="sourceLineNo">564</span><a name="line.564"></a>
+<span class="sourceLineNo">565</span> try {<a name="line.565"></a>
+<span class="sourceLineNo">566</span> success = currentFile.moveAndClose(archiveFile);<a name="line.566"></a>
+<span class="sourceLineNo">567</span> } catch (FileNotFoundException fnfe) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span> LOG.warn("Failed to archive " + currentFile +<a name="line.568"></a>
+<span class="sourceLineNo">569</span> " because it does not exist! Skipping and continuing on.", fnfe);<a name="line.569"></a>
+<span class="sourceLineNo">570</span> success = true;<a name="line.570"></a>
+<span class="sourceLineNo">571</span> } catch (IOException e) {<a name="line.571"></a>
+<span class="sourceLineNo">572</span> LOG.warn("Failed to archive " + currentFile + " on try #" + i, e);<a name="line.572"></a>
+<span class="sourceLineNo">573</span> success = false;<a name="line.573"></a>
+<span class="sourceLineNo">574</span> }<a name="line.574"></a>
+<span class="sourceLineNo">575</span> }<a name="line.575"></a>
+<span class="sourceLineNo">576</span><a name="line.576"></a>
+<span class="sourceLineNo">577</span> if (!success) {<a name="line.577"></a>
+<span class="sourceLineNo">578</span> LOG.error("Failed to archive " + currentFile);<a name="line.578"></a>
+<span class="sourceLineNo">579</span> return false;<a name="line.579"></a>
+<span class="sourceLineNo">580</span> }<a name="line.580"></a>
+<span class="sourceLineNo">581</span><a name="line.581"></a>
+<span class="sourceLineNo">582</span> LOG.debug("Archived from {} to {}", currentFile, archiveFile);<a name="line.582"></a>
+<span class="sourceLineNo">583</span> return true;<a name="line.583"></a>
+<span class="sourceLineNo">584</span> }<a name="line.584"></a>
+<span class="sourceLineNo">585</span><a name="line.585"></a>
+<span class="sourceLineNo">586</span> /**<a name="line.586"></a>
+<span class="sourceLineNo">587</span> * Without regard for backup, delete a region. Should be used with caution.<a name="line.587"></a>
+<span class="sourceLineNo">588</span> * @param regionDir {@link Path} to the region to be deleted.<a name="line.588"></a>
+<span class="sourceLineNo">589</span> * @param fs FileSystem from which to delete the region<a name="line.589"></a>
+<span class="sourceLineNo">590</span> * @return <tt>true</tt> on successful deletion, <tt>false</tt> otherwise<a name="line.590"></a>
+<span class="sourceLineNo">591</span> * @throws IOException on filesystem operation failure<a name="line.591"></a>
+<span class="sourceLineNo">592</span> */<a name="line.592"></a>
+<span class="sourceLineNo">593</span> private static boolean deleteRegionWithoutArchiving(FileSystem fs, Path regionDir)<a name="line.593"></a>
+<span class="sourceLineNo">594</span> throws IOException {<a name="line.594"></a>
+<span class="sourceLineNo">595</span> if (fs.delete(regionDir, true)) {<a name="line.595"></a>
+<span class="sourceLineNo">596</span> LOG.debug("Deleted {}", regionDir);<a name="line.596"></a>
+<span class="sourceLineNo">597</span> return true;<a name="line.597"></a>
+<span class="sourceLineNo">598</span> }<a name="line.598"></a>
+<span class="sourceLineNo">599</span> LOG.debug("Failed to delete directory {}", regionDir);<a name="line.599"></a>
+<span class="sourceLineNo">600</span> return false;<a name="line.600"></a>
+<span class="sourceLineNo">601</span> }<a name="line.601"></a>
+<span class="sourceLineNo">602</span><a name="line.602"></a>
+<span class="sourceLineNo">603</span> /**<a name="line.603"></a>
+<span class="sourceLineNo">604</span> * Just do a simple delete of the given store files<a name="line.604"></a>
+<span class="sourceLineNo">605</span> * <p><a name="line.605"></a>
+<span class="sourceLineNo">606</span> * A best effort is made to delete each of the files, rather than bailing on the first failure.<a name="line.606"></a>
+<span class="sourceLineNo">607</span> * <p><a name="line.607"></a>
+<span class="sourceLineNo">608</span> * @param compactedFiles store files to delete from the file system.<a name="line.608"></a>
+<span class="sourceLineNo">609</span> * @throws IOException if a file cannot be deleted. All files will be attempted to deleted before<a name="line.609"></a>
+<span class="sourceLineNo">610</span> * throwing the exception, rather than failing at the first file.<a name="line.610"></a>
+<span class="sourceLineNo">611</span> */<a name="line.611"></a>
+<span class="sourceLineNo">612</span> private static void deleteStoreFilesWithoutArchiving(Collection<HStoreFile> compactedFiles)<a name="line.612"></a>
+<span class="sourceLineNo">613</span> throws IOException {<a name="line.613"></a>
+<span class="sourceLineNo">614</span> LOG.debug("Deleting files without archiving.");<a name="line.614"></a>
+<span class="sourceLineNo">615</span> List<IOException> errors = new ArrayList<>(0);<a name="line.615"></a>
+<span class="sourceLineNo">616</span> for (HStoreFile hsf : compactedFiles) {<a name="line.616"></a>
+<span class="sourceLineNo">617</span> try {<a name="line.617"></a>
+<span class="sourceLineNo">618</span> hsf.deleteStoreFile();<a name="line.618"></a>
+<span class="sourceLineNo">619</span> } catch (IOException e) {<a name="line.619"></a>
+<span class="sourceLineNo">620</span> LOG.error("Failed to delete {}", hsf.getPath());<a name="line.620"></a>
+<span class="sourceLineNo">621</span> errors.add(e);<a name="line.621"></a>
+<span class="sourceLineNo">622</span> }<a name="line.622"></a>
+<span class="sourceLineNo">623</span> }<a name="line.623"></a>
+<span class="sourceLineNo">624</span> if (errors.size() > 0) {<a name="line.624"></a>
+<span class="sourceLineNo">625</span> throw MultipleIOException.createIOException(errors);<a name="line.625"></a>
+<span class="sourceLineNo">626</span> }<a name="line.626"></a>
+<span class="sourceLineNo">627</span> }<a name="line.627"></a>
+<span class="sourceLineNo">628</span><a name="line.628"></a>
+<span class="sourceLineNo">629</span> /**<a name="line.629"></a>
+<span class="sourceLineNo">630</span> * Adapt a type to match the {@link File} interface, which is used internally for handling<a name="line.630"></a>
+<span class="sourceLineNo">631</span> * archival/removal of files<a name="line.631"></a>
+<span class="sourceLineNo">632</span> * @param <T> type to adapt to the {@link File} interface<a name="line.632"></a>
+<span class="sourceLineNo">633</span> */<a name="line.633"></a>
+<span class="sourceLineNo">634</span> private static abstract class FileConverter<T> implements Function<T, File> {<a name="line.634"></a>
+<span class="sourceLineNo">635</span> protected final FileSystem fs;<a name="line.635"></a>
+<span class="sourceLineNo">636</span><a name="line.636"></a>
+<span class="sourceLineNo">637</span> public FileConverter(FileSystem fs) {<a name="line.637"></a>
+<span class="sourceLineNo">638</span> this.fs = fs;<a name="line.638"></a>
+<span class="sourceLineNo">639</span> }<a name="line.639"></a>
+<span class="sourceLineNo">640</span> }<a name="line.640"></a>
+<span class="sourceLineNo">641</span><a name="line.641"></a>
+<span class="sourceLineNo">642</span> /**<a name="line.642"></a>
+<span class="sourceLineNo">643</span> * Convert a FileStatus to something we can manage in the archiving<a name="line.643"></a>
+<span class="sourceLineNo">644</span> */<a name="line.644"></a>
+<span class="sourceLineNo">645</span> private static class FileStatusConverter extends FileConverter<FileStatus> {<a name="line.645"></a>
+<span class="sourceLineNo">646</span> public FileStatusConverter(FileSystem fs) {<a name="line.646"></a>
+<span class="sourceLineNo">647</span> super(fs);<a name="line.647"></a>
<span class="sourceLineNo">648</span> }<a name="line.648"></a>
<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span> /**<a name="line.650"></a>
-<span class="sourceLineNo">651</span> * Delete the file<a name="line.651"></a>
-<span class="sourceLineNo">652</span> * @throws IOException on failure<a name="line.652"></a>
-<span class="sourceLineNo">653</span> */<a name="line.653"></a>
-<span class="sourceLineNo">654</span> abstract void delete() throws IOException;<a name="line.654"></a>
+<span class="sourceLineNo">650</span> @Override<a name="line.650"></a>
+<span class="sourceLineNo">651</span> public File apply(FileStatus input) {<a name="line.651"></a>
+<span class="sourceLineNo">652</span> return new FileablePath(fs, input.getPath());<a name="line.652"></a>
+<span class="sourceLineNo">653</span> }<a name="line.653"></a>
+<span class="sourceLineNo">654</span> }<a name="line.654"></a>
<span class="sourceLineNo">655</span><a name="line.655"></a>
-<span class="sourceLineNo">656</span> /**<a name="line.656"></a>
-<span class="sourceLineNo">657</span> * Check to see if this is a file or a directory<a name="line.657"></a>
-<span class="sourceLineNo">658</span> * @return <tt>true</tt> if it is a file, <tt>false</tt> otherwise<a name="line.658"></a>
-<span class="sourceLineNo">659</span> * @throws IOException on {@link FileSystem} connection error<a name="line.659"></a>
-<span class="sourceLineNo">660</span> */<a name="line.660"></a>
-<span class="sourceLineNo">661</span> abstract boolean isFile() throws IOException;<a name="line.661"></a>
-<span class="sourceLineNo">662</span><a name="line.662"></a>
-<span class="sourceLineNo">663</span> /**<a name="line.663"></a>
-<span class="sourceLineNo">664</span> * @return if this is a directory, returns all the children in the<a name="line.664"></a>
-<span class="sourceLineNo">665</span> * directory, otherwise returns an empty list<a name="line.665"></a>
-<span class="sourceLineNo">666</span> * @throws IOException<a name="line.666"></a>
-<span class="sourceLineNo">667</span> */<a name="line.667"></a>
-<span class="sourceLineNo">668</span> abstract Collection<File> getChildren() throws IOException;<a name="line.668"></a>
-<span class="sourceLineNo">669</span><a name="line.669"></a>
-<span class="sourceLineNo">670</span> /**<a name="line.670"></a>
-<span class="sourceLineNo">671</span> * close any outside readers of the file<a name="line.671"></a>
-<span class="sourceLineNo">672</span> * @throws IOException<a name="line.672"></a>
-<span class="sourceLineNo">673</span> */<a name="line.673"></a>
-<span class="sourceLineNo">674</span> abstract void close() throws IOException;<a name="line.674"></a>
-<span class="sourceLineNo">675</span><a name="line.675"></a>
-<span class="sourceLineNo">676</span> /**<a name="line.676"></a>
-<span class="sourceLineNo">677</span> * @return the name of the file (not the full fs path, just the individual<a name="line.677"></a>
-<span class="sourceLineNo">678</span> * file name)<a name="line.678"></a>
-<span class="sourceLineNo">679</span> */<a name="line.679"></a>
-<span class="sourceLineNo">680</span> abstract String getName();<a name="line.680"></a>
-<span class="sourceLineNo">681</span><a name="line.681"></a>
-<span class="sourceLineNo">682</span> /**<a name="line.682"></a>
-<span class="sourceLineNo">683</span> * @return the path to this file<a name="line.683"></a>
+<span class="sourceLineNo">656</span> /**<a name="line.656"></a>
+<span class="sourceLineNo">657</span> * Convert the {@link HStoreFile} into something we can manage in the archive<a name="line.657"></a>
+<span class="sourceLineNo">658</span> * methods<a name="line.658"></a>
+<span class="sourceLineNo">659</span> */<a name="line.659"></a>
+<span class="sourceLineNo">660</span> private static class StoreToFile extends FileConverter<HStoreFile> {<a name="line.660"></a>
+<span class="sourceLineNo">661</span> public StoreToFile(FileSystem fs) {<a name="line.661"></a>
+<span class="sourceLineNo">662</span> super(fs);<a name="line.662"></a>
+<span class="sourceLineNo">663</span> }<a name="line.663"></a>
+<span class="sourceLineNo">664</span><a name="line.664"></a>
+<span class="sourceLineNo">665</span> @Override<a name="line.665"></a>
+<span class="sourceLineNo">666</span> public File apply(HStoreFile input) {<a name="line.666"></a>
+<span class="sourceLineNo">667</span> return new FileableStoreFile(fs, input);<a name="line.667"></a>
+<span class="sourceLineNo">668</span> }<a name="line.668"></a>
+<span class="sourceLineNo">669</span> }<a name="line.669"></a>
+<span class="sourceLineNo">670</span><a name="line.670"></a>
+<span class="sourceLineNo">671</span> /**<a name="line.671"></a>
+<span class="sourceLineNo">672</span> * Wrapper to handle file operations uniformly<a name="line.672"></a>
+<span class="sourceLineNo">673</span> */<a name="line.673"></a>
+<span class="sourceLineNo">674</span> private static abstract class File {<a name="line.674"></a>
+<span class="sourceLineNo">675</span> protected final FileSystem fs;<a name="line.675"></a>
+<span class="sourceLineNo">676</span><a name="line.676"></a>
+<span class="sourceLineNo">677</span> public File(FileSystem fs) {<a name="line.677"></a>
+<span class="sourceLineNo">678</span> this.fs = fs;<a name="line.678"></a>
+<span class="sourceLineNo">679</span> }<a name="line.679"></a>
+<span class="sourceLineNo">680</span><a name="line.680"></a>
+<span class="sourceLineNo">681</span> /**<a name="line.681"></a>
+<span class="sourceLineNo">682</span> * Delete the file<a name="line.682"></a>
+<span class="sourceLineNo">683</span> * @throws IOException on failure<a name="line.683"></a>
<span class="sourceLineNo">684</span> */<a name="line.684"></a>
-<span class="sourceLineNo">685</span> abstract Path getPath();<a name="line.685"></a>
+<span class="sourceLineNo">685</span> abstract void delete() throws IOException;<a name="line.685"></a>
<span class="sourceLineNo">686</span><a name="line.686"></a>
<span class="sourceLineNo">687</span> /**<a name="line.687"></a>
-<span class="sourceLineNo">688</span> * Move the file to the given destination<a name="line.688"></a>
-<span class="sourceLineNo">689</span> * @param dest<a name="line.689"></a>
-<span class="sourceLineNo">690</span> * @return <tt>true</tt> on success<a name="line.690"></a>
-<span class="sourceLineNo">691</span> * @throws IOException<a name="line.691"></a>
-<span class="sourceLineNo">692</span> */<a name="line.692"></a>
-<span class="sourceLineNo">693</span> public boolean moveAndClose(Path dest) throws IOException {<a name="line.693"></a>
-<span class="sourceLineNo">694</span> this.close();<a name="line.694"></a>
-<span class="sourceLineNo">695</span> Path p = this.getPath();<a name="line.695"></a>
-<span class="sourceLineNo">696</span> return CommonFSUtils.renameAndSetModifyTime(fs, p, dest);<a name="line.696"></a>
-<span class="sourceLineNo">697</span> }<a name="line.697"></a>
-<span class="sourceLineNo">698</span><a name="line.698"></a>
-<span class="sourceLineNo">699</span> /**<a name="line.699"></a>
-<span class="sourceLineNo">700</span> * @return the {@link FileSystem} on which this file resides<a name="line.700"></a>
-<span class="sourceLineNo">701</span> */<a name="line.701"></a>
-<span class="sourceLineNo">702</span> public FileSystem getFileSystem() {<a name="line.702"></a>
-<span class="sourceLineNo">703</span> return this.fs;<a name="line.703"></a>
-<span class="sourceLineNo">704</span> }<a name="line.704"></a>
-<span class="sourceLineNo">705</span><a name="line.705"></a>
-<span class="sourceLineNo">706</span> @Override<a name="line.706"></a>
-<span class="sourceLineNo">707</span> public String toString() {<a name="line.707"></a>
-<span class="sourceLineNo">708</span> return this.getClass().getSimpleName() + ", " + getPath().toString();<a name="line.708"></a>
-<span class="sourceLineNo">709</span> }<a name="line.709"></a>
-<span class="sourceLineNo">710</span> }<a name="line.710"></a>
-<span class="sourceLineNo">711</span><a name="line.711"></a>
-<span class="sourceLineNo">712</span> /**<a name="line.712"></a>
-<span class="sourceLineNo">713</span> * A {@link File} that wraps a simple {@link Path} on a {@link FileSystem}.<a name="line.713"></a>
-<span class="sourceLineNo">714</span> */<a name="line.714"></a>
-<span class="sourceLineNo">715</span> private static class FileablePath extends File {<a name="line.715"></a>
-<span class="sourceLineNo">716</span> private final Path file;<a name="line.716"></a>
-<span class="sourceLineNo">717</span> private final FileStatusConverter getAsFile;<a name="line.717"></a>
-<span class="sourceLineNo">718</span><a name="line.718"></a>
-<span class="sourceLineNo">719</span> public FileablePath(FileSystem fs, Path file) {<a name="line.719"></a>
-<span class="sourceLineNo">720</span> super(fs);<a name="line.720"></a>
-<span class="sourceLineNo">721</span> this.file = file;<a name="line.721"></a>
-<span class="sourceLineNo">722</span> this.getAsFile = new FileStatusConverter(fs);<a name="line.722"></a>
-<span class="sourceLineNo">723</span> }<a name="line.723"></a>
-<span class="sourceLineNo">724</span><a name="line.724"></a>
-<span class="sourceLineNo">725</span> @Override<a name="line.725"></a>
-<span class="sourceLineNo">726</span> public void delete() throws IOException {<a name="line.726"></a>
-<span class="sourceLineNo">727</span> if (!fs.delete(file, true)) throw new IOException("Failed to delete:" + this.file);<a name="line.727"></a>
+<span class="sourceLineNo">688</span> * Check to see if this is a file or a directory<a name="line.688"></a>
+<span class="sourceLineNo">689</span> * @return <tt>true</tt> if it is a file, <tt>false</tt> otherwise<a name="line.689"></a>
+<span class="sourceLineNo">690</span> * @throws IOException on {@link FileSystem} connection error<a name="line.690"></a>
+<span class="sourceLineNo">691</span> */<a name="line.691"></a>
+<span class="sourceLineNo">692</span> abstract boolean isFile() throws IOException;<a name="line.692"></a>
+<span class="sourceLineNo">693</span><a name="line.693"></a>
+<span class="sourceLineNo">694</span> /**<a name="line.694"></a>
+<span class="sourceLineNo">695</span> * @return if this is a directory, returns all the children in the<a name="line.695"></a>
+<span class="sourceLineNo">696</span> * directory, otherwise returns an empty list<a name="line.696"></a>
+<span class="sourceLineNo">697</span> * @throws IOException<a name="line.697"></a>
+<span class="sourceLineNo">698</span> */<a name="line.698"></a>
+<span class="sourceLineNo">699</span> abstract Collection<File> getChildren() throws IOException;<a name="line.699"></a>
+<span class="sourceLineNo">700</span><a name="line.700"></a>
+<span class="sourceLineNo">701</span> /**<a name="line.701"></a>
+<span class="sourceLineNo">702</span> * close any outside readers of the file<a name="line.702"></a>
+<span class="sourceLineNo">703</span> * @throws IOException<a name="line.703"></a>
+<span class="sourceLineNo">704</span> */<a name="line.704"></a>
+<span class="sourceLineNo">705</span> abstract void close() throws IOException;<a name="line.705"></a>
+<span class="sourceLineNo">706</span><a name="line.706"></a>
+<span class="sourceLineNo">707</span> /**<a name="line.707"></a>
+<span class="sourceLineNo">708</span> * @return the name of the file (not the full fs path, just the individual<a name="line.708"></a>
+<span class="sourceLineNo">709</span> * file name)<a name="line.709"></a>
+<span class="sourceLineNo">710</span> */<a name="line.710"></a>
+<span class="sourceLineNo">711</span> abstract String getName();<a name="line.711"></a>
+<span class="sourceLineNo">712</span><a name="line.712"></a>
+<span class="sourceLineNo">713</span> /**<a name="line.713"></a>
+<span class="sourceLineNo">714</span> * @return the path to this file<a name="line.714"></a>
+<span class="sourceLineNo">715</span> */<a name="line.715"></a>
+<span class="sourceLineNo">716</span> abstract Path getPath();<a name="line.716"></a>
+<span class="sourceLineNo">717</span><a name="line.717"></a>
+<span class="sourceLineNo">718</span> /**<a name="line.718"></a>
+<span class="sourceLineNo">719</span> * Move the file to the given destination<a name="line.719"></a>
+<span class="sourceLineNo">720</span> * @param dest<a name="line.720"></a>
+<span class="sourceLineNo">721</span> * @return <tt>true</tt> on success<a name="line.721"></a>
+<span class="sourceLineNo">722</span> * @throws IOException<a name="line.722"></a>
+<span class="sourceLineNo">723</span> */<a name="line.723"></a>
+<span class="sourceLineNo">724</span> public boolean moveAndClose(Path dest) throws IOException {<a name="line.724"></a>
+<span class="sourceLineNo">725</span> this.close();<a name="line.725"></a>
+<span class="sourceLineNo">726</span> Path p = this.getPath();<a name="line.726"></a>
+<span class="sourceLineNo">727</span> return CommonFSUtils.renameAndSetModifyTime(fs, p, dest);<a name="line.727"></a>
<span class="sourceLineNo">728</span> }<a name="line.728"></a>
<span class="sourceLineNo">729</span><a name="line.729"></a>
-<span class="sourceLineNo">730</span> @Override<a name="line.730"></a>
-<span class="sourceLineNo">731</span> public String getName() {<a name="line.731"></a>
-<span class="sourceLineNo">732</span> return file.getName();<a name="line.732"></a>
-<span class="sourceLineNo">733</span> }<a name="line.733"></a>
-<span class="sourceLineNo">734</span><a name="line.734"></a>
-<span class="sourceLineNo">735</span> @Override<a name="line.735"></a>
-<span class="sourceLineNo">736</span> public Collection<File> getChildren() throws IOException {<a name="line.736"></a>
-<span class="sourceLineNo">737</span> if (fs.isFile(file)) {<a name="line.737"></a>
-<span class="sourceLineNo">738</span> return Collections.emptyList();<a name="line.738"></a>
-<span class="sourceLineNo">739</span> }<a name="line.739"></a>
-<span class="sourceLineNo">740</span> return Stream.of(fs.listStatus(file)).map(getAsFile).collect(Collectors.toList());<a name="line.740"></a>
-<span class="sourceLineNo">741</span> }<a name="line.741"></a>
+<span class="sourceLineNo">730</span> /**<a name="line.730"></a>
+<span class="sourceLineNo">731</span> * @return the {@link FileSystem} on which this file resides<a name="line.731"></a>
+<span class="sourceLineNo">732</span> */<a name="line.732"></a>
+<span class="sourceLineNo">733</span> public FileSystem getFileSystem() {<a name="line.733"></a>
+<span class="sourceLineNo">734</span> return this.fs;<a name="line.734"></a>
+<span class="sourceLineNo">735</span> }<a name="line.735"></a>
+<span class="sourceLineNo">736</span><a name="line.736"></a>
+<span class="sourceLineNo">737</span> @Override<a name="line.737"></a>
+<span class="sourceLineNo">738</span> public String toString() {<a name="line.738"></a>
+<span class="sourceLineNo">739</span> return this.getClass().getSimpleName() + ", " + getPath().toString();<a name="line.739"></a>
+<span class="sourceLineNo">740</span> }<a name="line.740"></a>
+<span class="sourceLineNo">741</span> }<a name="line.741"></a>
<span class="sourceLineNo">742</span><a name="line.742"></a>
-<span class="sourceLineNo">743</span> @Override<a name="line.743"></a>
-<span class="sourceLineNo">744</span> public boolean isFile() throws IOException {<a name="line.744"></a>
-<span class="sourceLineNo">745</span> return fs.isFile(file);<a name="line.745"></a>
-<span class="sourceLineNo">746</span> }<a name="line.746"></a>
-<span class="sourceLineNo">747</span><a name="line.747"></a>
-<span class="sourceLineNo">748</span> @Override<a name="line.748"></a>
-<span class="sourceLineNo">749</span> public void close() throws IOException {<a name="line.749"></a>
-<span class="sourceLineNo">750</span> // NOOP - files are implicitly closed on removal<a name="line.750"></a>
-<span class="sourceLineNo">751</span> }<a name="line.751"></a>
-<span class="sourceLineNo">752</span><a name="line.752"></a>
-<span class="sourceLineNo">753</span> @Override<a name="line.753"></a>
-<span class="sourceLineNo">754</span> Path getPath() {<a name="line.754"></a>
-<span class="sourceLineNo">755</span> return file;<a name="line.755"></a>
-<span class="sourceLineNo">756</span> }<a name="line.756"></a>
-<span class="sourceLineNo">757</span> }<a name="line.757"></a>
-<span class="sourceLineNo">758</span><a name="line.758"></a>
-<span class="sourceLineNo">759</span> /**<a name="line.759"></a>
-<span class="sourceLineNo">760</span> * {@link File} adapter for a {@link HStoreFile} living on a {@link FileSystem}<a name="line.760"></a>
-<span class="sourceLineNo">761</span> * .<a name="line.761"></a>
-<span class="sourceLineNo">762</span> */<a name="line.762"></a>
-<span class="sourceLineNo">763</span> private static class FileableStoreFile extends File {<a name="line.763"></a>
-<span class="sourceLineNo">764</span> HStoreFile file;<a name="line.764"></a>
+<span class="sourceLineNo">743</span> /**<a name="line.743"></a>
+<span class="sourceLineNo">744</span> * A {@link File} that wraps a simple {@link Path} on a {@link FileSystem}.<a name="line.744"></a>
+<span class="sourceLineNo">745</span> */<a name="line.745"></a>
+<span class="sourceLineNo">746</span> private static class FileablePath extends File {<a name="line.746"></a>
+<span class="sourceLineNo">747</span> private final Path file;<a name="line.747"></a>
+<span class="sourceLineNo">748</span> private final FileStatusConverter getAsFile;<a name="line.748"></a>
+<span class="sourceLineNo">749</span><a name="line.749"></a>
+<span class="sourceLineNo">750</span> public FileablePath(FileSystem fs, Path file) {<a name="line.750"></a>
+<span class="sourceLineNo">751</span> super(fs);<a name="line.751"></a>
+<span class="sourceLineNo">752</span> this.file = file;<a name="line.752"></a>
+<span class="sourceLineNo">753</span> this.getAsFile = new FileStatusConverter(fs);<a name="line.753"></a>
+<span class="sourceLineNo">754</span> }<a name="line.754"></a>
+<span class="sourceLineNo">755</span><a name="line.755"></a>
+<span class="sourceLineNo">756</span> @Override<a name="line.756"></a>
+<span class="sourceLineNo">757</span> public void delete() throws IOException {<a name="line.757"></a>
+<span class="sourceLineNo">758</span> if (!fs.delete(file, true)) throw new IOException("Failed to delete:" + this.file);<a name="line.758"></a>
+<span class="sourceLineNo">759</span> }<a name="line.759"></a>
+<span class="sourceLineNo">760</span><a name="line.760"></a>
+<span class="sourceLineNo">761</span> @Override<a name="line.761"></a>
+<span class="sourceLineNo">762</span> public String getName() {<a name="line.762"></a>
+<span class="sourceLineNo">763</span> return file.getName();<a name="line.763"></a>
+<span class="sourceLineNo">764</span> }<a name="line.764"></a>
<span class="sourceLineNo">765</span><a name="line.765"></a>
-<span class="sourceLineNo">766</span> public FileableStoreFile(FileSystem fs, HStoreFile store) {<a name="line.766"></a>
-<span class="sourceLineNo">767</span> super(fs);<a name="line.767"></a>
-<span class="sourceLineNo">768</span> this.file = store;<a name="line.768"></a>
-<span class="sourceLineNo">769</span> }<a name="line.769"></a>
-<span class="sourceLineNo">770</span><a name="line.770"></a>
-<span class="sourceLineNo">771</span> @Override<a name="line.771"></a>
-<span class="sourceLineNo">772</span> public void delete() throws IOException {<a name="line.772"></a>
-<span class="sourceLineNo">773</span> file.deleteStoreFile();<a name="line.773"></a>
-<span class="sourceLineNo">774</span> }<a name="line.774"></a>
-<span class="sourceLineNo">775</span><a name="line.775"></a>
-<span class="sourceLineNo">776</span> @Override<a name="line.776"></a>
-<span class="sourceLineNo">777</span> public String getName() {<a name="line.777"></a>
-<span class="sourceLineNo">778</span> return file.getPath().getName();<a name="line.778"></a>
-<span class="sourceLineNo">779</span> }<a name="line.779"></a>
-<span class="sourceLineNo">780</span><a name="line.780"></a>
-<span class="sourceLineNo">781</span> @Override<a name="line.781"></a>
-<span class="sourceLineNo">782</span> public boolean isFile() {<a name="line.782"></a>
-<span class="sourceLineNo">783</span> return true;<a name="line.783"></a>
-<span class="sourceLineNo">784</span> }<a name="line.784"></a>
-<span class="sourceLineNo">785</span><a name="line.785"></a>
-<span class="sourceLineNo">786</span> @Override<a name="line.786"></a>
-<span class="sourceLineNo">787</span> public Collection<File> getChildren() throws IOException {<a name="line.787"></a>
-<span class="sourceLineNo">788</span> // storefiles don't have children<a name="line.788"></a>
-<span class="sourceLineNo">789</span> return Collections.emptyList();<a name="line.789"></a>
-<span class="sourceLineNo">790</span> }<a name="line.790"></a>
-<span class="sourceLineNo">791</span><a name="line.791"></a>
-<span class="sourceLineNo">792</span> @Override<a name="line.792"></a>
-<span class="sourceLineNo">793</span> public void close() throws IOException {<a name="line.793"></a>
-<span class="sourceLineNo">794</span> file.closeStoreFile(true);<a name="line.794"></a>
-<span class="sourceLineNo">795</span> }<a name="line.795"></a>
+<span class="sourceLineNo">766</span> @Override<a name="line.766"></a>
+<span class="sourceLineNo">767</span> public Collection<File> getChildren() throws IOException {<a name="line.767"></a>
+<span class="sourceLineNo">768</span> if (fs.isFile(file)) {<a name="line.768"></a>
+<span class="sourceLineNo">769</span> return Collections.emptyList();<a name="line.769"></a>
+<span class="sourceLineNo">770</span> }<a name="line.770"></a>
+<span class="sourceLineNo">771</span> return Stream.of(fs.listStatus(file)).map(getAsFile).collect(Collectors.toList());<a name="line.771"></a>
+<span class="sourceLineNo">772</span> }<a name="line.772"></a>
+<span class="sourceLineNo">773</span><a name="line.773"></a>
+<span class="sourceLineNo">774</span> @Override<a name="line.774"></a>
+<span class="sourceLineNo">775</span> public boolean isFile() throws IOException {<a name="line.775"></a>
+<span class="sourceLineNo">776</span> return fs.isFile(file);<a name="line.776"></a>
+<span class="sourceLineNo">777</span> }<a name="line.777"></a>
+<span class="sourceLineNo">778</span><a name="line.778"></a>
+<span class="sourceLineNo">779</span> @Override<a name="line.779"></a>
+<span class="sourceLineNo">780</span> public void close() throws IOException {<a name="line.780"></a>
+<span class="sourceLineNo">781</span> // NOOP - files are implicitly closed on removal<a name="line.781"></a>
+<span class="sourceLineNo">782</span> }<a name="line.782"></a>
+<span class="sourceLineNo">783</span><a name="line.783"></a>
+<span class="sourceLineNo">784</span> @Override<a name="line.784"></a>
+<span class="sourceLineNo">785</span> Path getPath() {<a name="line.785"></a>
+<span class="sourceLineNo">786</span> return file;<a name="line.786"></a>
+<span class="sourceLineNo">787</span> }<a name="line.787"></a>
+<span class="sourceLineNo">788</span> }<a name="line.788"></a>
+<span class="sourceLineNo">789</span><a name="line.789"></a>
+<span class="sourceLineNo">790</span> /**<a name="line.790"></a>
+<span class="sourceLineNo">791</span> * {@link File} adapter for a {@link HStoreFile} living on a {@link FileSystem}<a name="line.791"></a>
+<span class="sourceLineNo">792</span> * .<a name="line.792"></a>
+<span class="sourceLineNo">793</span> */<a name="line.793"></a>
+<span class="sourceLineNo">794</span> private static class FileableStoreFile extends File {<a name="line.794"></a>
+<span class="sourceLineNo">795</span> HStoreFile file;<a name="line.795"></a>
<span class="sourceLineNo">796</span><a name="line.796"></a>
-<span class="sourceLineNo">797</span> @Override<a name="line.797"></a>
-<span class="sourceLineNo">798</span> Path getPath() {<a name="line.798"></a>
-<span class="sourceLineNo">799</span> return file.getPath();<a name="line.799"></a>
+<span class="sourceLineNo">797</span> public FileableStoreFile(FileSystem fs, HStoreFile store) {<a name="line.797"></a>
+<span class="sourceLineNo">798</span> super(fs);<a name="line.798"></a>
+<span class="sourceLineNo">799</span> this.file = store;<a name="line.799"></a>
<span class="sourceLineNo">800</span> }<a name="line.800"></a>
-<span class="sourceLineNo">801</span> }<a name="line.801"></a>
-<span class="sourceLineNo">802</span>}<a name="line.802"></a>
+<span class="sourceLineNo">801</span><a name="line.801"></a>
+<span class="sourceLineNo">802</span> @Override<a name="line.802"></a>
+<span class="sourceLineNo">803</span> public void delete() throws IOException {<a name="line.803"></a>
+<span class="sourceLineNo">804</span> file.deleteStoreFile();<a name="line.804"></a>
+<span class="sourceLineNo">805</span> }<a name="line.805"></a>
+<span class="sourceLineNo">806</span><a name="line.806"></a>
+<span class="sourceLineNo">807</span> @Override<a name="line.807"></a>
+<span class="sourceLineNo">808</span> public String getName() {<a name="line.808"></a>
+<span class="sourceLineNo">809</span> return file.getPath().getName();<a name="line.809"></a>
+<span class="sourceLineNo">810</span> }<a name="line.810"></a>
+<span class="sourceLineNo">811</span><a name="line.811"></a>
+<span class="sourceLineNo">812</span> @Override<a name="line.812"></a>
+<span class="sourceLineNo">813</span> public boolean isFile() {<a name="line.813"></a>
+<span class="sourceLineNo">814</span> return true;<a name="line.814"></a>
+<span class="sourceLineNo">815</span> }<a name="line.815"></a>
+<span class="sourceLineNo">816</span><a name="line.816"></a>
+<span class="sourceLineNo">817</span> @Override<a name="line.817"></a>
+<span class="sourceLineNo">818</span> public Collection<File> getChildren() throws IOException {<a name="line.818"></a>
+<span class="sourceLineNo">819</span> // storefiles don't have children<a name="line.819"></a>
+<span class="sourceLineNo">820</span> return Collections.emptyList();<a name="line.820"></a>
+<span class="sourceLineNo">821</span> }<a name="line.821"></a>
+<span class="sourceLineNo">822</span><a name="line.822"></a>
+<span class="sourceLineNo">823</span> @Override<a name="line.823"></a>
+<span class="sourceLineNo">824</span> public void close() throws IOException {<a name="line.824"></a>
+<span class="sourceLineNo">825</span> file.closeStoreFile(true);<a name="line.825"></a>
+<span class="sourceLineNo">826</span> }<a name="line.826"></a>
+<span class="sourceLineNo">827</span><a name="line.827"></a>
+<span class="sourceLineNo">828</span> @Override<a name="line.828"></a>
+<span class="sourceLineNo">829</span> Path getPath() {<a name="line.829"></a>
+<span class="sourceLineNo">830</span> return file.getPath();<a name="line.830"></a>
+<span class="sourceLineNo">831</span> }<a name="line.831"></a>
+<span class="sourceLineNo">832</span> }<a name="line.832"></a>
+<span class="sourceLineNo">833</span>}<a name="line.833"></a>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html b/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html
index 22ea136..ee79f25 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileablePath.html
@@ -496,318 +496,349 @@
<span class="sourceLineNo">488</span> Path archiveFile = new Path(archiveDir, filename);<a name="line.488"></a>
<span class="sourceLineNo">489</span> FileSystem fs = currentFile.getFileSystem();<a name="line.489"></a>
<span class="sourceLineNo">490</span><a name="line.490"></a>
-<span class="sourceLineNo">491</span> // if the file already exists in the archive, move that one to a timestamped backup. This is a<a name="line.491"></a>
-<span class="sourceLineNo">492</span> // really, really unlikely situtation, where we get the same name for the existing file, but<a name="line.492"></a>
-<span class="sourceLineNo">493</span> // is included just for that 1 in trillion chance.<a name="line.493"></a>
-<span class="sourceLineNo">494</span> if (fs.exists(archiveFile)) {<a name="line.494"></a>
-<span class="sourceLineNo">495</span> LOG.debug("{} already exists in archive, moving to timestamped backup and " +<a name="line.495"></a>
-<span class="sourceLineNo">496</span> "overwriting current.", archiveFile);<a name="line.496"></a>
-<span class="sourceLineNo">497</span><a name="line.497"></a>
-<span class="sourceLineNo">498</span> // move the archive file to the stamped backup<a name="line.498"></a>
-<span class="sourceLineNo">499</span> Path backedupArchiveFile = new Path(archiveDir, filename + SEPARATOR + archiveStartTime);<a name="line.499"></a>
-<span class="sourceLineNo">500</span> if (!fs.rename(archiveFile, backedupArchiveFile)) {<a name="line.500"></a>
-<span class="sourceLineNo">501</span> LOG.error("Could not rename archive file to backup: " + backedupArchiveFile<a name="line.501"></a>
-<span class="sourceLineNo">502</span> + ", deleting existing file in favor of newer.");<a name="line.502"></a>
-<span class="sourceLineNo">503</span> // try to delete the exisiting file, if we can't rename it<a name="line.503"></a>
-<span class="sourceLineNo">504</span> if (!fs.delete(archiveFile, false)) {<a name="line.504"></a>
-<span class="sourceLineNo">505</span> throw new IOException("Couldn't delete existing archive file (" + archiveFile<a name="line.505"></a>
-<span class="sourceLineNo">506</span> + ") or rename it to the backup file (" + backedupArchiveFile<a name="line.506"></a>
-<span class="sourceLineNo">507</span> + ") to make room for similarly named file.");<a name="line.507"></a>
-<span class="sourceLineNo">508</span> }<a name="line.508"></a>
-<span class="sourceLineNo">509</span> }<a name="line.509"></a>
-<span class="sourceLineNo">510</span> LOG.debug("Backed up archive file from " + archiveFile);<a name="line.510"></a>
-<span class="sourceLineNo">511</span> }<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span> LOG.trace("No existing file in archive for {}, free to archive original file.", archiveFile);<a name="line.513"></a>
-<span class="sourceLineNo">514</span><a name="line.514"></a>
-<span class="sourceLineNo">515</span> // at this point, we should have a free spot for the archive file<a name="line.515"></a>
-<span class="sourceLineNo">516</span> boolean success = false;<a name="line.516"></a>
-<span class="sourceLineNo">517</span> for (int i = 0; !success && i < DEFAULT_RETRIES_NUMBER; ++i) {<a name="line.517"></a>
-<span class="sourceLineNo">518</span> if (i > 0) {<a name="line.518"></a>
-<span class="sourceLineNo">519</span> // Ensure that the archive directory exists.<a name="line.519"></a>
-<span class="sourceLineNo">520</span> // The previous "move to archive" operation has failed probably because<a name="line.520"></a>
-<span class="sourceLineNo">521</span> // the cleaner has removed our archive directory (HBASE-7643).<a name="line.521"></a>
-<span class="sourceLineNo">522</span> // (we're in a retry loop, so don't worry too much about the exception)<a name="line.522"></a>
-<span class="sourceLineNo">523</span> try {<a name="line.523"></a>
-<span class="sourceLineNo">524</span> if (!fs.exists(archiveDir)) {<a name="line.524"></a>
-<span class="sourceLineNo">525</span> if (fs.mkdirs(archiveDir)) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span> LOG.debug("Created archive directory {}", archiveDir);<a name="line.526"></a>
-<span class="sourceLineNo">527</span> }<a name="line.527"></a>
-<span class="sourceLineNo">528</span> }<a name="line.528"></a>
-<span class="sourceLineNo">529</span> } catch (IOException e) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span> LOG.warn("Failed to create directory {}", archiveDir, e);<a name="line.530"></a>
-<span class="sourceLineNo">531</span> }<a name="line.531"></a>
-<span class="sourceLineNo">532</span> }<a name="line.532"></a>
-<span class="sourceLineNo">533</span><a name="line.533"></a>
-<span class="sourceLineNo">534</span> try {<a name="line.534"></a>
-<span class="sourceLineNo">535</span> success = currentFile.moveAndClose(archiveFile);<a name="line.535"></a>
-<span class="sourceLineNo">536</span> } catch (FileNotFoundException fnfe) {<a name="line.536"></a>
-<span class="sourceLineNo">537</span> LOG.warn("Failed to archive " + currentFile +<a name="line.537"></a>
-<span class="sourceLineNo">538</span> " because it does not exist! Skipping and continuing on.", fnfe);<a name="line.538"></a>
-<span class="sourceLineNo">539</span> success = true;<a name="line.539"></a>
-<span class="sourceLineNo">540</span> } catch (IOException e) {<a name="line.540"></a>
-<span class="sourceLineNo">541</span> LOG.warn("Failed to archive " + currentFile + " on try #" + i, e);<a name="line.541"></a>
-<span class="sourceLineNo">542</span> success = false;<a name="line.542"></a>
-<span class="sourceLineNo">543</span> }<a name="line.543"></a>
-<span class="sourceLineNo">544</span> }<a name="line.544"></a>
+<span class="sourceLineNo">491</span> // An existing destination file in the archive is unexpected, but we handle it here.<a name="line.491"></a>
+<span class="sourceLineNo">492</span> if (fs.exists(archiveFile)) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span> if (!fs.exists(currentFile.getPath())) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span> // If the file already exists in the archive, and there is no current file to archive, then<a name="line.494"></a>
+<span class="sourceLineNo">495</span> // assume that the file in archive is correct. This is an unexpected situation, suggesting a<a name="line.495"></a>
+<span class="sourceLineNo">496</span> // race condition or split brain.<a name="line.496"></a>
+<span class="sourceLineNo">497</span> // In HBASE-26718 this was found when compaction incorrectly happened during warmupRegion.<a name="line.497"></a>
+<span class="sourceLineNo">498</span> LOG.warn("{} exists in archive. Attempted to archive nonexistent file {}.", archiveFile,<a name="line.498"></a>
+<span class="sourceLineNo">499</span> currentFile);<a name="line.499"></a>
+<span class="sourceLineNo">500</span> // We return success to match existing behavior in this method, where FileNotFoundException<a name="line.500"></a>
+<span class="sourceLineNo">501</span> // in moveAndClose is ignored.<a name="line.501"></a>
+<span class="sourceLineNo">502</span> return true;<a name="line.502"></a>
+<span class="sourceLineNo">503</span> }<a name="line.503"></a>
+<span class="sourceLineNo">504</span> // There is a conflict between the current file and the already existing archived file.<a name="line.504"></a>
+<span class="sourceLineNo">505</span> // Move the archived file to a timestamped backup. This is a really, really unlikely<a name="line.505"></a>
+<span class="sourceLineNo">506</span> // situation, where we get the same name for the existing file, but is included just for that<a name="line.506"></a>
+<span class="sourceLineNo">507</span> // 1 in trillion chance. We are potentially incurring data loss in the archive directory if<a name="line.507"></a>
+<span class="sourceLineNo">508</span> // the files are not identical. The timestamped backup will be cleaned by HFileCleaner as it<a name="line.508"></a>
+<span class="sourceLineNo">509</span> // has no references.<a name="line.509"></a>
+<span class="sourceLineNo">510</span> FileStatus curStatus = fs.getFileStatus(currentFile.getPath());<a name="line.510"></a>
+<span class="sourceLineNo">511</span> FileStatus archiveStatus = fs.getFileStatus(archiveFile);<a name="line.511"></a>
+<span class="sourceLineNo">512</span> long curLen = curStatus.getLen();<a name="line.512"></a>
+<span class="sourceLineNo">513</span> long archiveLen = archiveStatus.getLen();<a name="line.513"></a>
+<span class="sourceLineNo">514</span> long curMtime = curStatus.getModificationTime();<a name="line.514"></a>
+<span class="sourceLineNo">515</span> long archiveMtime = archiveStatus.getModificationTime();<a name="line.515"></a>
+<span class="sourceLineNo">516</span> if (curLen != archiveLen) {<a name="line.516"></a>
+<span class="sourceLineNo">517</span> LOG.error("{} already exists in archive with different size than current {}."<a name="line.517"></a>
+<span class="sourceLineNo">518</span> + " archiveLen: {} currentLen: {} archiveMtime: {} currentMtime: {}",<a name="line.518"></a>
+<span class="sourceLineNo">519</span> archiveFile, currentFile, archiveLen, curLen, archiveMtime, curMtime);<a name="line.519"></a>
+<span class="sourceLineNo">520</span> throw new IOException(archiveFile + " already exists in archive with different size" +<a name="line.520"></a>
+<span class="sourceLineNo">521</span> " than " + currentFile);<a name="line.521"></a>
+<span class="sourceLineNo">522</span> }<a name="line.522"></a>
+<span class="sourceLineNo">523</span><a name="line.523"></a>
+<span class="sourceLineNo">524</span> LOG.error("{} already exists in archive, moving to timestamped backup and overwriting"<a name="line.524"></a>
+<span class="sourceLineNo">525</span> + " current {}. archiveLen: {} currentLen: {} archiveMtime: {} currentMtime: {}",<a name="line.525"></a>
+<span class="sourceLineNo">526</span> archiveFile, currentFile, archiveLen, curLen, archiveMtime, curMtime);<a name="line.526"></a>
+<span class="sourceLineNo">527</span><a name="line.527"></a>
+<span class="sourceLineNo">528</span> // move the archive file to the stamped backup<a name="line.528"></a>
+<span class="sourceLineNo">529</span> Path backedupArchiveFile = new Path(archiveDir, filename + SEPARATOR + archiveStartTime);<a name="line.529"></a>
+<span class="sourceLineNo">530</span> if (!fs.rename(archiveFile, backedupArchiveFile)) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span> LOG.error("Could not rename archive file to backup: " + backedupArchiveFile<a name="line.531"></a>
+<span class="sourceLineNo">532</span> + ", deleting existing file in favor of newer.");<a name="line.532"></a>
+<span class="sourceLineNo">533</span> // try to delete the existing file, if we can't rename it<a name="line.533"></a>
+<span class="sourceLineNo">534</span> if (!fs.delete(archiveFile, false)) {<a name="line.534"></a>
+<span class="sourceLineNo">535</span> throw new IOException("Couldn't delete existing archive file (" + archiveFile<a name="line.535"></a>
+<span class="sourceLineNo">536</span> + ") or rename it to the backup file (" + backedupArchiveFile<a name="line.536"></a>
+<span class="sourceLineNo">537</span> + ") to make room for similarly named file.");<a name="line.537"></a>
+<span class="sourceLineNo">538</span> }<a name="line.538"></a>
+<span class="sourceLineNo">539</span> } else {<a name="line.539"></a>
+<span class="sourceLineNo">540</span> LOG.info("Backed up archive file from {} to {}.", archiveFile, backedupArchiveFile);<a name="line.540"></a>
+<span class="sourceLineNo">541</span> }<a name="line.541"></a>
+<span class="sourceLineNo">542</span> }<a name="line.542"></a>
+<span class="sourceLineNo">543</span><a name="line.543"></a>
+<span class="sourceLineNo">544</span> LOG.trace("No existing file in archive for {}, free to archive original file.", archiveFile);<a name="line.544"></a>
<span class="sourceLineNo">545</span><a name="line.545"></a>
-<span class="sourceLineNo">546</span> if (!success) {<a name="line.546"></a>
-<span class="sourceLineNo">547</span> LOG.error("Failed to archive " + currentFile);<a name="line.547"></a>
-<span class="sourceLineNo">548</span> return false;<a name="line.548"></a>
-<span class="sourceLineNo">549</span> }<a name="line.549"></a>
-<span class="sourceLineNo">550</span><a name="line.550"></a>
-<span class="sourceLineNo">551</span> LOG.debug("Archived from {} to {}", currentFile, archiveFile);<a name="line.551"></a>
-<span class="sourceLineNo">552</span> return true;<a name="line.552"></a>
-<span class="sourceLineNo">553</span> }<a name="line.553"></a>
-<span class="sourceLineNo">554</span><a name="line.554"></a>
-<span class="sourceLineNo">555</span> /**<a name="line.555"></a>
-<span class="sourceLineNo">556</span> * Without regard for backup, delete a region. Should be used with caution.<a name="line.556"></a>
-<span class="sourceLineNo">557</span> * @param regionDir {@link Path} to the region to be deleted.<a name="line.557"></a>
-<span class="sourceLineNo">558</span> * @param fs FileSystem from which to delete the region<a name="line.558"></a>
-<span class="sourceLineNo">559</span> * @return <tt>true</tt> on successful deletion, <tt>false</tt> otherwise<a name="line.559"></a>
-<span class="sourceLineNo">560</span> * @throws IOException on filesystem operation failure<a name="line.560"></a>
-<span class="sourceLineNo">561</span> */<a name="line.561"></a>
-<span class="sourceLineNo">562</span> private static boolean deleteRegionWithoutArchiving(FileSystem fs, Path regionDir)<a name="line.562"></a>
-<span class="sourceLineNo">563</span> throws IOException {<a name="line.563"></a>
-<span class="sourceLineNo">564</span> if (fs.delete(regionDir, true)) {<a name="line.564"></a>
-<span class="sourceLineNo">565</span> LOG.debug("Deleted {}", regionDir);<a name="line.565"></a>
-<span class="sourceLineNo">566</span> return true;<a name="line.566"></a>
-<span class="sourceLineNo">567</span> }<a name="line.567"></a>
-<span class="sourceLineNo">568</span> LOG.debug("Failed to delete directory {}", regionDir);<a name="line.568"></a>
-<span class="sourceLineNo">569</span> return false;<a name="line.569"></a>
-<span class="sourceLineNo">570</span> }<a name="line.570"></a>
-<span class="sourceLineNo">571</span><a name="line.571"></a>
-<span class="sourceLineNo">572</span> /**<a name="line.572"></a>
-<span class="sourceLineNo">573</span> * Just do a simple delete of the given store files<a name="line.573"></a>
-<span class="sourceLineNo">574</span> * <p><a name="line.574"></a>
-<span class="sourceLineNo">575</span> * A best effort is made to delete each of the files, rather than bailing on the first failure.<a name="line.575"></a>
-<span class="sourceLineNo">576</span> * <p><a name="line.576"></a>
-<span class="sourceLineNo">577</span> * @param compactedFiles store files to delete from the file system.<a name="line.577"></a>
-<span class="sourceLineNo">578</span> * @throws IOException if a file cannot be deleted. All files will be attempted to deleted before<a name="line.578"></a>
-<span class="sourceLineNo">579</span> * throwing the exception, rather than failing at the first file.<a name="line.579"></a>
-<span class="sourceLineNo">580</span> */<a name="line.580"></a>
-<span class="sourceLineNo">581</span> private static void deleteStoreFilesWithoutArchiving(Collection<HStoreFile> compactedFiles)<a name="line.581"></a>
-<span class="sourceLineNo">582</span> throws IOException {<a name="line.582"></a>
-<span class="sourceLineNo">583</span> LOG.debug("Deleting files without archiving.");<a name="line.583"></a>
-<span class="sourceLineNo">584</span> List<IOException> errors = new ArrayList<>(0);<a name="line.584"></a>
-<span class="sourceLineNo">585</span> for (HStoreFile hsf : compactedFiles) {<a name="line.585"></a>
-<span class="sourceLineNo">586</span> try {<a name="line.586"></a>
-<span class="sourceLineNo">587</span> hsf.deleteStoreFile();<a name="line.587"></a>
-<span class="sourceLineNo">588</span> } catch (IOException e) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span> LOG.error("Failed to delete {}", hsf.getPath());<a name="line.589"></a>
-<span class="sourceLineNo">590</span> errors.add(e);<a name="line.590"></a>
-<span class="sourceLineNo">591</span> }<a name="line.591"></a>
-<span class="sourceLineNo">592</span> }<a name="line.592"></a>
-<span class="sourceLineNo">593</span> if (errors.size() > 0) {<a name="line.593"></a>
-<span class="sourceLineNo">594</span> throw MultipleIOException.createIOException(errors);<a name="line.594"></a>
-<span class="sourceLineNo">595</span> }<a name="line.595"></a>
-<span class="sourceLineNo">596</span> }<a name="line.596"></a>
-<span class="sourceLineNo">597</span><a name="line.597"></a>
-<span class="sourceLineNo">598</span> /**<a name="line.598"></a>
-<span class="sourceLineNo">599</span> * Adapt a type to match the {@link File} interface, which is used internally for handling<a name="line.599"></a>
-<span class="sourceLineNo">600</span> * archival/removal of files<a name="line.600"></a>
-<span class="sourceLineNo">601</span> * @param <T> type to adapt to the {@link File} interface<a name="line.601"></a>
-<span class="sourceLineNo">602</span> */<a name="line.602"></a>
-<span class="sourceLineNo">603</span> private static abstract class FileConverter<T> implements Function<T, File> {<a name="line.603"></a>
-<span class="sourceLineNo">604</span> protected final FileSystem fs;<a name="line.604"></a>
-<span class="sourceLineNo">605</span><a name="line.605"></a>
-<span class="sourceLineNo">606</span> public FileConverter(FileSystem fs) {<a name="line.606"></a>
-<span class="sourceLineNo">607</span> this.fs = fs;<a name="line.607"></a>
-<span class="sourceLineNo">608</span> }<a name="line.608"></a>
-<span class="sourceLineNo">609</span> }<a name="line.609"></a>
-<span class="sourceLineNo">610</span><a name="line.610"></a>
-<span class="sourceLineNo">611</span> /**<a name="line.611"></a>
-<span class="sourceLineNo">612</span> * Convert a FileStatus to something we can manage in the archiving<a name="line.612"></a>
-<span class="sourceLineNo">613</span> */<a name="line.613"></a>
-<span class="sourceLineNo">614</span> private static class FileStatusConverter extends FileConverter<FileStatus> {<a name="line.614"></a>
-<span class="sourceLineNo">615</span> public FileStatusConverter(FileSystem fs) {<a name="line.615"></a>
-<span class="sourceLineNo">616</span> super(fs);<a name="line.616"></a>
-<span class="sourceLineNo">617</span> }<a name="line.617"></a>
-<span class="sourceLineNo">618</span><a name="line.618"></a>
-<span class="sourceLineNo">619</span> @Override<a name="line.619"></a>
-<span class="sourceLineNo">620</span> public File apply(FileStatus input) {<a name="line.620"></a>
-<span class="sourceLineNo">621</span> return new FileablePath(fs, input.getPath());<a name="line.621"></a>
-<span class="sourceLineNo">622</span> }<a name="line.622"></a>
-<span class="sourceLineNo">623</span> }<a name="line.623"></a>
-<span class="sourceLineNo">624</span><a name="line.624"></a>
-<span class="sourceLineNo">625</span> /**<a name="line.625"></a>
-<span class="sourceLineNo">626</span> * Convert the {@link HStoreFile} into something we can manage in the archive<a name="line.626"></a>
-<span class="sourceLineNo">627</span> * methods<a name="line.627"></a>
-<span class="sourceLineNo">628</span> */<a name="line.628"></a>
-<span class="sourceLineNo">629</span> private static class StoreToFile extends FileConverter<HStoreFile> {<a name="line.629"></a>
-<span class="sourceLineNo">630</span> public StoreToFile(FileSystem fs) {<a name="line.630"></a>
-<span class="sourceLineNo">631</span> super(fs);<a name="line.631"></a>
-<span class="sourceLineNo">632</span> }<a name="line.632"></a>
-<span class="sourceLineNo">633</span><a name="line.633"></a>
-<span class="sourceLineNo">634</span> @Override<a name="line.634"></a>
-<span class="sourceLineNo">635</span> public File apply(HStoreFile input) {<a name="line.635"></a>
-<span class="sourceLineNo">636</span> return new FileableStoreFile(fs, input);<a name="line.636"></a>
-<span class="sourceLineNo">637</span> }<a name="line.637"></a>
-<span class="sourceLineNo">638</span> }<a name="line.638"></a>
-<span class="sourceLineNo">639</span><a name="line.639"></a>
-<span class="sourceLineNo">640</span> /**<a name="line.640"></a>
-<span class="sourceLineNo">641</span> * Wrapper to handle file operations uniformly<a name="line.641"></a>
-<span class="sourceLineNo">642</span> */<a name="line.642"></a>
-<span class="sourceLineNo">643</span> private static abstract class File {<a name="line.643"></a>
-<span class="sourceLineNo">644</span> protected final FileSystem fs;<a name="line.644"></a>
-<span class="sourceLineNo">645</span><a name="line.645"></a>
-<span class="sourceLineNo">646</span> public File(FileSystem fs) {<a name="line.646"></a>
-<span class="sourceLineNo">647</span> this.fs = fs;<a name="line.647"></a>
+<span class="sourceLineNo">546</span> // at this point, we should have a free spot for the archive file<a name="line.546"></a>
+<span class="sourceLineNo">547</span> boolean success = false;<a name="line.547"></a>
+<span class="sourceLineNo">548</span> for (int i = 0; !success && i < DEFAULT_RETRIES_NUMBER; ++i) {<a name="line.548"></a>
+<span class="sourceLineNo">549</span> if (i > 0) {<a name="line.549"></a>
+<span class="sourceLineNo">550</span> // Ensure that the archive directory exists.<a name="line.550"></a>
+<span class="sourceLineNo">551</span> // The previous "move to archive" operation has failed probably because<a name="line.551"></a>
+<span class="sourceLineNo">552</span> // the cleaner has removed our archive directory (HBASE-7643).<a name="line.552"></a>
+<span class="sourceLineNo">553</span> // (we're in a retry loop, so don't worry too much about the exception)<a name="line.553"></a>
+<span class="sourceLineNo">554</span> try {<a name="line.554"></a>
+<span class="sourceLineNo">555</span> if (!fs.exists(archiveDir)) {<a name="line.555"></a>
+<span class="sourceLineNo">556</span> if (fs.mkdirs(archiveDir)) {<a name="line.556"></a>
+<span class="sourceLineNo">557</span> LOG.debug("Created archive directory {}", archiveDir);<a name="line.557"></a>
+<span class="sourceLineNo">558</span> }<a name="line.558"></a>
+<span class="sourceLineNo">559</span> }<a name="line.559"></a>
+<span class="sourceLineNo">560</span> } catch (IOException e) {<a name="line.560"></a>
+<span class="sourceLineNo">561</span> LOG.warn("Failed to create directory {}", archiveDir, e);<a name="line.561"></a>
+<span class="sourceLineNo">562</span> }<a name="line.562"></a>
+<span class="sourceLineNo">563</span> }<a name="line.563"></a>
+<span class="sourceLineNo">564</span><a name="line.564"></a>
+<span class="sourceLineNo">565</span> try {<a name="line.565"></a>
+<span class="sourceLineNo">566</span> success = currentFile.moveAndClose(archiveFile);<a name="line.566"></a>
+<span class="sourceLineNo">567</span> } catch (FileNotFoundException fnfe) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span> LOG.warn("Failed to archive " + currentFile +<a name="line.568"></a>
+<span class="sourceLineNo">569</span> " because it does not exist! Skipping and continuing on.", fnfe);<a name="line.569"></a>
+<span class="sourceLineNo">570</span> success = true;<a name="line.570"></a>
+<span class="sourceLineNo">571</span> } catch (IOException e) {<a name="line.571"></a>
+<span class="sourceLineNo">572</span> LOG.warn("Failed to archive " + currentFile + " on try #" + i, e);<a name="line.572"></a>
+<span class="sourceLineNo">573</span> success = false;<a name="line.573"></a>
+<span class="sourceLineNo">574</span> }<a name="line.574"></a>
+<span class="sourceLineNo">575</span> }<a name="line.575"></a>
+<span class="sourceLineNo">576</span><a name="line.576"></a>
+<span class="sourceLineNo">577</span> if (!success) {<a name="line.577"></a>
+<span class="sourceLineNo">578</span> LOG.error("Failed to archive " + currentFile);<a name="line.578"></a>
+<span class="sourceLineNo">579</span> return false;<a name="line.579"></a>
+<span class="sourceLineNo">580</span> }<a name="line.580"></a>
+<span class="sourceLineNo">581</span><a name="line.581"></a>
+<span class="sourceLineNo">582</span> LOG.debug("Archived from {} to {}", currentFile, archiveFile);<a name="line.582"></a>
+<span class="sourceLineNo">583</span> return true;<a name="line.583"></a>
+<span class="sourceLineNo">584</span> }<a name="line.584"></a>
+<span class="sourceLineNo">585</span><a name="line.585"></a>
+<span class="sourceLineNo">586</span> /**<a name="line.586"></a>
+<span class="sourceLineNo">587</span> * Without regard for backup, delete a region. Should be used with caution.<a name="line.587"></a>
+<span class="sourceLineNo">588</span> * @param regionDir {@link Path} to the region to be deleted.<a name="line.588"></a>
+<span class="sourceLineNo">589</span> * @param fs FileSystem from which to delete the region<a name="line.589"></a>
+<span class="sourceLineNo">590</span> * @return <tt>true</tt> on successful deletion, <tt>false</tt> otherwise<a name="line.590"></a>
+<span class="sourceLineNo">591</span> * @throws IOException on filesystem operation failure<a name="line.591"></a>
+<span class="sourceLineNo">592</span> */<a name="line.592"></a>
+<span class="sourceLineNo">593</span> private static boolean deleteRegionWithoutArchiving(FileSystem fs, Path regionDir)<a name="line.593"></a>
+<span class="sourceLineNo">594</span> throws IOException {<a name="line.594"></a>
+<span class="sourceLineNo">595</span> if (fs.delete(regionDir, true)) {<a name="line.595"></a>
+<span class="sourceLineNo">596</span> LOG.debug("Deleted {}", regionDir);<a name="line.596"></a>
+<span class="sourceLineNo">597</span> return true;<a name="line.597"></a>
+<span class="sourceLineNo">598</span> }<a name="line.598"></a>
+<span class="sourceLineNo">599</span> LOG.debug("Failed to delete directory {}", regionDir);<a name="line.599"></a>
+<span class="sourceLineNo">600</span> return false;<a name="line.600"></a>
+<span class="sourceLineNo">601</span> }<a name="line.601"></a>
+<span class="sourceLineNo">602</span><a name="line.602"></a>
+<span class="sourceLineNo">603</span> /**<a name="line.603"></a>
+<span class="sourceLineNo">604</span> * Just do a simple delete of the given store files<a name="line.604"></a>
+<span class="sourceLineNo">605</span> * <p><a name="line.605"></a>
+<span class="sourceLineNo">606</span> * A best effort is made to delete each of the files, rather than bailing on the first failure.<a name="line.606"></a>
+<span class="sourceLineNo">607</span> * <p><a name="line.607"></a>
+<span class="sourceLineNo">608</span> * @param compactedFiles store files to delete from the file system.<a name="line.608"></a>
+<span class="sourceLineNo">609</span> * @throws IOException if a file cannot be deleted. All files will be attempted to deleted before<a name="line.609"></a>
+<span class="sourceLineNo">610</span> * throwing the exception, rather than failing at the first file.<a name="line.610"></a>
+<span class="sourceLineNo">611</span> */<a name="line.611"></a>
+<span class="sourceLineNo">612</span> private static void deleteStoreFilesWithoutArchiving(Collection<HStoreFile> compactedFiles)<a name="line.612"></a>
+<span class="sourceLineNo">613</span> throws IOException {<a name="line.613"></a>
+<span class="sourceLineNo">614</span> LOG.debug("Deleting files without archiving.");<a name="line.614"></a>
+<span class="sourceLineNo">615</span> List<IOException> errors = new ArrayList<>(0);<a name="line.615"></a>
+<span class="sourceLineNo">616</span> for (HStoreFile hsf : compactedFiles) {<a name="line.616"></a>
+<span class="sourceLineNo">617</span> try {<a name="line.617"></a>
+<span class="sourceLineNo">618</span> hsf.deleteStoreFile();<a name="line.618"></a>
+<span class="sourceLineNo">619</span> } catch (IOException e) {<a name="line.619"></a>
+<span class="sourceLineNo">620</span> LOG.error("Failed to delete {}", hsf.getPath());<a name="line.620"></a>
+<span class="sourceLineNo">621</span> errors.add(e);<a name="line.621"></a>
+<span class="sourceLineNo">622</span> }<a name="line.622"></a>
+<span class="sourceLineNo">623</span> }<a name="line.623"></a>
+<span class="sourceLineNo">624</span> if (errors.size() > 0) {<a name="line.624"></a>
+<span class="sourceLineNo">625</span> throw MultipleIOException.createIOException(errors);<a name="line.625"></a>
+<span class="sourceLineNo">626</span> }<a name="line.626"></a>
+<span class="sourceLineNo">627</span> }<a name="line.627"></a>
+<span class="sourceLineNo">628</span><a name="line.628"></a>
+<span class="sourceLineNo">629</span> /**<a name="line.629"></a>
+<span class="sourceLineNo">630</span> * Adapt a type to match the {@link File} interface, which is used internally for handling<a name="line.630"></a>
+<span class="sourceLineNo">631</span> * archival/removal of files<a name="line.631"></a>
+<span class="sourceLineNo">632</span> * @param <T> type to adapt to the {@link File} interface<a name="line.632"></a>
+<span class="sourceLineNo">633</span> */<a name="line.633"></a>
+<span class="sourceLineNo">634</span> private static abstract class FileConverter<T> implements Function<T, File> {<a name="line.634"></a>
+<span class="sourceLineNo">635</span> protected final FileSystem fs;<a name="line.635"></a>
+<span class="sourceLineNo">636</span><a name="line.636"></a>
+<span class="sourceLineNo">637</span> public FileConverter(FileSystem fs) {<a name="line.637"></a>
+<span class="sourceLineNo">638</span> this.fs = fs;<a name="line.638"></a>
+<span class="sourceLineNo">639</span> }<a name="line.639"></a>
+<span class="sourceLineNo">640</span> }<a name="line.640"></a>
+<span class="sourceLineNo">641</span><a name="line.641"></a>
+<span class="sourceLineNo">642</span> /**<a name="line.642"></a>
+<span class="sourceLineNo">643</span> * Convert a FileStatus to something we can manage in the archiving<a name="line.643"></a>
+<span class="sourceLineNo">644</span> */<a name="line.644"></a>
+<span class="sourceLineNo">645</span> private static class FileStatusConverter extends FileConverter<FileStatus> {<a name="line.645"></a>
+<span class="sourceLineNo">646</span> public FileStatusConverter(FileSystem fs) {<a name="line.646"></a>
+<span class="sourceLineNo">647</span> super(fs);<a name="line.647"></a>
<span class="sourceLineNo">648</span> }<a name="line.648"></a>
<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span> /**<a name="line.650"></a>
-<span class="sourceLineNo">651</span> * Delete the file<a name="line.651"></a>
-<span class="sourceLineNo">652</span> * @throws IOException on failure<a name="line.652"></a>
-<span class="sourceLineNo">653</span> */<a name="line.653"></a>
-<span class="sourceLineNo">654</span> abstract void delete() throws IOException;<a name="line.654"></a>
+<span class="sourceLineNo">650</span> @Override<a name="line.650"></a>
+<span class="sourceLineNo">651</span> public File apply(FileStatus input) {<a name="line.651"></a>
+<span class="sourceLineNo">652</span> return new FileablePath(fs, input.getPath());<a name="line.652"></a>
+<span class="sourceLineNo">653</span> }<a name="line.653"></a>
+<span class="sourceLineNo">654</span> }<a name="line.654"></a>
<span class="sourceLineNo">655</span><a name="line.655"></a>
-<span class="sourceLineNo">656</span> /**<a name="line.656"></a>
-<span class="sourceLineNo">657</span> * Check to see if this is a file or a directory<a name="line.657"></a>
-<span class="sourceLineNo">658</span> * @return <tt>true</tt> if it is a file, <tt>false</tt> otherwise<a name="line.658"></a>
-<span class="sourceLineNo">659</span> * @throws IOException on {@link FileSystem} connection error<a name="line.659"></a>
-<span class="sourceLineNo">660</span> */<a name="line.660"></a>
-<span class="sourceLineNo">661</span> abstract boolean isFile() throws IOException;<a name="line.661"></a>
-<span class="sourceLineNo">662</span><a name="line.662"></a>
-<span class="sourceLineNo">663</span> /**<a name="line.663"></a>
-<span class="sourceLineNo">664</span> * @return if this is a directory, returns all the children in the<a name="line.664"></a>
-<span class="sourceLineNo">665</span> * directory, otherwise returns an empty list<a name="line.665"></a>
-<span class="sourceLineNo">666</span> * @throws IOException<a name="line.666"></a>
-<span class="sourceLineNo">667</span> */<a name="line.667"></a>
-<span class="sourceLineNo">668</span> abstract Collection<File> getChildren() throws IOException;<a name="line.668"></a>
-<span class="sourceLineNo">669</span><a name="line.669"></a>
-<span class="sourceLineNo">670</span> /**<a name="line.670"></a>
-<span class="sourceLineNo">671</span> * close any outside readers of the file<a name="line.671"></a>
-<span class="sourceLineNo">672</span> * @throws IOException<a name="line.672"></a>
-<span class="sourceLineNo">673</span> */<a name="line.673"></a>
-<span class="sourceLineNo">674</span> abstract void close() throws IOException;<a name="line.674"></a>
-<span class="sourceLineNo">675</span><a name="line.675"></a>
-<span class="sourceLineNo">676</span> /**<a name="line.676"></a>
-<span class="sourceLineNo">677</span> * @return the name of the file (not the full fs path, just the individual<a name="line.677"></a>
-<span class="sourceLineNo">678</span> * file name)<a name="line.678"></a>
-<span class="sourceLineNo">679</span> */<a name="line.679"></a>
-<span class="sourceLineNo">680</span> abstract String getName();<a name="line.680"></a>
-<span class="sourceLineNo">681</span><a name="line.681"></a>
-<span class="sourceLineNo">682</span> /**<a name="line.682"></a>
-<span class="sourceLineNo">683</span> * @return the path to this file<a name="line.683"></a>
+<span class="sourceLineNo">656</span> /**<a name="line.656"></a>
+<span class="sourceLineNo">657</span> * Convert the {@link HStoreFile} into something we can manage in the archive<a name="line.657"></a>
+<span class="sourceLineNo">658</span> * methods<a name="line.658"></a>
+<span class="sourceLineNo">659</span> */<a name="line.659"></a>
+<span class="sourceLineNo">660</span> private static class StoreToFile extends FileConverter<HStoreFile> {<a name="line.660"></a>
+<span class="sourceLineNo">661</span> public StoreToFile(FileSystem fs) {<a name="line.661"></a>
+<span class="sourceLineNo">662</span> super(fs);<a name="line.662"></a>
+<span class="sourceLineNo">663</span> }<a name="line.663"></a>
+<span class="sourceLineNo">664</span><a name="line.664"></a>
+<span class="sourceLineNo">665</span> @Override<a name="line.665"></a>
+<span class="sourceLineNo">666</span> public File apply(HStoreFile input) {<a name="line.666"></a>
+<span class="sourceLineNo">667</span> return new FileableStoreFile(fs, input);<a name="line.667"></a>
+<span class="sourceLineNo">668</span> }<a name="line.668"></a>
+<span class="sourceLineNo">669</span> }<a name="line.669"></a>
+<span class="sourceLineNo">670</span><a name="line.670"></a>
+<span class="sourceLineNo">671</span> /**<a name="line.671"></a>
+<span class="sourceLineNo">672</span> * Wrapper to handle file operations uniformly<a name="line.672"></a>
+<span class="sourceLineNo">673</span> */<a name="line.673"></a>
+<span class="sourceLineNo">674</span> private static abstract class File {<a name="line.674"></a>
+<span class="sourceLineNo">675</span> protected final FileSystem fs;<a name="line.675"></a>
+<span class="sourceLineNo">676</span><a name="line.676"></a>
+<span class="sourceLineNo">677</span> public File(FileSystem fs) {<a name="line.677"></a>
+<span class="sourceLineNo">678</span> this.fs = fs;<a name="line.678"></a>
+<span class="sourceLineNo">679</span> }<a name="line.679"></a>
+<span class="sourceLineNo">680</span><a name="line.680"></a>
+<span class="sourceLineNo">681</span> /**<a name="line.681"></a>
+<span class="sourceLineNo">682</span> * Delete the file<a name="line.682"></a>
+<span class="sourceLineNo">683</span> * @throws IOException on failure<a name="line.683"></a>
<span class="sourceLineNo">684</span> */<a name="line.684"></a>
-<span class="sourceLineNo">685</span> abstract Path getPath();<a name="line.685"></a>
+<span class="sourceLineNo">685</span> abstract void delete() throws IOException;<a name="line.685"></a>
<span class="sourceLineNo">686</span><a name="line.686"></a>
<span class="sourceLineNo">687</span> /**<a name="line.687"></a>
-<span class="sourceLineNo">688</span> * Move the file to the given destination<a name="line.688"></a>
-<span class="sourceLineNo">689</span> * @param dest<a name="line.689"></a>
-<span class="sourceLineNo">690</span> * @return <tt>true</tt> on success<a name="line.690"></a>
-<span class="sourceLineNo">691</span> * @throws IOException<a name="line.691"></a>
-<span class="sourceLineNo">692</span> */<a name="line.692"></a>
-<span class="sourceLineNo">693</span> public boolean moveAndClose(Path dest) throws IOException {<a name="line.693"></a>
-<span class="sourceLineNo">694</span> this.close();<a name="line.694"></a>
-<span class="sourceLineNo">695</span> Path p = this.getPath();<a name="line.695"></a>
-<span class="sourceLineNo">696</span> return CommonFSUtils.renameAndSetModifyTime(fs, p, dest);<a name="line.696"></a>
-<span class="sourceLineNo">697</span> }<a name="line.697"></a>
-<span class="sourceLineNo">698</span><a name="line.698"></a>
-<span class="sourceLineNo">699</span> /**<a name="line.699"></a>
-<span class="sourceLineNo">700</span> * @return the {@link FileSystem} on which this file resides<a name="line.700"></a>
-<span class="sourceLineNo">701</span> */<a name="line.701"></a>
-<span class="sourceLineNo">702</span> public FileSystem getFileSystem() {<a name="line.702"></a>
-<span class="sourceLineNo">703</span> return this.fs;<a name="line.703"></a>
-<span class="sourceLineNo">704</span> }<a name="line.704"></a>
-<span class="sourceLineNo">705</span><a name="line.705"></a>
-<span class="sourceLineNo">706</span> @Override<a name="line.706"></a>
-<span class="sourceLineNo">707</span> public String toString() {<a name="line.707"></a>
-<span class="sourceLineNo">708</span> return this.getClass().getSimpleName() + ", " + getPath().toString();<a name="line.708"></a>
-<span class="sourceLineNo">709</span> }<a name="line.709"></a>
-<span class="sourceLineNo">710</span> }<a name="line.710"></a>
-<span class="sourceLineNo">711</span><a name="line.711"></a>
-<span class="sourceLineNo">712</span> /**<a name="line.712"></a>
-<span class="sourceLineNo">713</span> * A {@link File} that wraps a simple {@link Path} on a {@link FileSystem}.<a name="line.713"></a>
-<span class="sourceLineNo">714</span> */<a name="line.714"></a>
-<span class="sourceLineNo">715</span> private static class FileablePath extends File {<a name="line.715"></a>
-<span class="sourceLineNo">716</span> private final Path file;<a name="line.716"></a>
-<span class="sourceLineNo">717</span> private final FileStatusConverter getAsFile;<a name="line.717"></a>
-<span class="sourceLineNo">718</span><a name="line.718"></a>
-<span class="sourceLineNo">719</span> public FileablePath(FileSystem fs, Path file) {<a name="line.719"></a>
-<span class="sourceLineNo">720</span> super(fs);<a name="line.720"></a>
-<span class="sourceLineNo">721</span> this.file = file;<a name="line.721"></a>
-<span class="sourceLineNo">722</span> this.getAsFile = new FileStatusConverter(fs);<a name="line.722"></a>
-<span class="sourceLineNo">723</span> }<a name="line.723"></a>
-<span class="sourceLineNo">724</span><a name="line.724"></a>
-<span class="sourceLineNo">725</span> @Override<a name="line.725"></a>
-<span class="sourceLineNo">726</span> public void delete() throws IOException {<a name="line.726"></a>
-<span class="sourceLineNo">727</span> if (!fs.delete(file, true)) throw new IOException("Failed to delete:" + this.file);<a name="line.727"></a>
+<span class="sourceLineNo">688</span> * Check to see if this is a file or a directory<a name="line.688"></a>
+<span class="sourceLineNo">689</span> * @return <tt>true</tt> if it is a file, <tt>false</tt> otherwise<a name="line.689"></a>
+<span class="sourceLineNo">690</span> * @throws IOException on {@link FileSystem} connection error<a name="line.690"></a>
+<span class="sourceLineNo">691</span> */<a name="line.691"></a>
+<span class="sourceLineNo">692</span> abstract boolean isFile() throws IOException;<a name="line.692"></a>
+<span class="sourceLineNo">693</span><a name="line.693"></a>
+<span class="sourceLineNo">694</span> /**<a name="line.694"></a>
+<span class="sourceLineNo">695</span> * @return if this is a directory, returns all the children in the<a name="line.695"></a>
+<span class="sourceLineNo">696</span> * directory, otherwise returns an empty list<a name="line.696"></a>
+<span class="sourceLineNo">697</span> * @throws IOException<a name="line.697"></a>
+<span class="sourceLineNo">698</span> */<a name="line.698"></a>
+<span class="sourceLineNo">699</span> abstract Collection<File> getChildren() throws IOException;<a name="line.699"></a>
+<span class="sourceLineNo">700</span><a name="line.700"></a>
+<span class="sourceLineNo">701</span> /**<a name="line.701"></a>
+<span class="sourceLineNo">702</span> * close any outside readers of the file<a name="line.702"></a>
+<span class="sourceLineNo">703</span> * @throws IOException<a name="line.703"></a>
+<span class="sourceLineNo">704</span> */<a name="line.704"></a>
+<span class="sourceLineNo">705</span> abstract void close() throws IOException;<a name="line.705"></a>
+<span class="sourceLineNo">706</span><a name="line.706"></a>
+<span class="sourceLineNo">707</span> /**<a name="line.707"></a>
+<span class="sourceLineNo">708</span> * @return the name of the file (not the full fs path, just the individual<a name="line.708"></a>
+<span class="sourceLineNo">709</span> * file name)<a name="line.709"></a>
+<span class="sourceLineNo">710</span> */<a name="line.710"></a>
+<span class="sourceLineNo">711</span> abstract String getName();<a name="line.711"></a>
+<span class="sourceLineNo">712</span><a name="line.712"></a>
+<span class="sourceLineNo">713</span> /**<a name="line.713"></a>
+<span class="sourceLineNo">714</span> * @return the path to this file<a name="line.714"></a>
+<span class="sourceLineNo">715</span> */<a name="line.715"></a>
+<span class="sourceLineNo">716</span> abstract Path getPath();<a name="line.716"></a>
+<span class="sourceLineNo">717</span><a name="line.717"></a>
+<span class="sourceLineNo">718</span> /**<a name="line.718"></a>
+<span class="sourceLineNo">719</span> * Move the file to the given destination<a name="line.719"></a>
+<span class="sourceLineNo">720</span> * @param dest<a name="line.720"></a>
+<span class="sourceLineNo">721</span> * @return <tt>true</tt> on success<a name="line.721"></a>
+<span class="sourceLineNo">722</span> * @throws IOException<a name="line.722"></a>
+<span class="sourceLineNo">723</span> */<a name="line.723"></a>
+<span class="sourceLineNo">724</span> public boolean moveAndClose(Path dest) throws IOException {<a name="line.724"></a>
+<span class="sourceLineNo">725</span> this.close();<a name="line.725"></a>
+<span class="sourceLineNo">726</span> Path p = this.getPath();<a name="line.726"></a>
+<span class="sourceLineNo">727</span> return CommonFSUtils.renameAndSetModifyTime(fs, p, dest);<a name="line.727"></a>
<span class="sourceLineNo">728</span> }<a name="line.728"></a>
<span class="sourceLineNo">729</span><a name="line.729"></a>
-<span class="sourceLineNo">730</span> @Override<a name="line.730"></a>
-<span class="sourceLineNo">731</span> public String getName() {<a name="line.731"></a>
-<span class="sourceLineNo">732</span> return file.getName();<a name="line.732"></a>
-<span class="sourceLineNo">733</span> }<a name="line.733"></a>
-<span class="sourceLineNo">734</span><a name="line.734"></a>
-<span class="sourceLineNo">735</span> @Override<a name="line.735"></a>
-<span class="sourceLineNo">736</span> public Collection<File> getChildren() throws IOException {<a name="line.736"></a>
-<span class="sourceLineNo">737</span> if (fs.isFile(file)) {<a name="line.737"></a>
-<span class="sourceLineNo">738</span> return Collections.emptyList();<a name="line.738"></a>
-<span class="sourceLineNo">739</span> }<a name="line.739"></a>
-<span class="sourceLineNo">740</span> return Stream.of(fs.listStatus(file)).map(getAsFile).collect(Collectors.toList());<a name="line.740"></a>
-<span class="sourceLineNo">741</span> }<a name="line.741"></a>
+<span class="sourceLineNo">730</span> /**<a name="line.730"></a>
+<span class="sourceLineNo">731</span> * @return the {@link FileSystem} on which this file resides<a name="line.731"></a>
+<span class="sourceLineNo">732</span> */<a name="line.732"></a>
+<span class="sourceLineNo">733</span> public FileSystem getFileSystem() {<a name="line.733"></a>
+<span class="sourceLineNo">734</span> return this.fs;<a name="line.734"></a>
+<span class="sourceLineNo">735</span> }<a name="line.735"></a>
+<span class="sourceLineNo">736</span><a name="line.736"></a>
+<span class="sourceLineNo">737</span> @Override<a name="line.737"></a>
+<span class="sourceLineNo">738</span> public String toString() {<a name="line.738"></a>
+<span class="sourceLineNo">739</span> return this.getClass().getSimpleName() + ", " + getPath().toString();<a name="line.739"></a>
+<span class="sourceLineNo">740</span> }<a name="line.740"></a>
+<span class="sourceLineNo">741</span> }<a name="line.741"></a>
<span class="sourceLineNo">742</span><a name="line.742"></a>
-<span class="sourceLineNo">743</span> @Override<a name="line.743"></a>
-<span class="sourceLineNo">744</span> public boolean isFile() throws IOException {<a name="line.744"></a>
-<span class="sourceLineNo">745</span> return fs.isFile(file);<a name="line.745"></a>
-<span class="sourceLineNo">746</span> }<a name="line.746"></a>
-<span class="sourceLineNo">747</span><a name="line.747"></a>
-<span class="sourceLineNo">748</span> @Override<a name="line.748"></a>
-<span class="sourceLineNo">749</span> public void close() throws IOException {<a name="line.749"></a>
-<span class="sourceLineNo">750</span> // NOOP - files are implicitly closed on removal<a name="line.750"></a>
-<span class="sourceLineNo">751</span> }<a name="line.751"></a>
-<span class="sourceLineNo">752</span><a name="line.752"></a>
-<span class="sourceLineNo">753</span> @Override<a name="line.753"></a>
-<span class="sourceLineNo">754</span> Path getPath() {<a name="line.754"></a>
-<span class="sourceLineNo">755</span> return file;<a name="line.755"></a>
-<span class="sourceLineNo">756</span> }<a name="line.756"></a>
-<span class="sourceLineNo">757</span> }<a name="line.757"></a>
-<span class="sourceLineNo">758</span><a name="line.758"></a>
-<span class="sourceLineNo">759</span> /**<a name="line.759"></a>
-<span class="sourceLineNo">760</span> * {@link File} adapter for a {@link HStoreFile} living on a {@link FileSystem}<a name="line.760"></a>
-<span class="sourceLineNo">761</span> * .<a name="line.761"></a>
-<span class="sourceLineNo">762</span> */<a name="line.762"></a>
-<span class="sourceLineNo">763</span> private static class FileableStoreFile extends File {<a name="line.763"></a>
-<span class="sourceLineNo">764</span> HStoreFile file;<a name="line.764"></a>
+<span class="sourceLineNo">743</span> /**<a name="line.743"></a>
+<span class="sourceLineNo">744</span> * A {@link File} that wraps a simple {@link Path} on a {@link FileSystem}.<a name="line.744"></a>
+<span class="sourceLineNo">745</span> */<a name="line.745"></a>
+<span class="sourceLineNo">746</span> private static class FileablePath extends File {<a name="line.746"></a>
+<span class="sourceLineNo">747</span> private final Path file;<a name="line.747"></a>
+<span class="sourceLineNo">748</span> private final FileStatusConverter getAsFile;<a name="line.748"></a>
+<span class="sourceLineNo">749</span><a name="line.749"></a>
+<span class="sourceLineNo">750</span> public FileablePath(FileSystem fs, Path file) {<a name="line.750"></a>
+<span class="sourceLineNo">751</span> super(fs);<a name="line.751"></a>
+<span class="sourceLineNo">752</span> this.file = file;<a name="line.752"></a>
+<span class="sourceLineNo">753</span> this.getAsFile = new FileStatusConverter(fs);<a name="line.753"></a>
+<span class="sourceLineNo">754</span> }<a name="line.754"></a>
+<span class="sourceLineNo">755</span><a name="line.755"></a>
+<span class="sourceLineNo">756</span> @Override<a name="line.756"></a>
+<span class="sourceLineNo">757</span> public void delete() throws IOException {<a name="line.757"></a>
+<span class="sourceLineNo">758</span> if (!fs.delete(file, true)) throw new IOException("Failed to delete:" + this.file);<a name="line.758"></a>
+<span class="sourceLineNo">759</span> }<a name="line.759"></a>
+<span class="sourceLineNo">760</span><a name="line.760"></a>
+<span class="sourceLineNo">761</span> @Override<a name="line.761"></a>
+<span class="sourceLineNo">762</span> public String getName() {<a name="line.762"></a>
+<span class="sourceLineNo">763</span> return file.getName();<a name="line.763"></a>
+<span class="sourceLineNo">764</span> }<a name="line.764"></a>
<span class="sourceLineNo">765</span><a name="line.765"></a>
-<span class="sourceLineNo">766</span> public FileableStoreFile(FileSystem fs, HStoreFile store) {<a name="line.766"></a>
-<span class="sourceLineNo">767</span> super(fs);<a name="line.767"></a>
-<span class="sourceLineNo">768</span> this.file = store;<a name="line.768"></a>
-<span class="sourceLineNo">769</span> }<a name="line.769"></a>
-<span class="sourceLineNo">770</span><a name="line.770"></a>
-<span class="sourceLineNo">771</span> @Override<a name="line.771"></a>
-<span class="sourceLineNo">772</span> public void delete() throws IOException {<a name="line.772"></a>
-<span class="sourceLineNo">773</span> file.deleteStoreFile();<a name="line.773"></a>
-<span class="sourceLineNo">774</span> }<a name="line.774"></a>
-<span class="sourceLineNo">775</span><a name="line.775"></a>
-<span class="sourceLineNo">776</span> @Override<a name="line.776"></a>
-<span class="sourceLineNo">777</span> public String getName() {<a name="line.777"></a>
-<span class="sourceLineNo">778</span> return file.getPath().getName();<a name="line.778"></a>
-<span class="sourceLineNo">779</span> }<a name="line.779"></a>
-<span class="sourceLineNo">780</span><a name="line.780"></a>
-<span class="sourceLineNo">781</span> @Override<a name="line.781"></a>
-<span class="sourceLineNo">782</span> public boolean isFile() {<a name="line.782"></a>
-<span class="sourceLineNo">783</span> return true;<a name="line.783"></a>
-<span class="sourceLineNo">784</span> }<a name="line.784"></a>
-<span class="sourceLineNo">785</span><a name="line.785"></a>
-<span class="sourceLineNo">786</span> @Override<a name="line.786"></a>
-<span class="sourceLineNo">787</span> public Collection<File> getChildren() throws IOException {<a name="line.787"></a>
-<span class="sourceLineNo">788</span> // storefiles don't have children<a name="line.788"></a>
-<span class="sourceLineNo">789</span> return Collections.emptyList();<a name="line.789"></a>
-<span class="sourceLineNo">790</span> }<a name="line.790"></a>
-<span class="sourceLineNo">791</span><a name="line.791"></a>
-<span class="sourceLineNo">792</span> @Override<a name="line.792"></a>
-<span class="sourceLineNo">793</span> public void close() throws IOException {<a name="line.793"></a>
-<span class="sourceLineNo">794</span> file.closeStoreFile(true);<a name="line.794"></a>
-<span class="sourceLineNo">795</span> }<a name="line.795"></a>
+<span class="sourceLineNo">766</span> @Override<a name="line.766"></a>
+<span class="sourceLineNo">767</span> public Collection<File> getChildren() throws IOException {<a name="line.767"></a>
+<span class="sourceLineNo">768</span> if (fs.isFile(file)) {<a name="line.768"></a>
+<span class="sourceLineNo">769</span> return Collections.emptyList();<a name="line.769"></a>
+<span class="sourceLineNo">770</span> }<a name="line.770"></a>
+<span class="sourceLineNo">771</span> return Stream.of(fs.listStatus(file)).map(getAsFile).collect(Collectors.toList());<a name="line.771"></a>
+<span class="sourceLineNo">772</span> }<a name="line.772"></a>
+<span class="sourceLineNo">773</span><a name="line.773"></a>
+<span class="sourceLineNo">774</span> @Override<a name="line.774"></a>
+<span class="sourceLineNo">775</span> public boolean isFile() throws IOException {<a name="line.775"></a>
+<span class="sourceLineNo">776</span> return fs.isFile(file);<a name="line.776"></a>
+<span class="sourceLineNo">777</span> }<a name="line.777"></a>
+<span class="sourceLineNo">778</span><a name="line.778"></a>
+<span class="sourceLineNo">779</span> @Override<a name="line.779"></a>
+<span class="sourceLineNo">780</span> public void close() throws IOException {<a name="line.780"></a>
+<span class="sourceLineNo">781</span> // NOOP - files are implicitly closed on removal<a name="line.781"></a>
+<span class="sourceLineNo">782</span> }<a name="line.782"></a>
+<span class="sourceLineNo">783</span><a name="line.783"></a>
+<span class="sourceLineNo">784</span> @Override<a name="line.784"></a>
+<span class="sourceLineNo">785</span> Path getPath() {<a name="line.785"></a>
+<span class="sourceLineNo">786</span> return file;<a name="line.786"></a>
+<span class="sourceLineNo">787</span> }<a name="line.787"></a>
+<span class="sourceLineNo">788</span> }<a name="line.788"></a>
+<span class="sourceLineNo">789</span><a name="line.789"></a>
+<span class="sourceLineNo">790</span> /**<a name="line.790"></a>
+<span class="sourceLineNo">791</span> * {@link File} adapter for a {@link HStoreFile} living on a {@link FileSystem}<a name="line.791"></a>
+<span class="sourceLineNo">792</span> * .<a name="line.792"></a>
+<span class="sourceLineNo">793</span> */<a name="line.793"></a>
+<span class="sourceLineNo">794</span> private static class FileableStoreFile extends File {<a name="line.794"></a>
+<span class="sourceLineNo">795</span> HStoreFile file;<a name="line.795"></a>
<span class="sourceLineNo">796</span><a name="line.796"></a>
-<span class="sourceLineNo">797</span> @Override<a name="line.797"></a>
-<span class="sourceLineNo">798</span> Path getPath() {<a name="line.798"></a>
-<span class="sourceLineNo">799</span> return file.getPath();<a name="line.799"></a>
+<span class="sourceLineNo">797</span> public FileableStoreFile(FileSystem fs, HStoreFile store) {<a name="line.797"></a>
+<span class="sourceLineNo">798</span> super(fs);<a name="line.798"></a>
+<span class="sourceLineNo">799</span> this.file = store;<a name="line.799"></a>
<span class="sourceLineNo">800</span> }<a name="line.800"></a>
-<span class="sourceLineNo">801</span> }<a name="line.801"></a>
-<span class="sourceLineNo">802</span>}<a name="line.802"></a>
+<span class="sourceLineNo">801</span><a name="line.801"></a>
+<span class="sourceLineNo">802</span> @Override<a name="line.802"></a>
+<span class="sourceLineNo">803</span> public void delete() throws IOException {<a name="line.803"></a>
+<span class="sourceLineNo">804</span> file.deleteStoreFile();<a name="line.804"></a>
+<span class="sourceLineNo">805</span> }<a name="line.805"></a>
+<span class="sourceLineNo">806</span><a name="line.806"></a>
+<span class="sourceLineNo">807</span> @Override<a name="line.807"></a>
+<span class="sourceLineNo">808</span> public String getName() {<a name="line.808"></a>
+<span class="sourceLineNo">809</span> return file.getPath().getName();<a name="line.809"></a>
+<span class="sourceLineNo">810</span> }<a name="line.810"></a>
+<span class="sourceLineNo">811</span><a name="line.811"></a>
+<span class="sourceLineNo">812</span> @Override<a name="line.812"></a>
+<span class="sourceLineNo">813</span> public boolean isFile() {<a name="line.813"></a>
+<span class="sourceLineNo">814</span> return true;<a name="line.814"></a>
+<span class="sourceLineNo">815</span> }<a name="line.815"></a>
+<span class="sourceLineNo">816</span><a name="line.816"></a>
+<span class="sourceLineNo">817</span> @Override<a name="line.817"></a>
+<span class="sourceLineNo">818</span> public Collection<File> getChildren() throws IOException {<a name="line.818"></a>
+<span class="sourceLineNo">819</span> // storefiles don't have children<a name="line.819"></a>
+<span class="sourceLineNo">820</span> return Collections.emptyList();<a name="line.820"></a>
+<span class="sourceLineNo">821</span> }<a name="line.821"></a>
+<span class="sourceLineNo">822</span><a name="line.822"></a>
+<span class="sourceLineNo">823</span> @Override<a name="line.823"></a>
+<span class="sourceLineNo">824</span> public void close() throws IOException {<a name="line.824"></a>
+<span class="sourceLineNo">825</span> file.closeStoreFile(true);<a name="line.825"></a>
+<span class="sourceLineNo">826</span> }<a name="line.826"></a>
+<span class="sourceLineNo">827</span><a name="line.827"></a>
+<span class="sourceLineNo">828</span> @Override<a name="line.828"></a>
+<span class="sourceLineNo">829</span> Path getPath() {<a name="line.829"></a>
+<span class="sourceLineNo">830</span> return file.getPath();<a name="line.830"></a>
+<span class="sourceLineNo">831</span> }<a name="line.831"></a>
+<span class="sourceLineNo">832</span> }<a name="line.832"></a>
+<span class="sourceLineNo">833</span>}<a name="line.833"></a>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html b/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html
index 22ea136..ee79f25 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.FileableStoreFile.html
@@ -496,318 +496,349 @@
<span class="sourceLineNo">488</span> Path archiveFile = new Path(archiveDir, filename);<a name="line.488"></a>
<span class="sourceLineNo">489</span> FileSystem fs = currentFile.getFileSystem();<a name="line.489"></a>
<span class="sourceLineNo">490</span><a name="line.490"></a>
-<span class="sourceLineNo">491</span> // if the file already exists in the archive, move that one to a timestamped backup. This is a<a name="line.491"></a>
-<span class="sourceLineNo">492</span> // really, really unlikely situtation, where we get the same name for the existing file, but<a name="line.492"></a>
-<span class="sourceLineNo">493</span> // is included just for that 1 in trillion chance.<a name="line.493"></a>
-<span class="sourceLineNo">494</span> if (fs.exists(archiveFile)) {<a name="line.494"></a>
-<span class="sourceLineNo">495</span> LOG.debug("{} already exists in archive, moving to timestamped backup and " +<a name="line.495"></a>
-<span class="sourceLineNo">496</span> "overwriting current.", archiveFile);<a name="line.496"></a>
-<span class="sourceLineNo">497</span><a name="line.497"></a>
-<span class="sourceLineNo">498</span> // move the archive file to the stamped backup<a name="line.498"></a>
-<span class="sourceLineNo">499</span> Path backedupArchiveFile = new Path(archiveDir, filename + SEPARATOR + archiveStartTime);<a name="line.499"></a>
-<span class="sourceLineNo">500</span> if (!fs.rename(archiveFile, backedupArchiveFile)) {<a name="line.500"></a>
-<span class="sourceLineNo">501</span> LOG.error("Could not rename archive file to backup: " + backedupArchiveFile<a name="line.501"></a>
-<span class="sourceLineNo">502</span> + ", deleting existing file in favor of newer.");<a name="line.502"></a>
-<span class="sourceLineNo">503</span> // try to delete the exisiting file, if we can't rename it<a name="line.503"></a>
-<span class="sourceLineNo">504</span> if (!fs.delete(archiveFile, false)) {<a name="line.504"></a>
-<span class="sourceLineNo">505</span> throw new IOException("Couldn't delete existing archive file (" + archiveFile<a name="line.505"></a>
-<span class="sourceLineNo">506</span> + ") or rename it to the backup file (" + backedupArchiveFile<a name="line.506"></a>
-<span class="sourceLineNo">507</span> + ") to make room for similarly named file.");<a name="line.507"></a>
-<span class="sourceLineNo">508</span> }<a name="line.508"></a>
-<span class="sourceLineNo">509</span> }<a name="line.509"></a>
-<span class="sourceLineNo">510</span> LOG.debug("Backed up archive file from " + archiveFile);<a name="line.510"></a>
-<span class="sourceLineNo">511</span> }<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span> LOG.trace("No existing file in archive for {}, free to archive original file.", archiveFile);<a name="line.513"></a>
-<span class="sourceLineNo">514</span><a name="line.514"></a>
-<span class="sourceLineNo">515</span> // at this point, we should have a free spot for the archive file<a name="line.515"></a>
-<span class="sourceLineNo">516</span> boolean success = false;<a name="line.516"></a>
-<span class="sourceLineNo">517</span> for (int i = 0; !success && i < DEFAULT_RETRIES_NUMBER; ++i) {<a name="line.517"></a>
-<span class="sourceLineNo">518</span> if (i > 0) {<a name="line.518"></a>
-<span class="sourceLineNo">519</span> // Ensure that the archive directory exists.<a name="line.519"></a>
-<span class="sourceLineNo">520</span> // The previous "move to archive" operation has failed probably because<a name="line.520"></a>
-<span class="sourceLineNo">521</span> // the cleaner has removed our archive directory (HBASE-7643).<a name="line.521"></a>
-<span class="sourceLineNo">522</span> // (we're in a retry loop, so don't worry too much about the exception)<a name="line.522"></a>
-<span class="sourceLineNo">523</span> try {<a name="line.523"></a>
-<span class="sourceLineNo">524</span> if (!fs.exists(archiveDir)) {<a name="line.524"></a>
-<span class="sourceLineNo">525</span> if (fs.mkdirs(archiveDir)) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span> LOG.debug("Created archive directory {}", archiveDir);<a name="line.526"></a>
-<span class="sourceLineNo">527</span> }<a name="line.527"></a>
-<span class="sourceLineNo">528</span> }<a name="line.528"></a>
-<span class="sourceLineNo">529</span> } catch (IOException e) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span> LOG.warn("Failed to create directory {}", archiveDir, e);<a name="line.530"></a>
-<span class="sourceLineNo">531</span> }<a name="line.531"></a>
-<span class="sourceLineNo">532</span> }<a name="line.532"></a>
-<span class="sourceLineNo">533</span><a name="line.533"></a>
-<span class="sourceLineNo">534</span> try {<a name="line.534"></a>
-<span class="sourceLineNo">535</span> success = currentFile.moveAndClose(archiveFile);<a name="line.535"></a>
-<span class="sourceLineNo">536</span> } catch (FileNotFoundException fnfe) {<a name="line.536"></a>
-<span class="sourceLineNo">537</span> LOG.warn("Failed to archive " + currentFile +<a name="line.537"></a>
-<span class="sourceLineNo">538</span> " because it does not exist! Skipping and continuing on.", fnfe);<a name="line.538"></a>
-<span class="sourceLineNo">539</span> success = true;<a name="line.539"></a>
-<span class="sourceLineNo">540</span> } catch (IOException e) {<a name="line.540"></a>
-<span class="sourceLineNo">541</span> LOG.warn("Failed to archive " + currentFile + " on try #" + i, e);<a name="line.541"></a>
-<span class="sourceLineNo">542</span> success = false;<a name="line.542"></a>
-<span class="sourceLineNo">543</span> }<a name="line.543"></a>
-<span class="sourceLineNo">544</span> }<a name="line.544"></a>
+<span class="sourceLineNo">491</span> // An existing destination file in the archive is unexpected, but we handle it here.<a name="line.491"></a>
+<span class="sourceLineNo">492</span> if (fs.exists(archiveFile)) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span> if (!fs.exists(currentFile.getPath())) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span> // If the file already exists in the archive, and there is no current file to archive, then<a name="line.494"></a>
+<span class="sourceLineNo">495</span> // assume that the file in archive is correct. This is an unexpected situation, suggesting a<a name="line.495"></a>
+<span class="sourceLineNo">496</span> // race condition or split brain.<a name="line.496"></a>
+<span class="sourceLineNo">497</span> // In HBASE-26718 this was found when compaction incorrectly happened during warmupRegion.<a name="line.497"></a>
+<span class="sourceLineNo">498</span> LOG.warn("{} exists in archive. Attempted to archive nonexistent file {}.", archiveFile,<a name="line.498"></a>
+<span class="sourceLineNo">499</span> currentFile);<a name="line.499"></a>
+<span class="sourceLineNo">500</span> // We return success to match existing behavior in this method, where FileNotFoundException<a name="line.500"></a>
+<span class="sourceLineNo">501</span> // in moveAndClose is ignored.<a name="line.501"></a>
+<span class="sourceLineNo">502</span> return true;<a name="line.502"></a>
+<span class="sourceLineNo">503</span> }<a name="line.503"></a>
+<span class="sourceLineNo">504</span> // There is a conflict between the current file and the already existing archived file.<a name="line.504"></a>
+<span class="sourceLineNo">505</span> // Move the archived file to a timestamped backup. This is a really, really unlikely<a name="line.505"></a>
+<span class="sourceLineNo">506</span> // situation, where we get the same name for the existing file, but is included just for that<a name="line.506"></a>
+<span class="sourceLineNo">507</span> // 1 in trillion chance. We are potentially incurring data loss in the archive directory if<a name="line.507"></a>
+<span class="sourceLineNo">508</span> // the files are not identical. The timestamped backup will be cleaned by HFileCleaner as it<a name="line.508"></a>
+<span class="sourceLineNo">509</span> // has no references.<a name="line.509"></a>
+<span class="sourceLineNo">510</span> FileStatus curStatus = fs.getFileStatus(currentFile.getPath());<a name="line.510"></a>
+<span class="sourceLineNo">511</span> FileStatus archiveStatus = fs.getFileStatus(archiveFile);<a name="line.511"></a>
+<span class="sourceLineNo">512</span> long curLen = curStatus.getLen();<a name="line.512"></a>
+<span class="sourceLineNo">513</span> long archiveLen = archiveStatus.getLen();<a name="line.513"></a>
+<span class="sourceLineNo">514</span> long curMtime = curStatus.getModificationTime();<a name="line.514"></a>
+<span class="sourceLineNo">515</span> long archiveMtime = archiveStatus.getModificationTime();<a name="line.515"></a>
+<span class="sourceLineNo">516</span> if (curLen != archiveLen) {<a name="line.516"></a>
+<span class="sourceLineNo">517</span> LOG.error("{} already exists in archive with different size than current {}."<a name="line.517"></a>
+<span class="sourceLineNo">518</span> + " archiveLen: {} currentLen: {} archiveMtime: {} currentMtime: {}",<a name="line.518"></a>
+<span class="sourceLineNo">519</span> archiveFile, currentFile, archiveLen, curLen, archiveMtime, curMtime);<a name="line.519"></a>
+<span class="sourceLineNo">520</span> throw new IOException(archiveFile + " already exists in archive with different size" +<a name="line.520"></a>
+<span class="sourceLineNo">521</span> " than " + currentFile);<a name="line.521"></a>
+<span class="sourceLineNo">522</span> }<a name="line.522"></a>
+<span class="sourceLineNo">523</span><a name="line.523"></a>
+<span class="sourceLineNo">524</span> LOG.error("{} already exists in archive, moving to timestamped backup and overwriting"<a name="line.524"></a>
+<span class="sourceLineNo">525</span> + " current {}. archiveLen: {} currentLen: {} archiveMtime: {} currentMtime: {}",<a name="line.525"></a>
+<span class="sourceLineNo">526</span> archiveFile, currentFile, archiveLen, curLen, archiveMtime, curMtime);<a name="line.526"></a>
+<span class="sourceLineNo">527</span><a name="line.527"></a>
+<span class="sourceLineNo">528</span> // move the archive file to the stamped backup<a name="line.528"></a>
+<span class="sourceLineNo">529</span> Path backedupArchiveFile = new Path(archiveDir, filename + SEPARATOR + archiveStartTime);<a name="line.529"></a>
+<span class="sourceLineNo">530</span> if (!fs.rename(archiveFile, backedupArchiveFile)) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span> LOG.error("Could not rename archive file to backup: " + backedupArchiveFile<a name="line.531"></a>
+<span class="sourceLineNo">532</span> + ", deleting existing file in favor of newer.");<a name="line.532"></a>
+<span class="sourceLineNo">533</span> // try to delete the existing file, if we can't rename it<a name="line.533"></a>
+<span class="sourceLineNo">534</span> if (!fs.delete(archiveFile, false)) {<a name="line.534"></a>
+<span class="sourceLineNo">535</span> throw new IOException("Couldn't delete existing archive file (" + archiveFile<a name="line.535"></a>
+<span class="sourceLineNo">536</span> + ") or rename it to the backup file (" + backedupArchiveFile<a name="line.536"></a>
+<span class="sourceLineNo">537</span> + ") to make room for similarly named file.");<a name="line.537"></a>
+<span class="sourceLineNo">538</span> }<a name="line.538"></a>
+<span class="sourceLineNo">539</span> } else {<a name="line.539"></a>
+<span class="sourceLineNo">540</span> LOG.info("Backed up archive file from {} to {}.", archiveFile, backedupArchiveFile);<a name="line.540"></a>
+<span class="sourceLineNo">541</span> }<a name="line.541"></a>
+<span class="sourceLineNo">542</span> }<a name="line.542"></a>
+<span class="sourceLineNo">543</span><a name="line.543"></a>
+<span class="sourceLineNo">544</span> LOG.trace("No existing file in archive for {}, free to archive original file.", archiveFile);<a name="line.544"></a>
<span class="sourceLineNo">545</span><a name="line.545"></a>
-<span class="sourceLineNo">546</span> if (!success) {<a name="line.546"></a>
-<span class="sourceLineNo">547</span> LOG.error("Failed to archive " + currentFile);<a name="line.547"></a>
-<span class="sourceLineNo">548</span> return false;<a name="line.548"></a>
-<span class="sourceLineNo">549</span> }<a name="line.549"></a>
-<span class="sourceLineNo">550</span><a name="line.550"></a>
-<span class="sourceLineNo">551</span> LOG.debug("Archived from {} to {}", currentFile, archiveFile);<a name="line.551"></a>
-<span class="sourceLineNo">552</span> return true;<a name="line.552"></a>
-<span class="sourceLineNo">553</span> }<a name="line.553"></a>
-<span class="sourceLineNo">554</span><a name="line.554"></a>
-<span class="sourceLineNo">555</span> /**<a name="line.555"></a>
-<span class="sourceLineNo">556</span> * Without regard for backup, delete a region. Should be used with caution.<a name="line.556"></a>
-<span class="sourceLineNo">557</span> * @param regionDir {@link Path} to the region to be deleted.<a name="line.557"></a>
-<span class="sourceLineNo">558</span> * @param fs FileSystem from which to delete the region<a name="line.558"></a>
-<span class="sourceLineNo">559</span> * @return <tt>true</tt> on successful deletion, <tt>false</tt> otherwise<a name="line.559"></a>
-<span class="sourceLineNo">560</span> * @throws IOException on filesystem operation failure<a name="line.560"></a>
-<span class="sourceLineNo">561</span> */<a name="line.561"></a>
-<span class="sourceLineNo">562</span> private static boolean deleteRegionWithoutArchiving(FileSystem fs, Path regionDir)<a name="line.562"></a>
-<span class="sourceLineNo">563</span> throws IOException {<a name="line.563"></a>
-<span class="sourceLineNo">564</span> if (fs.delete(regionDir, true)) {<a name="line.564"></a>
-<span class="sourceLineNo">565</span> LOG.debug("Deleted {}", regionDir);<a name="line.565"></a>
-<span class="sourceLineNo">566</span> return true;<a name="line.566"></a>
-<span class="sourceLineNo">567</span> }<a name="line.567"></a>
-<span class="sourceLineNo">568</span> LOG.debug("Failed to delete directory {}", regionDir);<a name="line.568"></a>
-<span class="sourceLineNo">569</span> return false;<a name="line.569"></a>
-<span class="sourceLineNo">570</span> }<a name="line.570"></a>
-<span class="sourceLineNo">571</span><a name="line.571"></a>
-<span class="sourceLineNo">572</span> /**<a name="line.572"></a>
-<span class="sourceLineNo">573</span> * Just do a simple delete of the given store files<a name="line.573"></a>
-<span class="sourceLineNo">574</span> * <p><a name="line.574"></a>
-<span class="sourceLineNo">575</span> * A best effort is made to delete each of the files, rather than bailing on the first failure.<a name="line.575"></a>
-<span class="sourceLineNo">576</span> * <p><a name="line.576"></a>
-<span class="sourceLineNo">577</span> * @param compactedFiles store files to delete from the file system.<a name="line.577"></a>
-<span class="sourceLineNo">578</span> * @throws IOException if a file cannot be deleted. All files will be attempted to deleted before<a name="line.578"></a>
-<span class="sourceLineNo">579</span> * throwing the exception, rather than failing at the first file.<a name="line.579"></a>
-<span class="sourceLineNo">580</span> */<a name="line.580"></a>
-<span class="sourceLineNo">581</span> private static void deleteStoreFilesWithoutArchiving(Collection<HStoreFile> compactedFiles)<a name="line.581"></a>
-<span class="sourceLineNo">582</span> throws IOException {<a name="line.582"></a>
-<span class="sourceLineNo">583</span> LOG.debug("Deleting files without archiving.");<a name="line.583"></a>
-<span class="sourceLineNo">584</span> List<IOException> errors = new ArrayList<>(0);<a name="line.584"></a>
-<span class="sourceLineNo">585</span> for (HStoreFile hsf : compactedFiles) {<a name="line.585"></a>
-<span class="sourceLineNo">586</span> try {<a name="line.586"></a>
-<span class="sourceLineNo">587</span> hsf.deleteStoreFile();<a name="line.587"></a>
-<span class="sourceLineNo">588</span> } catch (IOException e) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span> LOG.error("Failed to delete {}", hsf.getPath());<a name="line.589"></a>
-<span class="sourceLineNo">590</span> errors.add(e);<a name="line.590"></a>
-<span class="sourceLineNo">591</span> }<a name="line.591"></a>
-<span class="sourceLineNo">592</span> }<a name="line.592"></a>
-<span class="sourceLineNo">593</span> if (errors.size() > 0) {<a name="line.593"></a>
-<span class="sourceLineNo">594</span> throw MultipleIOException.createIOException(errors);<a name="line.594"></a>
-<span class="sourceLineNo">595</span> }<a name="line.595"></a>
-<span class="sourceLineNo">596</span> }<a name="line.596"></a>
-<span class="sourceLineNo">597</span><a name="line.597"></a>
-<span class="sourceLineNo">598</span> /**<a name="line.598"></a>
-<span class="sourceLineNo">599</span> * Adapt a type to match the {@link File} interface, which is used internally for handling<a name="line.599"></a>
-<span class="sourceLineNo">600</span> * archival/removal of files<a name="line.600"></a>
-<span class="sourceLineNo">601</span> * @param <T> type to adapt to the {@link File} interface<a name="line.601"></a>
-<span class="sourceLineNo">602</span> */<a name="line.602"></a>
-<span class="sourceLineNo">603</span> private static abstract class FileConverter<T> implements Function<T, File> {<a name="line.603"></a>
-<span class="sourceLineNo">604</span> protected final FileSystem fs;<a name="line.604"></a>
-<span class="sourceLineNo">605</span><a name="line.605"></a>
-<span class="sourceLineNo">606</span> public FileConverter(FileSystem fs) {<a name="line.606"></a>
-<span class="sourceLineNo">607</span> this.fs = fs;<a name="line.607"></a>
-<span class="sourceLineNo">608</span> }<a name="line.608"></a>
-<span class="sourceLineNo">609</span> }<a name="line.609"></a>
-<span class="sourceLineNo">610</span><a name="line.610"></a>
-<span class="sourceLineNo">611</span> /**<a name="line.611"></a>
-<span class="sourceLineNo">612</span> * Convert a FileStatus to something we can manage in the archiving<a name="line.612"></a>
-<span class="sourceLineNo">613</span> */<a name="line.613"></a>
-<span class="sourceLineNo">614</span> private static class FileStatusConverter extends FileConverter<FileStatus> {<a name="line.614"></a>
-<span class="sourceLineNo">615</span> public FileStatusConverter(FileSystem fs) {<a name="line.615"></a>
-<span class="sourceLineNo">616</span> super(fs);<a name="line.616"></a>
-<span class="sourceLineNo">617</span> }<a name="line.617"></a>
-<span class="sourceLineNo">618</span><a name="line.618"></a>
-<span class="sourceLineNo">619</span> @Override<a name="line.619"></a>
-<span class="sourceLineNo">620</span> public File apply(FileStatus input) {<a name="line.620"></a>
-<span class="sourceLineNo">621</span> return new FileablePath(fs, input.getPath());<a name="line.621"></a>
-<span class="sourceLineNo">622</span> }<a name="line.622"></a>
-<span class="sourceLineNo">623</span> }<a name="line.623"></a>
-<span class="sourceLineNo">624</span><a name="line.624"></a>
-<span class="sourceLineNo">625</span> /**<a name="line.625"></a>
-<span class="sourceLineNo">626</span> * Convert the {@link HStoreFile} into something we can manage in the archive<a name="line.626"></a>
-<span class="sourceLineNo">627</span> * methods<a name="line.627"></a>
-<span class="sourceLineNo">628</span> */<a name="line.628"></a>
-<span class="sourceLineNo">629</span> private static class StoreToFile extends FileConverter<HStoreFile> {<a name="line.629"></a>
-<span class="sourceLineNo">630</span> public StoreToFile(FileSystem fs) {<a name="line.630"></a>
-<span class="sourceLineNo">631</span> super(fs);<a name="line.631"></a>
-<span class="sourceLineNo">632</span> }<a name="line.632"></a>
-<span class="sourceLineNo">633</span><a name="line.633"></a>
-<span class="sourceLineNo">634</span> @Override<a name="line.634"></a>
-<span class="sourceLineNo">635</span> public File apply(HStoreFile input) {<a name="line.635"></a>
-<span class="sourceLineNo">636</span> return new FileableStoreFile(fs, input);<a name="line.636"></a>
-<span class="sourceLineNo">637</span> }<a name="line.637"></a>
-<span class="sourceLineNo">638</span> }<a name="line.638"></a>
-<span class="sourceLineNo">639</span><a name="line.639"></a>
-<span class="sourceLineNo">640</span> /**<a name="line.640"></a>
-<span class="sourceLineNo">641</span> * Wrapper to handle file operations uniformly<a name="line.641"></a>
-<span class="sourceLineNo">642</span> */<a name="line.642"></a>
-<span class="sourceLineNo">643</span> private static abstract class File {<a name="line.643"></a>
-<span class="sourceLineNo">644</span> protected final FileSystem fs;<a name="line.644"></a>
-<span class="sourceLineNo">645</span><a name="line.645"></a>
-<span class="sourceLineNo">646</span> public File(FileSystem fs) {<a name="line.646"></a>
-<span class="sourceLineNo">647</span> this.fs = fs;<a name="line.647"></a>
+<span class="sourceLineNo">546</span> // at this point, we should have a free spot for the archive file<a name="line.546"></a>
+<span class="sourceLineNo">547</span> boolean success = false;<a name="line.547"></a>
+<span class="sourceLineNo">548</span> for (int i = 0; !success && i < DEFAULT_RETRIES_NUMBER; ++i) {<a name="line.548"></a>
+<span class="sourceLineNo">549</span> if (i > 0) {<a name="line.549"></a>
+<span class="sourceLineNo">550</span> // Ensure that the archive directory exists.<a name="line.550"></a>
+<span class="sourceLineNo">551</span> // The previous "move to archive" operation has failed probably because<a name="line.551"></a>
+<span class="sourceLineNo">552</span> // the cleaner has removed our archive directory (HBASE-7643).<a name="line.552"></a>
+<span class="sourceLineNo">553</span> // (we're in a retry loop, so don't worry too much about the exception)<a name="line.553"></a>
+<span class="sourceLineNo">554</span> try {<a name="line.554"></a>
+<span class="sourceLineNo">555</span> if (!fs.exists(archiveDir)) {<a name="line.555"></a>
+<span class="sourceLineNo">556</span> if (fs.mkdirs(archiveDir)) {<a name="line.556"></a>
+<span class="sourceLineNo">557</span> LOG.debug("Created archive directory {}", archiveDir);<a name="line.557"></a>
+<span class="sourceLineNo">558</span> }<a name="line.558"></a>
+<span class="sourceLineNo">559</span> }<a name="line.559"></a>
+<span class="sourceLineNo">560</span> } catch (IOException e) {<a name="line.560"></a>
+<span class="sourceLineNo">561</span> LOG.warn("Failed to create directory {}", archiveDir, e);<a name="line.561"></a>
+<span class="sourceLineNo">562</span> }<a name="line.562"></a>
+<span class="sourceLineNo">563</span> }<a name="line.563"></a>
+<span class="sourceLineNo">564</span><a name="line.564"></a>
+<span class="sourceLineNo">565</span> try {<a name="line.565"></a>
+<span class="sourceLineNo">566</span> success = currentFile.moveAndClose(archiveFile);<a name="line.566"></a>
+<span class="sourceLineNo">567</span> } catch (FileNotFoundException fnfe) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span> LOG.warn("Failed to archive " + currentFile +<a name="line.568"></a>
+<span class="sourceLineNo">569</span> " because it does not exist! Skipping and continuing on.", fnfe);<a name="line.569"></a>
+<span class="sourceLineNo">570</span> success = true;<a name="line.570"></a>
+<span class="sourceLineNo">571</span> } catch (IOException e) {<a name="line.571"></a>
+<span class="sourceLineNo">572</span> LOG.warn("Failed to archive " + currentFile + " on try #" + i, e);<a name="line.572"></a>
+<span class="sourceLineNo">573</span> success = false;<a name="line.573"></a>
+<span class="sourceLineNo">574</span> }<a name="line.574"></a>
+<span class="sourceLineNo">575</span> }<a name="line.575"></a>
+<span class="sourceLineNo">576</span><a name="line.576"></a>
+<span class="sourceLineNo">577</span> if (!success) {<a name="line.577"></a>
+<span class="sourceLineNo">578</span> LOG.error("Failed to archive " + currentFile);<a name="line.578"></a>
+<span class="sourceLineNo">579</span> return false;<a name="line.579"></a>
+<span class="sourceLineNo">580</span> }<a name="line.580"></a>
+<span class="sourceLineNo">581</span><a name="line.581"></a>
+<span class="sourceLineNo">582</span> LOG.debug("Archived from {} to {}", currentFile, archiveFile);<a name="line.582"></a>
+<span class="sourceLineNo">583</span> return true;<a name="line.583"></a>
+<span class="sourceLineNo">584</span> }<a name="line.584"></a>
+<span class="sourceLineNo">585</span><a name="line.585"></a>
+<span class="sourceLineNo">586</span> /**<a name="line.586"></a>
+<span class="sourceLineNo">587</span> * Without regard for backup, delete a region. Should be used with caution.<a name="line.587"></a>
+<span class="sourceLineNo">588</span> * @param regionDir {@link Path} to the region to be deleted.<a name="line.588"></a>
+<span class="sourceLineNo">589</span> * @param fs FileSystem from which to delete the region<a name="line.589"></a>
+<span class="sourceLineNo">590</span> * @return <tt>true</tt> on successful deletion, <tt>false</tt> otherwise<a name="line.590"></a>
+<span class="sourceLineNo">591</span> * @throws IOException on filesystem operation failure<a name="line.591"></a>
+<span class="sourceLineNo">592</span> */<a name="line.592"></a>
+<span class="sourceLineNo">593</span> private static boolean deleteRegionWithoutArchiving(FileSystem fs, Path regionDir)<a name="line.593"></a>
+<span class="sourceLineNo">594</span> throws IOException {<a name="line.594"></a>
+<span class="sourceLineNo">595</span> if (fs.delete(regionDir, true)) {<a name="line.595"></a>
+<span class="sourceLineNo">596</span> LOG.debug("Deleted {}", regionDir);<a name="line.596"></a>
+<span class="sourceLineNo">597</span> return true;<a name="line.597"></a>
+<span class="sourceLineNo">598</span> }<a name="line.598"></a>
+<span class="sourceLineNo">599</span> LOG.debug("Failed to delete directory {}", regionDir);<a name="line.599"></a>
+<span class="sourceLineNo">600</span> return false;<a name="line.600"></a>
+<span class="sourceLineNo">601</span> }<a name="line.601"></a>
+<span class="sourceLineNo">602</span><a name="line.602"></a>
+<span class="sourceLineNo">603</span> /**<a name="line.603"></a>
+<span class="sourceLineNo">604</span> * Just do a simple delete of the given store files<a name="line.604"></a>
+<span class="sourceLineNo">605</span> * <p><a name="line.605"></a>
+<span class="sourceLineNo">606</span> * A best effort is made to delete each of the files, rather than bailing on the first failure.<a name="line.606"></a>
+<span class="sourceLineNo">607</span> * <p><a name="line.607"></a>
+<span class="sourceLineNo">608</span> * @param compactedFiles store files to delete from the file system.<a name="line.608"></a>
+<span class="sourceLineNo">609</span> * @throws IOException if a file cannot be deleted. All files will be attempted to deleted before<a name="line.609"></a>
+<span class="sourceLineNo">610</span> * throwing the exception, rather than failing at the first file.<a name="line.610"></a>
+<span class="sourceLineNo">611</span> */<a name="line.611"></a>
+<span class="sourceLineNo">612</span> private static void deleteStoreFilesWithoutArchiving(Collection<HStoreFile> compactedFiles)<a name="line.612"></a>
+<span class="sourceLineNo">613</span> throws IOException {<a name="line.613"></a>
+<span class="sourceLineNo">614</span> LOG.debug("Deleting files without archiving.");<a name="line.614"></a>
+<span class="sourceLineNo">615</span> List<IOException> errors = new ArrayList<>(0);<a name="line.615"></a>
+<span class="sourceLineNo">616</span> for (HStoreFile hsf : compactedFiles) {<a name="line.616"></a>
+<span class="sourceLineNo">617</span> try {<a name="line.617"></a>
+<span class="sourceLineNo">618</span> hsf.deleteStoreFile();<a name="line.618"></a>
+<span class="sourceLineNo">619</span> } catch (IOException e) {<a name="line.619"></a>
+<span class="sourceLineNo">620</span> LOG.error("Failed to delete {}", hsf.getPath());<a name="line.620"></a>
+<span class="sourceLineNo">621</span> errors.add(e);<a name="line.621"></a>
+<span class="sourceLineNo">622</span> }<a name="line.622"></a>
+<span class="sourceLineNo">623</span> }<a name="line.623"></a>
+<span class="sourceLineNo">624</span> if (errors.size() > 0) {<a name="line.624"></a>
+<span class="sourceLineNo">625</span> throw MultipleIOException.createIOException(errors);<a name="line.625"></a>
+<span class="sourceLineNo">626</span> }<a name="line.626"></a>
+<span class="sourceLineNo">627</span> }<a name="line.627"></a>
+<span class="sourceLineNo">628</span><a name="line.628"></a>
+<span class="sourceLineNo">629</span> /**<a name="line.629"></a>
+<span class="sourceLineNo">630</span> * Adapt a type to match the {@link File} interface, which is used internally for handling<a name="line.630"></a>
+<span class="sourceLineNo">631</span> * archival/removal of files<a name="line.631"></a>
+<span class="sourceLineNo">632</span> * @param <T> type to adapt to the {@link File} interface<a name="line.632"></a>
+<span class="sourceLineNo">633</span> */<a name="line.633"></a>
+<span class="sourceLineNo">634</span> private static abstract class FileConverter<T> implements Function<T, File> {<a name="line.634"></a>
+<span class="sourceLineNo">635</span> protected final FileSystem fs;<a name="line.635"></a>
+<span class="sourceLineNo">636</span><a name="line.636"></a>
+<span class="sourceLineNo">637</span> public FileConverter(FileSystem fs) {<a name="line.637"></a>
+<span class="sourceLineNo">638</span> this.fs = fs;<a name="line.638"></a>
+<span class="sourceLineNo">639</span> }<a name="line.639"></a>
+<span class="sourceLineNo">640</span> }<a name="line.640"></a>
+<span class="sourceLineNo">641</span><a name="line.641"></a>
+<span class="sourceLineNo">642</span> /**<a name="line.642"></a>
+<span class="sourceLineNo">643</span> * Convert a FileStatus to something we can manage in the archiving<a name="line.643"></a>
+<span class="sourceLineNo">644</span> */<a name="line.644"></a>
+<span class="sourceLineNo">645</span> private static class FileStatusConverter extends FileConverter<FileStatus> {<a name="line.645"></a>
+<span class="sourceLineNo">646</span> public FileStatusConverter(FileSystem fs) {<a name="line.646"></a>
+<span class="sourceLineNo">647</span> super(fs);<a name="line.647"></a>
<span class="sourceLineNo">648</span> }<a name="line.648"></a>
<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span> /**<a name="line.650"></a>
-<span class="sourceLineNo">651</span> * Delete the file<a name="line.651"></a>
-<span class="sourceLineNo">652</span> * @throws IOException on failure<a name="line.652"></a>
-<span class="sourceLineNo">653</span> */<a name="line.653"></a>
-<span class="sourceLineNo">654</span> abstract void delete() throws IOException;<a name="line.654"></a>
+<span class="sourceLineNo">650</span> @Override<a name="line.650"></a>
+<span class="sourceLineNo">651</span> public File apply(FileStatus input) {<a name="line.651"></a>
+<span class="sourceLineNo">652</span> return new FileablePath(fs, input.getPath());<a name="line.652"></a>
+<span class="sourceLineNo">653</span> }<a name="line.653"></a>
+<span class="sourceLineNo">654</span> }<a name="line.654"></a>
<span class="sourceLineNo">655</span><a name="line.655"></a>
-<span class="sourceLineNo">656</span> /**<a name="line.656"></a>
-<span class="sourceLineNo">657</span> * Check to see if this is a file or a directory<a name="line.657"></a>
-<span class="sourceLineNo">658</span> * @return <tt>true</tt> if it is a file, <tt>false</tt> otherwise<a name="line.658"></a>
-<span class="sourceLineNo">659</span> * @throws IOException on {@link FileSystem} connection error<a name="line.659"></a>
-<span class="sourceLineNo">660</span> */<a name="line.660"></a>
-<span class="sourceLineNo">661</span> abstract boolean isFile() throws IOException;<a name="line.661"></a>
-<span class="sourceLineNo">662</span><a name="line.662"></a>
-<span class="sourceLineNo">663</span> /**<a name="line.663"></a>
-<span class="sourceLineNo">664</span> * @return if this is a directory, returns all the children in the<a name="line.664"></a>
-<span class="sourceLineNo">665</span> * directory, otherwise returns an empty list<a name="line.665"></a>
-<span class="sourceLineNo">666</span> * @throws IOException<a name="line.666"></a>
-<span class="sourceLineNo">667</span> */<a name="line.667"></a>
-<span class="sourceLineNo">668</span> abstract Collection<File> getChildren() throws IOException;<a name="line.668"></a>
-<span class="sourceLineNo">669</span><a name="line.669"></a>
-<span class="sourceLineNo">670</span> /**<a name="line.670"></a>
-<span class="sourceLineNo">671</span> * close any outside readers of the file<a name="line.671"></a>
-<span class="sourceLineNo">672</span> * @throws IOException<a name="line.672"></a>
-<span class="sourceLineNo">673</span> */<a name="line.673"></a>
-<span class="sourceLineNo">674</span> abstract void close() throws IOException;<a name="line.674"></a>
-<span class="sourceLineNo">675</span><a name="line.675"></a>
-<span class="sourceLineNo">676</span> /**<a name="line.676"></a>
-<span class="sourceLineNo">677</span> * @return the name of the file (not the full fs path, just the individual<a name="line.677"></a>
-<span class="sourceLineNo">678</span> * file name)<a name="line.678"></a>
-<span class="sourceLineNo">679</span> */<a name="line.679"></a>
-<span class="sourceLineNo">680</span> abstract String getName();<a name="line.680"></a>
-<span class="sourceLineNo">681</span><a name="line.681"></a>
-<span class="sourceLineNo">682</span> /**<a name="line.682"></a>
-<span class="sourceLineNo">683</span> * @return the path to this file<a name="line.683"></a>
+<span class="sourceLineNo">656</span> /**<a name="line.656"></a>
+<span class="sourceLineNo">657</span> * Convert the {@link HStoreFile} into something we can manage in the archive<a name="line.657"></a>
+<span class="sourceLineNo">658</span> * methods<a name="line.658"></a>
+<span class="sourceLineNo">659</span> */<a name="line.659"></a>
+<span class="sourceLineNo">660</span> private static class StoreToFile extends FileConverter<HStoreFile> {<a name="line.660"></a>
+<span class="sourceLineNo">661</span> public StoreToFile(FileSystem fs) {<a name="line.661"></a>
+<span class="sourceLineNo">662</span> super(fs);<a name="line.662"></a>
+<span class="sourceLineNo">663</span> }<a name="line.663"></a>
+<span class="sourceLineNo">664</span><a name="line.664"></a>
+<span class="sourceLineNo">665</span> @Override<a name="line.665"></a>
+<span class="sourceLineNo">666</span> public File apply(HStoreFile input) {<a name="line.666"></a>
+<span class="sourceLineNo">667</span> return new FileableStoreFile(fs, input);<a name="line.667"></a>
+<span class="sourceLineNo">668</span> }<a name="line.668"></a>
+<span class="sourceLineNo">669</span> }<a name="line.669"></a>
+<span class="sourceLineNo">670</span><a name="line.670"></a>
+<span class="sourceLineNo">671</span> /**<a name="line.671"></a>
+<span class="sourceLineNo">672</span> * Wrapper to handle file operations uniformly<a name="line.672"></a>
+<span class="sourceLineNo">673</span> */<a name="line.673"></a>
+<span class="sourceLineNo">674</span> private static abstract class File {<a name="line.674"></a>
+<span class="sourceLineNo">675</span> protected final FileSystem fs;<a name="line.675"></a>
+<span class="sourceLineNo">676</span><a name="line.676"></a>
+<span class="sourceLineNo">677</span> public File(FileSystem fs) {<a name="line.677"></a>
+<span class="sourceLineNo">678</span> this.fs = fs;<a name="line.678"></a>
+<span class="sourceLineNo">679</span> }<a name="line.679"></a>
+<span class="sourceLineNo">680</span><a name="line.680"></a>
+<span class="sourceLineNo">681</span> /**<a name="line.681"></a>
+<span class="sourceLineNo">682</span> * Delete the file<a name="line.682"></a>
+<span class="sourceLineNo">683</span> * @throws IOException on failure<a name="line.683"></a>
<span class="sourceLineNo">684</span> */<a name="line.684"></a>
-<span class="sourceLineNo">685</span> abstract Path getPath();<a name="line.685"></a>
+<span class="sourceLineNo">685</span> abstract void delete() throws IOException;<a name="line.685"></a>
<span class="sourceLineNo">686</span><a name="line.686"></a>
<span class="sourceLineNo">687</span> /**<a name="line.687"></a>
-<span class="sourceLineNo">688</span> * Move the file to the given destination<a name="line.688"></a>
-<span class="sourceLineNo">689</span> * @param dest<a name="line.689"></a>
-<span class="sourceLineNo">690</span> * @return <tt>true</tt> on success<a name="line.690"></a>
-<span class="sourceLineNo">691</span> * @throws IOException<a name="line.691"></a>
-<span class="sourceLineNo">692</span> */<a name="line.692"></a>
-<span class="sourceLineNo">693</span> public boolean moveAndClose(Path dest) throws IOException {<a name="line.693"></a>
-<span class="sourceLineNo">694</span> this.close();<a name="line.694"></a>
-<span class="sourceLineNo">695</span> Path p = this.getPath();<a name="line.695"></a>
-<span class="sourceLineNo">696</span> return CommonFSUtils.renameAndSetModifyTime(fs, p, dest);<a name="line.696"></a>
-<span class="sourceLineNo">697</span> }<a name="line.697"></a>
-<span class="sourceLineNo">698</span><a name="line.698"></a>
-<span class="sourceLineNo">699</span> /**<a name="line.699"></a>
-<span class="sourceLineNo">700</span> * @return the {@link FileSystem} on which this file resides<a name="line.700"></a>
-<span class="sourceLineNo">701</span> */<a name="line.701"></a>
-<span class="sourceLineNo">702</span> public FileSystem getFileSystem() {<a name="line.702"></a>
-<span class="sourceLineNo">703</span> return this.fs;<a name="line.703"></a>
-<span class="sourceLineNo">704</span> }<a name="line.704"></a>
-<span class="sourceLineNo">705</span><a name="line.705"></a>
-<span class="sourceLineNo">706</span> @Override<a name="line.706"></a>
-<span class="sourceLineNo">707</span> public String toString() {<a name="line.707"></a>
-<span class="sourceLineNo">708</span> return this.getClass().getSimpleName() + ", " + getPath().toString();<a name="line.708"></a>
-<span class="sourceLineNo">709</span> }<a name="line.709"></a>
-<span class="sourceLineNo">710</span> }<a name="line.710"></a>
-<span class="sourceLineNo">711</span><a name="line.711"></a>
-<span class="sourceLineNo">712</span> /**<a name="line.712"></a>
-<span class="sourceLineNo">713</span> * A {@link File} that wraps a simple {@link Path} on a {@link FileSystem}.<a name="line.713"></a>
-<span class="sourceLineNo">714</span> */<a name="line.714"></a>
-<span class="sourceLineNo">715</span> private static class FileablePath extends File {<a name="line.715"></a>
-<span class="sourceLineNo">716</span> private final Path file;<a name="line.716"></a>
-<span class="sourceLineNo">717</span> private final FileStatusConverter getAsFile;<a name="line.717"></a>
-<span class="sourceLineNo">718</span><a name="line.718"></a>
-<span class="sourceLineNo">719</span> public FileablePath(FileSystem fs, Path file) {<a name="line.719"></a>
-<span class="sourceLineNo">720</span> super(fs);<a name="line.720"></a>
-<span class="sourceLineNo">721</span> this.file = file;<a name="line.721"></a>
-<span class="sourceLineNo">722</span> this.getAsFile = new FileStatusConverter(fs);<a name="line.722"></a>
-<span class="sourceLineNo">723</span> }<a name="line.723"></a>
-<span class="sourceLineNo">724</span><a name="line.724"></a>
-<span class="sourceLineNo">725</span> @Override<a name="line.725"></a>
-<span class="sourceLineNo">726</span> public void delete() throws IOException {<a name="line.726"></a>
-<span class="sourceLineNo">727</span> if (!fs.delete(file, true)) throw new IOException("Failed to delete:" + this.file);<a name="line.727"></a>
+<span class="sourceLineNo">688</span> * Check to see if this is a file or a directory<a name="line.688"></a>
+<span class="sourceLineNo">689</span> * @return <tt>true</tt> if it is a file, <tt>false</tt> otherwise<a name="line.689"></a>
+<span class="sourceLineNo">690</span> * @throws IOException on {@link FileSystem} connection error<a name="line.690"></a>
+<span class="sourceLineNo">691</span> */<a name="line.691"></a>
+<span class="sourceLineNo">692</span> abstract boolean isFile() throws IOException;<a name="line.692"></a>
+<span class="sourceLineNo">693</span><a name="line.693"></a>
+<span class="sourceLineNo">694</span> /**<a name="line.694"></a>
+<span class="sourceLineNo">695</span> * @return if this is a directory, returns all the children in the<a name="line.695"></a>
+<span class="sourceLineNo">696</span> * directory, otherwise returns an empty list<a name="line.696"></a>
+<span class="sourceLineNo">697</span> * @throws IOException<a name="line.697"></a>
+<span class="sourceLineNo">698</span> */<a name="line.698"></a>
+<span class="sourceLineNo">699</span> abstract Collection<File> getChildren() throws IOException;<a name="line.699"></a>
+<span class="sourceLineNo">700</span><a name="line.700"></a>
+<span class="sourceLineNo">701</span> /**<a name="line.701"></a>
+<span class="sourceLineNo">702</span> * close any outside readers of the file<a name="line.702"></a>
+<span class="sourceLineNo">703</span> * @throws IOException<a name="line.703"></a>
+<span class="sourceLineNo">704</span> */<a name="line.704"></a>
+<span class="sourceLineNo">705</span> abstract void close() throws IOException;<a name="line.705"></a>
+<span class="sourceLineNo">706</span><a name="line.706"></a>
+<span class="sourceLineNo">707</span> /**<a name="line.707"></a>
+<span class="sourceLineNo">708</span> * @return the name of the file (not the full fs path, just the individual<a name="line.708"></a>
+<span class="sourceLineNo">709</span> * file name)<a name="line.709"></a>
+<span class="sourceLineNo">710</span> */<a name="line.710"></a>
+<span class="sourceLineNo">711</span> abstract String getName();<a name="line.711"></a>
+<span class="sourceLineNo">712</span><a name="line.712"></a>
+<span class="sourceLineNo">713</span> /**<a name="line.713"></a>
+<span class="sourceLineNo">714</span> * @return the path to this file<a name="line.714"></a>
+<span class="sourceLineNo">715</span> */<a name="line.715"></a>
+<span class="sourceLineNo">716</span> abstract Path getPath();<a name="line.716"></a>
+<span class="sourceLineNo">717</span><a name="line.717"></a>
+<span class="sourceLineNo">718</span> /**<a name="line.718"></a>
+<span class="sourceLineNo">719</span> * Move the file to the given destination<a name="line.719"></a>
+<span class="sourceLineNo">720</span> * @param dest<a name="line.720"></a>
+<span class="sourceLineNo">721</span> * @return <tt>true</tt> on success<a name="line.721"></a>
+<span class="sourceLineNo">722</span> * @throws IOException<a name="line.722"></a>
+<span class="sourceLineNo">723</span> */<a name="line.723"></a>
+<span class="sourceLineNo">724</span> public boolean moveAndClose(Path dest) throws IOException {<a name="line.724"></a>
+<span class="sourceLineNo">725</span> this.close();<a name="line.725"></a>
+<span class="sourceLineNo">726</span> Path p = this.getPath();<a name="line.726"></a>
+<span class="sourceLineNo">727</span> return CommonFSUtils.renameAndSetModifyTime(fs, p, dest);<a name="line.727"></a>
<span class="sourceLineNo">728</span> }<a name="line.728"></a>
<span class="sourceLineNo">729</span><a name="line.729"></a>
-<span class="sourceLineNo">730</span> @Override<a name="line.730"></a>
-<span class="sourceLineNo">731</span> public String getName() {<a name="line.731"></a>
-<span class="sourceLineNo">732</span> return file.getName();<a name="line.732"></a>
-<span class="sourceLineNo">733</span> }<a name="line.733"></a>
-<span class="sourceLineNo">734</span><a name="line.734"></a>
-<span class="sourceLineNo">735</span> @Override<a name="line.735"></a>
-<span class="sourceLineNo">736</span> public Collection<File> getChildren() throws IOException {<a name="line.736"></a>
-<span class="sourceLineNo">737</span> if (fs.isFile(file)) {<a name="line.737"></a>
-<span class="sourceLineNo">738</span> return Collections.emptyList();<a name="line.738"></a>
-<span class="sourceLineNo">739</span> }<a name="line.739"></a>
-<span class="sourceLineNo">740</span> return Stream.of(fs.listStatus(file)).map(getAsFile).collect(Collectors.toList());<a name="line.740"></a>
-<span class="sourceLineNo">741</span> }<a name="line.741"></a>
+<span class="sourceLineNo">730</span> /**<a name="line.730"></a>
+<span class="sourceLineNo">731</span> * @return the {@link FileSystem} on which this file resides<a name="line.731"></a>
+<span class="sourceLineNo">732</span> */<a name="line.732"></a>
+<span class="sourceLineNo">733</span> public FileSystem getFileSystem() {<a name="line.733"></a>
+<span class="sourceLineNo">734</span> return this.fs;<a name="line.734"></a>
+<span class="sourceLineNo">735</span> }<a name="line.735"></a>
+<span class="sourceLineNo">736</span><a name="line.736"></a>
+<span class="sourceLineNo">737</span> @Override<a name="line.737"></a>
+<span class="sourceLineNo">738</span> public String toString() {<a name="line.738"></a>
+<span class="sourceLineNo">739</span> return this.getClass().getSimpleName() + ", " + getPath().toString();<a name="line.739"></a>
+<span class="sourceLineNo">740</span> }<a name="line.740"></a>
+<span class="sourceLineNo">741</span> }<a name="line.741"></a>
<span class="sourceLineNo">742</span><a name="line.742"></a>
-<span class="sourceLineNo">743</span> @Override<a name="line.743"></a>
-<span class="sourceLineNo">744</span> public boolean isFile() throws IOException {<a name="line.744"></a>
-<span class="sourceLineNo">745</span> return fs.isFile(file);<a name="line.745"></a>
-<span class="sourceLineNo">746</span> }<a name="line.746"></a>
-<span class="sourceLineNo">747</span><a name="line.747"></a>
-<span class="sourceLineNo">748</span> @Override<a name="line.748"></a>
-<span class="sourceLineNo">749</span> public void close() throws IOException {<a name="line.749"></a>
-<span class="sourceLineNo">750</span> // NOOP - files are implicitly closed on removal<a name="line.750"></a>
-<span class="sourceLineNo">751</span> }<a name="line.751"></a>
-<span class="sourceLineNo">752</span><a name="line.752"></a>
-<span class="sourceLineNo">753</span> @Override<a name="line.753"></a>
-<span class="sourceLineNo">754</span> Path getPath() {<a name="line.754"></a>
-<span class="sourceLineNo">755</span> return file;<a name="line.755"></a>
-<span class="sourceLineNo">756</span> }<a name="line.756"></a>
-<span class="sourceLineNo">757</span> }<a name="line.757"></a>
-<span class="sourceLineNo">758</span><a name="line.758"></a>
-<span class="sourceLineNo">759</span> /**<a name="line.759"></a>
-<span class="sourceLineNo">760</span> * {@link File} adapter for a {@link HStoreFile} living on a {@link FileSystem}<a name="line.760"></a>
-<span class="sourceLineNo">761</span> * .<a name="line.761"></a>
-<span class="sourceLineNo">762</span> */<a name="line.762"></a>
-<span class="sourceLineNo">763</span> private static class FileableStoreFile extends File {<a name="line.763"></a>
-<span class="sourceLineNo">764</span> HStoreFile file;<a name="line.764"></a>
+<span class="sourceLineNo">743</span> /**<a name="line.743"></a>
+<span class="sourceLineNo">744</span> * A {@link File} that wraps a simple {@link Path} on a {@link FileSystem}.<a name="line.744"></a>
+<span class="sourceLineNo">745</span> */<a name="line.745"></a>
+<span class="sourceLineNo">746</span> private static class FileablePath extends File {<a name="line.746"></a>
+<span class="sourceLineNo">747</span> private final Path file;<a name="line.747"></a>
+<span class="sourceLineNo">748</span> private final FileStatusConverter getAsFile;<a name="line.748"></a>
+<span class="sourceLineNo">749</span><a name="line.749"></a>
+<span class="sourceLineNo">750</span> public FileablePath(FileSystem fs, Path file) {<a name="line.750"></a>
+<span class="sourceLineNo">751</span> super(fs);<a name="line.751"></a>
+<span class="sourceLineNo">752</span> this.file = file;<a name="line.752"></a>
+<span class="sourceLineNo">753</span> this.getAsFile = new FileStatusConverter(fs);<a name="line.753"></a>
+<span class="sourceLineNo">754</span> }<a name="line.754"></a>
+<span class="sourceLineNo">755</span><a name="line.755"></a>
+<span class="sourceLineNo">756</span> @Override<a name="line.756"></a>
+<span class="sourceLineNo">757</span> public void delete() throws IOException {<a name="line.757"></a>
+<span class="sourceLineNo">758</span> if (!fs.delete(file, true)) throw new IOException("Failed to delete:" + this.file);<a name="line.758"></a>
+<span class="sourceLineNo">759</span> }<a name="line.759"></a>
+<span class="sourceLineNo">760</span><a name="line.760"></a>
+<span class="sourceLineNo">761</span> @Override<a name="line.761"></a>
+<span class="sourceLineNo">762</span> public String getName() {<a name="line.762"></a>
+<span class="sourceLineNo">763</span> return file.getName();<a name="line.763"></a>
+<span class="sourceLineNo">764</span> }<a name="line.764"></a>
<span class="sourceLineNo">765</span><a name="line.765"></a>
-<span class="sourceLineNo">766</span> public FileableStoreFile(FileSystem fs, HStoreFile store) {<a name="line.766"></a>
-<span class="sourceLineNo">767</span> super(fs);<a name="line.767"></a>
-<span class="sourceLineNo">768</span> this.file = store;<a name="line.768"></a>
-<span class="sourceLineNo">769</span> }<a name="line.769"></a>
-<span class="sourceLineNo">770</span><a name="line.770"></a>
-<span class="sourceLineNo">771</span> @Override<a name="line.771"></a>
-<span class="sourceLineNo">772</span> public void delete() throws IOException {<a name="line.772"></a>
-<span class="sourceLineNo">773</span> file.deleteStoreFile();<a name="line.773"></a>
-<span class="sourceLineNo">774</span> }<a name="line.774"></a>
-<span class="sourceLineNo">775</span><a name="line.775"></a>
-<span class="sourceLineNo">776</span> @Override<a name="line.776"></a>
-<span class="sourceLineNo">777</span> public String getName() {<a name="line.777"></a>
-<span class="sourceLineNo">778</span> return file.getPath().getName();<a name="line.778"></a>
-<span class="sourceLineNo">779</span> }<a name="line.779"></a>
-<span class="sourceLineNo">780</span><a name="line.780"></a>
-<span class="sourceLineNo">781</span> @Override<a name="line.781"></a>
-<span class="sourceLineNo">782</span> public boolean isFile() {<a name="line.782"></a>
-<span class="sourceLineNo">783</span> return true;<a name="line.783"></a>
-<span class="sourceLineNo">784</span> }<a name="line.784"></a>
-<span class="sourceLineNo">785</span><a name="line.785"></a>
-<span class="sourceLineNo">786</span> @Override<a name="line.786"></a>
-<span class="sourceLineNo">787</span> public Collection<File> getChildren() throws IOException {<a name="line.787"></a>
-<span class="sourceLineNo">788</span> // storefiles don't have children<a name="line.788"></a>
-<span class="sourceLineNo">789</span> return Collections.emptyList();<a name="line.789"></a>
-<span class="sourceLineNo">790</span> }<a name="line.790"></a>
-<span class="sourceLineNo">791</span><a name="line.791"></a>
-<span class="sourceLineNo">792</span> @Override<a name="line.792"></a>
-<span class="sourceLineNo">793</span> public void close() throws IOException {<a name="line.793"></a>
-<span class="sourceLineNo">794</span> file.closeStoreFile(true);<a name="line.794"></a>
-<span class="sourceLineNo">795</span> }<a name="line.795"></a>
+<span class="sourceLineNo">766</span> @Override<a name="line.766"></a>
+<span class="sourceLineNo">767</span> public Collection<File> getChildren() throws IOException {<a name="line.767"></a>
+<span class="sourceLineNo">768</span> if (fs.isFile(file)) {<a name="line.768"></a>
+<span class="sourceLineNo">769</span> return Collections.emptyList();<a name="line.769"></a>
+<span class="sourceLineNo">770</span> }<a name="line.770"></a>
+<span class="sourceLineNo">771</span> return Stream.of(fs.listStatus(file)).map(getAsFile).collect(Collectors.toList());<a name="line.771"></a>
+<span class="sourceLineNo">772</span> }<a name="line.772"></a>
+<span class="sourceLineNo">773</span><a name="line.773"></a>
+<span class="sourceLineNo">774</span> @Override<a name="line.774"></a>
+<span class="sourceLineNo">775</span> public boolean isFile() throws IOException {<a name="line.775"></a>
+<span class="sourceLineNo">776</span> return fs.isFile(file);<a name="line.776"></a>
+<span class="sourceLineNo">777</span> }<a name="line.777"></a>
+<span class="sourceLineNo">778</span><a name="line.778"></a>
+<span class="sourceLineNo">779</span> @Override<a name="line.779"></a>
+<span class="sourceLineNo">780</span> public void close() throws IOException {<a name="line.780"></a>
+<span class="sourceLineNo">781</span> // NOOP - files are implicitly closed on removal<a name="line.781"></a>
+<span class="sourceLineNo">782</span> }<a name="line.782"></a>
+<span class="sourceLineNo">783</span><a name="line.783"></a>
+<span class="sourceLineNo">784</span> @Override<a name="line.784"></a>
+<span class="sourceLineNo">785</span> Path getPath() {<a name="line.785"></a>
+<span class="sourceLineNo">786</span> return file;<a name="line.786"></a>
+<span class="sourceLineNo">787</span> }<a name="line.787"></a>
+<span class="sourceLineNo">788</span> }<a name="line.788"></a>
+<span class="sourceLineNo">789</span><a name="line.789"></a>
+<span class="sourceLineNo">790</span> /**<a name="line.790"></a>
+<span class="sourceLineNo">791</span> * {@link File} adapter for a {@link HStoreFile} living on a {@link FileSystem}<a name="line.791"></a>
+<span class="sourceLineNo">792</span> * .<a name="line.792"></a>
+<span class="sourceLineNo">793</span> */<a name="line.793"></a>
+<span class="sourceLineNo">794</span> private static class FileableStoreFile extends File {<a name="line.794"></a>
+<span class="sourceLineNo">795</span> HStoreFile file;<a name="line.795"></a>
<span class="sourceLineNo">796</span><a name="line.796"></a>
-<span class="sourceLineNo">797</span> @Override<a name="line.797"></a>
-<span class="sourceLineNo">798</span> Path getPath() {<a name="line.798"></a>
-<span class="sourceLineNo">799</span> return file.getPath();<a name="line.799"></a>
+<span class="sourceLineNo">797</span> public FileableStoreFile(FileSystem fs, HStoreFile store) {<a name="line.797"></a>
+<span class="sourceLineNo">798</span> super(fs);<a name="line.798"></a>
+<span class="sourceLineNo">799</span> this.file = store;<a name="line.799"></a>
<span class="sourceLineNo">800</span> }<a name="line.800"></a>
-<span class="sourceLineNo">801</span> }<a name="line.801"></a>
-<span class="sourceLineNo">802</span>}<a name="line.802"></a>
+<span class="sourceLineNo">801</span><a name="line.801"></a>
+<span class="sourceLineNo">802</span> @Override<a name="line.802"></a>
+<span class="sourceLineNo">803</span> public void delete() throws IOException {<a name="line.803"></a>
+<span class="sourceLineNo">804</span> file.deleteStoreFile();<a name="line.804"></a>
+<span class="sourceLineNo">805</span> }<a name="line.805"></a>
+<span class="sourceLineNo">806</span><a name="line.806"></a>
+<span class="sourceLineNo">807</span> @Override<a name="line.807"></a>
+<span class="sourceLineNo">808</span> public String getName() {<a name="line.808"></a>
+<span class="sourceLineNo">809</span> return file.getPath().getName();<a name="line.809"></a>
+<span class="sourceLineNo">810</span> }<a name="line.810"></a>
+<span class="sourceLineNo">811</span><a name="line.811"></a>
+<span class="sourceLineNo">812</span> @Override<a name="line.812"></a>
+<span class="sourceLineNo">813</span> public boolean isFile() {<a name="line.813"></a>
+<span class="sourceLineNo">814</span> return true;<a name="line.814"></a>
+<span class="sourceLineNo">815</span> }<a name="line.815"></a>
+<span class="sourceLineNo">816</span><a name="line.816"></a>
+<span class="sourceLineNo">817</span> @Override<a name="line.817"></a>
+<span class="sourceLineNo">818</span> public Collection<File> getChildren() throws IOException {<a name="line.818"></a>
+<span class="sourceLineNo">819</span> // storefiles don't have children<a name="line.819"></a>
+<span class="sourceLineNo">820</span> return Collections.emptyList();<a name="line.820"></a>
+<span class="sourceLineNo">821</span> }<a name="line.821"></a>
+<span class="sourceLineNo">822</span><a name="line.822"></a>
+<span class="sourceLineNo">823</span> @Override<a name="line.823"></a>
+<span class="sourceLineNo">824</span> public void close() throws IOException {<a name="line.824"></a>
+<span class="sourceLineNo">825</span> file.closeStoreFile(true);<a name="line.825"></a>
+<span class="sourceLineNo">826</span> }<a name="line.826"></a>
+<span class="sourceLineNo">827</span><a name="line.827"></a>
+<span class="sourceLineNo">828</span> @Override<a name="line.828"></a>
+<span class="sourceLineNo">829</span> Path getPath() {<a name="line.829"></a>
+<span class="sourceLineNo">830</span> return file.getPath();<a name="line.830"></a>
+<span class="sourceLineNo">831</span> }<a name="line.831"></a>
+<span class="sourceLineNo">832</span> }<a name="line.832"></a>
+<span class="sourceLineNo">833</span>}<a name="line.833"></a>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.StoreToFile.html b/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.StoreToFile.html
index 22ea136..ee79f25 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.StoreToFile.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.StoreToFile.html
@@ -496,318 +496,349 @@
<span class="sourceLineNo">488</span> Path archiveFile = new Path(archiveDir, filename);<a name="line.488"></a>
<span class="sourceLineNo">489</span> FileSystem fs = currentFile.getFileSystem();<a name="line.489"></a>
<span class="sourceLineNo">490</span><a name="line.490"></a>
-<span class="sourceLineNo">491</span> // if the file already exists in the archive, move that one to a timestamped backup. This is a<a name="line.491"></a>
-<span class="sourceLineNo">492</span> // really, really unlikely situtation, where we get the same name for the existing file, but<a name="line.492"></a>
-<span class="sourceLineNo">493</span> // is included just for that 1 in trillion chance.<a name="line.493"></a>
-<span class="sourceLineNo">494</span> if (fs.exists(archiveFile)) {<a name="line.494"></a>
-<span class="sourceLineNo">495</span> LOG.debug("{} already exists in archive, moving to timestamped backup and " +<a name="line.495"></a>
-<span class="sourceLineNo">496</span> "overwriting current.", archiveFile);<a name="line.496"></a>
-<span class="sourceLineNo">497</span><a name="line.497"></a>
-<span class="sourceLineNo">498</span> // move the archive file to the stamped backup<a name="line.498"></a>
-<span class="sourceLineNo">499</span> Path backedupArchiveFile = new Path(archiveDir, filename + SEPARATOR + archiveStartTime);<a name="line.499"></a>
-<span class="sourceLineNo">500</span> if (!fs.rename(archiveFile, backedupArchiveFile)) {<a name="line.500"></a>
-<span class="sourceLineNo">501</span> LOG.error("Could not rename archive file to backup: " + backedupArchiveFile<a name="line.501"></a>
-<span class="sourceLineNo">502</span> + ", deleting existing file in favor of newer.");<a name="line.502"></a>
-<span class="sourceLineNo">503</span> // try to delete the exisiting file, if we can't rename it<a name="line.503"></a>
-<span class="sourceLineNo">504</span> if (!fs.delete(archiveFile, false)) {<a name="line.504"></a>
-<span class="sourceLineNo">505</span> throw new IOException("Couldn't delete existing archive file (" + archiveFile<a name="line.505"></a>
-<span class="sourceLineNo">506</span> + ") or rename it to the backup file (" + backedupArchiveFile<a name="line.506"></a>
-<span class="sourceLineNo">507</span> + ") to make room for similarly named file.");<a name="line.507"></a>
-<span class="sourceLineNo">508</span> }<a name="line.508"></a>
-<span class="sourceLineNo">509</span> }<a name="line.509"></a>
-<span class="sourceLineNo">510</span> LOG.debug("Backed up archive file from " + archiveFile);<a name="line.510"></a>
-<span class="sourceLineNo">511</span> }<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span> LOG.trace("No existing file in archive for {}, free to archive original file.", archiveFile);<a name="line.513"></a>
-<span class="sourceLineNo">514</span><a name="line.514"></a>
-<span class="sourceLineNo">515</span> // at this point, we should have a free spot for the archive file<a name="line.515"></a>
-<span class="sourceLineNo">516</span> boolean success = false;<a name="line.516"></a>
-<span class="sourceLineNo">517</span> for (int i = 0; !success && i < DEFAULT_RETRIES_NUMBER; ++i) {<a name="line.517"></a>
-<span class="sourceLineNo">518</span> if (i > 0) {<a name="line.518"></a>
-<span class="sourceLineNo">519</span> // Ensure that the archive directory exists.<a name="line.519"></a>
-<span class="sourceLineNo">520</span> // The previous "move to archive" operation has failed probably because<a name="line.520"></a>
-<span class="sourceLineNo">521</span> // the cleaner has removed our archive directory (HBASE-7643).<a name="line.521"></a>
-<span class="sourceLineNo">522</span> // (we're in a retry loop, so don't worry too much about the exception)<a name="line.522"></a>
-<span class="sourceLineNo">523</span> try {<a name="line.523"></a>
-<span class="sourceLineNo">524</span> if (!fs.exists(archiveDir)) {<a name="line.524"></a>
-<span class="sourceLineNo">525</span> if (fs.mkdirs(archiveDir)) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span> LOG.debug("Created archive directory {}", archiveDir);<a name="line.526"></a>
-<span class="sourceLineNo">527</span> }<a name="line.527"></a>
-<span class="sourceLineNo">528</span> }<a name="line.528"></a>
-<span class="sourceLineNo">529</span> } catch (IOException e) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span> LOG.warn("Failed to create directory {}", archiveDir, e);<a name="line.530"></a>
-<span class="sourceLineNo">531</span> }<a name="line.531"></a>
-<span class="sourceLineNo">532</span> }<a name="line.532"></a>
-<span class="sourceLineNo">533</span><a name="line.533"></a>
-<span class="sourceLineNo">534</span> try {<a name="line.534"></a>
-<span class="sourceLineNo">535</span> success = currentFile.moveAndClose(archiveFile);<a name="line.535"></a>
-<span class="sourceLineNo">536</span> } catch (FileNotFoundException fnfe) {<a name="line.536"></a>
-<span class="sourceLineNo">537</span> LOG.warn("Failed to archive " + currentFile +<a name="line.537"></a>
-<span class="sourceLineNo">538</span> " because it does not exist! Skipping and continuing on.", fnfe);<a name="line.538"></a>
-<span class="sourceLineNo">539</span> success = true;<a name="line.539"></a>
-<span class="sourceLineNo">540</span> } catch (IOException e) {<a name="line.540"></a>
-<span class="sourceLineNo">541</span> LOG.warn("Failed to archive " + currentFile + " on try #" + i, e);<a name="line.541"></a>
-<span class="sourceLineNo">542</span> success = false;<a name="line.542"></a>
-<span class="sourceLineNo">543</span> }<a name="line.543"></a>
-<span class="sourceLineNo">544</span> }<a name="line.544"></a>
+<span class="sourceLineNo">491</span> // An existing destination file in the archive is unexpected, but we handle it here.<a name="line.491"></a>
+<span class="sourceLineNo">492</span> if (fs.exists(archiveFile)) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span> if (!fs.exists(currentFile.getPath())) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span> // If the file already exists in the archive, and there is no current file to archive, then<a name="line.494"></a>
+<span class="sourceLineNo">495</span> // assume that the file in archive is correct. This is an unexpected situation, suggesting a<a name="line.495"></a>
+<span class="sourceLineNo">496</span> // race condition or split brain.<a name="line.496"></a>
+<span class="sourceLineNo">497</span> // In HBASE-26718 this was found when compaction incorrectly happened during warmupRegion.<a name="line.497"></a>
+<span class="sourceLineNo">498</span> LOG.warn("{} exists in archive. Attempted to archive nonexistent file {}.", archiveFile,<a name="line.498"></a>
+<span class="sourceLineNo">499</span> currentFile);<a name="line.499"></a>
+<span class="sourceLineNo">500</span> // We return success to match existing behavior in this method, where FileNotFoundException<a name="line.500"></a>
+<span class="sourceLineNo">501</span> // in moveAndClose is ignored.<a name="line.501"></a>
+<span class="sourceLineNo">502</span> return true;<a name="line.502"></a>
+<span class="sourceLineNo">503</span> }<a name="line.503"></a>
+<span class="sourceLineNo">504</span> // There is a conflict between the current file and the already existing archived file.<a name="line.504"></a>
+<span class="sourceLineNo">505</span> // Move the archived file to a timestamped backup. This is a really, really unlikely<a name="line.505"></a>
+<span class="sourceLineNo">506</span> // situation, where we get the same name for the existing file, but is included just for that<a name="line.506"></a>
+<span class="sourceLineNo">507</span> // 1 in trillion chance. We are potentially incurring data loss in the archive directory if<a name="line.507"></a>
+<span class="sourceLineNo">508</span> // the files are not identical. The timestamped backup will be cleaned by HFileCleaner as it<a name="line.508"></a>
+<span class="sourceLineNo">509</span> // has no references.<a name="line.509"></a>
+<span class="sourceLineNo">510</span> FileStatus curStatus = fs.getFileStatus(currentFile.getPath());<a name="line.510"></a>
+<span class="sourceLineNo">511</span> FileStatus archiveStatus = fs.getFileStatus(archiveFile);<a name="line.511"></a>
+<span class="sourceLineNo">512</span> long curLen = curStatus.getLen();<a name="line.512"></a>
+<span class="sourceLineNo">513</span> long archiveLen = archiveStatus.getLen();<a name="line.513"></a>
+<span class="sourceLineNo">514</span> long curMtime = curStatus.getModificationTime();<a name="line.514"></a>
+<span class="sourceLineNo">515</span> long archiveMtime = archiveStatus.getModificationTime();<a name="line.515"></a>
+<span class="sourceLineNo">516</span> if (curLen != archiveLen) {<a name="line.516"></a>
+<span class="sourceLineNo">517</span> LOG.error("{} already exists in archive with different size than current {}."<a name="line.517"></a>
+<span class="sourceLineNo">518</span> + " archiveLen: {} currentLen: {} archiveMtime: {} currentMtime: {}",<a name="line.518"></a>
+<span class="sourceLineNo">519</span> archiveFile, currentFile, archiveLen, curLen, archiveMtime, curMtime);<a name="line.519"></a>
+<span class="sourceLineNo">520</span> throw new IOException(archiveFile + " already exists in archive with different size" +<a name="line.520"></a>
+<span class="sourceLineNo">521</span> " than " + currentFile);<a name="line.521"></a>
+<span class="sourceLineNo">522</span> }<a name="line.522"></a>
+<span class="sourceLineNo">523</span><a name="line.523"></a>
+<span class="sourceLineNo">524</span> LOG.error("{} already exists in archive, moving to timestamped backup and overwriting"<a name="line.524"></a>
+<span class="sourceLineNo">525</span> + " current {}. archiveLen: {} currentLen: {} archiveMtime: {} currentMtime: {}",<a name="line.525"></a>
+<span class="sourceLineNo">526</span> archiveFile, currentFile, archiveLen, curLen, archiveMtime, curMtime);<a name="line.526"></a>
+<span class="sourceLineNo">527</span><a name="line.527"></a>
+<span class="sourceLineNo">528</span> // move the archive file to the stamped backup<a name="line.528"></a>
+<span class="sourceLineNo">529</span> Path backedupArchiveFile = new Path(archiveDir, filename + SEPARATOR + archiveStartTime);<a name="line.529"></a>
+<span class="sourceLineNo">530</span> if (!fs.rename(archiveFile, backedupArchiveFile)) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span> LOG.error("Could not rename archive file to backup: " + backedupArchiveFile<a name="line.531"></a>
+<span class="sourceLineNo">532</span> + ", deleting existing file in favor of newer.");<a name="line.532"></a>
+<span class="sourceLineNo">533</span> // try to delete the existing file, if we can't rename it<a name="line.533"></a>
+<span class="sourceLineNo">534</span> if (!fs.delete(archiveFile, false)) {<a name="line.534"></a>
+<span class="sourceLineNo">535</span> throw new IOException("Couldn't delete existing archive file (" + archiveFile<a name="line.535"></a>
+<span class="sourceLineNo">536</span> + ") or rename it to the backup file (" + backedupArchiveFile<a name="line.536"></a>
+<span class="sourceLineNo">537</span> + ") to make room for similarly named file.");<a name="line.537"></a>
+<span class="sourceLineNo">538</span> }<a name="line.538"></a>
+<span class="sourceLineNo">539</span> } else {<a name="line.539"></a>
+<span class="sourceLineNo">540</span> LOG.info("Backed up archive file from {} to {}.", archiveFile, backedupArchiveFile);<a name="line.540"></a>
+<span class="sourceLineNo">541</span> }<a name="line.541"></a>
+<span class="sourceLineNo">542</span> }<a name="line.542"></a>
+<span class="sourceLineNo">543</span><a name="line.543"></a>
+<span class="sourceLineNo">544</span> LOG.trace("No existing file in archive for {}, free to archive original file.", archiveFile);<a name="line.544"></a>
<span class="sourceLineNo">545</span><a name="line.545"></a>
-<span class="sourceLineNo">546</span> if (!success) {<a name="line.546"></a>
-<span class="sourceLineNo">547</span> LOG.error("Failed to archive " + currentFile);<a name="line.547"></a>
-<span class="sourceLineNo">548</span> return false;<a name="line.548"></a>
-<span class="sourceLineNo">549</span> }<a name="line.549"></a>
-<span class="sourceLineNo">550</span><a name="line.550"></a>
-<span class="sourceLineNo">551</span> LOG.debug("Archived from {} to {}", currentFile, archiveFile);<a name="line.551"></a>
-<span class="sourceLineNo">552</span> return true;<a name="line.552"></a>
-<span class="sourceLineNo">553</span> }<a name="line.553"></a>
-<span class="sourceLineNo">554</span><a name="line.554"></a>
-<span class="sourceLineNo">555</span> /**<a name="line.555"></a>
-<span class="sourceLineNo">556</span> * Without regard for backup, delete a region. Should be used with caution.<a name="line.556"></a>
-<span class="sourceLineNo">557</span> * @param regionDir {@link Path} to the region to be deleted.<a name="line.557"></a>
-<span class="sourceLineNo">558</span> * @param fs FileSystem from which to delete the region<a name="line.558"></a>
-<span class="sourceLineNo">559</span> * @return <tt>true</tt> on successful deletion, <tt>false</tt> otherwise<a name="line.559"></a>
-<span class="sourceLineNo">560</span> * @throws IOException on filesystem operation failure<a name="line.560"></a>
-<span class="sourceLineNo">561</span> */<a name="line.561"></a>
-<span class="sourceLineNo">562</span> private static boolean deleteRegionWithoutArchiving(FileSystem fs, Path regionDir)<a name="line.562"></a>
-<span class="sourceLineNo">563</span> throws IOException {<a name="line.563"></a>
-<span class="sourceLineNo">564</span> if (fs.delete(regionDir, true)) {<a name="line.564"></a>
-<span class="sourceLineNo">565</span> LOG.debug("Deleted {}", regionDir);<a name="line.565"></a>
-<span class="sourceLineNo">566</span> return true;<a name="line.566"></a>
-<span class="sourceLineNo">567</span> }<a name="line.567"></a>
-<span class="sourceLineNo">568</span> LOG.debug("Failed to delete directory {}", regionDir);<a name="line.568"></a>
-<span class="sourceLineNo">569</span> return false;<a name="line.569"></a>
-<span class="sourceLineNo">570</span> }<a name="line.570"></a>
-<span class="sourceLineNo">571</span><a name="line.571"></a>
-<span class="sourceLineNo">572</span> /**<a name="line.572"></a>
-<span class="sourceLineNo">573</span> * Just do a simple delete of the given store files<a name="line.573"></a>
-<span class="sourceLineNo">574</span> * <p><a name="line.574"></a>
-<span class="sourceLineNo">575</span> * A best effort is made to delete each of the files, rather than bailing on the first failure.<a name="line.575"></a>
-<span class="sourceLineNo">576</span> * <p><a name="line.576"></a>
-<span class="sourceLineNo">577</span> * @param compactedFiles store files to delete from the file system.<a name="line.577"></a>
-<span class="sourceLineNo">578</span> * @throws IOException if a file cannot be deleted. All files will be attempted to deleted before<a name="line.578"></a>
-<span class="sourceLineNo">579</span> * throwing the exception, rather than failing at the first file.<a name="line.579"></a>
-<span class="sourceLineNo">580</span> */<a name="line.580"></a>
-<span class="sourceLineNo">581</span> private static void deleteStoreFilesWithoutArchiving(Collection<HStoreFile> compactedFiles)<a name="line.581"></a>
-<span class="sourceLineNo">582</span> throws IOException {<a name="line.582"></a>
-<span class="sourceLineNo">583</span> LOG.debug("Deleting files without archiving.");<a name="line.583"></a>
-<span class="sourceLineNo">584</span> List<IOException> errors = new ArrayList<>(0);<a name="line.584"></a>
-<span class="sourceLineNo">585</span> for (HStoreFile hsf : compactedFiles) {<a name="line.585"></a>
-<span class="sourceLineNo">586</span> try {<a name="line.586"></a>
-<span class="sourceLineNo">587</span> hsf.deleteStoreFile();<a name="line.587"></a>
-<span class="sourceLineNo">588</span> } catch (IOException e) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span> LOG.error("Failed to delete {}", hsf.getPath());<a name="line.589"></a>
-<span class="sourceLineNo">590</span> errors.add(e);<a name="line.590"></a>
-<span class="sourceLineNo">591</span> }<a name="line.591"></a>
-<span class="sourceLineNo">592</span> }<a name="line.592"></a>
-<span class="sourceLineNo">593</span> if (errors.size() > 0) {<a name="line.593"></a>
-<span class="sourceLineNo">594</span> throw MultipleIOException.createIOException(errors);<a name="line.594"></a>
-<span class="sourceLineNo">595</span> }<a name="line.595"></a>
-<span class="sourceLineNo">596</span> }<a name="line.596"></a>
-<span class="sourceLineNo">597</span><a name="line.597"></a>
-<span class="sourceLineNo">598</span> /**<a name="line.598"></a>
-<span class="sourceLineNo">599</span> * Adapt a type to match the {@link File} interface, which is used internally for handling<a name="line.599"></a>
-<span class="sourceLineNo">600</span> * archival/removal of files<a name="line.600"></a>
-<span class="sourceLineNo">601</span> * @param <T> type to adapt to the {@link File} interface<a name="line.601"></a>
-<span class="sourceLineNo">602</span> */<a name="line.602"></a>
-<span class="sourceLineNo">603</span> private static abstract class FileConverter<T> implements Function<T, File> {<a name="line.603"></a>
-<span class="sourceLineNo">604</span> protected final FileSystem fs;<a name="line.604"></a>
-<span class="sourceLineNo">605</span><a name="line.605"></a>
-<span class="sourceLineNo">606</span> public FileConverter(FileSystem fs) {<a name="line.606"></a>
-<span class="sourceLineNo">607</span> this.fs = fs;<a name="line.607"></a>
-<span class="sourceLineNo">608</span> }<a name="line.608"></a>
-<span class="sourceLineNo">609</span> }<a name="line.609"></a>
-<span class="sourceLineNo">610</span><a name="line.610"></a>
-<span class="sourceLineNo">611</span> /**<a name="line.611"></a>
-<span class="sourceLineNo">612</span> * Convert a FileStatus to something we can manage in the archiving<a name="line.612"></a>
-<span class="sourceLineNo">613</span> */<a name="line.613"></a>
-<span class="sourceLineNo">614</span> private static class FileStatusConverter extends FileConverter<FileStatus> {<a name="line.614"></a>
-<span class="sourceLineNo">615</span> public FileStatusConverter(FileSystem fs) {<a name="line.615"></a>
-<span class="sourceLineNo">616</span> super(fs);<a name="line.616"></a>
-<span class="sourceLineNo">617</span> }<a name="line.617"></a>
-<span class="sourceLineNo">618</span><a name="line.618"></a>
-<span class="sourceLineNo">619</span> @Override<a name="line.619"></a>
-<span class="sourceLineNo">620</span> public File apply(FileStatus input) {<a name="line.620"></a>
-<span class="sourceLineNo">621</span> return new FileablePath(fs, input.getPath());<a name="line.621"></a>
-<span class="sourceLineNo">622</span> }<a name="line.622"></a>
-<span class="sourceLineNo">623</span> }<a name="line.623"></a>
-<span class="sourceLineNo">624</span><a name="line.624"></a>
-<span class="sourceLineNo">625</span> /**<a name="line.625"></a>
-<span class="sourceLineNo">626</span> * Convert the {@link HStoreFile} into something we can manage in the archive<a name="line.626"></a>
-<span class="sourceLineNo">627</span> * methods<a name="line.627"></a>
-<span class="sourceLineNo">628</span> */<a name="line.628"></a>
-<span class="sourceLineNo">629</span> private static class StoreToFile extends FileConverter<HStoreFile> {<a name="line.629"></a>
-<span class="sourceLineNo">630</span> public StoreToFile(FileSystem fs) {<a name="line.630"></a>
-<span class="sourceLineNo">631</span> super(fs);<a name="line.631"></a>
-<span class="sourceLineNo">632</span> }<a name="line.632"></a>
-<span class="sourceLineNo">633</span><a name="line.633"></a>
-<span class="sourceLineNo">634</span> @Override<a name="line.634"></a>
-<span class="sourceLineNo">635</span> public File apply(HStoreFile input) {<a name="line.635"></a>
-<span class="sourceLineNo">636</span> return new FileableStoreFile(fs, input);<a name="line.636"></a>
-<span class="sourceLineNo">637</span> }<a name="line.637"></a>
-<span class="sourceLineNo">638</span> }<a name="line.638"></a>
-<span class="sourceLineNo">639</span><a name="line.639"></a>
-<span class="sourceLineNo">640</span> /**<a name="line.640"></a>
-<span class="sourceLineNo">641</span> * Wrapper to handle file operations uniformly<a name="line.641"></a>
-<span class="sourceLineNo">642</span> */<a name="line.642"></a>
-<span class="sourceLineNo">643</span> private static abstract class File {<a name="line.643"></a>
-<span class="sourceLineNo">644</span> protected final FileSystem fs;<a name="line.644"></a>
-<span class="sourceLineNo">645</span><a name="line.645"></a>
-<span class="sourceLineNo">646</span> public File(FileSystem fs) {<a name="line.646"></a>
-<span class="sourceLineNo">647</span> this.fs = fs;<a name="line.647"></a>
+<span class="sourceLineNo">546</span> // at this point, we should have a free spot for the archive file<a name="line.546"></a>
+<span class="sourceLineNo">547</span> boolean success = false;<a name="line.547"></a>
+<span class="sourceLineNo">548</span> for (int i = 0; !success && i < DEFAULT_RETRIES_NUMBER; ++i) {<a name="line.548"></a>
+<span class="sourceLineNo">549</span> if (i > 0) {<a name="line.549"></a>
+<span class="sourceLineNo">550</span> // Ensure that the archive directory exists.<a name="line.550"></a>
+<span class="sourceLineNo">551</span> // The previous "move to archive" operation has failed probably because<a name="line.551"></a>
+<span class="sourceLineNo">552</span> // the cleaner has removed our archive directory (HBASE-7643).<a name="line.552"></a>
+<span class="sourceLineNo">553</span> // (we're in a retry loop, so don't worry too much about the exception)<a name="line.553"></a>
+<span class="sourceLineNo">554</span> try {<a name="line.554"></a>
+<span class="sourceLineNo">555</span> if (!fs.exists(archiveDir)) {<a name="line.555"></a>
+<span class="sourceLineNo">556</span> if (fs.mkdirs(archiveDir)) {<a name="line.556"></a>
+<span class="sourceLineNo">557</span> LOG.debug("Created archive directory {}", archiveDir);<a name="line.557"></a>
+<span class="sourceLineNo">558</span> }<a name="line.558"></a>
+<span class="sourceLineNo">559</span> }<a name="line.559"></a>
+<span class="sourceLineNo">560</span> } catch (IOException e) {<a name="line.560"></a>
+<span class="sourceLineNo">561</span> LOG.warn("Failed to create directory {}", archiveDir, e);<a name="line.561"></a>
+<span class="sourceLineNo">562</span> }<a name="line.562"></a>
+<span class="sourceLineNo">563</span> }<a name="line.563"></a>
+<span class="sourceLineNo">564</span><a name="line.564"></a>
+<span class="sourceLineNo">565</span> try {<a name="line.565"></a>
+<span class="sourceLineNo">566</span> success = currentFile.moveAndClose(archiveFile);<a name="line.566"></a>
+<span class="sourceLineNo">567</span> } catch (FileNotFoundException fnfe) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span> LOG.warn("Failed to archive " + currentFile +<a name="line.568"></a>
+<span class="sourceLineNo">569</span> " because it does not exist! Skipping and continuing on.", fnfe);<a name="line.569"></a>
+<span class="sourceLineNo">570</span> success = true;<a name="line.570"></a>
+<span class="sourceLineNo">571</span> } catch (IOException e) {<a name="line.571"></a>
+<span class="sourceLineNo">572</span> LOG.warn("Failed to archive " + currentFile + " on try #" + i, e);<a name="line.572"></a>
+<span class="sourceLineNo">573</span> success = false;<a name="line.573"></a>
+<span class="sourceLineNo">574</span> }<a name="line.574"></a>
+<span class="sourceLineNo">575</span> }<a name="line.575"></a>
+<span class="sourceLineNo">576</span><a name="line.576"></a>
+<span class="sourceLineNo">577</span> if (!success) {<a name="line.577"></a>
+<span class="sourceLineNo">578</span> LOG.error("Failed to archive " + currentFile);<a name="line.578"></a>
+<span class="sourceLineNo">579</span> return false;<a name="line.579"></a>
+<span class="sourceLineNo">580</span> }<a name="line.580"></a>
+<span class="sourceLineNo">581</span><a name="line.581"></a>
+<span class="sourceLineNo">582</span> LOG.debug("Archived from {} to {}", currentFile, archiveFile);<a name="line.582"></a>
+<span class="sourceLineNo">583</span> return true;<a name="line.583"></a>
+<span class="sourceLineNo">584</span> }<a name="line.584"></a>
+<span class="sourceLineNo">585</span><a name="line.585"></a>
+<span class="sourceLineNo">586</span> /**<a name="line.586"></a>
+<span class="sourceLineNo">587</span> * Without regard for backup, delete a region. Should be used with caution.<a name="line.587"></a>
+<span class="sourceLineNo">588</span> * @param regionDir {@link Path} to the region to be deleted.<a name="line.588"></a>
+<span class="sourceLineNo">589</span> * @param fs FileSystem from which to delete the region<a name="line.589"></a>
+<span class="sourceLineNo">590</span> * @return <tt>true</tt> on successful deletion, <tt>false</tt> otherwise<a name="line.590"></a>
+<span class="sourceLineNo">591</span> * @throws IOException on filesystem operation failure<a name="line.591"></a>
+<span class="sourceLineNo">592</span> */<a name="line.592"></a>
+<span class="sourceLineNo">593</span> private static boolean deleteRegionWithoutArchiving(FileSystem fs, Path regionDir)<a name="line.593"></a>
+<span class="sourceLineNo">594</span> throws IOException {<a name="line.594"></a>
+<span class="sourceLineNo">595</span> if (fs.delete(regionDir, true)) {<a name="line.595"></a>
+<span class="sourceLineNo">596</span> LOG.debug("Deleted {}", regionDir);<a name="line.596"></a>
+<span class="sourceLineNo">597</span> return true;<a name="line.597"></a>
+<span class="sourceLineNo">598</span> }<a name="line.598"></a>
+<span class="sourceLineNo">599</span> LOG.debug("Failed to delete directory {}", regionDir);<a name="line.599"></a>
+<span class="sourceLineNo">600</span> return false;<a name="line.600"></a>
+<span class="sourceLineNo">601</span> }<a name="line.601"></a>
+<span class="sourceLineNo">602</span><a name="line.602"></a>
+<span class="sourceLineNo">603</span> /**<a name="line.603"></a>
+<span class="sourceLineNo">604</span> * Just do a simple delete of the given store files<a name="line.604"></a>
+<span class="sourceLineNo">605</span> * <p><a name="line.605"></a>
+<span class="sourceLineNo">606</span> * A best effort is made to delete each of the files, rather than bailing on the first failure.<a name="line.606"></a>
+<span class="sourceLineNo">607</span> * <p><a name="line.607"></a>
+<span class="sourceLineNo">608</span> * @param compactedFiles store files to delete from the file system.<a name="line.608"></a>
+<span class="sourceLineNo">609</span> * @throws IOException if a file cannot be deleted. All files will be attempted to deleted before<a name="line.609"></a>
+<span class="sourceLineNo">610</span> * throwing the exception, rather than failing at the first file.<a name="line.610"></a>
+<span class="sourceLineNo">611</span> */<a name="line.611"></a>
+<span class="sourceLineNo">612</span> private static void deleteStoreFilesWithoutArchiving(Collection<HStoreFile> compactedFiles)<a name="line.612"></a>
+<span class="sourceLineNo">613</span> throws IOException {<a name="line.613"></a>
+<span class="sourceLineNo">614</span> LOG.debug("Deleting files without archiving.");<a name="line.614"></a>
+<span class="sourceLineNo">615</span> List<IOException> errors = new ArrayList<>(0);<a name="line.615"></a>
+<span class="sourceLineNo">616</span> for (HStoreFile hsf : compactedFiles) {<a name="line.616"></a>
+<span class="sourceLineNo">617</span> try {<a name="line.617"></a>
+<span class="sourceLineNo">618</span> hsf.deleteStoreFile();<a name="line.618"></a>
+<span class="sourceLineNo">619</span> } catch (IOException e) {<a name="line.619"></a>
+<span class="sourceLineNo">620</span> LOG.error("Failed to delete {}", hsf.getPath());<a name="line.620"></a>
+<span class="sourceLineNo">621</span> errors.add(e);<a name="line.621"></a>
+<span class="sourceLineNo">622</span> }<a name="line.622"></a>
+<span class="sourceLineNo">623</span> }<a name="line.623"></a>
+<span class="sourceLineNo">624</span> if (errors.size() > 0) {<a name="line.624"></a>
+<span class="sourceLineNo">625</span> throw MultipleIOException.createIOException(errors);<a name="line.625"></a>
+<span class="sourceLineNo">626</span> }<a name="line.626"></a>
+<span class="sourceLineNo">627</span> }<a name="line.627"></a>
+<span class="sourceLineNo">628</span><a name="line.628"></a>
+<span class="sourceLineNo">629</span> /**<a name="line.629"></a>
+<span class="sourceLineNo">630</span> * Adapt a type to match the {@link File} interface, which is used internally for handling<a name="line.630"></a>
+<span class="sourceLineNo">631</span> * archival/removal of files<a name="line.631"></a>
+<span class="sourceLineNo">632</span> * @param <T> type to adapt to the {@link File} interface<a name="line.632"></a>
+<span class="sourceLineNo">633</span> */<a name="line.633"></a>
+<span class="sourceLineNo">634</span> private static abstract class FileConverter<T> implements Function<T, File> {<a name="line.634"></a>
+<span class="sourceLineNo">635</span> protected final FileSystem fs;<a name="line.635"></a>
+<span class="sourceLineNo">636</span><a name="line.636"></a>
+<span class="sourceLineNo">637</span> public FileConverter(FileSystem fs) {<a name="line.637"></a>
+<span class="sourceLineNo">638</span> this.fs = fs;<a name="line.638"></a>
+<span class="sourceLineNo">639</span> }<a name="line.639"></a>
+<span class="sourceLineNo">640</span> }<a name="line.640"></a>
+<span class="sourceLineNo">641</span><a name="line.641"></a>
+<span class="sourceLineNo">642</span> /**<a name="line.642"></a>
+<span class="sourceLineNo">643</span> * Convert a FileStatus to something we can manage in the archiving<a name="line.643"></a>
+<span class="sourceLineNo">644</span> */<a name="line.644"></a>
+<span class="sourceLineNo">645</span> private static class FileStatusConverter extends FileConverter<FileStatus> {<a name="line.645"></a>
+<span class="sourceLineNo">646</span> public FileStatusConverter(FileSystem fs) {<a name="line.646"></a>
+<span class="sourceLineNo">647</span> super(fs);<a name="line.647"></a>
<span class="sourceLineNo">648</span> }<a name="line.648"></a>
<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span> /**<a name="line.650"></a>
-<span class="sourceLineNo">651</span> * Delete the file<a name="line.651"></a>
-<span class="sourceLineNo">652</span> * @throws IOException on failure<a name="line.652"></a>
-<span class="sourceLineNo">653</span> */<a name="line.653"></a>
-<span class="sourceLineNo">654</span> abstract void delete() throws IOException;<a name="line.654"></a>
+<span class="sourceLineNo">650</span> @Override<a name="line.650"></a>
+<span class="sourceLineNo">651</span> public File apply(FileStatus input) {<a name="line.651"></a>
+<span class="sourceLineNo">652</span> return new FileablePath(fs, input.getPath());<a name="line.652"></a>
+<span class="sourceLineNo">653</span> }<a name="line.653"></a>
+<span class="sourceLineNo">654</span> }<a name="line.654"></a>
<span class="sourceLineNo">655</span><a name="line.655"></a>
-<span class="sourceLineNo">656</span> /**<a name="line.656"></a>
-<span class="sourceLineNo">657</span> * Check to see if this is a file or a directory<a name="line.657"></a>
-<span class="sourceLineNo">658</span> * @return <tt>true</tt> if it is a file, <tt>false</tt> otherwise<a name="line.658"></a>
-<span class="sourceLineNo">659</span> * @throws IOException on {@link FileSystem} connection error<a name="line.659"></a>
-<span class="sourceLineNo">660</span> */<a name="line.660"></a>
-<span class="sourceLineNo">661</span> abstract boolean isFile() throws IOException;<a name="line.661"></a>
-<span class="sourceLineNo">662</span><a name="line.662"></a>
-<span class="sourceLineNo">663</span> /**<a name="line.663"></a>
-<span class="sourceLineNo">664</span> * @return if this is a directory, returns all the children in the<a name="line.664"></a>
-<span class="sourceLineNo">665</span> * directory, otherwise returns an empty list<a name="line.665"></a>
-<span class="sourceLineNo">666</span> * @throws IOException<a name="line.666"></a>
-<span class="sourceLineNo">667</span> */<a name="line.667"></a>
-<span class="sourceLineNo">668</span> abstract Collection<File> getChildren() throws IOException;<a name="line.668"></a>
-<span class="sourceLineNo">669</span><a name="line.669"></a>
-<span class="sourceLineNo">670</span> /**<a name="line.670"></a>
-<span class="sourceLineNo">671</span> * close any outside readers of the file<a name="line.671"></a>
-<span class="sourceLineNo">672</span> * @throws IOException<a name="line.672"></a>
-<span class="sourceLineNo">673</span> */<a name="line.673"></a>
-<span class="sourceLineNo">674</span> abstract void close() throws IOException;<a name="line.674"></a>
-<span class="sourceLineNo">675</span><a name="line.675"></a>
-<span class="sourceLineNo">676</span> /**<a name="line.676"></a>
-<span class="sourceLineNo">677</span> * @return the name of the file (not the full fs path, just the individual<a name="line.677"></a>
-<span class="sourceLineNo">678</span> * file name)<a name="line.678"></a>
-<span class="sourceLineNo">679</span> */<a name="line.679"></a>
-<span class="sourceLineNo">680</span> abstract String getName();<a name="line.680"></a>
-<span class="sourceLineNo">681</span><a name="line.681"></a>
-<span class="sourceLineNo">682</span> /**<a name="line.682"></a>
-<span class="sourceLineNo">683</span> * @return the path to this file<a name="line.683"></a>
+<span class="sourceLineNo">656</span> /**<a name="line.656"></a>
+<span class="sourceLineNo">657</span> * Convert the {@link HStoreFile} into something we can manage in the archive<a name="line.657"></a>
+<span class="sourceLineNo">658</span> * methods<a name="line.658"></a>
+<span class="sourceLineNo">659</span> */<a name="line.659"></a>
+<span class="sourceLineNo">660</span> private static class StoreToFile extends FileConverter<HStoreFile> {<a name="line.660"></a>
+<span class="sourceLineNo">661</span> public StoreToFile(FileSystem fs) {<a name="line.661"></a>
+<span class="sourceLineNo">662</span> super(fs);<a name="line.662"></a>
+<span class="sourceLineNo">663</span> }<a name="line.663"></a>
+<span class="sourceLineNo">664</span><a name="line.664"></a>
+<span class="sourceLineNo">665</span> @Override<a name="line.665"></a>
+<span class="sourceLineNo">666</span> public File apply(HStoreFile input) {<a name="line.666"></a>
+<span class="sourceLineNo">667</span> return new FileableStoreFile(fs, input);<a name="line.667"></a>
+<span class="sourceLineNo">668</span> }<a name="line.668"></a>
+<span class="sourceLineNo">669</span> }<a name="line.669"></a>
+<span class="sourceLineNo">670</span><a name="line.670"></a>
+<span class="sourceLineNo">671</span> /**<a name="line.671"></a>
+<span class="sourceLineNo">672</span> * Wrapper to handle file operations uniformly<a name="line.672"></a>
+<span class="sourceLineNo">673</span> */<a name="line.673"></a>
+<span class="sourceLineNo">674</span> private static abstract class File {<a name="line.674"></a>
+<span class="sourceLineNo">675</span> protected final FileSystem fs;<a name="line.675"></a>
+<span class="sourceLineNo">676</span><a name="line.676"></a>
+<span class="sourceLineNo">677</span> public File(FileSystem fs) {<a name="line.677"></a>
+<span class="sourceLineNo">678</span> this.fs = fs;<a name="line.678"></a>
+<span class="sourceLineNo">679</span> }<a name="line.679"></a>
+<span class="sourceLineNo">680</span><a name="line.680"></a>
+<span class="sourceLineNo">681</span> /**<a name="line.681"></a>
+<span class="sourceLineNo">682</span> * Delete the file<a name="line.682"></a>
+<span class="sourceLineNo">683</span> * @throws IOException on failure<a name="line.683"></a>
<span class="sourceLineNo">684</span> */<a name="line.684"></a>
-<span class="sourceLineNo">685</span> abstract Path getPath();<a name="line.685"></a>
+<span class="sourceLineNo">685</span> abstract void delete() throws IOException;<a name="line.685"></a>
<span class="sourceLineNo">686</span><a name="line.686"></a>
<span class="sourceLineNo">687</span> /**<a name="line.687"></a>
-<span class="sourceLineNo">688</span> * Move the file to the given destination<a name="line.688"></a>
-<span class="sourceLineNo">689</span> * @param dest<a name="line.689"></a>
-<span class="sourceLineNo">690</span> * @return <tt>true</tt> on success<a name="line.690"></a>
-<span class="sourceLineNo">691</span> * @throws IOException<a name="line.691"></a>
-<span class="sourceLineNo">692</span> */<a name="line.692"></a>
-<span class="sourceLineNo">693</span> public boolean moveAndClose(Path dest) throws IOException {<a name="line.693"></a>
-<span class="sourceLineNo">694</span> this.close();<a name="line.694"></a>
-<span class="sourceLineNo">695</span> Path p = this.getPath();<a name="line.695"></a>
-<span class="sourceLineNo">696</span> return CommonFSUtils.renameAndSetModifyTime(fs, p, dest);<a name="line.696"></a>
-<span class="sourceLineNo">697</span> }<a name="line.697"></a>
-<span class="sourceLineNo">698</span><a name="line.698"></a>
-<span class="sourceLineNo">699</span> /**<a name="line.699"></a>
-<span class="sourceLineNo">700</span> * @return the {@link FileSystem} on which this file resides<a name="line.700"></a>
-<span class="sourceLineNo">701</span> */<a name="line.701"></a>
-<span class="sourceLineNo">702</span> public FileSystem getFileSystem() {<a name="line.702"></a>
-<span class="sourceLineNo">703</span> return this.fs;<a name="line.703"></a>
-<span class="sourceLineNo">704</span> }<a name="line.704"></a>
-<span class="sourceLineNo">705</span><a name="line.705"></a>
-<span class="sourceLineNo">706</span> @Override<a name="line.706"></a>
-<span class="sourceLineNo">707</span> public String toString() {<a name="line.707"></a>
-<span class="sourceLineNo">708</span> return this.getClass().getSimpleName() + ", " + getPath().toString();<a name="line.708"></a>
-<span class="sourceLineNo">709</span> }<a name="line.709"></a>
-<span class="sourceLineNo">710</span> }<a name="line.710"></a>
-<span class="sourceLineNo">711</span><a name="line.711"></a>
-<span class="sourceLineNo">712</span> /**<a name="line.712"></a>
-<span class="sourceLineNo">713</span> * A {@link File} that wraps a simple {@link Path} on a {@link FileSystem}.<a name="line.713"></a>
-<span class="sourceLineNo">714</span> */<a name="line.714"></a>
-<span class="sourceLineNo">715</span> private static class FileablePath extends File {<a name="line.715"></a>
-<span class="sourceLineNo">716</span> private final Path file;<a name="line.716"></a>
-<span class="sourceLineNo">717</span> private final FileStatusConverter getAsFile;<a name="line.717"></a>
-<span class="sourceLineNo">718</span><a name="line.718"></a>
-<span class="sourceLineNo">719</span> public FileablePath(FileSystem fs, Path file) {<a name="line.719"></a>
-<span class="sourceLineNo">720</span> super(fs);<a name="line.720"></a>
-<span class="sourceLineNo">721</span> this.file = file;<a name="line.721"></a>
-<span class="sourceLineNo">722</span> this.getAsFile = new FileStatusConverter(fs);<a name="line.722"></a>
-<span class="sourceLineNo">723</span> }<a name="line.723"></a>
-<span class="sourceLineNo">724</span><a name="line.724"></a>
-<span class="sourceLineNo">725</span> @Override<a name="line.725"></a>
-<span class="sourceLineNo">726</span> public void delete() throws IOException {<a name="line.726"></a>
-<span class="sourceLineNo">727</span> if (!fs.delete(file, true)) throw new IOException("Failed to delete:" + this.file);<a name="line.727"></a>
+<span class="sourceLineNo">688</span> * Check to see if this is a file or a directory<a name="line.688"></a>
+<span class="sourceLineNo">689</span> * @return <tt>true</tt> if it is a file, <tt>false</tt> otherwise<a name="line.689"></a>
+<span class="sourceLineNo">690</span> * @throws IOException on {@link FileSystem} connection error<a name="line.690"></a>
+<span class="sourceLineNo">691</span> */<a name="line.691"></a>
+<span class="sourceLineNo">692</span> abstract boolean isFile() throws IOException;<a name="line.692"></a>
+<span class="sourceLineNo">693</span><a name="line.693"></a>
+<span class="sourceLineNo">694</span> /**<a name="line.694"></a>
+<span class="sourceLineNo">695</span> * @return if this is a directory, returns all the children in the<a name="line.695"></a>
+<span class="sourceLineNo">696</span> * directory, otherwise returns an empty list<a name="line.696"></a>
+<span class="sourceLineNo">697</span> * @throws IOException<a name="line.697"></a>
+<span class="sourceLineNo">698</span> */<a name="line.698"></a>
+<span class="sourceLineNo">699</span> abstract Collection<File> getChildren() throws IOException;<a name="line.699"></a>
+<span class="sourceLineNo">700</span><a name="line.700"></a>
+<span class="sourceLineNo">701</span> /**<a name="line.701"></a>
+<span class="sourceLineNo">702</span> * close any outside readers of the file<a name="line.702"></a>
+<span class="sourceLineNo">703</span> * @throws IOException<a name="line.703"></a>
+<span class="sourceLineNo">704</span> */<a name="line.704"></a>
+<span class="sourceLineNo">705</span> abstract void close() throws IOException;<a name="line.705"></a>
+<span class="sourceLineNo">706</span><a name="line.706"></a>
+<span class="sourceLineNo">707</span> /**<a name="line.707"></a>
+<span class="sourceLineNo">708</span> * @return the name of the file (not the full fs path, just the individual<a name="line.708"></a>
+<span class="sourceLineNo">709</span> * file name)<a name="line.709"></a>
+<span class="sourceLineNo">710</span> */<a name="line.710"></a>
+<span class="sourceLineNo">711</span> abstract String getName();<a name="line.711"></a>
+<span class="sourceLineNo">712</span><a name="line.712"></a>
+<span class="sourceLineNo">713</span> /**<a name="line.713"></a>
+<span class="sourceLineNo">714</span> * @return the path to this file<a name="line.714"></a>
+<span class="sourceLineNo">715</span> */<a name="line.715"></a>
+<span class="sourceLineNo">716</span> abstract Path getPath();<a name="line.716"></a>
+<span class="sourceLineNo">717</span><a name="line.717"></a>
+<span class="sourceLineNo">718</span> /**<a name="line.718"></a>
+<span class="sourceLineNo">719</span> * Move the file to the given destination<a name="line.719"></a>
+<span class="sourceLineNo">720</span> * @param dest<a name="line.720"></a>
+<span class="sourceLineNo">721</span> * @return <tt>true</tt> on success<a name="line.721"></a>
+<span class="sourceLineNo">722</span> * @throws IOException<a name="line.722"></a>
+<span class="sourceLineNo">723</span> */<a name="line.723"></a>
+<span class="sourceLineNo">724</span> public boolean moveAndClose(Path dest) throws IOException {<a name="line.724"></a>
+<span class="sourceLineNo">725</span> this.close();<a name="line.725"></a>
+<span class="sourceLineNo">726</span> Path p = this.getPath();<a name="line.726"></a>
+<span class="sourceLineNo">727</span> return CommonFSUtils.renameAndSetModifyTime(fs, p, dest);<a name="line.727"></a>
<span class="sourceLineNo">728</span> }<a name="line.728"></a>
<span class="sourceLineNo">729</span><a name="line.729"></a>
-<span class="sourceLineNo">730</span> @Override<a name="line.730"></a>
-<span class="sourceLineNo">731</span> public String getName() {<a name="line.731"></a>
-<span class="sourceLineNo">732</span> return file.getName();<a name="line.732"></a>
-<span class="sourceLineNo">733</span> }<a name="line.733"></a>
-<span class="sourceLineNo">734</span><a name="line.734"></a>
-<span class="sourceLineNo">735</span> @Override<a name="line.735"></a>
-<span class="sourceLineNo">736</span> public Collection<File> getChildren() throws IOException {<a name="line.736"></a>
-<span class="sourceLineNo">737</span> if (fs.isFile(file)) {<a name="line.737"></a>
-<span class="sourceLineNo">738</span> return Collections.emptyList();<a name="line.738"></a>
-<span class="sourceLineNo">739</span> }<a name="line.739"></a>
-<span class="sourceLineNo">740</span> return Stream.of(fs.listStatus(file)).map(getAsFile).collect(Collectors.toList());<a name="line.740"></a>
-<span class="sourceLineNo">741</span> }<a name="line.741"></a>
+<span class="sourceLineNo">730</span> /**<a name="line.730"></a>
+<span class="sourceLineNo">731</span> * @return the {@link FileSystem} on which this file resides<a name="line.731"></a>
+<span class="sourceLineNo">732</span> */<a name="line.732"></a>
+<span class="sourceLineNo">733</span> public FileSystem getFileSystem() {<a name="line.733"></a>
+<span class="sourceLineNo">734</span> return this.fs;<a name="line.734"></a>
+<span class="sourceLineNo">735</span> }<a name="line.735"></a>
+<span class="sourceLineNo">736</span><a name="line.736"></a>
+<span class="sourceLineNo">737</span> @Override<a name="line.737"></a>
+<span class="sourceLineNo">738</span> public String toString() {<a name="line.738"></a>
+<span class="sourceLineNo">739</span> return this.getClass().getSimpleName() + ", " + getPath().toString();<a name="line.739"></a>
+<span class="sourceLineNo">740</span> }<a name="line.740"></a>
+<span class="sourceLineNo">741</span> }<a name="line.741"></a>
<span class="sourceLineNo">742</span><a name="line.742"></a>
-<span class="sourceLineNo">743</span> @Override<a name="line.743"></a>
-<span class="sourceLineNo">744</span> public boolean isFile() throws IOException {<a name="line.744"></a>
-<span class="sourceLineNo">745</span> return fs.isFile(file);<a name="line.745"></a>
-<span class="sourceLineNo">746</span> }<a name="line.746"></a>
-<span class="sourceLineNo">747</span><a name="line.747"></a>
-<span class="sourceLineNo">748</span> @Override<a name="line.748"></a>
-<span class="sourceLineNo">749</span> public void close() throws IOException {<a name="line.749"></a>
-<span class="sourceLineNo">750</span> // NOOP - files are implicitly closed on removal<a name="line.750"></a>
-<span class="sourceLineNo">751</span> }<a name="line.751"></a>
-<span class="sourceLineNo">752</span><a name="line.752"></a>
-<span class="sourceLineNo">753</span> @Override<a name="line.753"></a>
-<span class="sourceLineNo">754</span> Path getPath() {<a name="line.754"></a>
-<span class="sourceLineNo">755</span> return file;<a name="line.755"></a>
-<span class="sourceLineNo">756</span> }<a name="line.756"></a>
-<span class="sourceLineNo">757</span> }<a name="line.757"></a>
-<span class="sourceLineNo">758</span><a name="line.758"></a>
-<span class="sourceLineNo">759</span> /**<a name="line.759"></a>
-<span class="sourceLineNo">760</span> * {@link File} adapter for a {@link HStoreFile} living on a {@link FileSystem}<a name="line.760"></a>
-<span class="sourceLineNo">761</span> * .<a name="line.761"></a>
-<span class="sourceLineNo">762</span> */<a name="line.762"></a>
-<span class="sourceLineNo">763</span> private static class FileableStoreFile extends File {<a name="line.763"></a>
-<span class="sourceLineNo">764</span> HStoreFile file;<a name="line.764"></a>
+<span class="sourceLineNo">743</span> /**<a name="line.743"></a>
+<span class="sourceLineNo">744</span> * A {@link File} that wraps a simple {@link Path} on a {@link FileSystem}.<a name="line.744"></a>
+<span class="sourceLineNo">745</span> */<a name="line.745"></a>
+<span class="sourceLineNo">746</span> private static class FileablePath extends File {<a name="line.746"></a>
+<span class="sourceLineNo">747</span> private final Path file;<a name="line.747"></a>
+<span class="sourceLineNo">748</span> private final FileStatusConverter getAsFile;<a name="line.748"></a>
+<span class="sourceLineNo">749</span><a name="line.749"></a>
+<span class="sourceLineNo">750</span> public FileablePath(FileSystem fs, Path file) {<a name="line.750"></a>
+<span class="sourceLineNo">751</span> super(fs);<a name="line.751"></a>
+<span class="sourceLineNo">752</span> this.file = file;<a name="line.752"></a>
+<span class="sourceLineNo">753</span> this.getAsFile = new FileStatusConverter(fs);<a name="line.753"></a>
+<span class="sourceLineNo">754</span> }<a name="line.754"></a>
+<span class="sourceLineNo">755</span><a name="line.755"></a>
+<span class="sourceLineNo">756</span> @Override<a name="line.756"></a>
+<span class="sourceLineNo">757</span> public void delete() throws IOException {<a name="line.757"></a>
+<span class="sourceLineNo">758</span> if (!fs.delete(file, true)) throw new IOException("Failed to delete:" + this.file);<a name="line.758"></a>
+<span class="sourceLineNo">759</span> }<a name="line.759"></a>
+<span class="sourceLineNo">760</span><a name="line.760"></a>
+<span class="sourceLineNo">761</span> @Override<a name="line.761"></a>
+<span class="sourceLineNo">762</span> public String getName() {<a name="line.762"></a>
+<span class="sourceLineNo">763</span> return file.getName();<a name="line.763"></a>
+<span class="sourceLineNo">764</span> }<a name="line.764"></a>
<span class="sourceLineNo">765</span><a name="line.765"></a>
-<span class="sourceLineNo">766</span> public FileableStoreFile(FileSystem fs, HStoreFile store) {<a name="line.766"></a>
-<span class="sourceLineNo">767</span> super(fs);<a name="line.767"></a>
-<span class="sourceLineNo">768</span> this.file = store;<a name="line.768"></a>
-<span class="sourceLineNo">769</span> }<a name="line.769"></a>
-<span class="sourceLineNo">770</span><a name="line.770"></a>
-<span class="sourceLineNo">771</span> @Override<a name="line.771"></a>
-<span class="sourceLineNo">772</span> public void delete() throws IOException {<a name="line.772"></a>
-<span class="sourceLineNo">773</span> file.deleteStoreFile();<a name="line.773"></a>
-<span class="sourceLineNo">774</span> }<a name="line.774"></a>
-<span class="sourceLineNo">775</span><a name="line.775"></a>
-<span class="sourceLineNo">776</span> @Override<a name="line.776"></a>
-<span class="sourceLineNo">777</span> public String getName() {<a name="line.777"></a>
-<span class="sourceLineNo">778</span> return file.getPath().getName();<a name="line.778"></a>
-<span class="sourceLineNo">779</span> }<a name="line.779"></a>
-<span class="sourceLineNo">780</span><a name="line.780"></a>
-<span class="sourceLineNo">781</span> @Override<a name="line.781"></a>
-<span class="sourceLineNo">782</span> public boolean isFile() {<a name="line.782"></a>
-<span class="sourceLineNo">783</span> return true;<a name="line.783"></a>
-<span class="sourceLineNo">784</span> }<a name="line.784"></a>
-<span class="sourceLineNo">785</span><a name="line.785"></a>
-<span class="sourceLineNo">786</span> @Override<a name="line.786"></a>
-<span class="sourceLineNo">787</span> public Collection<File> getChildren() throws IOException {<a name="line.787"></a>
-<span class="sourceLineNo">788</span> // storefiles don't have children<a name="line.788"></a>
-<span class="sourceLineNo">789</span> return Collections.emptyList();<a name="line.789"></a>
-<span class="sourceLineNo">790</span> }<a name="line.790"></a>
-<span class="sourceLineNo">791</span><a name="line.791"></a>
-<span class="sourceLineNo">792</span> @Override<a name="line.792"></a>
-<span class="sourceLineNo">793</span> public void close() throws IOException {<a name="line.793"></a>
-<span class="sourceLineNo">794</span> file.closeStoreFile(true);<a name="line.794"></a>
-<span class="sourceLineNo">795</span> }<a name="line.795"></a>
+<span class="sourceLineNo">766</span> @Override<a name="line.766"></a>
+<span class="sourceLineNo">767</span> public Collection<File> getChildren() throws IOException {<a name="line.767"></a>
+<span class="sourceLineNo">768</span> if (fs.isFile(file)) {<a name="line.768"></a>
+<span class="sourceLineNo">769</span> return Collections.emptyList();<a name="line.769"></a>
+<span class="sourceLineNo">770</span> }<a name="line.770"></a>
+<span class="sourceLineNo">771</span> return Stream.of(fs.listStatus(file)).map(getAsFile).collect(Collectors.toList());<a name="line.771"></a>
+<span class="sourceLineNo">772</span> }<a name="line.772"></a>
+<span class="sourceLineNo">773</span><a name="line.773"></a>
+<span class="sourceLineNo">774</span> @Override<a name="line.774"></a>
+<span class="sourceLineNo">775</span> public boolean isFile() throws IOException {<a name="line.775"></a>
+<span class="sourceLineNo">776</span> return fs.isFile(file);<a name="line.776"></a>
+<span class="sourceLineNo">777</span> }<a name="line.777"></a>
+<span class="sourceLineNo">778</span><a name="line.778"></a>
+<span class="sourceLineNo">779</span> @Override<a name="line.779"></a>
+<span class="sourceLineNo">780</span> public void close() throws IOException {<a name="line.780"></a>
+<span class="sourceLineNo">781</span> // NOOP - files are implicitly closed on removal<a name="line.781"></a>
+<span class="sourceLineNo">782</span> }<a name="line.782"></a>
+<span class="sourceLineNo">783</span><a name="line.783"></a>
+<span class="sourceLineNo">784</span> @Override<a name="line.784"></a>
+<span class="sourceLineNo">785</span> Path getPath() {<a name="line.785"></a>
+<span class="sourceLineNo">786</span> return file;<a name="line.786"></a>
+<span class="sourceLineNo">787</span> }<a name="line.787"></a>
+<span class="sourceLineNo">788</span> }<a name="line.788"></a>
+<span class="sourceLineNo">789</span><a name="line.789"></a>
+<span class="sourceLineNo">790</span> /**<a name="line.790"></a>
+<span class="sourceLineNo">791</span> * {@link File} adapter for a {@link HStoreFile} living on a {@link FileSystem}<a name="line.791"></a>
+<span class="sourceLineNo">792</span> * .<a name="line.792"></a>
+<span class="sourceLineNo">793</span> */<a name="line.793"></a>
+<span class="sourceLineNo">794</span> private static class FileableStoreFile extends File {<a name="line.794"></a>
+<span class="sourceLineNo">795</span> HStoreFile file;<a name="line.795"></a>
<span class="sourceLineNo">796</span><a name="line.796"></a>
-<span class="sourceLineNo">797</span> @Override<a name="line.797"></a>
-<span class="sourceLineNo">798</span> Path getPath() {<a name="line.798"></a>
-<span class="sourceLineNo">799</span> return file.getPath();<a name="line.799"></a>
+<span class="sourceLineNo">797</span> public FileableStoreFile(FileSystem fs, HStoreFile store) {<a name="line.797"></a>
+<span class="sourceLineNo">798</span> super(fs);<a name="line.798"></a>
+<span class="sourceLineNo">799</span> this.file = store;<a name="line.799"></a>
<span class="sourceLineNo">800</span> }<a name="line.800"></a>
-<span class="sourceLineNo">801</span> }<a name="line.801"></a>
-<span class="sourceLineNo">802</span>}<a name="line.802"></a>
+<span class="sourceLineNo">801</span><a name="line.801"></a>
+<span class="sourceLineNo">802</span> @Override<a name="line.802"></a>
+<span class="sourceLineNo">803</span> public void delete() throws IOException {<a name="line.803"></a>
+<span class="sourceLineNo">804</span> file.deleteStoreFile();<a name="line.804"></a>
+<span class="sourceLineNo">805</span> }<a name="line.805"></a>
+<span class="sourceLineNo">806</span><a name="line.806"></a>
+<span class="sourceLineNo">807</span> @Override<a name="line.807"></a>
+<span class="sourceLineNo">808</span> public String getName() {<a name="line.808"></a>
+<span class="sourceLineNo">809</span> return file.getPath().getName();<a name="line.809"></a>
+<span class="sourceLineNo">810</span> }<a name="line.810"></a>
+<span class="sourceLineNo">811</span><a name="line.811"></a>
+<span class="sourceLineNo">812</span> @Override<a name="line.812"></a>
+<span class="sourceLineNo">813</span> public boolean isFile() {<a name="line.813"></a>
+<span class="sourceLineNo">814</span> return true;<a name="line.814"></a>
+<span class="sourceLineNo">815</span> }<a name="line.815"></a>
+<span class="sourceLineNo">816</span><a name="line.816"></a>
+<span class="sourceLineNo">817</span> @Override<a name="line.817"></a>
+<span class="sourceLineNo">818</span> public Collection<File> getChildren() throws IOException {<a name="line.818"></a>
+<span class="sourceLineNo">819</span> // storefiles don't have children<a name="line.819"></a>
+<span class="sourceLineNo">820</span> return Collections.emptyList();<a name="line.820"></a>
+<span class="sourceLineNo">821</span> }<a name="line.821"></a>
+<span class="sourceLineNo">822</span><a name="line.822"></a>
+<span class="sourceLineNo">823</span> @Override<a name="line.823"></a>
+<span class="sourceLineNo">824</span> public void close() throws IOException {<a name="line.824"></a>
+<span class="sourceLineNo">825</span> file.closeStoreFile(true);<a name="line.825"></a>
+<span class="sourceLineNo">826</span> }<a name="line.826"></a>
+<span class="sourceLineNo">827</span><a name="line.827"></a>
+<span class="sourceLineNo">828</span> @Override<a name="line.828"></a>
+<span class="sourceLineNo">829</span> Path getPath() {<a name="line.829"></a>
+<span class="sourceLineNo">830</span> return file.getPath();<a name="line.830"></a>
+<span class="sourceLineNo">831</span> }<a name="line.831"></a>
+<span class="sourceLineNo">832</span> }<a name="line.832"></a>
+<span class="sourceLineNo">833</span>}<a name="line.833"></a>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html b/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html
index 22ea136..ee79f25 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/backup/HFileArchiver.html
@@ -496,318 +496,349 @@
<span class="sourceLineNo">488</span> Path archiveFile = new Path(archiveDir, filename);<a name="line.488"></a>
<span class="sourceLineNo">489</span> FileSystem fs = currentFile.getFileSystem();<a name="line.489"></a>
<span class="sourceLineNo">490</span><a name="line.490"></a>
-<span class="sourceLineNo">491</span> // if the file already exists in the archive, move that one to a timestamped backup. This is a<a name="line.491"></a>
-<span class="sourceLineNo">492</span> // really, really unlikely situtation, where we get the same name for the existing file, but<a name="line.492"></a>
-<span class="sourceLineNo">493</span> // is included just for that 1 in trillion chance.<a name="line.493"></a>
-<span class="sourceLineNo">494</span> if (fs.exists(archiveFile)) {<a name="line.494"></a>
-<span class="sourceLineNo">495</span> LOG.debug("{} already exists in archive, moving to timestamped backup and " +<a name="line.495"></a>
-<span class="sourceLineNo">496</span> "overwriting current.", archiveFile);<a name="line.496"></a>
-<span class="sourceLineNo">497</span><a name="line.497"></a>
-<span class="sourceLineNo">498</span> // move the archive file to the stamped backup<a name="line.498"></a>
-<span class="sourceLineNo">499</span> Path backedupArchiveFile = new Path(archiveDir, filename + SEPARATOR + archiveStartTime);<a name="line.499"></a>
-<span class="sourceLineNo">500</span> if (!fs.rename(archiveFile, backedupArchiveFile)) {<a name="line.500"></a>
-<span class="sourceLineNo">501</span> LOG.error("Could not rename archive file to backup: " + backedupArchiveFile<a name="line.501"></a>
-<span class="sourceLineNo">502</span> + ", deleting existing file in favor of newer.");<a name="line.502"></a>
-<span class="sourceLineNo">503</span> // try to delete the exisiting file, if we can't rename it<a name="line.503"></a>
-<span class="sourceLineNo">504</span> if (!fs.delete(archiveFile, false)) {<a name="line.504"></a>
-<span class="sourceLineNo">505</span> throw new IOException("Couldn't delete existing archive file (" + archiveFile<a name="line.505"></a>
-<span class="sourceLineNo">506</span> + ") or rename it to the backup file (" + backedupArchiveFile<a name="line.506"></a>
-<span class="sourceLineNo">507</span> + ") to make room for similarly named file.");<a name="line.507"></a>
-<span class="sourceLineNo">508</span> }<a name="line.508"></a>
-<span class="sourceLineNo">509</span> }<a name="line.509"></a>
-<span class="sourceLineNo">510</span> LOG.debug("Backed up archive file from " + archiveFile);<a name="line.510"></a>
-<span class="sourceLineNo">511</span> }<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span> LOG.trace("No existing file in archive for {}, free to archive original file.", archiveFile);<a name="line.513"></a>
-<span class="sourceLineNo">514</span><a name="line.514"></a>
-<span class="sourceLineNo">515</span> // at this point, we should have a free spot for the archive file<a name="line.515"></a>
-<span class="sourceLineNo">516</span> boolean success = false;<a name="line.516"></a>
-<span class="sourceLineNo">517</span> for (int i = 0; !success && i < DEFAULT_RETRIES_NUMBER; ++i) {<a name="line.517"></a>
-<span class="sourceLineNo">518</span> if (i > 0) {<a name="line.518"></a>
-<span class="sourceLineNo">519</span> // Ensure that the archive directory exists.<a name="line.519"></a>
-<span class="sourceLineNo">520</span> // The previous "move to archive" operation has failed probably because<a name="line.520"></a>
-<span class="sourceLineNo">521</span> // the cleaner has removed our archive directory (HBASE-7643).<a name="line.521"></a>
-<span class="sourceLineNo">522</span> // (we're in a retry loop, so don't worry too much about the exception)<a name="line.522"></a>
-<span class="sourceLineNo">523</span> try {<a name="line.523"></a>
-<span class="sourceLineNo">524</span> if (!fs.exists(archiveDir)) {<a name="line.524"></a>
-<span class="sourceLineNo">525</span> if (fs.mkdirs(archiveDir)) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span> LOG.debug("Created archive directory {}", archiveDir);<a name="line.526"></a>
-<span class="sourceLineNo">527</span> }<a name="line.527"></a>
-<span class="sourceLineNo">528</span> }<a name="line.528"></a>
-<span class="sourceLineNo">529</span> } catch (IOException e) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span> LOG.warn("Failed to create directory {}", archiveDir, e);<a name="line.530"></a>
-<span class="sourceLineNo">531</span> }<a name="line.531"></a>
-<span class="sourceLineNo">532</span> }<a name="line.532"></a>
-<span class="sourceLineNo">533</span><a name="line.533"></a>
-<span class="sourceLineNo">534</span> try {<a name="line.534"></a>
-<span class="sourceLineNo">535</span> success = currentFile.moveAndClose(archiveFile);<a name="line.535"></a>
-<span class="sourceLineNo">536</span> } catch (FileNotFoundException fnfe) {<a name="line.536"></a>
-<span class="sourceLineNo">537</span> LOG.warn("Failed to archive " + currentFile +<a name="line.537"></a>
-<span class="sourceLineNo">538</span> " because it does not exist! Skipping and continuing on.", fnfe);<a name="line.538"></a>
-<span class="sourceLineNo">539</span> success = true;<a name="line.539"></a>
-<span class="sourceLineNo">540</span> } catch (IOException e) {<a name="line.540"></a>
-<span class="sourceLineNo">541</span> LOG.warn("Failed to archive " + currentFile + " on try #" + i, e);<a name="line.541"></a>
-<span class="sourceLineNo">542</span> success = false;<a name="line.542"></a>
-<span class="sourceLineNo">543</span> }<a name="line.543"></a>
-<span class="sourceLineNo">544</span> }<a name="line.544"></a>
+<span class="sourceLineNo">491</span> // An existing destination file in the archive is unexpected, but we handle it here.<a name="line.491"></a>
+<span class="sourceLineNo">492</span> if (fs.exists(archiveFile)) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span> if (!fs.exists(currentFile.getPath())) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span> // If the file already exists in the archive, and there is no current file to archive, then<a name="line.494"></a>
+<span class="sourceLineNo">495</span> // assume that the file in archive is correct. This is an unexpected situation, suggesting a<a name="line.495"></a>
+<span class="sourceLineNo">496</span> // race condition or split brain.<a name="line.496"></a>
+<span class="sourceLineNo">497</span> // In HBASE-26718 this was found when compaction incorrectly happened during warmupRegion.<a name="line.497"></a>
+<span class="sourceLineNo">498</span> LOG.warn("{} exists in archive. Attempted to archive nonexistent file {}.", archiveFile,<a name="line.498"></a>
+<span class="sourceLineNo">499</span> currentFile);<a name="line.499"></a>
+<span class="sourceLineNo">500</span> // We return success to match existing behavior in this method, where FileNotFoundException<a name="line.500"></a>
+<span class="sourceLineNo">501</span> // in moveAndClose is ignored.<a name="line.501"></a>
+<span class="sourceLineNo">502</span> return true;<a name="line.502"></a>
+<span class="sourceLineNo">503</span> }<a name="line.503"></a>
+<span class="sourceLineNo">504</span> // There is a conflict between the current file and the already existing archived file.<a name="line.504"></a>
+<span class="sourceLineNo">505</span> // Move the archived file to a timestamped backup. This is a really, really unlikely<a name="line.505"></a>
+<span class="sourceLineNo">506</span> // situation, where we get the same name for the existing file, but is included just for that<a name="line.506"></a>
+<span class="sourceLineNo">507</span> // 1 in trillion chance. We are potentially incurring data loss in the archive directory if<a name="line.507"></a>
+<span class="sourceLineNo">508</span> // the files are not identical. The timestamped backup will be cleaned by HFileCleaner as it<a name="line.508"></a>
+<span class="sourceLineNo">509</span> // has no references.<a name="line.509"></a>
+<span class="sourceLineNo">510</span> FileStatus curStatus = fs.getFileStatus(currentFile.getPath());<a name="line.510"></a>
+<span class="sourceLineNo">511</span> FileStatus archiveStatus = fs.getFileStatus(archiveFile);<a name="line.511"></a>
+<span class="sourceLineNo">512</span> long curLen = curStatus.getLen();<a name="line.512"></a>
+<span class="sourceLineNo">513</span> long archiveLen = archiveStatus.getLen();<a name="line.513"></a>
+<span class="sourceLineNo">514</span> long curMtime = curStatus.getModificationTime();<a name="line.514"></a>
+<span class="sourceLineNo">515</span> long archiveMtime = archiveStatus.getModificationTime();<a name="line.515"></a>
+<span class="sourceLineNo">516</span> if (curLen != archiveLen) {<a name="line.516"></a>
+<span class="sourceLineNo">517</span> LOG.error("{} already exists in archive with different size than current {}."<a name="line.517"></a>
+<span class="sourceLineNo">518</span> + " archiveLen: {} currentLen: {} archiveMtime: {} currentMtime: {}",<a name="line.518"></a>
+<span class="sourceLineNo">519</span> archiveFile, currentFile, archiveLen, curLen, archiveMtime, curMtime);<a name="line.519"></a>
+<span class="sourceLineNo">520</span> throw new IOException(archiveFile + " already exists in archive with different size" +<a name="line.520"></a>
+<span class="sourceLineNo">521</span> " than " + currentFile);<a name="line.521"></a>
+<span class="sourceLineNo">522</span> }<a name="line.522"></a>
+<span class="sourceLineNo">523</span><a name="line.523"></a>
+<span class="sourceLineNo">524</span> LOG.error("{} already exists in archive, moving to timestamped backup and overwriting"<a name="line.524"></a>
+<span class="sourceLineNo">525</span> + " current {}. archiveLen: {} currentLen: {} archiveMtime: {} currentMtime: {}",<a name="line.525"></a>
+<span class="sourceLineNo">526</span> archiveFile, currentFile, archiveLen, curLen, archiveMtime, curMtime);<a name="line.526"></a>
+<span class="sourceLineNo">527</span><a name="line.527"></a>
+<span class="sourceLineNo">528</span> // move the archive file to the stamped backup<a name="line.528"></a>
+<span class="sourceLineNo">529</span> Path backedupArchiveFile = new Path(archiveDir, filename + SEPARATOR + archiveStartTime);<a name="line.529"></a>
+<span class="sourceLineNo">530</span> if (!fs.rename(archiveFile, backedupArchiveFile)) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span> LOG.error("Could not rename archive file to backup: " + backedupArchiveFile<a name="line.531"></a>
+<span class="sourceLineNo">532</span> + ", deleting existing file in favor of newer.");<a name="line.532"></a>
+<span class="sourceLineNo">533</span> // try to delete the existing file, if we can't rename it<a name="line.533"></a>
+<span class="sourceLineNo">534</span> if (!fs.delete(archiveFile, false)) {<a name="line.534"></a>
+<span class="sourceLineNo">535</span> throw new IOException("Couldn't delete existing archive file (" + archiveFile<a name="line.535"></a>
+<span class="sourceLineNo">536</span> + ") or rename it to the backup file (" + backedupArchiveFile<a name="line.536"></a>
+<span class="sourceLineNo">537</span> + ") to make room for similarly named file.");<a name="line.537"></a>
+<span class="sourceLineNo">538</span> }<a name="line.538"></a>
+<span class="sourceLineNo">539</span> } else {<a name="line.539"></a>
+<span class="sourceLineNo">540</span> LOG.info("Backed up archive file from {} to {}.", archiveFile, backedupArchiveFile);<a name="line.540"></a>
+<span class="sourceLineNo">541</span> }<a name="line.541"></a>
+<span class="sourceLineNo">542</span> }<a name="line.542"></a>
+<span class="sourceLineNo">543</span><a name="line.543"></a>
+<span class="sourceLineNo">544</span> LOG.trace("No existing file in archive for {}, free to archive original file.", archiveFile);<a name="line.544"></a>
<span class="sourceLineNo">545</span><a name="line.545"></a>
-<span class="sourceLineNo">546</span> if (!success) {<a name="line.546"></a>
-<span class="sourceLineNo">547</span> LOG.error("Failed to archive " + currentFile);<a name="line.547"></a>
-<span class="sourceLineNo">548</span> return false;<a name="line.548"></a>
-<span class="sourceLineNo">549</span> }<a name="line.549"></a>
-<span class="sourceLineNo">550</span><a name="line.550"></a>
-<span class="sourceLineNo">551</span> LOG.debug("Archived from {} to {}", currentFile, archiveFile);<a name="line.551"></a>
-<span class="sourceLineNo">552</span> return true;<a name="line.552"></a>
-<span class="sourceLineNo">553</span> }<a name="line.553"></a>
-<span class="sourceLineNo">554</span><a name="line.554"></a>
-<span class="sourceLineNo">555</span> /**<a name="line.555"></a>
-<span class="sourceLineNo">556</span> * Without regard for backup, delete a region. Should be used with caution.<a name="line.556"></a>
-<span class="sourceLineNo">557</span> * @param regionDir {@link Path} to the region to be deleted.<a name="line.557"></a>
-<span class="sourceLineNo">558</span> * @param fs FileSystem from which to delete the region<a name="line.558"></a>
-<span class="sourceLineNo">559</span> * @return <tt>true</tt> on successful deletion, <tt>false</tt> otherwise<a name="line.559"></a>
-<span class="sourceLineNo">560</span> * @throws IOException on filesystem operation failure<a name="line.560"></a>
-<span class="sourceLineNo">561</span> */<a name="line.561"></a>
-<span class="sourceLineNo">562</span> private static boolean deleteRegionWithoutArchiving(FileSystem fs, Path regionDir)<a name="line.562"></a>
-<span class="sourceLineNo">563</span> throws IOException {<a name="line.563"></a>
-<span class="sourceLineNo">564</span> if (fs.delete(regionDir, true)) {<a name="line.564"></a>
-<span class="sourceLineNo">565</span> LOG.debug("Deleted {}", regionDir);<a name="line.565"></a>
-<span class="sourceLineNo">566</span> return true;<a name="line.566"></a>
-<span class="sourceLineNo">567</span> }<a name="line.567"></a>
-<span class="sourceLineNo">568</span> LOG.debug("Failed to delete directory {}", regionDir);<a name="line.568"></a>
-<span class="sourceLineNo">569</span> return false;<a name="line.569"></a>
-<span class="sourceLineNo">570</span> }<a name="line.570"></a>
-<span class="sourceLineNo">571</span><a name="line.571"></a>
-<span class="sourceLineNo">572</span> /**<a name="line.572"></a>
-<span class="sourceLineNo">573</span> * Just do a simple delete of the given store files<a name="line.573"></a>
-<span class="sourceLineNo">574</span> * <p><a name="line.574"></a>
-<span class="sourceLineNo">575</span> * A best effort is made to delete each of the files, rather than bailing on the first failure.<a name="line.575"></a>
-<span class="sourceLineNo">576</span> * <p><a name="line.576"></a>
-<span class="sourceLineNo">577</span> * @param compactedFiles store files to delete from the file system.<a name="line.577"></a>
-<span class="sourceLineNo">578</span> * @throws IOException if a file cannot be deleted. All files will be attempted to deleted before<a name="line.578"></a>
-<span class="sourceLineNo">579</span> * throwing the exception, rather than failing at the first file.<a name="line.579"></a>
-<span class="sourceLineNo">580</span> */<a name="line.580"></a>
-<span class="sourceLineNo">581</span> private static void deleteStoreFilesWithoutArchiving(Collection<HStoreFile> compactedFiles)<a name="line.581"></a>
-<span class="sourceLineNo">582</span> throws IOException {<a name="line.582"></a>
-<span class="sourceLineNo">583</span> LOG.debug("Deleting files without archiving.");<a name="line.583"></a>
-<span class="sourceLineNo">584</span> List<IOException> errors = new ArrayList<>(0);<a name="line.584"></a>
-<span class="sourceLineNo">585</span> for (HStoreFile hsf : compactedFiles) {<a name="line.585"></a>
-<span class="sourceLineNo">586</span> try {<a name="line.586"></a>
-<span class="sourceLineNo">587</span> hsf.deleteStoreFile();<a name="line.587"></a>
-<span class="sourceLineNo">588</span> } catch (IOException e) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span> LOG.error("Failed to delete {}", hsf.getPath());<a name="line.589"></a>
-<span class="sourceLineNo">590</span> errors.add(e);<a name="line.590"></a>
-<span class="sourceLineNo">591</span> }<a name="line.591"></a>
-<span class="sourceLineNo">592</span> }<a name="line.592"></a>
-<span class="sourceLineNo">593</span> if (errors.size() > 0) {<a name="line.593"></a>
-<span class="sourceLineNo">594</span> throw MultipleIOException.createIOException(errors);<a name="line.594"></a>
-<span class="sourceLineNo">595</span> }<a name="line.595"></a>
-<span class="sourceLineNo">596</span> }<a name="line.596"></a>
-<span class="sourceLineNo">597</span><a name="line.597"></a>
-<span class="sourceLineNo">598</span> /**<a name="line.598"></a>
-<span class="sourceLineNo">599</span> * Adapt a type to match the {@link File} interface, which is used internally for handling<a name="line.599"></a>
-<span class="sourceLineNo">600</span> * archival/removal of files<a name="line.600"></a>
-<span class="sourceLineNo">601</span> * @param <T> type to adapt to the {@link File} interface<a name="line.601"></a>
-<span class="sourceLineNo">602</span> */<a name="line.602"></a>
-<span class="sourceLineNo">603</span> private static abstract class FileConverter<T> implements Function<T, File> {<a name="line.603"></a>
-<span class="sourceLineNo">604</span> protected final FileSystem fs;<a name="line.604"></a>
-<span class="sourceLineNo">605</span><a name="line.605"></a>
-<span class="sourceLineNo">606</span> public FileConverter(FileSystem fs) {<a name="line.606"></a>
-<span class="sourceLineNo">607</span> this.fs = fs;<a name="line.607"></a>
-<span class="sourceLineNo">608</span> }<a name="line.608"></a>
-<span class="sourceLineNo">609</span> }<a name="line.609"></a>
-<span class="sourceLineNo">610</span><a name="line.610"></a>
-<span class="sourceLineNo">611</span> /**<a name="line.611"></a>
-<span class="sourceLineNo">612</span> * Convert a FileStatus to something we can manage in the archiving<a name="line.612"></a>
-<span class="sourceLineNo">613</span> */<a name="line.613"></a>
-<span class="sourceLineNo">614</span> private static class FileStatusConverter extends FileConverter<FileStatus> {<a name="line.614"></a>
-<span class="sourceLineNo">615</span> public FileStatusConverter(FileSystem fs) {<a name="line.615"></a>
-<span class="sourceLineNo">616</span> super(fs);<a name="line.616"></a>
-<span class="sourceLineNo">617</span> }<a name="line.617"></a>
-<span class="sourceLineNo">618</span><a name="line.618"></a>
-<span class="sourceLineNo">619</span> @Override<a name="line.619"></a>
-<span class="sourceLineNo">620</span> public File apply(FileStatus input) {<a name="line.620"></a>
-<span class="sourceLineNo">621</span> return new FileablePath(fs, input.getPath());<a name="line.621"></a>
-<span class="sourceLineNo">622</span> }<a name="line.622"></a>
-<span class="sourceLineNo">623</span> }<a name="line.623"></a>
-<span class="sourceLineNo">624</span><a name="line.624"></a>
-<span class="sourceLineNo">625</span> /**<a name="line.625"></a>
-<span class="sourceLineNo">626</span> * Convert the {@link HStoreFile} into something we can manage in the archive<a name="line.626"></a>
-<span class="sourceLineNo">627</span> * methods<a name="line.627"></a>
-<span class="sourceLineNo">628</span> */<a name="line.628"></a>
-<span class="sourceLineNo">629</span> private static class StoreToFile extends FileConverter<HStoreFile> {<a name="line.629"></a>
-<span class="sourceLineNo">630</span> public StoreToFile(FileSystem fs) {<a name="line.630"></a>
-<span class="sourceLineNo">631</span> super(fs);<a name="line.631"></a>
-<span class="sourceLineNo">632</span> }<a name="line.632"></a>
-<span class="sourceLineNo">633</span><a name="line.633"></a>
-<span class="sourceLineNo">634</span> @Override<a name="line.634"></a>
-<span class="sourceLineNo">635</span> public File apply(HStoreFile input) {<a name="line.635"></a>
-<span class="sourceLineNo">636</span> return new FileableStoreFile(fs, input);<a name="line.636"></a>
-<span class="sourceLineNo">637</span> }<a name="line.637"></a>
-<span class="sourceLineNo">638</span> }<a name="line.638"></a>
-<span class="sourceLineNo">639</span><a name="line.639"></a>
-<span class="sourceLineNo">640</span> /**<a name="line.640"></a>
-<span class="sourceLineNo">641</span> * Wrapper to handle file operations uniformly<a name="line.641"></a>
-<span class="sourceLineNo">642</span> */<a name="line.642"></a>
-<span class="sourceLineNo">643</span> private static abstract class File {<a name="line.643"></a>
-<span class="sourceLineNo">644</span> protected final FileSystem fs;<a name="line.644"></a>
-<span class="sourceLineNo">645</span><a name="line.645"></a>
-<span class="sourceLineNo">646</span> public File(FileSystem fs) {<a name="line.646"></a>
-<span class="sourceLineNo">647</span> this.fs = fs;<a name="line.647"></a>
+<span class="sourceLineNo">546</span> // at this point, we should have a free spot for the archive file<a name="line.546"></a>
+<span class="sourceLineNo">547</span> boolean success = false;<a name="line.547"></a>
+<span class="sourceLineNo">548</span> for (int i = 0; !success && i < DEFAULT_RETRIES_NUMBER; ++i) {<a name="line.548"></a>
+<span class="sourceLineNo">549</span> if (i > 0) {<a name="line.549"></a>
+<span class="sourceLineNo">550</span> // Ensure that the archive directory exists.<a name="line.550"></a>
+<span class="sourceLineNo">551</span> // The previous "move to archive" operation has failed probably because<a name="line.551"></a>
+<span class="sourceLineNo">552</span> // the cleaner has removed our archive directory (HBASE-7643).<a name="line.552"></a>
+<span class="sourceLineNo">553</span> // (we're in a retry loop, so don't worry too much about the exception)<a name="line.553"></a>
+<span class="sourceLineNo">554</span> try {<a name="line.554"></a>
+<span class="sourceLineNo">555</span> if (!fs.exists(archiveDir)) {<a name="line.555"></a>
+<span class="sourceLineNo">556</span> if (fs.mkdirs(archiveDir)) {<a name="line.556"></a>
+<span class="sourceLineNo">557</span> LOG.debug("Created archive directory {}", archiveDir);<a name="line.557"></a>
+<span class="sourceLineNo">558</span> }<a name="line.558"></a>
+<span class="sourceLineNo">559</span> }<a name="line.559"></a>
+<span class="sourceLineNo">560</span> } catch (IOException e) {<a name="line.560"></a>
+<span class="sourceLineNo">561</span> LOG.warn("Failed to create directory {}", archiveDir, e);<a name="line.561"></a>
+<span class="sourceLineNo">562</span> }<a name="line.562"></a>
+<span class="sourceLineNo">563</span> }<a name="line.563"></a>
+<span class="sourceLineNo">564</span><a name="line.564"></a>
+<span class="sourceLineNo">565</span> try {<a name="line.565"></a>
+<span class="sourceLineNo">566</span> success = currentFile.moveAndClose(archiveFile);<a name="line.566"></a>
+<span class="sourceLineNo">567</span> } catch (FileNotFoundException fnfe) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span> LOG.warn("Failed to archive " + currentFile +<a name="line.568"></a>
+<span class="sourceLineNo">569</span> " because it does not exist! Skipping and continuing on.", fnfe);<a name="line.569"></a>
+<span class="sourceLineNo">570</span> success = true;<a name="line.570"></a>
+<span class="sourceLineNo">571</span> } catch (IOException e) {<a name="line.571"></a>
+<span class="sourceLineNo">572</span> LOG.warn("Failed to archive " + currentFile + " on try #" + i, e);<a name="line.572"></a>
+<span class="sourceLineNo">573</span> success = false;<a name="line.573"></a>
+<span class="sourceLineNo">574</span> }<a name="line.574"></a>
+<span class="sourceLineNo">575</span> }<a name="line.575"></a>
+<span class="sourceLineNo">576</span><a name="line.576"></a>
+<span class="sourceLineNo">577</span> if (!success) {<a name="line.577"></a>
+<span class="sourceLineNo">578</span> LOG.error("Failed to archive " + currentFile);<a name="line.578"></a>
+<span class="sourceLineNo">579</span> return false;<a name="line.579"></a>
+<span class="sourceLineNo">580</span> }<a name="line.580"></a>
+<span class="sourceLineNo">581</span><a name="line.581"></a>
+<span class="sourceLineNo">582</span> LOG.debug("Archived from {} to {}", currentFile, archiveFile);<a name="line.582"></a>
+<span class="sourceLineNo">583</span> return true;<a name="line.583"></a>
+<span class="sourceLineNo">584</span> }<a name="line.584"></a>
+<span class="sourceLineNo">585</span><a name="line.585"></a>
+<span class="sourceLineNo">586</span> /**<a name="line.586"></a>
+<span class="sourceLineNo">587</span> * Without regard for backup, delete a region. Should be used with caution.<a name="line.587"></a>
+<span class="sourceLineNo">588</span> * @param regionDir {@link Path} to the region to be deleted.<a name="line.588"></a>
+<span class="sourceLineNo">589</span> * @param fs FileSystem from which to delete the region<a name="line.589"></a>
+<span class="sourceLineNo">590</span> * @return <tt>true</tt> on successful deletion, <tt>false</tt> otherwise<a name="line.590"></a>
+<span class="sourceLineNo">591</span> * @throws IOException on filesystem operation failure<a name="line.591"></a>
+<span class="sourceLineNo">592</span> */<a name="line.592"></a>
+<span class="sourceLineNo">593</span> private static boolean deleteRegionWithoutArchiving(FileSystem fs, Path regionDir)<a name="line.593"></a>
+<span class="sourceLineNo">594</span> throws IOException {<a name="line.594"></a>
+<span class="sourceLineNo">595</span> if (fs.delete(regionDir, true)) {<a name="line.595"></a>
+<span class="sourceLineNo">596</span> LOG.debug("Deleted {}", regionDir);<a name="line.596"></a>
+<span class="sourceLineNo">597</span> return true;<a name="line.597"></a>
+<span class="sourceLineNo">598</span> }<a name="line.598"></a>
+<span class="sourceLineNo">599</span> LOG.debug("Failed to delete directory {}", regionDir);<a name="line.599"></a>
+<span class="sourceLineNo">600</span> return false;<a name="line.600"></a>
+<span class="sourceLineNo">601</span> }<a name="line.601"></a>
+<span class="sourceLineNo">602</span><a name="line.602"></a>
+<span class="sourceLineNo">603</span> /**<a name="line.603"></a>
+<span class="sourceLineNo">604</span> * Just do a simple delete of the given store files<a name="line.604"></a>
+<span class="sourceLineNo">605</span> * <p><a name="line.605"></a>
+<span class="sourceLineNo">606</span> * A best effort is made to delete each of the files, rather than bailing on the first failure.<a name="line.606"></a>
+<span class="sourceLineNo">607</span> * <p><a name="line.607"></a>
+<span class="sourceLineNo">608</span> * @param compactedFiles store files to delete from the file system.<a name="line.608"></a>
+<span class="sourceLineNo">609</span> * @throws IOException if a file cannot be deleted. All files will be attempted to deleted before<a name="line.609"></a>
+<span class="sourceLineNo">610</span> * throwing the exception, rather than failing at the first file.<a name="line.610"></a>
+<span class="sourceLineNo">611</span> */<a name="line.611"></a>
+<span class="sourceLineNo">612</span> private static void deleteStoreFilesWithoutArchiving(Collection<HStoreFile> compactedFiles)<a name="line.612"></a>
+<span class="sourceLineNo">613</span> throws IOException {<a name="line.613"></a>
+<span class="sourceLineNo">614</span> LOG.debug("Deleting files without archiving.");<a name="line.614"></a>
+<span class="sourceLineNo">615</span> List<IOException> errors = new ArrayList<>(0);<a name="line.615"></a>
+<span class="sourceLineNo">616</span> for (HStoreFile hsf : compactedFiles) {<a name="line.616"></a>
+<span class="sourceLineNo">617</span> try {<a name="line.617"></a>
+<span class="sourceLineNo">618</span> hsf.deleteStoreFile();<a name="line.618"></a>
+<span class="sourceLineNo">619</span> } catch (IOException e) {<a name="line.619"></a>
+<span class="sourceLineNo">620</span> LOG.error("Failed to delete {}", hsf.getPath());<a name="line.620"></a>
+<span class="sourceLineNo">621</span> errors.add(e);<a name="line.621"></a>
+<span class="sourceLineNo">622</span> }<a name="line.622"></a>
+<span class="sourceLineNo">623</span> }<a name="line.623"></a>
+<span class="sourceLineNo">624</span> if (errors.size() > 0) {<a name="line.624"></a>
+<span class="sourceLineNo">625</span> throw MultipleIOException.createIOException(errors);<a name="line.625"></a>
+<span class="sourceLineNo">626</span> }<a name="line.626"></a>
+<span class="sourceLineNo">627</span> }<a name="line.627"></a>
+<span class="sourceLineNo">628</span><a name="line.628"></a>
+<span class="sourceLineNo">629</span> /**<a name="line.629"></a>
+<span class="sourceLineNo">630</span> * Adapt a type to match the {@link File} interface, which is used internally for handling<a name="line.630"></a>
+<span class="sourceLineNo">631</span> * archival/removal of files<a name="line.631"></a>
+<span class="sourceLineNo">632</span> * @param <T> type to adapt to the {@link File} interface<a name="line.632"></a>
+<span class="sourceLineNo">633</span> */<a name="line.633"></a>
+<span class="sourceLineNo">634</span> private static abstract class FileConverter<T> implements Function<T, File> {<a name="line.634"></a>
+<span class="sourceLineNo">635</span> protected final FileSystem fs;<a name="line.635"></a>
+<span class="sourceLineNo">636</span><a name="line.636"></a>
+<span class="sourceLineNo">637</span> public FileConverter(FileSystem fs) {<a name="line.637"></a>
+<span class="sourceLineNo">638</span> this.fs = fs;<a name="line.638"></a>
+<span class="sourceLineNo">639</span> }<a name="line.639"></a>
+<span class="sourceLineNo">640</span> }<a name="line.640"></a>
+<span class="sourceLineNo">641</span><a name="line.641"></a>
+<span class="sourceLineNo">642</span> /**<a name="line.642"></a>
+<span class="sourceLineNo">643</span> * Convert a FileStatus to something we can manage in the archiving<a name="line.643"></a>
+<span class="sourceLineNo">644</span> */<a name="line.644"></a>
+<span class="sourceLineNo">645</span> private static class FileStatusConverter extends FileConverter<FileStatus> {<a name="line.645"></a>
+<span class="sourceLineNo">646</span> public FileStatusConverter(FileSystem fs) {<a name="line.646"></a>
+<span class="sourceLineNo">647</span> super(fs);<a name="line.647"></a>
<span class="sourceLineNo">648</span> }<a name="line.648"></a>
<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span> /**<a name="line.650"></a>
-<span class="sourceLineNo">651</span> * Delete the file<a name="line.651"></a>
-<span class="sourceLineNo">652</span> * @throws IOException on failure<a name="line.652"></a>
-<span class="sourceLineNo">653</span> */<a name="line.653"></a>
-<span class="sourceLineNo">654</span> abstract void delete() throws IOException;<a name="line.654"></a>
+<span class="sourceLineNo">650</span> @Override<a name="line.650"></a>
+<span class="sourceLineNo">651</span> public File apply(FileStatus input) {<a name="line.651"></a>
+<span class="sourceLineNo">652</span> return new FileablePath(fs, input.getPath());<a name="line.652"></a>
+<span class="sourceLineNo">653</span> }<a name="line.653"></a>
+<span class="sourceLineNo">654</span> }<a name="line.654"></a>
<span class="sourceLineNo">655</span><a name="line.655"></a>
-<span class="sourceLineNo">656</span> /**<a name="line.656"></a>
-<span class="sourceLineNo">657</span> * Check to see if this is a file or a directory<a name="line.657"></a>
-<span class="sourceLineNo">658</span> * @return <tt>true</tt> if it is a file, <tt>false</tt> otherwise<a name="line.658"></a>
-<span class="sourceLineNo">659</span> * @throws IOException on {@link FileSystem} connection error<a name="line.659"></a>
-<span class="sourceLineNo">660</span> */<a name="line.660"></a>
-<span class="sourceLineNo">661</span> abstract boolean isFile() throws IOException;<a name="line.661"></a>
-<span class="sourceLineNo">662</span><a name="line.662"></a>
-<span class="sourceLineNo">663</span> /**<a name="line.663"></a>
-<span class="sourceLineNo">664</span> * @return if this is a directory, returns all the children in the<a name="line.664"></a>
-<span class="sourceLineNo">665</span> * directory, otherwise returns an empty list<a name="line.665"></a>
-<span class="sourceLineNo">666</span> * @throws IOException<a name="line.666"></a>
-<span class="sourceLineNo">667</span> */<a name="line.667"></a>
-<span class="sourceLineNo">668</span> abstract Collection<File> getChildren() throws IOException;<a name="line.668"></a>
-<span class="sourceLineNo">669</span><a name="line.669"></a>
-<span class="sourceLineNo">670</span> /**<a name="line.670"></a>
-<span class="sourceLineNo">671</span> * close any outside readers of the file<a name="line.671"></a>
-<span class="sourceLineNo">672</span> * @throws IOException<a name="line.672"></a>
-<span class="sourceLineNo">673</span> */<a name="line.673"></a>
-<span class="sourceLineNo">674</span> abstract void close() throws IOException;<a name="line.674"></a>
-<span class="sourceLineNo">675</span><a name="line.675"></a>
-<span class="sourceLineNo">676</span> /**<a name="line.676"></a>
-<span class="sourceLineNo">677</span> * @return the name of the file (not the full fs path, just the individual<a name="line.677"></a>
-<span class="sourceLineNo">678</span> * file name)<a name="line.678"></a>
-<span class="sourceLineNo">679</span> */<a name="line.679"></a>
-<span class="sourceLineNo">680</span> abstract String getName();<a name="line.680"></a>
-<span class="sourceLineNo">681</span><a name="line.681"></a>
-<span class="sourceLineNo">682</span> /**<a name="line.682"></a>
-<span class="sourceLineNo">683</span> * @return the path to this file<a name="line.683"></a>
+<span class="sourceLineNo">656</span> /**<a name="line.656"></a>
+<span class="sourceLineNo">657</span> * Convert the {@link HStoreFile} into something we can manage in the archive<a name="line.657"></a>
+<span class="sourceLineNo">658</span> * methods<a name="line.658"></a>
+<span class="sourceLineNo">659</span> */<a name="line.659"></a>
+<span class="sourceLineNo">660</span> private static class StoreToFile extends FileConverter<HStoreFile> {<a name="line.660"></a>
+<span class="sourceLineNo">661</span> public StoreToFile(FileSystem fs) {<a name="line.661"></a>
+<span class="sourceLineNo">662</span> super(fs);<a name="line.662"></a>
+<span class="sourceLineNo">663</span> }<a name="line.663"></a>
+<span class="sourceLineNo">664</span><a name="line.664"></a>
+<span class="sourceLineNo">665</span> @Override<a name="line.665"></a>
+<span class="sourceLineNo">666</span> public File apply(HStoreFile input) {<a name="line.666"></a>
+<span class="sourceLineNo">667</span> return new FileableStoreFile(fs, input);<a name="line.667"></a>
+<span class="sourceLineNo">668</span> }<a name="line.668"></a>
+<span class="sourceLineNo">669</span> }<a name="line.669"></a>
+<span class="sourceLineNo">670</span><a name="line.670"></a>
+<span class="sourceLineNo">671</span> /**<a name="line.671"></a>
+<span class="sourceLineNo">672</span> * Wrapper to handle file operations uniformly<a name="line.672"></a>
+<span class="sourceLineNo">673</span> */<a name="line.673"></a>
+<span class="sourceLineNo">674</span> private static abstract class File {<a name="line.674"></a>
+<span class="sourceLineNo">675</span> protected final FileSystem fs;<a name="line.675"></a>
+<span class="sourceLineNo">676</span><a name="line.676"></a>
+<span class="sourceLineNo">677</span> public File(FileSystem fs) {<a name="line.677"></a>
+<span class="sourceLineNo">678</span> this.fs = fs;<a name="line.678"></a>
+<span class="sourceLineNo">679</span> }<a name="line.679"></a>
+<span class="sourceLineNo">680</span><a name="line.680"></a>
+<span class="sourceLineNo">681</span> /**<a name="line.681"></a>
+<span class="sourceLineNo">682</span> * Delete the file<a name="line.682"></a>
+<span class="sourceLineNo">683</span> * @throws IOException on failure<a name="line.683"></a>
<span class="sourceLineNo">684</span> */<a name="line.684"></a>
-<span class="sourceLineNo">685</span> abstract Path getPath();<a name="line.685"></a>
+<span class="sourceLineNo">685</span> abstract void delete() throws IOException;<a name="line.685"></a>
<span class="sourceLineNo">686</span><a name="line.686"></a>
<span class="sourceLineNo">687</span> /**<a name="line.687"></a>
-<span class="sourceLineNo">688</span> * Move the file to the given destination<a name="line.688"></a>
-<span class="sourceLineNo">689</span> * @param dest<a name="line.689"></a>
-<span class="sourceLineNo">690</span> * @return <tt>true</tt> on success<a name="line.690"></a>
-<span class="sourceLineNo">691</span> * @throws IOException<a name="line.691"></a>
-<span class="sourceLineNo">692</span> */<a name="line.692"></a>
-<span class="sourceLineNo">693</span> public boolean moveAndClose(Path dest) throws IOException {<a name="line.693"></a>
-<span class="sourceLineNo">694</span> this.close();<a name="line.694"></a>
-<span class="sourceLineNo">695</span> Path p = this.getPath();<a name="line.695"></a>
-<span class="sourceLineNo">696</span> return CommonFSUtils.renameAndSetModifyTime(fs, p, dest);<a name="line.696"></a>
-<span class="sourceLineNo">697</span> }<a name="line.697"></a>
-<span class="sourceLineNo">698</span><a name="line.698"></a>
-<span class="sourceLineNo">699</span> /**<a name="line.699"></a>
-<span class="sourceLineNo">700</span> * @return the {@link FileSystem} on which this file resides<a name="line.700"></a>
-<span class="sourceLineNo">701</span> */<a name="line.701"></a>
-<span class="sourceLineNo">702</span> public FileSystem getFileSystem() {<a name="line.702"></a>
-<span class="sourceLineNo">703</span> return this.fs;<a name="line.703"></a>
-<span class="sourceLineNo">704</span> }<a name="line.704"></a>
-<span class="sourceLineNo">705</span><a name="line.705"></a>
-<span class="sourceLineNo">706</span> @Override<a name="line.706"></a>
-<span class="sourceLineNo">707</span> public String toString() {<a name="line.707"></a>
-<span class="sourceLineNo">708</span> return this.getClass().getSimpleName() + ", " + getPath().toString();<a name="line.708"></a>
-<span class="sourceLineNo">709</span> }<a name="line.709"></a>
-<span class="sourceLineNo">710</span> }<a name="line.710"></a>
-<span class="sourceLineNo">711</span><a name="line.711"></a>
-<span class="sourceLineNo">712</span> /**<a name="line.712"></a>
-<span class="sourceLineNo">713</span> * A {@link File} that wraps a simple {@link Path} on a {@link FileSystem}.<a name="line.713"></a>
-<span class="sourceLineNo">714</span> */<a name="line.714"></a>
-<span class="sourceLineNo">715</span> private static class FileablePath extends File {<a name="line.715"></a>
-<span class="sourceLineNo">716</span> private final Path file;<a name="line.716"></a>
-<span class="sourceLineNo">717</span> private final FileStatusConverter getAsFile;<a name="line.717"></a>
-<span class="sourceLineNo">718</span><a name="line.718"></a>
-<span class="sourceLineNo">719</span> public FileablePath(FileSystem fs, Path file) {<a name="line.719"></a>
-<span class="sourceLineNo">720</span> super(fs);<a name="line.720"></a>
-<span class="sourceLineNo">721</span> this.file = file;<a name="line.721"></a>
-<span class="sourceLineNo">722</span> this.getAsFile = new FileStatusConverter(fs);<a name="line.722"></a>
-<span class="sourceLineNo">723</span> }<a name="line.723"></a>
-<span class="sourceLineNo">724</span><a name="line.724"></a>
-<span class="sourceLineNo">725</span> @Override<a name="line.725"></a>
-<span class="sourceLineNo">726</span> public void delete() throws IOException {<a name="line.726"></a>
-<span class="sourceLineNo">727</span> if (!fs.delete(file, true)) throw new IOException("Failed to delete:" + this.file);<a name="line.727"></a>
+<span class="sourceLineNo">688</span> * Check to see if this is a file or a directory<a name="line.688"></a>
+<span class="sourceLineNo">689</span> * @return <tt>true</tt> if it is a file, <tt>false</tt> otherwise<a name="line.689"></a>
+<span class="sourceLineNo">690</span> * @throws IOException on {@link FileSystem} connection error<a name="line.690"></a>
+<span class="sourceLineNo">691</span> */<a name="line.691"></a>
+<span class="sourceLineNo">692</span> abstract boolean isFile() throws IOException;<a name="line.692"></a>
+<span class="sourceLineNo">693</span><a name="line.693"></a>
+<span class="sourceLineNo">694</span> /**<a name="line.694"></a>
+<span class="sourceLineNo">695</span> * @return if this is a directory, returns all the children in the<a name="line.695"></a>
+<span class="sourceLineNo">696</span> * directory, otherwise returns an empty list<a name="line.696"></a>
+<span class="sourceLineNo">697</span> * @throws IOException<a name="line.697"></a>
+<span class="sourceLineNo">698</span> */<a name="line.698"></a>
+<span class="sourceLineNo">699</span> abstract Collection<File> getChildren() throws IOException;<a name="line.699"></a>
+<span class="sourceLineNo">700</span><a name="line.700"></a>
+<span class="sourceLineNo">701</span> /**<a name="line.701"></a>
+<span class="sourceLineNo">702</span> * close any outside readers of the file<a name="line.702"></a>
+<span class="sourceLineNo">703</span> * @throws IOException<a name="line.703"></a>
+<span class="sourceLineNo">704</span> */<a name="line.704"></a>
+<span class="sourceLineNo">705</span> abstract void close() throws IOException;<a name="line.705"></a>
+<span class="sourceLineNo">706</span><a name="line.706"></a>
+<span class="sourceLineNo">707</span> /**<a name="line.707"></a>
+<span class="sourceLineNo">708</span> * @return the name of the file (not the full fs path, just the individual<a name="line.708"></a>
+<span class="sourceLineNo">709</span> * file name)<a name="line.709"></a>
+<span class="sourceLineNo">710</span> */<a name="line.710"></a>
+<span class="sourceLineNo">711</span> abstract String getName();<a name="line.711"></a>
+<span class="sourceLineNo">712</span><a name="line.712"></a>
+<span class="sourceLineNo">713</span> /**<a name="line.713"></a>
+<span class="sourceLineNo">714</span> * @return the path to this file<a name="line.714"></a>
+<span class="sourceLineNo">715</span> */<a name="line.715"></a>
+<span class="sourceLineNo">716</span> abstract Path getPath();<a name="line.716"></a>
+<span class="sourceLineNo">717</span><a name="line.717"></a>
+<span class="sourceLineNo">718</span> /**<a name="line.718"></a>
+<span class="sourceLineNo">719</span> * Move the file to the given destination<a name="line.719"></a>
+<span class="sourceLineNo">720</span> * @param dest<a name="line.720"></a>
+<span class="sourceLineNo">721</span> * @return <tt>true</tt> on success<a name="line.721"></a>
+<span class="sourceLineNo">722</span> * @throws IOException<a name="line.722"></a>
+<span class="sourceLineNo">723</span> */<a name="line.723"></a>
+<span class="sourceLineNo">724</span> public boolean moveAndClose(Path dest) throws IOException {<a name="line.724"></a>
+<span class="sourceLineNo">725</span> this.close();<a name="line.725"></a>
+<span class="sourceLineNo">726</span> Path p = this.getPath();<a name="line.726"></a>
+<span class="sourceLineNo">727</span> return CommonFSUtils.renameAndSetModifyTime(fs, p, dest);<a name="line.727"></a>
<span class="sourceLineNo">728</span> }<a name="line.728"></a>
<span class="sourceLineNo">729</span><a name="line.729"></a>
-<span class="sourceLineNo">730</span> @Override<a name="line.730"></a>
-<span class="sourceLineNo">731</span> public String getName() {<a name="line.731"></a>
-<span class="sourceLineNo">732</span> return file.getName();<a name="line.732"></a>
-<span class="sourceLineNo">733</span> }<a name="line.733"></a>
-<span class="sourceLineNo">734</span><a name="line.734"></a>
-<span class="sourceLineNo">735</span> @Override<a name="line.735"></a>
-<span class="sourceLineNo">736</span> public Collection<File> getChildren() throws IOException {<a name="line.736"></a>
-<span class="sourceLineNo">737</span> if (fs.isFile(file)) {<a name="line.737"></a>
-<span class="sourceLineNo">738</span> return Collections.emptyList();<a name="line.738"></a>
-<span class="sourceLineNo">739</span> }<a name="line.739"></a>
-<span class="sourceLineNo">740</span> return Stream.of(fs.listStatus(file)).map(getAsFile).collect(Collectors.toList());<a name="line.740"></a>
-<span class="sourceLineNo">741</span> }<a name="line.741"></a>
+<span class="sourceLineNo">730</span> /**<a name="line.730"></a>
+<span class="sourceLineNo">731</span> * @return the {@link FileSystem} on which this file resides<a name="line.731"></a>
+<span class="sourceLineNo">732</span> */<a name="line.732"></a>
+<span class="sourceLineNo">733</span> public FileSystem getFileSystem() {<a name="line.733"></a>
+<span class="sourceLineNo">734</span> return this.fs;<a name="line.734"></a>
+<span class="sourceLineNo">735</span> }<a name="line.735"></a>
+<span class="sourceLineNo">736</span><a name="line.736"></a>
+<span class="sourceLineNo">737</span> @Override<a name="line.737"></a>
+<span class="sourceLineNo">738</span> public String toString() {<a name="line.738"></a>
+<span class="sourceLineNo">739</span> return this.getClass().getSimpleName() + ", " + getPath().toString();<a name="line.739"></a>
+<span class="sourceLineNo">740</span> }<a name="line.740"></a>
+<span class="sourceLineNo">741</span> }<a name="line.741"></a>
<span class="sourceLineNo">742</span><a name="line.742"></a>
-<span class="sourceLineNo">743</span> @Override<a name="line.743"></a>
-<span class="sourceLineNo">744</span> public boolean isFile() throws IOException {<a name="line.744"></a>
-<span class="sourceLineNo">745</span> return fs.isFile(file);<a name="line.745"></a>
-<span class="sourceLineNo">746</span> }<a name="line.746"></a>
-<span class="sourceLineNo">747</span><a name="line.747"></a>
-<span class="sourceLineNo">748</span> @Override<a name="line.748"></a>
-<span class="sourceLineNo">749</span> public void close() throws IOException {<a name="line.749"></a>
-<span class="sourceLineNo">750</span> // NOOP - files are implicitly closed on removal<a name="line.750"></a>
-<span class="sourceLineNo">751</span> }<a name="line.751"></a>
-<span class="sourceLineNo">752</span><a name="line.752"></a>
-<span class="sourceLineNo">753</span> @Override<a name="line.753"></a>
-<span class="sourceLineNo">754</span> Path getPath() {<a name="line.754"></a>
-<span class="sourceLineNo">755</span> return file;<a name="line.755"></a>
-<span class="sourceLineNo">756</span> }<a name="line.756"></a>
-<span class="sourceLineNo">757</span> }<a name="line.757"></a>
-<span class="sourceLineNo">758</span><a name="line.758"></a>
-<span class="sourceLineNo">759</span> /**<a name="line.759"></a>
-<span class="sourceLineNo">760</span> * {@link File} adapter for a {@link HStoreFile} living on a {@link FileSystem}<a name="line.760"></a>
-<span class="sourceLineNo">761</span> * .<a name="line.761"></a>
-<span class="sourceLineNo">762</span> */<a name="line.762"></a>
-<span class="sourceLineNo">763</span> private static class FileableStoreFile extends File {<a name="line.763"></a>
-<span class="sourceLineNo">764</span> HStoreFile file;<a name="line.764"></a>
+<span class="sourceLineNo">743</span> /**<a name="line.743"></a>
+<span class="sourceLineNo">744</span> * A {@link File} that wraps a simple {@link Path} on a {@link FileSystem}.<a name="line.744"></a>
+<span class="sourceLineNo">745</span> */<a name="line.745"></a>
+<span class="sourceLineNo">746</span> private static class FileablePath extends File {<a name="line.746"></a>
+<span class="sourceLineNo">747</span> private final Path file;<a name="line.747"></a>
+<span class="sourceLineNo">748</span> private final FileStatusConverter getAsFile;<a name="line.748"></a>
+<span class="sourceLineNo">749</span><a name="line.749"></a>
+<span class="sourceLineNo">750</span> public FileablePath(FileSystem fs, Path file) {<a name="line.750"></a>
+<span class="sourceLineNo">751</span> super(fs);<a name="line.751"></a>
+<span class="sourceLineNo">752</span> this.file = file;<a name="line.752"></a>
+<span class="sourceLineNo">753</span> this.getAsFile = new FileStatusConverter(fs);<a name="line.753"></a>
+<span class="sourceLineNo">754</span> }<a name="line.754"></a>
+<span class="sourceLineNo">755</span><a name="line.755"></a>
+<span class="sourceLineNo">756</span> @Override<a name="line.756"></a>
+<span class="sourceLineNo">757</span> public void delete() throws IOException {<a name="line.757"></a>
+<span class="sourceLineNo">758</span> if (!fs.delete(file, true)) throw new IOException("Failed to delete:" + this.file);<a name="line.758"></a>
+<span class="sourceLineNo">759</span> }<a name="line.759"></a>
+<span class="sourceLineNo">760</span><a name="line.760"></a>
+<span class="sourceLineNo">761</span> @Override<a name="line.761"></a>
+<span class="sourceLineNo">762</span> public String getName() {<a name="line.762"></a>
+<span class="sourceLineNo">763</span> return file.getName();<a name="line.763"></a>
+<span class="sourceLineNo">764</span> }<a name="line.764"></a>
<span class="sourceLineNo">765</span><a name="line.765"></a>
-<span class="sourceLineNo">766</span> public FileableStoreFile(FileSystem fs, HStoreFile store) {<a name="line.766"></a>
-<span class="sourceLineNo">767</span> super(fs);<a name="line.767"></a>
-<span class="sourceLineNo">768</span> this.file = store;<a name="line.768"></a>
-<span class="sourceLineNo">769</span> }<a name="line.769"></a>
-<span class="sourceLineNo">770</span><a name="line.770"></a>
-<span class="sourceLineNo">771</span> @Override<a name="line.771"></a>
-<span class="sourceLineNo">772</span> public void delete() throws IOException {<a name="line.772"></a>
-<span class="sourceLineNo">773</span> file.deleteStoreFile();<a name="line.773"></a>
-<span class="sourceLineNo">774</span> }<a name="line.774"></a>
-<span class="sourceLineNo">775</span><a name="line.775"></a>
-<span class="sourceLineNo">776</span> @Override<a name="line.776"></a>
-<span class="sourceLineNo">777</span> public String getName() {<a name="line.777"></a>
-<span class="sourceLineNo">778</span> return file.getPath().getName();<a name="line.778"></a>
-<span class="sourceLineNo">779</span> }<a name="line.779"></a>
-<span class="sourceLineNo">780</span><a name="line.780"></a>
-<span class="sourceLineNo">781</span> @Override<a name="line.781"></a>
-<span class="sourceLineNo">782</span> public boolean isFile() {<a name="line.782"></a>
-<span class="sourceLineNo">783</span> return true;<a name="line.783"></a>
-<span class="sourceLineNo">784</span> }<a name="line.784"></a>
-<span class="sourceLineNo">785</span><a name="line.785"></a>
-<span class="sourceLineNo">786</span> @Override<a name="line.786"></a>
-<span class="sourceLineNo">787</span> public Collection<File> getChildren() throws IOException {<a name="line.787"></a>
-<span class="sourceLineNo">788</span> // storefiles don't have children<a name="line.788"></a>
-<span class="sourceLineNo">789</span> return Collections.emptyList();<a name="line.789"></a>
-<span class="sourceLineNo">790</span> }<a name="line.790"></a>
-<span class="sourceLineNo">791</span><a name="line.791"></a>
-<span class="sourceLineNo">792</span> @Override<a name="line.792"></a>
-<span class="sourceLineNo">793</span> public void close() throws IOException {<a name="line.793"></a>
-<span class="sourceLineNo">794</span> file.closeStoreFile(true);<a name="line.794"></a>
-<span class="sourceLineNo">795</span> }<a name="line.795"></a>
+<span class="sourceLineNo">766</span> @Override<a name="line.766"></a>
+<span class="sourceLineNo">767</span> public Collection<File> getChildren() throws IOException {<a name="line.767"></a>
+<span class="sourceLineNo">768</span> if (fs.isFile(file)) {<a name="line.768"></a>
+<span class="sourceLineNo">769</span> return Collections.emptyList();<a name="line.769"></a>
+<span class="sourceLineNo">770</span> }<a name="line.770"></a>
+<span class="sourceLineNo">771</span> return Stream.of(fs.listStatus(file)).map(getAsFile).collect(Collectors.toList());<a name="line.771"></a>
+<span class="sourceLineNo">772</span> }<a name="line.772"></a>
+<span class="sourceLineNo">773</span><a name="line.773"></a>
+<span class="sourceLineNo">774</span> @Override<a name="line.774"></a>
+<span class="sourceLineNo">775</span> public boolean isFile() throws IOException {<a name="line.775"></a>
+<span class="sourceLineNo">776</span> return fs.isFile(file);<a name="line.776"></a>
+<span class="sourceLineNo">777</span> }<a name="line.777"></a>
+<span class="sourceLineNo">778</span><a name="line.778"></a>
+<span class="sourceLineNo">779</span> @Override<a name="line.779"></a>
+<span class="sourceLineNo">780</span> public void close() throws IOException {<a name="line.780"></a>
+<span class="sourceLineNo">781</span> // NOOP - files are implicitly closed on removal<a name="line.781"></a>
+<span class="sourceLineNo">782</span> }<a name="line.782"></a>
+<span class="sourceLineNo">783</span><a name="line.783"></a>
+<span class="sourceLineNo">784</span> @Override<a name="line.784"></a>
+<span class="sourceLineNo">785</span> Path getPath() {<a name="line.785"></a>
+<span class="sourceLineNo">786</span> return file;<a name="line.786"></a>
+<span class="sourceLineNo">787</span> }<a name="line.787"></a>
+<span class="sourceLineNo">788</span> }<a name="line.788"></a>
+<span class="sourceLineNo">789</span><a name="line.789"></a>
+<span class="sourceLineNo">790</span> /**<a name="line.790"></a>
+<span class="sourceLineNo">791</span> * {@link File} adapter for a {@link HStoreFile} living on a {@link FileSystem}<a name="line.791"></a>
+<span class="sourceLineNo">792</span> * .<a name="line.792"></a>
+<span class="sourceLineNo">793</span> */<a name="line.793"></a>
+<span class="sourceLineNo">794</span> private static class FileableStoreFile extends File {<a name="line.794"></a>
+<span class="sourceLineNo">795</span> HStoreFile file;<a name="line.795"></a>
<span class="sourceLineNo">796</span><a name="line.796"></a>
-<span class="sourceLineNo">797</span> @Override<a name="line.797"></a>
-<span class="sourceLineNo">798</span> Path getPath() {<a name="line.798"></a>
-<span class="sourceLineNo">799</span> return file.getPath();<a name="line.799"></a>
+<span class="sourceLineNo">797</span> public FileableStoreFile(FileSystem fs, HStoreFile store) {<a name="line.797"></a>
+<span class="sourceLineNo">798</span> super(fs);<a name="line.798"></a>
+<span class="sourceLineNo">799</span> this.file = store;<a name="line.799"></a>
<span class="sourceLineNo">800</span> }<a name="line.800"></a>
-<span class="sourceLineNo">801</span> }<a name="line.801"></a>
-<span class="sourceLineNo">802</span>}<a name="line.802"></a>
+<span class="sourceLineNo">801</span><a name="line.801"></a>
+<span class="sourceLineNo">802</span> @Override<a name="line.802"></a>
+<span class="sourceLineNo">803</span> public void delete() throws IOException {<a name="line.803"></a>
+<span class="sourceLineNo">804</span> file.deleteStoreFile();<a name="line.804"></a>
+<span class="sourceLineNo">805</span> }<a name="line.805"></a>
+<span class="sourceLineNo">806</span><a name="line.806"></a>
+<span class="sourceLineNo">807</span> @Override<a name="line.807"></a>
+<span class="sourceLineNo">808</span> public String getName() {<a name="line.808"></a>
+<span class="sourceLineNo">809</span> return file.getPath().getName();<a name="line.809"></a>
+<span class="sourceLineNo">810</span> }<a name="line.810"></a>
+<span class="sourceLineNo">811</span><a name="line.811"></a>
+<span class="sourceLineNo">812</span> @Override<a name="line.812"></a>
+<span class="sourceLineNo">813</span> public boolean isFile() {<a name="line.813"></a>
+<span class="sourceLineNo">814</span> return true;<a name="line.814"></a>
+<span class="sourceLineNo">815</span> }<a name="line.815"></a>
+<span class="sourceLineNo">816</span><a name="line.816"></a>
+<span class="sourceLineNo">817</span> @Override<a name="line.817"></a>
+<span class="sourceLineNo">818</span> public Collection<File> getChildren() throws IOException {<a name="line.818"></a>
+<span class="sourceLineNo">819</span> // storefiles don't have children<a name="line.819"></a>
+<span class="sourceLineNo">820</span> return Collections.emptyList();<a name="line.820"></a>
+<span class="sourceLineNo">821</span> }<a name="line.821"></a>
+<span class="sourceLineNo">822</span><a name="line.822"></a>
+<span class="sourceLineNo">823</span> @Override<a name="line.823"></a>
+<span class="sourceLineNo">824</span> public void close() throws IOException {<a name="line.824"></a>
+<span class="sourceLineNo">825</span> file.closeStoreFile(true);<a name="line.825"></a>
+<span class="sourceLineNo">826</span> }<a name="line.826"></a>
+<span class="sourceLineNo">827</span><a name="line.827"></a>
+<span class="sourceLineNo">828</span> @Override<a name="line.828"></a>
+<span class="sourceLineNo">829</span> Path getPath() {<a name="line.829"></a>
+<span class="sourceLineNo">830</span> return file.getPath();<a name="line.830"></a>
+<span class="sourceLineNo">831</span> }<a name="line.831"></a>
+<span class="sourceLineNo">832</span> }<a name="line.832"></a>
+<span class="sourceLineNo">833</span>}<a name="line.833"></a>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html b/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html
index 3392220..3a56a19 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html
@@ -25,577 +25,579 @@
<span class="sourceLineNo">017</span> */<a name="line.17"></a>
<span class="sourceLineNo">018</span>package org.apache.hadoop.hbase.master.assignment;<a name="line.18"></a>
<span class="sourceLineNo">019</span><a name="line.19"></a>
-<span class="sourceLineNo">020</span>import edu.umd.cs.findbugs.annotations.Nullable;<a name="line.20"></a>
-<span class="sourceLineNo">021</span>import java.io.IOException;<a name="line.21"></a>
-<span class="sourceLineNo">022</span>import org.apache.hadoop.hbase.HBaseIOException;<a name="line.22"></a>
-<span class="sourceLineNo">023</span>import org.apache.hadoop.hbase.ServerName;<a name="line.23"></a>
-<span class="sourceLineNo">024</span>import org.apache.hadoop.hbase.TableName;<a name="line.24"></a>
-<span class="sourceLineNo">025</span>import org.apache.hadoop.hbase.client.RegionInfo;<a name="line.25"></a>
-<span class="sourceLineNo">026</span>import org.apache.hadoop.hbase.client.RegionReplicaUtil;<a name="line.26"></a>
-<span class="sourceLineNo">027</span>import org.apache.hadoop.hbase.client.RetriesExhaustedException;<a name="line.27"></a>
-<span class="sourceLineNo">028</span>import org.apache.hadoop.hbase.master.MetricsAssignmentManager;<a name="line.28"></a>
-<span class="sourceLineNo">029</span>import org.apache.hadoop.hbase.master.RegionState.State;<a name="line.29"></a>
-<span class="sourceLineNo">030</span>import org.apache.hadoop.hbase.master.procedure.AbstractStateMachineRegionProcedure;<a name="line.30"></a>
-<span class="sourceLineNo">031</span>import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;<a name="line.31"></a>
-<span class="sourceLineNo">032</span>import org.apache.hadoop.hbase.master.procedure.ServerCrashProcedure;<a name="line.32"></a>
-<span class="sourceLineNo">033</span>import org.apache.hadoop.hbase.procedure2.Procedure;<a name="line.33"></a>
-<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.procedure2.ProcedureMetrics;<a name="line.34"></a>
-<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer;<a name="line.35"></a>
-<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.procedure2.ProcedureSuspendedException;<a name="line.36"></a>
-<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.procedure2.ProcedureUtil;<a name="line.37"></a>
-<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.procedure2.ProcedureYieldException;<a name="line.38"></a>
-<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.util.RetryCounter;<a name="line.39"></a>
-<span class="sourceLineNo">040</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.40"></a>
-<span class="sourceLineNo">041</span>import org.slf4j.Logger;<a name="line.41"></a>
-<span class="sourceLineNo">042</span>import org.slf4j.LoggerFactory;<a name="line.42"></a>
-<span class="sourceLineNo">043</span><a name="line.43"></a>
-<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.44"></a>
-<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState;<a name="line.45"></a>
-<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionStateData;<a name="line.46"></a>
-<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionTransitionType;<a name="line.47"></a>
-<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos;<a name="line.48"></a>
-<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionStateTransition.TransitionCode;<a name="line.49"></a>
-<span class="sourceLineNo">050</span><a name="line.50"></a>
-<span class="sourceLineNo">051</span>/**<a name="line.51"></a>
-<span class="sourceLineNo">052</span> * The procedure to deal with the state transition of a region. A region with a TRSP in place is<a name="line.52"></a>
-<span class="sourceLineNo">053</span> * called RIT, i.e, RegionInTransition.<a name="line.53"></a>
-<span class="sourceLineNo">054</span> * <p/><a name="line.54"></a>
-<span class="sourceLineNo">055</span> * It can be used to assign/unassign/reopen/move a region, and for<a name="line.55"></a>
-<span class="sourceLineNo">056</span> * {@link #unassign(MasterProcedureEnv, RegionInfo)} and<a name="line.56"></a>
-<span class="sourceLineNo">057</span> * {@link #reopen(MasterProcedureEnv, RegionInfo)}, you do not need to specify a target server, and<a name="line.57"></a>
-<span class="sourceLineNo">058</span> * for {@link #assign(MasterProcedureEnv, RegionInfo, ServerName)} and<a name="line.58"></a>
-<span class="sourceLineNo">059</span> * {@link #move(MasterProcedureEnv, RegionInfo, ServerName)}, if you want to you can provide a<a name="line.59"></a>
-<span class="sourceLineNo">060</span> * target server. And for {@link #move(MasterProcedureEnv, RegionInfo, ServerName)}, if you do not<a name="line.60"></a>
-<span class="sourceLineNo">061</span> * specify a targetServer, we will select one randomly.<a name="line.61"></a>
-<span class="sourceLineNo">062</span> * <p/><a name="line.62"></a>
-<span class="sourceLineNo">063</span> * <p/><a name="line.63"></a>
-<span class="sourceLineNo">064</span> * The typical state transition for assigning a region is:<a name="line.64"></a>
-<span class="sourceLineNo">065</span> *<a name="line.65"></a>
-<span class="sourceLineNo">066</span> * <pre><a name="line.66"></a>
-<span class="sourceLineNo">067</span> * GET_ASSIGN_CANDIDATE ------> OPEN -----> CONFIRM_OPENED<a name="line.67"></a>
-<span class="sourceLineNo">068</span> * </pre><a name="line.68"></a>
-<span class="sourceLineNo">069</span> *<a name="line.69"></a>
-<span class="sourceLineNo">070</span> * Notice that, if there are failures we may go back to the {@code GET_ASSIGN_CANDIDATE} state to<a name="line.70"></a>
-<span class="sourceLineNo">071</span> * try again.<a name="line.71"></a>
-<span class="sourceLineNo">072</span> * <p/><a name="line.72"></a>
-<span class="sourceLineNo">073</span> * The typical state transition for unassigning a region is:<a name="line.73"></a>
-<span class="sourceLineNo">074</span> *<a name="line.74"></a>
-<span class="sourceLineNo">075</span> * <pre><a name="line.75"></a>
-<span class="sourceLineNo">076</span> * CLOSE -----> CONFIRM_CLOSED<a name="line.76"></a>
-<span class="sourceLineNo">077</span> * </pre><a name="line.77"></a>
-<span class="sourceLineNo">078</span> *<a name="line.78"></a>
-<span class="sourceLineNo">079</span> * Here things go a bit different, if there are failures, especially that if there is a server<a name="line.79"></a>
-<span class="sourceLineNo">080</span> * crash, we will go to the {@code GET_ASSIGN_CANDIDATE} state to bring the region online first, and<a name="line.80"></a>
-<span class="sourceLineNo">081</span> * then go through the normal way to unassign it.<a name="line.81"></a>
-<span class="sourceLineNo">082</span> * <p/><a name="line.82"></a>
-<span class="sourceLineNo">083</span> * The typical state transition for reopening/moving a region is:<a name="line.83"></a>
-<span class="sourceLineNo">084</span> *<a name="line.84"></a>
-<span class="sourceLineNo">085</span> * <pre><a name="line.85"></a>
-<span class="sourceLineNo">086</span> * CLOSE -----> CONFIRM_CLOSED -----> GET_ASSIGN_CANDIDATE ------> OPEN -----> CONFIRM_OPENED<a name="line.86"></a>
-<span class="sourceLineNo">087</span> * </pre><a name="line.87"></a>
-<span class="sourceLineNo">088</span> *<a name="line.88"></a>
-<span class="sourceLineNo">089</span> * The retry logic is the same with the above assign/unassign.<a name="line.89"></a>
-<span class="sourceLineNo">090</span> * <p/><a name="line.90"></a>
-<span class="sourceLineNo">091</span> * Notice that, although we allow specify a target server, it just acts as a candidate, we do not<a name="line.91"></a>
-<span class="sourceLineNo">092</span> * guarantee that the region will finally be on the target server. If this is important for you, you<a name="line.92"></a>
-<span class="sourceLineNo">093</span> * should check whether the region is on the target server after the procedure is finished.<a name="line.93"></a>
-<span class="sourceLineNo">094</span> * <p/><a name="line.94"></a>
-<span class="sourceLineNo">095</span> * When you want to schedule a TRSP, please check whether there is still one for this region, and<a name="line.95"></a>
-<span class="sourceLineNo">096</span> * the check should be under the RegionStateNode lock. We will remove the TRSP from a<a name="line.96"></a>
-<span class="sourceLineNo">097</span> * RegionStateNode when we are done, see the code in {@code reportTransition} method below. There<a name="line.97"></a>
-<span class="sourceLineNo">098</span> * could be at most one TRSP for a give region.<a name="line.98"></a>
-<span class="sourceLineNo">099</span> */<a name="line.99"></a>
-<span class="sourceLineNo">100</span>@InterfaceAudience.Private<a name="line.100"></a>
-<span class="sourceLineNo">101</span>public class TransitRegionStateProcedure<a name="line.101"></a>
-<span class="sourceLineNo">102</span> extends AbstractStateMachineRegionProcedure<RegionStateTransitionState> {<a name="line.102"></a>
-<span class="sourceLineNo">103</span><a name="line.103"></a>
-<span class="sourceLineNo">104</span> private static final Logger LOG = LoggerFactory.getLogger(TransitRegionStateProcedure.class);<a name="line.104"></a>
+<span class="sourceLineNo">020</span>import static org.apache.hadoop.hbase.master.LoadBalancer.BOGUS_SERVER_NAME;<a name="line.20"></a>
+<span class="sourceLineNo">021</span><a name="line.21"></a>
+<span class="sourceLineNo">022</span>import edu.umd.cs.findbugs.annotations.Nullable;<a name="line.22"></a>
+<span class="sourceLineNo">023</span>import java.io.IOException;<a name="line.23"></a>
+<span class="sourceLineNo">024</span>import org.apache.hadoop.hbase.HBaseIOException;<a name="line.24"></a>
+<span class="sourceLineNo">025</span>import org.apache.hadoop.hbase.ServerName;<a name="line.25"></a>
+<span class="sourceLineNo">026</span>import org.apache.hadoop.hbase.TableName;<a name="line.26"></a>
+<span class="sourceLineNo">027</span>import org.apache.hadoop.hbase.client.RegionInfo;<a name="line.27"></a>
+<span class="sourceLineNo">028</span>import org.apache.hadoop.hbase.client.RegionReplicaUtil;<a name="line.28"></a>
+<span class="sourceLineNo">029</span>import org.apache.hadoop.hbase.client.RetriesExhaustedException;<a name="line.29"></a>
+<span class="sourceLineNo">030</span>import org.apache.hadoop.hbase.master.MetricsAssignmentManager;<a name="line.30"></a>
+<span class="sourceLineNo">031</span>import org.apache.hadoop.hbase.master.RegionState.State;<a name="line.31"></a>
+<span class="sourceLineNo">032</span>import org.apache.hadoop.hbase.master.procedure.AbstractStateMachineRegionProcedure;<a name="line.32"></a>
+<span class="sourceLineNo">033</span>import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;<a name="line.33"></a>
+<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.master.procedure.ServerCrashProcedure;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.procedure2.Procedure;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.procedure2.ProcedureMetrics;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.procedure2.ProcedureSuspendedException;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.procedure2.ProcedureUtil;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.procedure2.ProcedureYieldException;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.util.RetryCounter;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.slf4j.Logger;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.slf4j.LoggerFactory;<a name="line.44"></a>
+<span class="sourceLineNo">045</span><a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionStateData;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionTransitionType;<a name="line.49"></a>
+<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos;<a name="line.50"></a>
+<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionStateTransition.TransitionCode;<a name="line.51"></a>
+<span class="sourceLineNo">052</span><a name="line.52"></a>
+<span class="sourceLineNo">053</span>/**<a name="line.53"></a>
+<span class="sourceLineNo">054</span> * The procedure to deal with the state transition of a region. A region with a TRSP in place is<a name="line.54"></a>
+<span class="sourceLineNo">055</span> * called RIT, i.e, RegionInTransition.<a name="line.55"></a>
+<span class="sourceLineNo">056</span> * <p/><a name="line.56"></a>
+<span class="sourceLineNo">057</span> * It can be used to assign/unassign/reopen/move a region, and for<a name="line.57"></a>
+<span class="sourceLineNo">058</span> * {@link #unassign(MasterProcedureEnv, RegionInfo)} and<a name="line.58"></a>
+<span class="sourceLineNo">059</span> * {@link #reopen(MasterProcedureEnv, RegionInfo)}, you do not need to specify a target server, and<a name="line.59"></a>
+<span class="sourceLineNo">060</span> * for {@link #assign(MasterProcedureEnv, RegionInfo, ServerName)} and<a name="line.60"></a>
+<span class="sourceLineNo">061</span> * {@link #move(MasterProcedureEnv, RegionInfo, ServerName)}, if you want to you can provide a<a name="line.61"></a>
+<span class="sourceLineNo">062</span> * target server. And for {@link #move(MasterProcedureEnv, RegionInfo, ServerName)}, if you do not<a name="line.62"></a>
+<span class="sourceLineNo">063</span> * specify a targetServer, we will select one randomly.<a name="line.63"></a>
+<span class="sourceLineNo">064</span> * <p/><a name="line.64"></a>
+<span class="sourceLineNo">065</span> * <p/><a name="line.65"></a>
+<span class="sourceLineNo">066</span> * The typical state transition for assigning a region is:<a name="line.66"></a>
+<span class="sourceLineNo">067</span> *<a name="line.67"></a>
+<span class="sourceLineNo">068</span> * <pre><a name="line.68"></a>
+<span class="sourceLineNo">069</span> * GET_ASSIGN_CANDIDATE ------> OPEN -----> CONFIRM_OPENED<a name="line.69"></a>
+<span class="sourceLineNo">070</span> * </pre><a name="line.70"></a>
+<span class="sourceLineNo">071</span> *<a name="line.71"></a>
+<span class="sourceLineNo">072</span> * Notice that, if there are failures we may go back to the {@code GET_ASSIGN_CANDIDATE} state to<a name="line.72"></a>
+<span class="sourceLineNo">073</span> * try again.<a name="line.73"></a>
+<span class="sourceLineNo">074</span> * <p/><a name="line.74"></a>
+<span class="sourceLineNo">075</span> * The typical state transition for unassigning a region is:<a name="line.75"></a>
+<span class="sourceLineNo">076</span> *<a name="line.76"></a>
+<span class="sourceLineNo">077</span> * <pre><a name="line.77"></a>
+<span class="sourceLineNo">078</span> * CLOSE -----> CONFIRM_CLOSED<a name="line.78"></a>
+<span class="sourceLineNo">079</span> * </pre><a name="line.79"></a>
+<span class="sourceLineNo">080</span> *<a name="line.80"></a>
+<span class="sourceLineNo">081</span> * Here things go a bit different, if there are failures, especially that if there is a server<a name="line.81"></a>
+<span class="sourceLineNo">082</span> * crash, we will go to the {@code GET_ASSIGN_CANDIDATE} state to bring the region online first, and<a name="line.82"></a>
+<span class="sourceLineNo">083</span> * then go through the normal way to unassign it.<a name="line.83"></a>
+<span class="sourceLineNo">084</span> * <p/><a name="line.84"></a>
+<span class="sourceLineNo">085</span> * The typical state transition for reopening/moving a region is:<a name="line.85"></a>
+<span class="sourceLineNo">086</span> *<a name="line.86"></a>
+<span class="sourceLineNo">087</span> * <pre><a name="line.87"></a>
+<span class="sourceLineNo">088</span> * CLOSE -----> CONFIRM_CLOSED -----> GET_ASSIGN_CANDIDATE ------> OPEN -----> CONFIRM_OPENED<a name="line.88"></a>
+<span class="sourceLineNo">089</span> * </pre><a name="line.89"></a>
+<span class="sourceLineNo">090</span> *<a name="line.90"></a>
+<span class="sourceLineNo">091</span> * The retry logic is the same with the above assign/unassign.<a name="line.91"></a>
+<span class="sourceLineNo">092</span> * <p/><a name="line.92"></a>
+<span class="sourceLineNo">093</span> * Notice that, although we allow specify a target server, it just acts as a candidate, we do not<a name="line.93"></a>
+<span class="sourceLineNo">094</span> * guarantee that the region will finally be on the target server. If this is important for you, you<a name="line.94"></a>
+<span class="sourceLineNo">095</span> * should check whether the region is on the target server after the procedure is finished.<a name="line.95"></a>
+<span class="sourceLineNo">096</span> * <p/><a name="line.96"></a>
+<span class="sourceLineNo">097</span> * When you want to schedule a TRSP, please check whether there is still one for this region, and<a name="line.97"></a>
+<span class="sourceLineNo">098</span> * the check should be under the RegionStateNode lock. We will remove the TRSP from a<a name="line.98"></a>
+<span class="sourceLineNo">099</span> * RegionStateNode when we are done, see the code in {@code reportTransition} method below. There<a name="line.99"></a>
+<span class="sourceLineNo">100</span> * could be at most one TRSP for a give region.<a name="line.100"></a>
+<span class="sourceLineNo">101</span> */<a name="line.101"></a>
+<span class="sourceLineNo">102</span>@InterfaceAudience.Private<a name="line.102"></a>
+<span class="sourceLineNo">103</span>public class TransitRegionStateProcedure<a name="line.103"></a>
+<span class="sourceLineNo">104</span> extends AbstractStateMachineRegionProcedure<RegionStateTransitionState> {<a name="line.104"></a>
<span class="sourceLineNo">105</span><a name="line.105"></a>
-<span class="sourceLineNo">106</span> private TransitionType type;<a name="line.106"></a>
+<span class="sourceLineNo">106</span> private static final Logger LOG = LoggerFactory.getLogger(TransitRegionStateProcedure.class);<a name="line.106"></a>
<span class="sourceLineNo">107</span><a name="line.107"></a>
-<span class="sourceLineNo">108</span> private RegionStateTransitionState initialState;<a name="line.108"></a>
+<span class="sourceLineNo">108</span> private TransitionType type;<a name="line.108"></a>
<span class="sourceLineNo">109</span><a name="line.109"></a>
-<span class="sourceLineNo">110</span> private RegionStateTransitionState lastState;<a name="line.110"></a>
+<span class="sourceLineNo">110</span> private RegionStateTransitionState initialState;<a name="line.110"></a>
<span class="sourceLineNo">111</span><a name="line.111"></a>
-<span class="sourceLineNo">112</span> // the candidate where we want to assign the region to.<a name="line.112"></a>
-<span class="sourceLineNo">113</span> private ServerName assignCandidate;<a name="line.113"></a>
-<span class="sourceLineNo">114</span><a name="line.114"></a>
-<span class="sourceLineNo">115</span> private boolean forceNewPlan;<a name="line.115"></a>
+<span class="sourceLineNo">112</span> private RegionStateTransitionState lastState;<a name="line.112"></a>
+<span class="sourceLineNo">113</span><a name="line.113"></a>
+<span class="sourceLineNo">114</span> // the candidate where we want to assign the region to.<a name="line.114"></a>
+<span class="sourceLineNo">115</span> private ServerName assignCandidate;<a name="line.115"></a>
<span class="sourceLineNo">116</span><a name="line.116"></a>
-<span class="sourceLineNo">117</span> private RetryCounter retryCounter;<a name="line.117"></a>
+<span class="sourceLineNo">117</span> private boolean forceNewPlan;<a name="line.117"></a>
<span class="sourceLineNo">118</span><a name="line.118"></a>
-<span class="sourceLineNo">119</span> private RegionRemoteProcedureBase remoteProc;<a name="line.119"></a>
+<span class="sourceLineNo">119</span> private RetryCounter retryCounter;<a name="line.119"></a>
<span class="sourceLineNo">120</span><a name="line.120"></a>
-<span class="sourceLineNo">121</span> public TransitRegionStateProcedure() {<a name="line.121"></a>
-<span class="sourceLineNo">122</span> }<a name="line.122"></a>
-<span class="sourceLineNo">123</span><a name="line.123"></a>
-<span class="sourceLineNo">124</span> private void setInitialAndLastState() {<a name="line.124"></a>
-<span class="sourceLineNo">125</span> switch (type) {<a name="line.125"></a>
-<span class="sourceLineNo">126</span> case ASSIGN:<a name="line.126"></a>
-<span class="sourceLineNo">127</span> initialState = RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE;<a name="line.127"></a>
-<span class="sourceLineNo">128</span> lastState = RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED;<a name="line.128"></a>
-<span class="sourceLineNo">129</span> break;<a name="line.129"></a>
-<span class="sourceLineNo">130</span> case UNASSIGN:<a name="line.130"></a>
-<span class="sourceLineNo">131</span> initialState = RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE;<a name="line.131"></a>
-<span class="sourceLineNo">132</span> lastState = RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED;<a name="line.132"></a>
-<span class="sourceLineNo">133</span> break;<a name="line.133"></a>
-<span class="sourceLineNo">134</span> case MOVE:<a name="line.134"></a>
-<span class="sourceLineNo">135</span> case REOPEN:<a name="line.135"></a>
-<span class="sourceLineNo">136</span> initialState = RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE;<a name="line.136"></a>
-<span class="sourceLineNo">137</span> lastState = RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED;<a name="line.137"></a>
-<span class="sourceLineNo">138</span> break;<a name="line.138"></a>
-<span class="sourceLineNo">139</span> default:<a name="line.139"></a>
-<span class="sourceLineNo">140</span> throw new IllegalArgumentException("Unknown TransitionType: " + type);<a name="line.140"></a>
-<span class="sourceLineNo">141</span> }<a name="line.141"></a>
-<span class="sourceLineNo">142</span> }<a name="line.142"></a>
-<span class="sourceLineNo">143</span><a name="line.143"></a>
-<span class="sourceLineNo">144</span> protected TransitRegionStateProcedure(MasterProcedureEnv env, RegionInfo hri,<a name="line.144"></a>
-<span class="sourceLineNo">145</span> ServerName assignCandidate, boolean forceNewPlan, TransitionType type) {<a name="line.145"></a>
-<span class="sourceLineNo">146</span> super(env, hri);<a name="line.146"></a>
-<span class="sourceLineNo">147</span> this.assignCandidate = assignCandidate;<a name="line.147"></a>
-<span class="sourceLineNo">148</span> this.forceNewPlan = forceNewPlan;<a name="line.148"></a>
-<span class="sourceLineNo">149</span> this.type = type;<a name="line.149"></a>
-<span class="sourceLineNo">150</span> setInitialAndLastState();<a name="line.150"></a>
-<span class="sourceLineNo">151</span><a name="line.151"></a>
-<span class="sourceLineNo">152</span> // when do reopen TRSP, let the rs know the targetServer so it can keep some info on close<a name="line.152"></a>
-<span class="sourceLineNo">153</span> if (type == TransitionType.REOPEN) {<a name="line.153"></a>
-<span class="sourceLineNo">154</span> this.assignCandidate = getRegionStateNode(env).getRegionLocation();<a name="line.154"></a>
-<span class="sourceLineNo">155</span> }<a name="line.155"></a>
-<span class="sourceLineNo">156</span> }<a name="line.156"></a>
-<span class="sourceLineNo">157</span><a name="line.157"></a>
-<span class="sourceLineNo">158</span> @Override<a name="line.158"></a>
-<span class="sourceLineNo">159</span> public TableOperationType getTableOperationType() {<a name="line.159"></a>
-<span class="sourceLineNo">160</span> // TODO: maybe we should make another type here, REGION_TRANSITION?<a name="line.160"></a>
-<span class="sourceLineNo">161</span> return TableOperationType.REGION_EDIT;<a name="line.161"></a>
-<span class="sourceLineNo">162</span> }<a name="line.162"></a>
-<span class="sourceLineNo">163</span><a name="line.163"></a>
-<span class="sourceLineNo">164</span> @Override<a name="line.164"></a>
-<span class="sourceLineNo">165</span> protected boolean waitInitialized(MasterProcedureEnv env) {<a name="line.165"></a>
-<span class="sourceLineNo">166</span> if (TableName.isMetaTableName(getTableName())) {<a name="line.166"></a>
-<span class="sourceLineNo">167</span> return false;<a name="line.167"></a>
-<span class="sourceLineNo">168</span> }<a name="line.168"></a>
-<span class="sourceLineNo">169</span> // First we need meta to be loaded, and second, if meta is not online then we will likely to<a name="line.169"></a>
-<span class="sourceLineNo">170</span> // fail when updating meta so we wait until it is assigned.<a name="line.170"></a>
-<span class="sourceLineNo">171</span> AssignmentManager am = env.getAssignmentManager();<a name="line.171"></a>
-<span class="sourceLineNo">172</span> return am.waitMetaLoaded(this) || am.waitMetaAssigned(this, getRegion());<a name="line.172"></a>
-<span class="sourceLineNo">173</span> }<a name="line.173"></a>
-<span class="sourceLineNo">174</span><a name="line.174"></a>
-<span class="sourceLineNo">175</span> private void queueAssign(MasterProcedureEnv env, RegionStateNode regionNode)<a name="line.175"></a>
-<span class="sourceLineNo">176</span> throws ProcedureSuspendedException {<a name="line.176"></a>
-<span class="sourceLineNo">177</span> boolean retain = false;<a name="line.177"></a>
-<span class="sourceLineNo">178</span> if (forceNewPlan) {<a name="line.178"></a>
-<span class="sourceLineNo">179</span> // set the region location to null if forceNewPlan is true<a name="line.179"></a>
-<span class="sourceLineNo">180</span> regionNode.setRegionLocation(null);<a name="line.180"></a>
-<span class="sourceLineNo">181</span> } else {<a name="line.181"></a>
-<span class="sourceLineNo">182</span> if (assignCandidate != null) {<a name="line.182"></a>
-<span class="sourceLineNo">183</span> retain = assignCandidate.equals(regionNode.getLastHost());<a name="line.183"></a>
-<span class="sourceLineNo">184</span> regionNode.setRegionLocation(assignCandidate);<a name="line.184"></a>
-<span class="sourceLineNo">185</span> } else if (regionNode.getLastHost() != null) {<a name="line.185"></a>
-<span class="sourceLineNo">186</span> retain = true;<a name="line.186"></a>
-<span class="sourceLineNo">187</span> LOG.info("Setting lastHost as the region location {}", regionNode.getLastHost());<a name="line.187"></a>
-<span class="sourceLineNo">188</span> regionNode.setRegionLocation(regionNode.getLastHost());<a name="line.188"></a>
-<span class="sourceLineNo">189</span> }<a name="line.189"></a>
-<span class="sourceLineNo">190</span> }<a name="line.190"></a>
-<span class="sourceLineNo">191</span> LOG.info("Starting {}; {}; forceNewPlan={}, retain={}", this, regionNode.toShortString(),<a name="line.191"></a>
-<span class="sourceLineNo">192</span> forceNewPlan, retain);<a name="line.192"></a>
-<span class="sourceLineNo">193</span> env.getAssignmentManager().queueAssign(regionNode);<a name="line.193"></a>
-<span class="sourceLineNo">194</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_OPEN);<a name="line.194"></a>
-<span class="sourceLineNo">195</span> if (regionNode.getProcedureEvent().suspendIfNotReady(this)) {<a name="line.195"></a>
-<span class="sourceLineNo">196</span> throw new ProcedureSuspendedException();<a name="line.196"></a>
-<span class="sourceLineNo">197</span> }<a name="line.197"></a>
-<span class="sourceLineNo">198</span> }<a name="line.198"></a>
-<span class="sourceLineNo">199</span><a name="line.199"></a>
-<span class="sourceLineNo">200</span> private void openRegion(MasterProcedureEnv env, RegionStateNode regionNode) throws IOException {<a name="line.200"></a>
-<span class="sourceLineNo">201</span> ServerName loc = regionNode.getRegionLocation();<a name="line.201"></a>
-<span class="sourceLineNo">202</span> if (loc == null) {<a name="line.202"></a>
-<span class="sourceLineNo">203</span> LOG.warn("No location specified for {}, jump back to state {} to get one", getRegion(),<a name="line.203"></a>
-<span class="sourceLineNo">204</span> RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.204"></a>
-<span class="sourceLineNo">205</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.205"></a>
-<span class="sourceLineNo">206</span> return;<a name="line.206"></a>
-<span class="sourceLineNo">207</span> }<a name="line.207"></a>
-<span class="sourceLineNo">208</span> env.getAssignmentManager().regionOpening(regionNode);<a name="line.208"></a>
-<span class="sourceLineNo">209</span> addChildProcedure(new OpenRegionProcedure(this, getRegion(), loc));<a name="line.209"></a>
-<span class="sourceLineNo">210</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED);<a name="line.210"></a>
-<span class="sourceLineNo">211</span> }<a name="line.211"></a>
-<span class="sourceLineNo">212</span><a name="line.212"></a>
-<span class="sourceLineNo">213</span> private Flow confirmOpened(MasterProcedureEnv env, RegionStateNode regionNode)<a name="line.213"></a>
-<span class="sourceLineNo">214</span> throws IOException {<a name="line.214"></a>
-<span class="sourceLineNo">215</span> if (regionNode.isInState(State.OPEN)) {<a name="line.215"></a>
-<span class="sourceLineNo">216</span> retryCounter = null;<a name="line.216"></a>
-<span class="sourceLineNo">217</span> if (lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED) {<a name="line.217"></a>
-<span class="sourceLineNo">218</span> // we are the last state, finish<a name="line.218"></a>
-<span class="sourceLineNo">219</span> regionNode.unsetProcedure(this);<a name="line.219"></a>
-<span class="sourceLineNo">220</span> ServerCrashProcedure.updateProgress(env, getParentProcId());<a name="line.220"></a>
-<span class="sourceLineNo">221</span> return Flow.NO_MORE_STATE;<a name="line.221"></a>
-<span class="sourceLineNo">222</span> }<a name="line.222"></a>
-<span class="sourceLineNo">223</span> // It is possible that we arrive here but confirm opened is not the last state, for example,<a name="line.223"></a>
-<span class="sourceLineNo">224</span> // when merging or splitting a region, we unassign the region from a RS and the RS is crashed,<a name="line.224"></a>
-<span class="sourceLineNo">225</span> // then there will be recovered edits for this region, we'd better make the region online<a name="line.225"></a>
-<span class="sourceLineNo">226</span> // again and then unassign it, otherwise we have to fail the merge/split procedure as we may<a name="line.226"></a>
-<span class="sourceLineNo">227</span> // loss data.<a name="line.227"></a>
-<span class="sourceLineNo">228</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE);<a name="line.228"></a>
-<span class="sourceLineNo">229</span> return Flow.HAS_MORE_STATE;<a name="line.229"></a>
-<span class="sourceLineNo">230</span> }<a name="line.230"></a>
-<span class="sourceLineNo">231</span><a name="line.231"></a>
-<span class="sourceLineNo">232</span> int retries = env.getAssignmentManager().getRegionStates().addToFailedOpen(regionNode)<a name="line.232"></a>
-<span class="sourceLineNo">233</span> .incrementAndGetRetries();<a name="line.233"></a>
-<span class="sourceLineNo">234</span> int maxAttempts = env.getAssignmentManager().getAssignMaxAttempts();<a name="line.234"></a>
-<span class="sourceLineNo">235</span> LOG.info("Retry={} of max={}; {}; {}", retries, maxAttempts, this, regionNode.toShortString());<a name="line.235"></a>
-<span class="sourceLineNo">236</span><a name="line.236"></a>
-<span class="sourceLineNo">237</span> if (retries >= maxAttempts) {<a name="line.237"></a>
-<span class="sourceLineNo">238</span> env.getAssignmentManager().regionFailedOpen(regionNode, true);<a name="line.238"></a>
-<span class="sourceLineNo">239</span> setFailure(getClass().getSimpleName(), new RetriesExhaustedException(<a name="line.239"></a>
-<span class="sourceLineNo">240</span> "Max attempts " + env.getAssignmentManager().getAssignMaxAttempts() + " exceeded"));<a name="line.240"></a>
-<span class="sourceLineNo">241</span> regionNode.unsetProcedure(this);<a name="line.241"></a>
-<span class="sourceLineNo">242</span> return Flow.NO_MORE_STATE;<a name="line.242"></a>
-<span class="sourceLineNo">243</span> }<a name="line.243"></a>
-<span class="sourceLineNo">244</span><a name="line.244"></a>
-<span class="sourceLineNo">245</span> env.getAssignmentManager().regionFailedOpen(regionNode, false);<a name="line.245"></a>
-<span class="sourceLineNo">246</span> // we failed to assign the region, force a new plan<a name="line.246"></a>
-<span class="sourceLineNo">247</span> forceNewPlan = true;<a name="line.247"></a>
-<span class="sourceLineNo">248</span> regionNode.setRegionLocation(null);<a name="line.248"></a>
-<span class="sourceLineNo">249</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.249"></a>
-<span class="sourceLineNo">250</span><a name="line.250"></a>
-<span class="sourceLineNo">251</span> if (retries > env.getAssignmentManager().getAssignRetryImmediatelyMaxAttempts()) {<a name="line.251"></a>
-<span class="sourceLineNo">252</span> // Throw exception to backoff and retry when failed open too many times<a name="line.252"></a>
-<span class="sourceLineNo">253</span> throw new HBaseIOException("Failed confirm OPEN of " + regionNode +<a name="line.253"></a>
-<span class="sourceLineNo">254</span> " (remote log may yield more detail on why).");<a name="line.254"></a>
-<span class="sourceLineNo">255</span> } else {<a name="line.255"></a>
-<span class="sourceLineNo">256</span> // Here we do not throw exception because we want to the region to be online ASAP<a name="line.256"></a>
-<span class="sourceLineNo">257</span> return Flow.HAS_MORE_STATE;<a name="line.257"></a>
-<span class="sourceLineNo">258</span> }<a name="line.258"></a>
-<span class="sourceLineNo">259</span> }<a name="line.259"></a>
-<span class="sourceLineNo">260</span><a name="line.260"></a>
-<span class="sourceLineNo">261</span> private void closeRegion(MasterProcedureEnv env, RegionStateNode regionNode) throws IOException {<a name="line.261"></a>
-<span class="sourceLineNo">262</span> if (regionNode.isInState(State.OPEN, State.CLOSING, State.MERGING, State.SPLITTING)) {<a name="line.262"></a>
-<span class="sourceLineNo">263</span> // this is the normal case<a name="line.263"></a>
-<span class="sourceLineNo">264</span> env.getAssignmentManager().regionClosing(regionNode);<a name="line.264"></a>
-<span class="sourceLineNo">265</span> addChildProcedure(new CloseRegionProcedure(this, getRegion(), regionNode.getRegionLocation(),<a name="line.265"></a>
-<span class="sourceLineNo">266</span> assignCandidate));<a name="line.266"></a>
-<span class="sourceLineNo">267</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED);<a name="line.267"></a>
-<span class="sourceLineNo">268</span> } else {<a name="line.268"></a>
-<span class="sourceLineNo">269</span> forceNewPlan = true;<a name="line.269"></a>
-<span class="sourceLineNo">270</span> regionNode.setRegionLocation(null);<a name="line.270"></a>
-<span class="sourceLineNo">271</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.271"></a>
-<span class="sourceLineNo">272</span> }<a name="line.272"></a>
-<span class="sourceLineNo">273</span> }<a name="line.273"></a>
-<span class="sourceLineNo">274</span><a name="line.274"></a>
-<span class="sourceLineNo">275</span> private Flow confirmClosed(MasterProcedureEnv env, RegionStateNode regionNode)<a name="line.275"></a>
-<span class="sourceLineNo">276</span> throws IOException {<a name="line.276"></a>
-<span class="sourceLineNo">277</span> if (regionNode.isInState(State.CLOSED)) {<a name="line.277"></a>
-<span class="sourceLineNo">278</span> retryCounter = null;<a name="line.278"></a>
-<span class="sourceLineNo">279</span> if (lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED) {<a name="line.279"></a>
-<span class="sourceLineNo">280</span> // we are the last state, finish<a name="line.280"></a>
-<span class="sourceLineNo">281</span> regionNode.unsetProcedure(this);<a name="line.281"></a>
-<span class="sourceLineNo">282</span> return Flow.NO_MORE_STATE;<a name="line.282"></a>
-<span class="sourceLineNo">283</span> }<a name="line.283"></a>
-<span class="sourceLineNo">284</span> // This means we need to open the region again, should be a move or reopen<a name="line.284"></a>
-<span class="sourceLineNo">285</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.285"></a>
-<span class="sourceLineNo">286</span> return Flow.HAS_MORE_STATE;<a name="line.286"></a>
-<span class="sourceLineNo">287</span> }<a name="line.287"></a>
-<span class="sourceLineNo">288</span> if (regionNode.isInState(State.CLOSING)) {<a name="line.288"></a>
-<span class="sourceLineNo">289</span> // This is possible, think the target RS crashes and restarts immediately, the close region<a name="line.289"></a>
-<span class="sourceLineNo">290</span> // operation will return a NotServingRegionException soon, we can only recover after SCP takes<a name="line.290"></a>
-<span class="sourceLineNo">291</span> // care of this RS. So here we throw an IOException to let upper layer to retry with backoff.<a name="line.291"></a>
-<span class="sourceLineNo">292</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE);<a name="line.292"></a>
-<span class="sourceLineNo">293</span> throw new HBaseIOException("Failed to close region");<a name="line.293"></a>
-<span class="sourceLineNo">294</span> }<a name="line.294"></a>
-<span class="sourceLineNo">295</span> // abnormally closed, need to reopen it, no matter what is the last state, see the comment in<a name="line.295"></a>
-<span class="sourceLineNo">296</span> // confirmOpened for more details that why we need to reopen the region first even if we just<a name="line.296"></a>
-<span class="sourceLineNo">297</span> // want to close it.<a name="line.297"></a>
-<span class="sourceLineNo">298</span> // The only exception is for non-default replica, where we do not need to deal with recovered<a name="line.298"></a>
-<span class="sourceLineNo">299</span> // edits. Notice that the region will remain in ABNORMALLY_CLOSED state, the upper layer need to<a name="line.299"></a>
-<span class="sourceLineNo">300</span> // deal with this state. For non-default replica, this is usually the same with CLOSED.<a name="line.300"></a>
-<span class="sourceLineNo">301</span> assert regionNode.isInState(State.ABNORMALLY_CLOSED);<a name="line.301"></a>
-<span class="sourceLineNo">302</span> if (!RegionReplicaUtil.isDefaultReplica(getRegion()) &&<a name="line.302"></a>
-<span class="sourceLineNo">303</span> lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED) {<a name="line.303"></a>
-<span class="sourceLineNo">304</span> regionNode.unsetProcedure(this);<a name="line.304"></a>
-<span class="sourceLineNo">305</span> return Flow.NO_MORE_STATE;<a name="line.305"></a>
-<span class="sourceLineNo">306</span> }<a name="line.306"></a>
-<span class="sourceLineNo">307</span> retryCounter = null;<a name="line.307"></a>
-<span class="sourceLineNo">308</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.308"></a>
-<span class="sourceLineNo">309</span> return Flow.HAS_MORE_STATE;<a name="line.309"></a>
-<span class="sourceLineNo">310</span> }<a name="line.310"></a>
-<span class="sourceLineNo">311</span><a name="line.311"></a>
-<span class="sourceLineNo">312</span> // Override to lock RegionStateNode<a name="line.312"></a>
-<span class="sourceLineNo">313</span> @SuppressWarnings("rawtypes")<a name="line.313"></a>
-<span class="sourceLineNo">314</span> @Override<a name="line.314"></a>
-<span class="sourceLineNo">315</span> protected Procedure[] execute(MasterProcedureEnv env)<a name="line.315"></a>
-<span class="sourceLineNo">316</span> throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException {<a name="line.316"></a>
-<span class="sourceLineNo">317</span> RegionStateNode regionNode =<a name="line.317"></a>
-<span class="sourceLineNo">318</span> env.getAssignmentManager().getRegionStates().getOrCreateRegionStateNode(getRegion());<a name="line.318"></a>
-<span class="sourceLineNo">319</span> regionNode.lock();<a name="line.319"></a>
-<span class="sourceLineNo">320</span> try {<a name="line.320"></a>
-<span class="sourceLineNo">321</span> return super.execute(env);<a name="line.321"></a>
-<span class="sourceLineNo">322</span> } finally {<a name="line.322"></a>
-<span class="sourceLineNo">323</span> regionNode.unlock();<a name="line.323"></a>
-<span class="sourceLineNo">324</span> }<a name="line.324"></a>
-<span class="sourceLineNo">325</span> }<a name="line.325"></a>
-<span class="sourceLineNo">326</span><a name="line.326"></a>
-<span class="sourceLineNo">327</span> private RegionStateNode getRegionStateNode(MasterProcedureEnv env) {<a name="line.327"></a>
-<span class="sourceLineNo">328</span> return env.getAssignmentManager().getRegionStates().getOrCreateRegionStateNode(getRegion());<a name="line.328"></a>
-<span class="sourceLineNo">329</span> }<a name="line.329"></a>
-<span class="sourceLineNo">330</span><a name="line.330"></a>
-<span class="sourceLineNo">331</span> @Override<a name="line.331"></a>
-<span class="sourceLineNo">332</span> protected Flow executeFromState(MasterProcedureEnv env, RegionStateTransitionState state)<a name="line.332"></a>
-<span class="sourceLineNo">333</span> throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException {<a name="line.333"></a>
-<span class="sourceLineNo">334</span> RegionStateNode regionNode = getRegionStateNode(env);<a name="line.334"></a>
-<span class="sourceLineNo">335</span> try {<a name="line.335"></a>
-<span class="sourceLineNo">336</span> switch (state) {<a name="line.336"></a>
-<span class="sourceLineNo">337</span> case REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE:<a name="line.337"></a>
-<span class="sourceLineNo">338</span> // Need to do some sanity check for replica region, if the region does not exist at<a name="line.338"></a>
-<span class="sourceLineNo">339</span> // master, do not try to assign the replica region, log error and return.<a name="line.339"></a>
-<span class="sourceLineNo">340</span> if (!RegionReplicaUtil.isDefaultReplica(regionNode.getRegionInfo())) {<a name="line.340"></a>
-<span class="sourceLineNo">341</span> RegionInfo defaultRI =<a name="line.341"></a>
-<span class="sourceLineNo">342</span> RegionReplicaUtil.getRegionInfoForDefaultReplica(regionNode.getRegionInfo());<a name="line.342"></a>
-<span class="sourceLineNo">343</span> if (env.getMasterServices().getAssignmentManager().getRegionStates().<a name="line.343"></a>
-<span class="sourceLineNo">344</span> getRegionStateNode(defaultRI) == null) {<a name="line.344"></a>
-<span class="sourceLineNo">345</span> LOG.error(<a name="line.345"></a>
-<span class="sourceLineNo">346</span> "Cannot assign replica region {} because its primary region {} does not exist.",<a name="line.346"></a>
-<span class="sourceLineNo">347</span> regionNode.getRegionInfo(), defaultRI);<a name="line.347"></a>
-<span class="sourceLineNo">348</span> regionNode.unsetProcedure(this);<a name="line.348"></a>
-<span class="sourceLineNo">349</span> return Flow.NO_MORE_STATE;<a name="line.349"></a>
-<span class="sourceLineNo">350</span> }<a name="line.350"></a>
-<span class="sourceLineNo">351</span> }<a name="line.351"></a>
-<span class="sourceLineNo">352</span> queueAssign(env, regionNode);<a name="line.352"></a>
-<span class="sourceLineNo">353</span> return Flow.HAS_MORE_STATE;<a name="line.353"></a>
-<span class="sourceLineNo">354</span> case REGION_STATE_TRANSITION_OPEN:<a name="line.354"></a>
-<span class="sourceLineNo">355</span> openRegion(env, regionNode);<a name="line.355"></a>
-<span class="sourceLineNo">356</span> return Flow.HAS_MORE_STATE;<a name="line.356"></a>
-<span class="sourceLineNo">357</span> case REGION_STATE_TRANSITION_CONFIRM_OPENED:<a name="line.357"></a>
-<span class="sourceLineNo">358</span> return confirmOpened(env, regionNode);<a name="line.358"></a>
-<span class="sourceLineNo">359</span> case REGION_STATE_TRANSITION_CLOSE:<a name="line.359"></a>
-<span class="sourceLineNo">360</span> closeRegion(env, regionNode);<a name="line.360"></a>
-<span class="sourceLineNo">361</span> return Flow.HAS_MORE_STATE;<a name="line.361"></a>
-<span class="sourceLineNo">362</span> case REGION_STATE_TRANSITION_CONFIRM_CLOSED:<a name="line.362"></a>
-<span class="sourceLineNo">363</span> return confirmClosed(env, regionNode);<a name="line.363"></a>
-<span class="sourceLineNo">364</span> default:<a name="line.364"></a>
-<span class="sourceLineNo">365</span> throw new UnsupportedOperationException("unhandled state=" + state);<a name="line.365"></a>
-<span class="sourceLineNo">366</span> }<a name="line.366"></a>
-<span class="sourceLineNo">367</span> } catch (IOException e) {<a name="line.367"></a>
-<span class="sourceLineNo">368</span> if (retryCounter == null) {<a name="line.368"></a>
-<span class="sourceLineNo">369</span> retryCounter = ProcedureUtil.createRetryCounter(env.getMasterConfiguration());<a name="line.369"></a>
-<span class="sourceLineNo">370</span> }<a name="line.370"></a>
-<span class="sourceLineNo">371</span> long backoff = retryCounter.getBackoffTimeAndIncrementAttempts();<a name="line.371"></a>
-<span class="sourceLineNo">372</span> LOG.warn(<a name="line.372"></a>
-<span class="sourceLineNo">373</span> "Failed transition, suspend {}secs {}; {}; waiting on rectified condition fixed " +<a name="line.373"></a>
-<span class="sourceLineNo">374</span> "by other Procedure or operator intervention",<a name="line.374"></a>
-<span class="sourceLineNo">375</span> backoff / 1000, this, regionNode.toShortString(), e);<a name="line.375"></a>
-<span class="sourceLineNo">376</span> setTimeout(Math.toIntExact(backoff));<a name="line.376"></a>
-<span class="sourceLineNo">377</span> setState(ProcedureProtos.ProcedureState.WAITING_TIMEOUT);<a name="line.377"></a>
-<span class="sourceLineNo">378</span> skipPersistence();<a name="line.378"></a>
-<span class="sourceLineNo">379</span> throw new ProcedureSuspendedException();<a name="line.379"></a>
-<span class="sourceLineNo">380</span> }<a name="line.380"></a>
-<span class="sourceLineNo">381</span> }<a name="line.381"></a>
-<span class="sourceLineNo">382</span><a name="line.382"></a>
-<span class="sourceLineNo">383</span> /**<a name="line.383"></a>
-<span class="sourceLineNo">384</span> * At end of timeout, wake ourselves up so we run again.<a name="line.384"></a>
-<span class="sourceLineNo">385</span> */<a name="line.385"></a>
-<span class="sourceLineNo">386</span> @Override<a name="line.386"></a>
-<span class="sourceLineNo">387</span> protected synchronized boolean setTimeoutFailure(MasterProcedureEnv env) {<a name="line.387"></a>
-<span class="sourceLineNo">388</span> setState(ProcedureProtos.ProcedureState.RUNNABLE);<a name="line.388"></a>
-<span class="sourceLineNo">389</span> env.getProcedureScheduler().addFront(this);<a name="line.389"></a>
-<span class="sourceLineNo">390</span> return false; // 'false' means that this procedure handled the timeout<a name="line.390"></a>
-<span class="sourceLineNo">391</span> }<a name="line.391"></a>
-<span class="sourceLineNo">392</span><a name="line.392"></a>
-<span class="sourceLineNo">393</span> // Should be called with RegionStateNode locked<a name="line.393"></a>
-<span class="sourceLineNo">394</span> public void reportTransition(MasterProcedureEnv env, RegionStateNode regionNode,<a name="line.394"></a>
-<span class="sourceLineNo">395</span> ServerName serverName, TransitionCode code, long seqId, long procId) throws IOException {<a name="line.395"></a>
-<span class="sourceLineNo">396</span> if (remoteProc == null) {<a name="line.396"></a>
-<span class="sourceLineNo">397</span> LOG.warn(<a name="line.397"></a>
-<span class="sourceLineNo">398</span> "There is no outstanding remote region procedure for {}, serverName={}, code={}," +<a name="line.398"></a>
-<span class="sourceLineNo">399</span> " seqId={}, proc={}, should be a retry, ignore",<a name="line.399"></a>
-<span class="sourceLineNo">400</span> regionNode, serverName, code, seqId, this);<a name="line.400"></a>
-<span class="sourceLineNo">401</span> return;<a name="line.401"></a>
-<span class="sourceLineNo">402</span> }<a name="line.402"></a>
-<span class="sourceLineNo">403</span> // The procId could be -1 if it is from an old region server, we need to deal with it so that we<a name="line.403"></a>
-<span class="sourceLineNo">404</span> // can do rolling upgraing.<a name="line.404"></a>
-<span class="sourceLineNo">405</span> if (procId >= 0 && remoteProc.getProcId() != procId) {<a name="line.405"></a>
-<span class="sourceLineNo">406</span> LOG.warn(<a name="line.406"></a>
-<span class="sourceLineNo">407</span> "The pid of remote region procedure for {} is {}, the reported pid={}, serverName={}," +<a name="line.407"></a>
-<span class="sourceLineNo">408</span> " code={}, seqId={}, proc={}, should be a retry, ignore",<a name="line.408"></a>
-<span class="sourceLineNo">409</span> regionNode, remoteProc.getProcId(), procId, serverName, code, seqId, this);<a name="line.409"></a>
-<span class="sourceLineNo">410</span> return;<a name="line.410"></a>
-<span class="sourceLineNo">411</span> }<a name="line.411"></a>
-<span class="sourceLineNo">412</span> remoteProc.reportTransition(env, regionNode, serverName, code, seqId);<a name="line.412"></a>
-<span class="sourceLineNo">413</span> }<a name="line.413"></a>
-<span class="sourceLineNo">414</span><a name="line.414"></a>
-<span class="sourceLineNo">415</span> // Should be called with RegionStateNode locked<a name="line.415"></a>
-<span class="sourceLineNo">416</span> public void serverCrashed(MasterProcedureEnv env, RegionStateNode regionNode,<a name="line.416"></a>
-<span class="sourceLineNo">417</span> ServerName serverName, boolean forceNewPlan) throws IOException {<a name="line.417"></a>
-<span class="sourceLineNo">418</span> this.forceNewPlan = forceNewPlan;<a name="line.418"></a>
-<span class="sourceLineNo">419</span> if (remoteProc != null) {<a name="line.419"></a>
-<span class="sourceLineNo">420</span> // this means we are waiting for the sub procedure, so wake it up<a name="line.420"></a>
-<span class="sourceLineNo">421</span> remoteProc.serverCrashed(env, regionNode, serverName);<a name="line.421"></a>
-<span class="sourceLineNo">422</span> } else {<a name="line.422"></a>
-<span class="sourceLineNo">423</span> // we are in RUNNING state, just update the region state, and we will process it later.<a name="line.423"></a>
-<span class="sourceLineNo">424</span> env.getAssignmentManager().regionClosedAbnormally(regionNode);<a name="line.424"></a>
-<span class="sourceLineNo">425</span> }<a name="line.425"></a>
-<span class="sourceLineNo">426</span> }<a name="line.426"></a>
-<span class="sourceLineNo">427</span><a name="line.427"></a>
-<span class="sourceLineNo">428</span> void attachRemoteProc(RegionRemoteProcedureBase proc) {<a name="line.428"></a>
-<span class="sourceLineNo">429</span> this.remoteProc = proc;<a name="line.429"></a>
-<span class="sourceLineNo">430</span> }<a name="line.430"></a>
-<span class="sourceLineNo">431</span><a name="line.431"></a>
-<span class="sourceLineNo">432</span> void unattachRemoteProc(RegionRemoteProcedureBase proc) {<a name="line.432"></a>
-<span class="sourceLineNo">433</span> assert this.remoteProc == proc;<a name="line.433"></a>
-<span class="sourceLineNo">434</span> this.remoteProc = null;<a name="line.434"></a>
-<span class="sourceLineNo">435</span> }<a name="line.435"></a>
-<span class="sourceLineNo">436</span><a name="line.436"></a>
-<span class="sourceLineNo">437</span> // will be called after we finish loading the meta entry for this region.<a name="line.437"></a>
-<span class="sourceLineNo">438</span> // used to change the state of the region node if we have a sub procedure, as we may not persist<a name="line.438"></a>
-<span class="sourceLineNo">439</span> // the state to meta yet. See the code in RegionRemoteProcedureBase.execute for more details.<a name="line.439"></a>
-<span class="sourceLineNo">440</span> void stateLoaded(AssignmentManager am, RegionStateNode regionNode) {<a name="line.440"></a>
-<span class="sourceLineNo">441</span> if (remoteProc != null) {<a name="line.441"></a>
-<span class="sourceLineNo">442</span> remoteProc.stateLoaded(am, regionNode);<a name="line.442"></a>
-<span class="sourceLineNo">443</span> }<a name="line.443"></a>
-<span class="sourceLineNo">444</span> }<a name="line.444"></a>
-<span class="sourceLineNo">445</span><a name="line.445"></a>
-<span class="sourceLineNo">446</span> @Override<a name="line.446"></a>
-<span class="sourceLineNo">447</span> protected void rollbackState(MasterProcedureEnv env, RegionStateTransitionState state)<a name="line.447"></a>
-<span class="sourceLineNo">448</span> throws IOException, InterruptedException {<a name="line.448"></a>
-<span class="sourceLineNo">449</span> // no rollback<a name="line.449"></a>
-<span class="sourceLineNo">450</span> throw new UnsupportedOperationException();<a name="line.450"></a>
-<span class="sourceLineNo">451</span> }<a name="line.451"></a>
-<span class="sourceLineNo">452</span><a name="line.452"></a>
-<span class="sourceLineNo">453</span> @Override<a name="line.453"></a>
-<span class="sourceLineNo">454</span> protected RegionStateTransitionState getState(int stateId) {<a name="line.454"></a>
-<span class="sourceLineNo">455</span> return RegionStateTransitionState.forNumber(stateId);<a name="line.455"></a>
-<span class="sourceLineNo">456</span> }<a name="line.456"></a>
-<span class="sourceLineNo">457</span><a name="line.457"></a>
-<span class="sourceLineNo">458</span> @Override<a name="line.458"></a>
-<span class="sourceLineNo">459</span> protected int getStateId(RegionStateTransitionState state) {<a name="line.459"></a>
-<span class="sourceLineNo">460</span> return state.getNumber();<a name="line.460"></a>
-<span class="sourceLineNo">461</span> }<a name="line.461"></a>
-<span class="sourceLineNo">462</span><a name="line.462"></a>
-<span class="sourceLineNo">463</span> @Override<a name="line.463"></a>
-<span class="sourceLineNo">464</span> protected RegionStateTransitionState getInitialState() {<a name="line.464"></a>
-<span class="sourceLineNo">465</span> return initialState;<a name="line.465"></a>
-<span class="sourceLineNo">466</span> }<a name="line.466"></a>
-<span class="sourceLineNo">467</span><a name="line.467"></a>
-<span class="sourceLineNo">468</span> private static TransitionType convert(RegionTransitionType type) {<a name="line.468"></a>
-<span class="sourceLineNo">469</span> switch (type) {<a name="line.469"></a>
-<span class="sourceLineNo">470</span> case ASSIGN:<a name="line.470"></a>
-<span class="sourceLineNo">471</span> return TransitionType.ASSIGN;<a name="line.471"></a>
-<span class="sourceLineNo">472</span> case UNASSIGN:<a name="line.472"></a>
-<span class="sourceLineNo">473</span> return TransitionType.UNASSIGN;<a name="line.473"></a>
-<span class="sourceLineNo">474</span> case MOVE:<a name="line.474"></a>
-<span class="sourceLineNo">475</span> return TransitionType.MOVE;<a name="line.475"></a>
-<span class="sourceLineNo">476</span> case REOPEN:<a name="line.476"></a>
-<span class="sourceLineNo">477</span> return TransitionType.REOPEN;<a name="line.477"></a>
-<span class="sourceLineNo">478</span> default:<a name="line.478"></a>
-<span class="sourceLineNo">479</span> throw new IllegalArgumentException("Unknown RegionTransitionType: " + type);<a name="line.479"></a>
-<span class="sourceLineNo">480</span> }<a name="line.480"></a>
-<span class="sourceLineNo">481</span> }<a name="line.481"></a>
-<span class="sourceLineNo">482</span><a name="line.482"></a>
-<span class="sourceLineNo">483</span> private static RegionTransitionType convert(TransitionType type) {<a name="line.483"></a>
-<span class="sourceLineNo">484</span> switch (type) {<a name="line.484"></a>
-<span class="sourceLineNo">485</span> case ASSIGN:<a name="line.485"></a>
-<span class="sourceLineNo">486</span> return RegionTransitionType.ASSIGN;<a name="line.486"></a>
-<span class="sourceLineNo">487</span> case UNASSIGN:<a name="line.487"></a>
-<span class="sourceLineNo">488</span> return RegionTransitionType.UNASSIGN;<a name="line.488"></a>
-<span class="sourceLineNo">489</span> case MOVE:<a name="line.489"></a>
-<span class="sourceLineNo">490</span> return RegionTransitionType.MOVE;<a name="line.490"></a>
-<span class="sourceLineNo">491</span> case REOPEN:<a name="line.491"></a>
-<span class="sourceLineNo">492</span> return RegionTransitionType.REOPEN;<a name="line.492"></a>
-<span class="sourceLineNo">493</span> default:<a name="line.493"></a>
-<span class="sourceLineNo">494</span> throw new IllegalArgumentException("Unknown TransitionType: " + type);<a name="line.494"></a>
-<span class="sourceLineNo">495</span> }<a name="line.495"></a>
-<span class="sourceLineNo">496</span> }<a name="line.496"></a>
-<span class="sourceLineNo">497</span><a name="line.497"></a>
-<span class="sourceLineNo">498</span> @Override<a name="line.498"></a>
-<span class="sourceLineNo">499</span> protected void serializeStateData(ProcedureStateSerializer serializer) throws IOException {<a name="line.499"></a>
-<span class="sourceLineNo">500</span> super.serializeStateData(serializer);<a name="line.500"></a>
-<span class="sourceLineNo">501</span> RegionStateTransitionStateData.Builder builder = RegionStateTransitionStateData.newBuilder()<a name="line.501"></a>
-<span class="sourceLineNo">502</span> .setType(convert(type)).setForceNewPlan(forceNewPlan);<a name="line.502"></a>
-<span class="sourceLineNo">503</span> if (assignCandidate != null) {<a name="line.503"></a>
-<span class="sourceLineNo">504</span> builder.setAssignCandidate(ProtobufUtil.toServerName(assignCandidate));<a name="line.504"></a>
-<span class="sourceLineNo">505</span> }<a name="line.505"></a>
-<span class="sourceLineNo">506</span> serializer.serialize(builder.build());<a name="line.506"></a>
-<span class="sourceLineNo">507</span> }<a name="line.507"></a>
-<span class="sourceLineNo">508</span><a name="line.508"></a>
-<span class="sourceLineNo">509</span> @Override<a name="line.509"></a>
-<span class="sourceLineNo">510</span> protected void deserializeStateData(ProcedureStateSerializer serializer) throws IOException {<a name="line.510"></a>
-<span class="sourceLineNo">511</span> super.deserializeStateData(serializer);<a name="line.511"></a>
-<span class="sourceLineNo">512</span> RegionStateTransitionStateData data =<a name="line.512"></a>
-<span class="sourceLineNo">513</span> serializer.deserialize(RegionStateTransitionStateData.class);<a name="line.513"></a>
-<span class="sourceLineNo">514</span> type = convert(data.getType());<a name="line.514"></a>
-<span class="sourceLineNo">515</span> setInitialAndLastState();<a name="line.515"></a>
-<span class="sourceLineNo">516</span> forceNewPlan = data.getForceNewPlan();<a name="line.516"></a>
-<span class="sourceLineNo">517</span> if (data.hasAssignCandidate()) {<a name="line.517"></a>
-<span class="sourceLineNo">518</span> assignCandidate = ProtobufUtil.toServerName(data.getAssignCandidate());<a name="line.518"></a>
-<span class="sourceLineNo">519</span> }<a name="line.519"></a>
-<span class="sourceLineNo">520</span> }<a name="line.520"></a>
-<span class="sourceLineNo">521</span><a name="line.521"></a>
-<span class="sourceLineNo">522</span> @Override<a name="line.522"></a>
-<span class="sourceLineNo">523</span> protected ProcedureMetrics getProcedureMetrics(MasterProcedureEnv env) {<a name="line.523"></a>
-<span class="sourceLineNo">524</span> MetricsAssignmentManager metrics = env.getAssignmentManager().getAssignmentManagerMetrics();<a name="line.524"></a>
-<span class="sourceLineNo">525</span> switch (type) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span> case ASSIGN:<a name="line.526"></a>
-<span class="sourceLineNo">527</span> return metrics.getAssignProcMetrics();<a name="line.527"></a>
-<span class="sourceLineNo">528</span> case UNASSIGN:<a name="line.528"></a>
-<span class="sourceLineNo">529</span> return metrics.getUnassignProcMetrics();<a name="line.529"></a>
-<span class="sourceLineNo">530</span> case MOVE:<a name="line.530"></a>
-<span class="sourceLineNo">531</span> return metrics.getMoveProcMetrics();<a name="line.531"></a>
-<span class="sourceLineNo">532</span> case REOPEN:<a name="line.532"></a>
-<span class="sourceLineNo">533</span> return metrics.getReopenProcMetrics();<a name="line.533"></a>
-<span class="sourceLineNo">534</span> default:<a name="line.534"></a>
-<span class="sourceLineNo">535</span> throw new IllegalArgumentException("Unknown transition type: " + type);<a name="line.535"></a>
-<span class="sourceLineNo">536</span> }<a name="line.536"></a>
-<span class="sourceLineNo">537</span> }<a name="line.537"></a>
-<span class="sourceLineNo">538</span><a name="line.538"></a>
-<span class="sourceLineNo">539</span> @Override<a name="line.539"></a>
-<span class="sourceLineNo">540</span> public void toStringClassDetails(StringBuilder sb) {<a name="line.540"></a>
-<span class="sourceLineNo">541</span> super.toStringClassDetails(sb);<a name="line.541"></a>
-<span class="sourceLineNo">542</span> if (initialState == RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE) {<a name="line.542"></a>
-<span class="sourceLineNo">543</span> sb.append(", ASSIGN");<a name="line.543"></a>
-<span class="sourceLineNo">544</span> } else if (lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED) {<a name="line.544"></a>
-<span class="sourceLineNo">545</span> sb.append(", UNASSIGN");<a name="line.545"></a>
-<span class="sourceLineNo">546</span> } else {<a name="line.546"></a>
-<span class="sourceLineNo">547</span> sb.append(", REOPEN/MOVE");<a name="line.547"></a>
-<span class="sourceLineNo">548</span> }<a name="line.548"></a>
-<span class="sourceLineNo">549</span> }<a name="line.549"></a>
-<span class="sourceLineNo">550</span><a name="line.550"></a>
-<span class="sourceLineNo">551</span> private static TransitRegionStateProcedure setOwner(MasterProcedureEnv env,<a name="line.551"></a>
-<span class="sourceLineNo">552</span> TransitRegionStateProcedure proc) {<a name="line.552"></a>
-<span class="sourceLineNo">553</span> proc.setOwner(env.getRequestUser().getShortName());<a name="line.553"></a>
-<span class="sourceLineNo">554</span> return proc;<a name="line.554"></a>
-<span class="sourceLineNo">555</span> }<a name="line.555"></a>
-<span class="sourceLineNo">556</span><a name="line.556"></a>
-<span class="sourceLineNo">557</span> public enum TransitionType {<a name="line.557"></a>
-<span class="sourceLineNo">558</span> ASSIGN, UNASSIGN, MOVE, REOPEN<a name="line.558"></a>
-<span class="sourceLineNo">559</span> }<a name="line.559"></a>
-<span class="sourceLineNo">560</span><a name="line.560"></a>
-<span class="sourceLineNo">561</span> // Be careful that, when you call these 4 methods below, you need to manually attach the returned<a name="line.561"></a>
-<span class="sourceLineNo">562</span> // procedure with the RegionStateNode, otherwise the procedure will quit immediately without doing<a name="line.562"></a>
-<span class="sourceLineNo">563</span> // anything. See the comment in executeFromState to find out why we need this assumption.<a name="line.563"></a>
-<span class="sourceLineNo">564</span> public static TransitRegionStateProcedure assign(MasterProcedureEnv env, RegionInfo region,<a name="line.564"></a>
-<span class="sourceLineNo">565</span> @Nullable ServerName targetServer) {<a name="line.565"></a>
-<span class="sourceLineNo">566</span> return assign(env, region, false, targetServer);<a name="line.566"></a>
-<span class="sourceLineNo">567</span> }<a name="line.567"></a>
-<span class="sourceLineNo">568</span><a name="line.568"></a>
-<span class="sourceLineNo">569</span> public static TransitRegionStateProcedure assign(MasterProcedureEnv env, RegionInfo region,<a name="line.569"></a>
-<span class="sourceLineNo">570</span> boolean forceNewPlan, @Nullable ServerName targetServer) {<a name="line.570"></a>
-<span class="sourceLineNo">571</span> return setOwner(env, new TransitRegionStateProcedure(env, region, targetServer, forceNewPlan,<a name="line.571"></a>
-<span class="sourceLineNo">572</span> TransitionType.ASSIGN));<a name="line.572"></a>
-<span class="sourceLineNo">573</span> }<a name="line.573"></a>
-<span class="sourceLineNo">574</span><a name="line.574"></a>
-<span class="sourceLineNo">575</span> public static TransitRegionStateProcedure unassign(MasterProcedureEnv env, RegionInfo region) {<a name="line.575"></a>
-<span class="sourceLineNo">576</span> return setOwner(env,<a name="line.576"></a>
-<span class="sourceLineNo">577</span> new TransitRegionStateProcedure(env, region, null, false, TransitionType.UNASSIGN));<a name="line.577"></a>
-<span class="sourceLineNo">578</span> }<a name="line.578"></a>
-<span class="sourceLineNo">579</span><a name="line.579"></a>
-<span class="sourceLineNo">580</span> public static TransitRegionStateProcedure reopen(MasterProcedureEnv env, RegionInfo region) {<a name="line.580"></a>
-<span class="sourceLineNo">581</span> return setOwner(env,<a name="line.581"></a>
-<span class="sourceLineNo">582</span> new TransitRegionStateProcedure(env, region, null, false, TransitionType.REOPEN));<a name="line.582"></a>
-<span class="sourceLineNo">583</span> }<a name="line.583"></a>
-<span class="sourceLineNo">584</span><a name="line.584"></a>
-<span class="sourceLineNo">585</span> public static TransitRegionStateProcedure move(MasterProcedureEnv env, RegionInfo region,<a name="line.585"></a>
-<span class="sourceLineNo">586</span> @Nullable ServerName targetServer) {<a name="line.586"></a>
-<span class="sourceLineNo">587</span> return setOwner(env, new TransitRegionStateProcedure(env, region, targetServer,<a name="line.587"></a>
-<span class="sourceLineNo">588</span> targetServer == null, TransitionType.MOVE));<a name="line.588"></a>
-<span class="sourceLineNo">589</span> }<a name="line.589"></a>
-<span class="sourceLineNo">590</span>}<a name="line.590"></a>
+<span class="sourceLineNo">121</span> private RegionRemoteProcedureBase remoteProc;<a name="line.121"></a>
+<span class="sourceLineNo">122</span><a name="line.122"></a>
+<span class="sourceLineNo">123</span> public TransitRegionStateProcedure() {<a name="line.123"></a>
+<span class="sourceLineNo">124</span> }<a name="line.124"></a>
+<span class="sourceLineNo">125</span><a name="line.125"></a>
+<span class="sourceLineNo">126</span> private void setInitialAndLastState() {<a name="line.126"></a>
+<span class="sourceLineNo">127</span> switch (type) {<a name="line.127"></a>
+<span class="sourceLineNo">128</span> case ASSIGN:<a name="line.128"></a>
+<span class="sourceLineNo">129</span> initialState = RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE;<a name="line.129"></a>
+<span class="sourceLineNo">130</span> lastState = RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED;<a name="line.130"></a>
+<span class="sourceLineNo">131</span> break;<a name="line.131"></a>
+<span class="sourceLineNo">132</span> case UNASSIGN:<a name="line.132"></a>
+<span class="sourceLineNo">133</span> initialState = RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE;<a name="line.133"></a>
+<span class="sourceLineNo">134</span> lastState = RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED;<a name="line.134"></a>
+<span class="sourceLineNo">135</span> break;<a name="line.135"></a>
+<span class="sourceLineNo">136</span> case MOVE:<a name="line.136"></a>
+<span class="sourceLineNo">137</span> case REOPEN:<a name="line.137"></a>
+<span class="sourceLineNo">138</span> initialState = RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE;<a name="line.138"></a>
+<span class="sourceLineNo">139</span> lastState = RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED;<a name="line.139"></a>
+<span class="sourceLineNo">140</span> break;<a name="line.140"></a>
+<span class="sourceLineNo">141</span> default:<a name="line.141"></a>
+<span class="sourceLineNo">142</span> throw new IllegalArgumentException("Unknown TransitionType: " + type);<a name="line.142"></a>
+<span class="sourceLineNo">143</span> }<a name="line.143"></a>
+<span class="sourceLineNo">144</span> }<a name="line.144"></a>
+<span class="sourceLineNo">145</span><a name="line.145"></a>
+<span class="sourceLineNo">146</span> protected TransitRegionStateProcedure(MasterProcedureEnv env, RegionInfo hri,<a name="line.146"></a>
+<span class="sourceLineNo">147</span> ServerName assignCandidate, boolean forceNewPlan, TransitionType type) {<a name="line.147"></a>
+<span class="sourceLineNo">148</span> super(env, hri);<a name="line.148"></a>
+<span class="sourceLineNo">149</span> this.assignCandidate = assignCandidate;<a name="line.149"></a>
+<span class="sourceLineNo">150</span> this.forceNewPlan = forceNewPlan;<a name="line.150"></a>
+<span class="sourceLineNo">151</span> this.type = type;<a name="line.151"></a>
+<span class="sourceLineNo">152</span> setInitialAndLastState();<a name="line.152"></a>
+<span class="sourceLineNo">153</span><a name="line.153"></a>
+<span class="sourceLineNo">154</span> // when do reopen TRSP, let the rs know the targetServer so it can keep some info on close<a name="line.154"></a>
+<span class="sourceLineNo">155</span> if (type == TransitionType.REOPEN) {<a name="line.155"></a>
+<span class="sourceLineNo">156</span> this.assignCandidate = getRegionStateNode(env).getRegionLocation();<a name="line.156"></a>
+<span class="sourceLineNo">157</span> }<a name="line.157"></a>
+<span class="sourceLineNo">158</span> }<a name="line.158"></a>
+<span class="sourceLineNo">159</span><a name="line.159"></a>
+<span class="sourceLineNo">160</span> @Override<a name="line.160"></a>
+<span class="sourceLineNo">161</span> public TableOperationType getTableOperationType() {<a name="line.161"></a>
+<span class="sourceLineNo">162</span> // TODO: maybe we should make another type here, REGION_TRANSITION?<a name="line.162"></a>
+<span class="sourceLineNo">163</span> return TableOperationType.REGION_EDIT;<a name="line.163"></a>
+<span class="sourceLineNo">164</span> }<a name="line.164"></a>
+<span class="sourceLineNo">165</span><a name="line.165"></a>
+<span class="sourceLineNo">166</span> @Override<a name="line.166"></a>
+<span class="sourceLineNo">167</span> protected boolean waitInitialized(MasterProcedureEnv env) {<a name="line.167"></a>
+<span class="sourceLineNo">168</span> if (TableName.isMetaTableName(getTableName())) {<a name="line.168"></a>
+<span class="sourceLineNo">169</span> return false;<a name="line.169"></a>
+<span class="sourceLineNo">170</span> }<a name="line.170"></a>
+<span class="sourceLineNo">171</span> // First we need meta to be loaded, and second, if meta is not online then we will likely to<a name="line.171"></a>
+<span class="sourceLineNo">172</span> // fail when updating meta so we wait until it is assigned.<a name="line.172"></a>
+<span class="sourceLineNo">173</span> AssignmentManager am = env.getAssignmentManager();<a name="line.173"></a>
+<span class="sourceLineNo">174</span> return am.waitMetaLoaded(this) || am.waitMetaAssigned(this, getRegion());<a name="line.174"></a>
+<span class="sourceLineNo">175</span> }<a name="line.175"></a>
+<span class="sourceLineNo">176</span><a name="line.176"></a>
+<span class="sourceLineNo">177</span> private void queueAssign(MasterProcedureEnv env, RegionStateNode regionNode)<a name="line.177"></a>
+<span class="sourceLineNo">178</span> throws ProcedureSuspendedException {<a name="line.178"></a>
+<span class="sourceLineNo">179</span> boolean retain = false;<a name="line.179"></a>
+<span class="sourceLineNo">180</span> if (forceNewPlan) {<a name="line.180"></a>
+<span class="sourceLineNo">181</span> // set the region location to null if forceNewPlan is true<a name="line.181"></a>
+<span class="sourceLineNo">182</span> regionNode.setRegionLocation(null);<a name="line.182"></a>
+<span class="sourceLineNo">183</span> } else {<a name="line.183"></a>
+<span class="sourceLineNo">184</span> if (assignCandidate != null) {<a name="line.184"></a>
+<span class="sourceLineNo">185</span> retain = assignCandidate.equals(regionNode.getLastHost());<a name="line.185"></a>
+<span class="sourceLineNo">186</span> regionNode.setRegionLocation(assignCandidate);<a name="line.186"></a>
+<span class="sourceLineNo">187</span> } else if (regionNode.getLastHost() != null) {<a name="line.187"></a>
+<span class="sourceLineNo">188</span> retain = true;<a name="line.188"></a>
+<span class="sourceLineNo">189</span> LOG.info("Setting lastHost as the region location {}", regionNode.getLastHost());<a name="line.189"></a>
+<span class="sourceLineNo">190</span> regionNode.setRegionLocation(regionNode.getLastHost());<a name="line.190"></a>
+<span class="sourceLineNo">191</span> }<a name="line.191"></a>
+<span class="sourceLineNo">192</span> }<a name="line.192"></a>
+<span class="sourceLineNo">193</span> LOG.info("Starting {}; {}; forceNewPlan={}, retain={}", this, regionNode.toShortString(),<a name="line.193"></a>
+<span class="sourceLineNo">194</span> forceNewPlan, retain);<a name="line.194"></a>
+<span class="sourceLineNo">195</span> env.getAssignmentManager().queueAssign(regionNode);<a name="line.195"></a>
+<span class="sourceLineNo">196</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_OPEN);<a name="line.196"></a>
+<span class="sourceLineNo">197</span> if (regionNode.getProcedureEvent().suspendIfNotReady(this)) {<a name="line.197"></a>
+<span class="sourceLineNo">198</span> throw new ProcedureSuspendedException();<a name="line.198"></a>
+<span class="sourceLineNo">199</span> }<a name="line.199"></a>
+<span class="sourceLineNo">200</span> }<a name="line.200"></a>
+<span class="sourceLineNo">201</span><a name="line.201"></a>
+<span class="sourceLineNo">202</span> private void openRegion(MasterProcedureEnv env, RegionStateNode regionNode) throws IOException {<a name="line.202"></a>
+<span class="sourceLineNo">203</span> ServerName loc = regionNode.getRegionLocation();<a name="line.203"></a>
+<span class="sourceLineNo">204</span> if (loc == null || BOGUS_SERVER_NAME.equals(loc)) {<a name="line.204"></a>
+<span class="sourceLineNo">205</span> LOG.warn("No location specified for {}, jump back to state {} to get one", getRegion(),<a name="line.205"></a>
+<span class="sourceLineNo">206</span> RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.206"></a>
+<span class="sourceLineNo">207</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.207"></a>
+<span class="sourceLineNo">208</span> return;<a name="line.208"></a>
+<span class="sourceLineNo">209</span> }<a name="line.209"></a>
+<span class="sourceLineNo">210</span> env.getAssignmentManager().regionOpening(regionNode);<a name="line.210"></a>
+<span class="sourceLineNo">211</span> addChildProcedure(new OpenRegionProcedure(this, getRegion(), loc));<a name="line.211"></a>
+<span class="sourceLineNo">212</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED);<a name="line.212"></a>
+<span class="sourceLineNo">213</span> }<a name="line.213"></a>
+<span class="sourceLineNo">214</span><a name="line.214"></a>
+<span class="sourceLineNo">215</span> private Flow confirmOpened(MasterProcedureEnv env, RegionStateNode regionNode)<a name="line.215"></a>
+<span class="sourceLineNo">216</span> throws IOException {<a name="line.216"></a>
+<span class="sourceLineNo">217</span> if (regionNode.isInState(State.OPEN)) {<a name="line.217"></a>
+<span class="sourceLineNo">218</span> retryCounter = null;<a name="line.218"></a>
+<span class="sourceLineNo">219</span> if (lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED) {<a name="line.219"></a>
+<span class="sourceLineNo">220</span> // we are the last state, finish<a name="line.220"></a>
+<span class="sourceLineNo">221</span> regionNode.unsetProcedure(this);<a name="line.221"></a>
+<span class="sourceLineNo">222</span> ServerCrashProcedure.updateProgress(env, getParentProcId());<a name="line.222"></a>
+<span class="sourceLineNo">223</span> return Flow.NO_MORE_STATE;<a name="line.223"></a>
+<span class="sourceLineNo">224</span> }<a name="line.224"></a>
+<span class="sourceLineNo">225</span> // It is possible that we arrive here but confirm opened is not the last state, for example,<a name="line.225"></a>
+<span class="sourceLineNo">226</span> // when merging or splitting a region, we unassign the region from a RS and the RS is crashed,<a name="line.226"></a>
+<span class="sourceLineNo">227</span> // then there will be recovered edits for this region, we'd better make the region online<a name="line.227"></a>
+<span class="sourceLineNo">228</span> // again and then unassign it, otherwise we have to fail the merge/split procedure as we may<a name="line.228"></a>
+<span class="sourceLineNo">229</span> // loss data.<a name="line.229"></a>
+<span class="sourceLineNo">230</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE);<a name="line.230"></a>
+<span class="sourceLineNo">231</span> return Flow.HAS_MORE_STATE;<a name="line.231"></a>
+<span class="sourceLineNo">232</span> }<a name="line.232"></a>
+<span class="sourceLineNo">233</span><a name="line.233"></a>
+<span class="sourceLineNo">234</span> int retries = env.getAssignmentManager().getRegionStates().addToFailedOpen(regionNode)<a name="line.234"></a>
+<span class="sourceLineNo">235</span> .incrementAndGetRetries();<a name="line.235"></a>
+<span class="sourceLineNo">236</span> int maxAttempts = env.getAssignmentManager().getAssignMaxAttempts();<a name="line.236"></a>
+<span class="sourceLineNo">237</span> LOG.info("Retry={} of max={}; {}; {}", retries, maxAttempts, this, regionNode.toShortString());<a name="line.237"></a>
+<span class="sourceLineNo">238</span><a name="line.238"></a>
+<span class="sourceLineNo">239</span> if (retries >= maxAttempts) {<a name="line.239"></a>
+<span class="sourceLineNo">240</span> env.getAssignmentManager().regionFailedOpen(regionNode, true);<a name="line.240"></a>
+<span class="sourceLineNo">241</span> setFailure(getClass().getSimpleName(), new RetriesExhaustedException(<a name="line.241"></a>
+<span class="sourceLineNo">242</span> "Max attempts " + env.getAssignmentManager().getAssignMaxAttempts() + " exceeded"));<a name="line.242"></a>
+<span class="sourceLineNo">243</span> regionNode.unsetProcedure(this);<a name="line.243"></a>
+<span class="sourceLineNo">244</span> return Flow.NO_MORE_STATE;<a name="line.244"></a>
+<span class="sourceLineNo">245</span> }<a name="line.245"></a>
+<span class="sourceLineNo">246</span><a name="line.246"></a>
+<span class="sourceLineNo">247</span> env.getAssignmentManager().regionFailedOpen(regionNode, false);<a name="line.247"></a>
+<span class="sourceLineNo">248</span> // we failed to assign the region, force a new plan<a name="line.248"></a>
+<span class="sourceLineNo">249</span> forceNewPlan = true;<a name="line.249"></a>
+<span class="sourceLineNo">250</span> regionNode.setRegionLocation(null);<a name="line.250"></a>
+<span class="sourceLineNo">251</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.251"></a>
+<span class="sourceLineNo">252</span><a name="line.252"></a>
+<span class="sourceLineNo">253</span> if (retries > env.getAssignmentManager().getAssignRetryImmediatelyMaxAttempts()) {<a name="line.253"></a>
+<span class="sourceLineNo">254</span> // Throw exception to backoff and retry when failed open too many times<a name="line.254"></a>
+<span class="sourceLineNo">255</span> throw new HBaseIOException("Failed confirm OPEN of " + regionNode +<a name="line.255"></a>
+<span class="sourceLineNo">256</span> " (remote log may yield more detail on why).");<a name="line.256"></a>
+<span class="sourceLineNo">257</span> } else {<a name="line.257"></a>
+<span class="sourceLineNo">258</span> // Here we do not throw exception because we want to the region to be online ASAP<a name="line.258"></a>
+<span class="sourceLineNo">259</span> return Flow.HAS_MORE_STATE;<a name="line.259"></a>
+<span class="sourceLineNo">260</span> }<a name="line.260"></a>
+<span class="sourceLineNo">261</span> }<a name="line.261"></a>
+<span class="sourceLineNo">262</span><a name="line.262"></a>
+<span class="sourceLineNo">263</span> private void closeRegion(MasterProcedureEnv env, RegionStateNode regionNode) throws IOException {<a name="line.263"></a>
+<span class="sourceLineNo">264</span> if (regionNode.isInState(State.OPEN, State.CLOSING, State.MERGING, State.SPLITTING)) {<a name="line.264"></a>
+<span class="sourceLineNo">265</span> // this is the normal case<a name="line.265"></a>
+<span class="sourceLineNo">266</span> env.getAssignmentManager().regionClosing(regionNode);<a name="line.266"></a>
+<span class="sourceLineNo">267</span> addChildProcedure(new CloseRegionProcedure(this, getRegion(), regionNode.getRegionLocation(),<a name="line.267"></a>
+<span class="sourceLineNo">268</span> assignCandidate));<a name="line.268"></a>
+<span class="sourceLineNo">269</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED);<a name="line.269"></a>
+<span class="sourceLineNo">270</span> } else {<a name="line.270"></a>
+<span class="sourceLineNo">271</span> forceNewPlan = true;<a name="line.271"></a>
+<span class="sourceLineNo">272</span> regionNode.setRegionLocation(null);<a name="line.272"></a>
+<span class="sourceLineNo">273</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.273"></a>
+<span class="sourceLineNo">274</span> }<a name="line.274"></a>
+<span class="sourceLineNo">275</span> }<a name="line.275"></a>
+<span class="sourceLineNo">276</span><a name="line.276"></a>
+<span class="sourceLineNo">277</span> private Flow confirmClosed(MasterProcedureEnv env, RegionStateNode regionNode)<a name="line.277"></a>
+<span class="sourceLineNo">278</span> throws IOException {<a name="line.278"></a>
+<span class="sourceLineNo">279</span> if (regionNode.isInState(State.CLOSED)) {<a name="line.279"></a>
+<span class="sourceLineNo">280</span> retryCounter = null;<a name="line.280"></a>
+<span class="sourceLineNo">281</span> if (lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED) {<a name="line.281"></a>
+<span class="sourceLineNo">282</span> // we are the last state, finish<a name="line.282"></a>
+<span class="sourceLineNo">283</span> regionNode.unsetProcedure(this);<a name="line.283"></a>
+<span class="sourceLineNo">284</span> return Flow.NO_MORE_STATE;<a name="line.284"></a>
+<span class="sourceLineNo">285</span> }<a name="line.285"></a>
+<span class="sourceLineNo">286</span> // This means we need to open the region again, should be a move or reopen<a name="line.286"></a>
+<span class="sourceLineNo">287</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.287"></a>
+<span class="sourceLineNo">288</span> return Flow.HAS_MORE_STATE;<a name="line.288"></a>
+<span class="sourceLineNo">289</span> }<a name="line.289"></a>
+<span class="sourceLineNo">290</span> if (regionNode.isInState(State.CLOSING)) {<a name="line.290"></a>
+<span class="sourceLineNo">291</span> // This is possible, think the target RS crashes and restarts immediately, the close region<a name="line.291"></a>
+<span class="sourceLineNo">292</span> // operation will return a NotServingRegionException soon, we can only recover after SCP takes<a name="line.292"></a>
+<span class="sourceLineNo">293</span> // care of this RS. So here we throw an IOException to let upper layer to retry with backoff.<a name="line.293"></a>
+<span class="sourceLineNo">294</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE);<a name="line.294"></a>
+<span class="sourceLineNo">295</span> throw new HBaseIOException("Failed to close region");<a name="line.295"></a>
+<span class="sourceLineNo">296</span> }<a name="line.296"></a>
+<span class="sourceLineNo">297</span> // abnormally closed, need to reopen it, no matter what is the last state, see the comment in<a name="line.297"></a>
+<span class="sourceLineNo">298</span> // confirmOpened for more details that why we need to reopen the region first even if we just<a name="line.298"></a>
+<span class="sourceLineNo">299</span> // want to close it.<a name="line.299"></a>
+<span class="sourceLineNo">300</span> // The only exception is for non-default replica, where we do not need to deal with recovered<a name="line.300"></a>
+<span class="sourceLineNo">301</span> // edits. Notice that the region will remain in ABNORMALLY_CLOSED state, the upper layer need to<a name="line.301"></a>
+<span class="sourceLineNo">302</span> // deal with this state. For non-default replica, this is usually the same with CLOSED.<a name="line.302"></a>
+<span class="sourceLineNo">303</span> assert regionNode.isInState(State.ABNORMALLY_CLOSED);<a name="line.303"></a>
+<span class="sourceLineNo">304</span> if (!RegionReplicaUtil.isDefaultReplica(getRegion()) &&<a name="line.304"></a>
+<span class="sourceLineNo">305</span> lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED) {<a name="line.305"></a>
+<span class="sourceLineNo">306</span> regionNode.unsetProcedure(this);<a name="line.306"></a>
+<span class="sourceLineNo">307</span> return Flow.NO_MORE_STATE;<a name="line.307"></a>
+<span class="sourceLineNo">308</span> }<a name="line.308"></a>
+<span class="sourceLineNo">309</span> retryCounter = null;<a name="line.309"></a>
+<span class="sourceLineNo">310</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.310"></a>
+<span class="sourceLineNo">311</span> return Flow.HAS_MORE_STATE;<a name="line.311"></a>
+<span class="sourceLineNo">312</span> }<a name="line.312"></a>
+<span class="sourceLineNo">313</span><a name="line.313"></a>
+<span class="sourceLineNo">314</span> // Override to lock RegionStateNode<a name="line.314"></a>
+<span class="sourceLineNo">315</span> @SuppressWarnings("rawtypes")<a name="line.315"></a>
+<span class="sourceLineNo">316</span> @Override<a name="line.316"></a>
+<span class="sourceLineNo">317</span> protected Procedure[] execute(MasterProcedureEnv env)<a name="line.317"></a>
+<span class="sourceLineNo">318</span> throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException {<a name="line.318"></a>
+<span class="sourceLineNo">319</span> RegionStateNode regionNode =<a name="line.319"></a>
+<span class="sourceLineNo">320</span> env.getAssignmentManager().getRegionStates().getOrCreateRegionStateNode(getRegion());<a name="line.320"></a>
+<span class="sourceLineNo">321</span> regionNode.lock();<a name="line.321"></a>
+<span class="sourceLineNo">322</span> try {<a name="line.322"></a>
+<span class="sourceLineNo">323</span> return super.execute(env);<a name="line.323"></a>
+<span class="sourceLineNo">324</span> } finally {<a name="line.324"></a>
+<span class="sourceLineNo">325</span> regionNode.unlock();<a name="line.325"></a>
+<span class="sourceLineNo">326</span> }<a name="line.326"></a>
+<span class="sourceLineNo">327</span> }<a name="line.327"></a>
+<span class="sourceLineNo">328</span><a name="line.328"></a>
+<span class="sourceLineNo">329</span> private RegionStateNode getRegionStateNode(MasterProcedureEnv env) {<a name="line.329"></a>
+<span class="sourceLineNo">330</span> return env.getAssignmentManager().getRegionStates().getOrCreateRegionStateNode(getRegion());<a name="line.330"></a>
+<span class="sourceLineNo">331</span> }<a name="line.331"></a>
+<span class="sourceLineNo">332</span><a name="line.332"></a>
+<span class="sourceLineNo">333</span> @Override<a name="line.333"></a>
+<span class="sourceLineNo">334</span> protected Flow executeFromState(MasterProcedureEnv env, RegionStateTransitionState state)<a name="line.334"></a>
+<span class="sourceLineNo">335</span> throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException {<a name="line.335"></a>
+<span class="sourceLineNo">336</span> RegionStateNode regionNode = getRegionStateNode(env);<a name="line.336"></a>
+<span class="sourceLineNo">337</span> try {<a name="line.337"></a>
+<span class="sourceLineNo">338</span> switch (state) {<a name="line.338"></a>
+<span class="sourceLineNo">339</span> case REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE:<a name="line.339"></a>
+<span class="sourceLineNo">340</span> // Need to do some sanity check for replica region, if the region does not exist at<a name="line.340"></a>
+<span class="sourceLineNo">341</span> // master, do not try to assign the replica region, log error and return.<a name="line.341"></a>
+<span class="sourceLineNo">342</span> if (!RegionReplicaUtil.isDefaultReplica(regionNode.getRegionInfo())) {<a name="line.342"></a>
+<span class="sourceLineNo">343</span> RegionInfo defaultRI =<a name="line.343"></a>
+<span class="sourceLineNo">344</span> RegionReplicaUtil.getRegionInfoForDefaultReplica(regionNode.getRegionInfo());<a name="line.344"></a>
+<span class="sourceLineNo">345</span> if (env.getMasterServices().getAssignmentManager().getRegionStates().<a name="line.345"></a>
+<span class="sourceLineNo">346</span> getRegionStateNode(defaultRI) == null) {<a name="line.346"></a>
+<span class="sourceLineNo">347</span> LOG.error(<a name="line.347"></a>
+<span class="sourceLineNo">348</span> "Cannot assign replica region {} because its primary region {} does not exist.",<a name="line.348"></a>
+<span class="sourceLineNo">349</span> regionNode.getRegionInfo(), defaultRI);<a name="line.349"></a>
+<span class="sourceLineNo">350</span> regionNode.unsetProcedure(this);<a name="line.350"></a>
+<span class="sourceLineNo">351</span> return Flow.NO_MORE_STATE;<a name="line.351"></a>
+<span class="sourceLineNo">352</span> }<a name="line.352"></a>
+<span class="sourceLineNo">353</span> }<a name="line.353"></a>
+<span class="sourceLineNo">354</span> queueAssign(env, regionNode);<a name="line.354"></a>
+<span class="sourceLineNo">355</span> return Flow.HAS_MORE_STATE;<a name="line.355"></a>
+<span class="sourceLineNo">356</span> case REGION_STATE_TRANSITION_OPEN:<a name="line.356"></a>
+<span class="sourceLineNo">357</span> openRegion(env, regionNode);<a name="line.357"></a>
+<span class="sourceLineNo">358</span> return Flow.HAS_MORE_STATE;<a name="line.358"></a>
+<span class="sourceLineNo">359</span> case REGION_STATE_TRANSITION_CONFIRM_OPENED:<a name="line.359"></a>
+<span class="sourceLineNo">360</span> return confirmOpened(env, regionNode);<a name="line.360"></a>
+<span class="sourceLineNo">361</span> case REGION_STATE_TRANSITION_CLOSE:<a name="line.361"></a>
+<span class="sourceLineNo">362</span> closeRegion(env, regionNode);<a name="line.362"></a>
+<span class="sourceLineNo">363</span> return Flow.HAS_MORE_STATE;<a name="line.363"></a>
+<span class="sourceLineNo">364</span> case REGION_STATE_TRANSITION_CONFIRM_CLOSED:<a name="line.364"></a>
+<span class="sourceLineNo">365</span> return confirmClosed(env, regionNode);<a name="line.365"></a>
+<span class="sourceLineNo">366</span> default:<a name="line.366"></a>
+<span class="sourceLineNo">367</span> throw new UnsupportedOperationException("unhandled state=" + state);<a name="line.367"></a>
+<span class="sourceLineNo">368</span> }<a name="line.368"></a>
+<span class="sourceLineNo">369</span> } catch (IOException e) {<a name="line.369"></a>
+<span class="sourceLineNo">370</span> if (retryCounter == null) {<a name="line.370"></a>
+<span class="sourceLineNo">371</span> retryCounter = ProcedureUtil.createRetryCounter(env.getMasterConfiguration());<a name="line.371"></a>
+<span class="sourceLineNo">372</span> }<a name="line.372"></a>
+<span class="sourceLineNo">373</span> long backoff = retryCounter.getBackoffTimeAndIncrementAttempts();<a name="line.373"></a>
+<span class="sourceLineNo">374</span> LOG.warn(<a name="line.374"></a>
+<span class="sourceLineNo">375</span> "Failed transition, suspend {}secs {}; {}; waiting on rectified condition fixed " +<a name="line.375"></a>
+<span class="sourceLineNo">376</span> "by other Procedure or operator intervention",<a name="line.376"></a>
+<span class="sourceLineNo">377</span> backoff / 1000, this, regionNode.toShortString(), e);<a name="line.377"></a>
+<span class="sourceLineNo">378</span> setTimeout(Math.toIntExact(backoff));<a name="line.378"></a>
+<span class="sourceLineNo">379</span> setState(ProcedureProtos.ProcedureState.WAITING_TIMEOUT);<a name="line.379"></a>
+<span class="sourceLineNo">380</span> skipPersistence();<a name="line.380"></a>
+<span class="sourceLineNo">381</span> throw new ProcedureSuspendedException();<a name="line.381"></a>
+<span class="sourceLineNo">382</span> }<a name="line.382"></a>
+<span class="sourceLineNo">383</span> }<a name="line.383"></a>
+<span class="sourceLineNo">384</span><a name="line.384"></a>
+<span class="sourceLineNo">385</span> /**<a name="line.385"></a>
+<span class="sourceLineNo">386</span> * At end of timeout, wake ourselves up so we run again.<a name="line.386"></a>
+<span class="sourceLineNo">387</span> */<a name="line.387"></a>
+<span class="sourceLineNo">388</span> @Override<a name="line.388"></a>
+<span class="sourceLineNo">389</span> protected synchronized boolean setTimeoutFailure(MasterProcedureEnv env) {<a name="line.389"></a>
+<span class="sourceLineNo">390</span> setState(ProcedureProtos.ProcedureState.RUNNABLE);<a name="line.390"></a>
+<span class="sourceLineNo">391</span> env.getProcedureScheduler().addFront(this);<a name="line.391"></a>
+<span class="sourceLineNo">392</span> return false; // 'false' means that this procedure handled the timeout<a name="line.392"></a>
+<span class="sourceLineNo">393</span> }<a name="line.393"></a>
+<span class="sourceLineNo">394</span><a name="line.394"></a>
+<span class="sourceLineNo">395</span> // Should be called with RegionStateNode locked<a name="line.395"></a>
+<span class="sourceLineNo">396</span> public void reportTransition(MasterProcedureEnv env, RegionStateNode regionNode,<a name="line.396"></a>
+<span class="sourceLineNo">397</span> ServerName serverName, TransitionCode code, long seqId, long procId) throws IOException {<a name="line.397"></a>
+<span class="sourceLineNo">398</span> if (remoteProc == null) {<a name="line.398"></a>
+<span class="sourceLineNo">399</span> LOG.warn(<a name="line.399"></a>
+<span class="sourceLineNo">400</span> "There is no outstanding remote region procedure for {}, serverName={}, code={}," +<a name="line.400"></a>
+<span class="sourceLineNo">401</span> " seqId={}, proc={}, should be a retry, ignore",<a name="line.401"></a>
+<span class="sourceLineNo">402</span> regionNode, serverName, code, seqId, this);<a name="line.402"></a>
+<span class="sourceLineNo">403</span> return;<a name="line.403"></a>
+<span class="sourceLineNo">404</span> }<a name="line.404"></a>
+<span class="sourceLineNo">405</span> // The procId could be -1 if it is from an old region server, we need to deal with it so that we<a name="line.405"></a>
+<span class="sourceLineNo">406</span> // can do rolling upgraing.<a name="line.406"></a>
+<span class="sourceLineNo">407</span> if (procId >= 0 && remoteProc.getProcId() != procId) {<a name="line.407"></a>
+<span class="sourceLineNo">408</span> LOG.warn(<a name="line.408"></a>
+<span class="sourceLineNo">409</span> "The pid of remote region procedure for {} is {}, the reported pid={}, serverName={}," +<a name="line.409"></a>
+<span class="sourceLineNo">410</span> " code={}, seqId={}, proc={}, should be a retry, ignore",<a name="line.410"></a>
+<span class="sourceLineNo">411</span> regionNode, remoteProc.getProcId(), procId, serverName, code, seqId, this);<a name="line.411"></a>
+<span class="sourceLineNo">412</span> return;<a name="line.412"></a>
+<span class="sourceLineNo">413</span> }<a name="line.413"></a>
+<span class="sourceLineNo">414</span> remoteProc.reportTransition(env, regionNode, serverName, code, seqId);<a name="line.414"></a>
+<span class="sourceLineNo">415</span> }<a name="line.415"></a>
+<span class="sourceLineNo">416</span><a name="line.416"></a>
+<span class="sourceLineNo">417</span> // Should be called with RegionStateNode locked<a name="line.417"></a>
+<span class="sourceLineNo">418</span> public void serverCrashed(MasterProcedureEnv env, RegionStateNode regionNode,<a name="line.418"></a>
+<span class="sourceLineNo">419</span> ServerName serverName, boolean forceNewPlan) throws IOException {<a name="line.419"></a>
+<span class="sourceLineNo">420</span> this.forceNewPlan = forceNewPlan;<a name="line.420"></a>
+<span class="sourceLineNo">421</span> if (remoteProc != null) {<a name="line.421"></a>
+<span class="sourceLineNo">422</span> // this means we are waiting for the sub procedure, so wake it up<a name="line.422"></a>
+<span class="sourceLineNo">423</span> remoteProc.serverCrashed(env, regionNode, serverName);<a name="line.423"></a>
+<span class="sourceLineNo">424</span> } else {<a name="line.424"></a>
+<span class="sourceLineNo">425</span> // we are in RUNNING state, just update the region state, and we will process it later.<a name="line.425"></a>
+<span class="sourceLineNo">426</span> env.getAssignmentManager().regionClosedAbnormally(regionNode);<a name="line.426"></a>
+<span class="sourceLineNo">427</span> }<a name="line.427"></a>
+<span class="sourceLineNo">428</span> }<a name="line.428"></a>
+<span class="sourceLineNo">429</span><a name="line.429"></a>
+<span class="sourceLineNo">430</span> void attachRemoteProc(RegionRemoteProcedureBase proc) {<a name="line.430"></a>
+<span class="sourceLineNo">431</span> this.remoteProc = proc;<a name="line.431"></a>
+<span class="sourceLineNo">432</span> }<a name="line.432"></a>
+<span class="sourceLineNo">433</span><a name="line.433"></a>
+<span class="sourceLineNo">434</span> void unattachRemoteProc(RegionRemoteProcedureBase proc) {<a name="line.434"></a>
+<span class="sourceLineNo">435</span> assert this.remoteProc == proc;<a name="line.435"></a>
+<span class="sourceLineNo">436</span> this.remoteProc = null;<a name="line.436"></a>
+<span class="sourceLineNo">437</span> }<a name="line.437"></a>
+<span class="sourceLineNo">438</span><a name="line.438"></a>
+<span class="sourceLineNo">439</span> // will be called after we finish loading the meta entry for this region.<a name="line.439"></a>
+<span class="sourceLineNo">440</span> // used to change the state of the region node if we have a sub procedure, as we may not persist<a name="line.440"></a>
+<span class="sourceLineNo">441</span> // the state to meta yet. See the code in RegionRemoteProcedureBase.execute for more details.<a name="line.441"></a>
+<span class="sourceLineNo">442</span> void stateLoaded(AssignmentManager am, RegionStateNode regionNode) {<a name="line.442"></a>
+<span class="sourceLineNo">443</span> if (remoteProc != null) {<a name="line.443"></a>
+<span class="sourceLineNo">444</span> remoteProc.stateLoaded(am, regionNode);<a name="line.444"></a>
+<span class="sourceLineNo">445</span> }<a name="line.445"></a>
+<span class="sourceLineNo">446</span> }<a name="line.446"></a>
+<span class="sourceLineNo">447</span><a name="line.447"></a>
+<span class="sourceLineNo">448</span> @Override<a name="line.448"></a>
+<span class="sourceLineNo">449</span> protected void rollbackState(MasterProcedureEnv env, RegionStateTransitionState state)<a name="line.449"></a>
+<span class="sourceLineNo">450</span> throws IOException, InterruptedException {<a name="line.450"></a>
+<span class="sourceLineNo">451</span> // no rollback<a name="line.451"></a>
+<span class="sourceLineNo">452</span> throw new UnsupportedOperationException();<a name="line.452"></a>
+<span class="sourceLineNo">453</span> }<a name="line.453"></a>
+<span class="sourceLineNo">454</span><a name="line.454"></a>
+<span class="sourceLineNo">455</span> @Override<a name="line.455"></a>
+<span class="sourceLineNo">456</span> protected RegionStateTransitionState getState(int stateId) {<a name="line.456"></a>
+<span class="sourceLineNo">457</span> return RegionStateTransitionState.forNumber(stateId);<a name="line.457"></a>
+<span class="sourceLineNo">458</span> }<a name="line.458"></a>
+<span class="sourceLineNo">459</span><a name="line.459"></a>
+<span class="sourceLineNo">460</span> @Override<a name="line.460"></a>
+<span class="sourceLineNo">461</span> protected int getStateId(RegionStateTransitionState state) {<a name="line.461"></a>
+<span class="sourceLineNo">462</span> return state.getNumber();<a name="line.462"></a>
+<span class="sourceLineNo">463</span> }<a name="line.463"></a>
+<span class="sourceLineNo">464</span><a name="line.464"></a>
+<span class="sourceLineNo">465</span> @Override<a name="line.465"></a>
+<span class="sourceLineNo">466</span> protected RegionStateTransitionState getInitialState() {<a name="line.466"></a>
+<span class="sourceLineNo">467</span> return initialState;<a name="line.467"></a>
+<span class="sourceLineNo">468</span> }<a name="line.468"></a>
+<span class="sourceLineNo">469</span><a name="line.469"></a>
+<span class="sourceLineNo">470</span> private static TransitionType convert(RegionTransitionType type) {<a name="line.470"></a>
+<span class="sourceLineNo">471</span> switch (type) {<a name="line.471"></a>
+<span class="sourceLineNo">472</span> case ASSIGN:<a name="line.472"></a>
+<span class="sourceLineNo">473</span> return TransitionType.ASSIGN;<a name="line.473"></a>
+<span class="sourceLineNo">474</span> case UNASSIGN:<a name="line.474"></a>
+<span class="sourceLineNo">475</span> return TransitionType.UNASSIGN;<a name="line.475"></a>
+<span class="sourceLineNo">476</span> case MOVE:<a name="line.476"></a>
+<span class="sourceLineNo">477</span> return TransitionType.MOVE;<a name="line.477"></a>
+<span class="sourceLineNo">478</span> case REOPEN:<a name="line.478"></a>
+<span class="sourceLineNo">479</span> return TransitionType.REOPEN;<a name="line.479"></a>
+<span class="sourceLineNo">480</span> default:<a name="line.480"></a>
+<span class="sourceLineNo">481</span> throw new IllegalArgumentException("Unknown RegionTransitionType: " + type);<a name="line.481"></a>
+<span class="sourceLineNo">482</span> }<a name="line.482"></a>
+<span class="sourceLineNo">483</span> }<a name="line.483"></a>
+<span class="sourceLineNo">484</span><a name="line.484"></a>
+<span class="sourceLineNo">485</span> private static RegionTransitionType convert(TransitionType type) {<a name="line.485"></a>
+<span class="sourceLineNo">486</span> switch (type) {<a name="line.486"></a>
+<span class="sourceLineNo">487</span> case ASSIGN:<a name="line.487"></a>
+<span class="sourceLineNo">488</span> return RegionTransitionType.ASSIGN;<a name="line.488"></a>
+<span class="sourceLineNo">489</span> case UNASSIGN:<a name="line.489"></a>
+<span class="sourceLineNo">490</span> return RegionTransitionType.UNASSIGN;<a name="line.490"></a>
+<span class="sourceLineNo">491</span> case MOVE:<a name="line.491"></a>
+<span class="sourceLineNo">492</span> return RegionTransitionType.MOVE;<a name="line.492"></a>
+<span class="sourceLineNo">493</span> case REOPEN:<a name="line.493"></a>
+<span class="sourceLineNo">494</span> return RegionTransitionType.REOPEN;<a name="line.494"></a>
+<span class="sourceLineNo">495</span> default:<a name="line.495"></a>
+<span class="sourceLineNo">496</span> throw new IllegalArgumentException("Unknown TransitionType: " + type);<a name="line.496"></a>
+<span class="sourceLineNo">497</span> }<a name="line.497"></a>
+<span class="sourceLineNo">498</span> }<a name="line.498"></a>
+<span class="sourceLineNo">499</span><a name="line.499"></a>
+<span class="sourceLineNo">500</span> @Override<a name="line.500"></a>
+<span class="sourceLineNo">501</span> protected void serializeStateData(ProcedureStateSerializer serializer) throws IOException {<a name="line.501"></a>
+<span class="sourceLineNo">502</span> super.serializeStateData(serializer);<a name="line.502"></a>
+<span class="sourceLineNo">503</span> RegionStateTransitionStateData.Builder builder = RegionStateTransitionStateData.newBuilder()<a name="line.503"></a>
+<span class="sourceLineNo">504</span> .setType(convert(type)).setForceNewPlan(forceNewPlan);<a name="line.504"></a>
+<span class="sourceLineNo">505</span> if (assignCandidate != null) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span> builder.setAssignCandidate(ProtobufUtil.toServerName(assignCandidate));<a name="line.506"></a>
+<span class="sourceLineNo">507</span> }<a name="line.507"></a>
+<span class="sourceLineNo">508</span> serializer.serialize(builder.build());<a name="line.508"></a>
+<span class="sourceLineNo">509</span> }<a name="line.509"></a>
+<span class="sourceLineNo">510</span><a name="line.510"></a>
+<span class="sourceLineNo">511</span> @Override<a name="line.511"></a>
+<span class="sourceLineNo">512</span> protected void deserializeStateData(ProcedureStateSerializer serializer) throws IOException {<a name="line.512"></a>
+<span class="sourceLineNo">513</span> super.deserializeStateData(serializer);<a name="line.513"></a>
+<span class="sourceLineNo">514</span> RegionStateTransitionStateData data =<a name="line.514"></a>
+<span class="sourceLineNo">515</span> serializer.deserialize(RegionStateTransitionStateData.class);<a name="line.515"></a>
+<span class="sourceLineNo">516</span> type = convert(data.getType());<a name="line.516"></a>
+<span class="sourceLineNo">517</span> setInitialAndLastState();<a name="line.517"></a>
+<span class="sourceLineNo">518</span> forceNewPlan = data.getForceNewPlan();<a name="line.518"></a>
+<span class="sourceLineNo">519</span> if (data.hasAssignCandidate()) {<a name="line.519"></a>
+<span class="sourceLineNo">520</span> assignCandidate = ProtobufUtil.toServerName(data.getAssignCandidate());<a name="line.520"></a>
+<span class="sourceLineNo">521</span> }<a name="line.521"></a>
+<span class="sourceLineNo">522</span> }<a name="line.522"></a>
+<span class="sourceLineNo">523</span><a name="line.523"></a>
+<span class="sourceLineNo">524</span> @Override<a name="line.524"></a>
+<span class="sourceLineNo">525</span> protected ProcedureMetrics getProcedureMetrics(MasterProcedureEnv env) {<a name="line.525"></a>
+<span class="sourceLineNo">526</span> MetricsAssignmentManager metrics = env.getAssignmentManager().getAssignmentManagerMetrics();<a name="line.526"></a>
+<span class="sourceLineNo">527</span> switch (type) {<a name="line.527"></a>
+<span class="sourceLineNo">528</span> case ASSIGN:<a name="line.528"></a>
+<span class="sourceLineNo">529</span> return metrics.getAssignProcMetrics();<a name="line.529"></a>
+<span class="sourceLineNo">530</span> case UNASSIGN:<a name="line.530"></a>
+<span class="sourceLineNo">531</span> return metrics.getUnassignProcMetrics();<a name="line.531"></a>
+<span class="sourceLineNo">532</span> case MOVE:<a name="line.532"></a>
+<span class="sourceLineNo">533</span> return metrics.getMoveProcMetrics();<a name="line.533"></a>
+<span class="sourceLineNo">534</span> case REOPEN:<a name="line.534"></a>
+<span class="sourceLineNo">535</span> return metrics.getReopenProcMetrics();<a name="line.535"></a>
+<span class="sourceLineNo">536</span> default:<a name="line.536"></a>
+<span class="sourceLineNo">537</span> throw new IllegalArgumentException("Unknown transition type: " + type);<a name="line.537"></a>
+<span class="sourceLineNo">538</span> }<a name="line.538"></a>
+<span class="sourceLineNo">539</span> }<a name="line.539"></a>
+<span class="sourceLineNo">540</span><a name="line.540"></a>
+<span class="sourceLineNo">541</span> @Override<a name="line.541"></a>
+<span class="sourceLineNo">542</span> public void toStringClassDetails(StringBuilder sb) {<a name="line.542"></a>
+<span class="sourceLineNo">543</span> super.toStringClassDetails(sb);<a name="line.543"></a>
+<span class="sourceLineNo">544</span> if (initialState == RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE) {<a name="line.544"></a>
+<span class="sourceLineNo">545</span> sb.append(", ASSIGN");<a name="line.545"></a>
+<span class="sourceLineNo">546</span> } else if (lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED) {<a name="line.546"></a>
+<span class="sourceLineNo">547</span> sb.append(", UNASSIGN");<a name="line.547"></a>
+<span class="sourceLineNo">548</span> } else {<a name="line.548"></a>
+<span class="sourceLineNo">549</span> sb.append(", REOPEN/MOVE");<a name="line.549"></a>
+<span class="sourceLineNo">550</span> }<a name="line.550"></a>
+<span class="sourceLineNo">551</span> }<a name="line.551"></a>
+<span class="sourceLineNo">552</span><a name="line.552"></a>
+<span class="sourceLineNo">553</span> private static TransitRegionStateProcedure setOwner(MasterProcedureEnv env,<a name="line.553"></a>
+<span class="sourceLineNo">554</span> TransitRegionStateProcedure proc) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span> proc.setOwner(env.getRequestUser().getShortName());<a name="line.555"></a>
+<span class="sourceLineNo">556</span> return proc;<a name="line.556"></a>
+<span class="sourceLineNo">557</span> }<a name="line.557"></a>
+<span class="sourceLineNo">558</span><a name="line.558"></a>
+<span class="sourceLineNo">559</span> public enum TransitionType {<a name="line.559"></a>
+<span class="sourceLineNo">560</span> ASSIGN, UNASSIGN, MOVE, REOPEN<a name="line.560"></a>
+<span class="sourceLineNo">561</span> }<a name="line.561"></a>
+<span class="sourceLineNo">562</span><a name="line.562"></a>
+<span class="sourceLineNo">563</span> // Be careful that, when you call these 4 methods below, you need to manually attach the returned<a name="line.563"></a>
+<span class="sourceLineNo">564</span> // procedure with the RegionStateNode, otherwise the procedure will quit immediately without doing<a name="line.564"></a>
+<span class="sourceLineNo">565</span> // anything. See the comment in executeFromState to find out why we need this assumption.<a name="line.565"></a>
+<span class="sourceLineNo">566</span> public static TransitRegionStateProcedure assign(MasterProcedureEnv env, RegionInfo region,<a name="line.566"></a>
+<span class="sourceLineNo">567</span> @Nullable ServerName targetServer) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span> return assign(env, region, false, targetServer);<a name="line.568"></a>
+<span class="sourceLineNo">569</span> }<a name="line.569"></a>
+<span class="sourceLineNo">570</span><a name="line.570"></a>
+<span class="sourceLineNo">571</span> public static TransitRegionStateProcedure assign(MasterProcedureEnv env, RegionInfo region,<a name="line.571"></a>
+<span class="sourceLineNo">572</span> boolean forceNewPlan, @Nullable ServerName targetServer) {<a name="line.572"></a>
+<span class="sourceLineNo">573</span> return setOwner(env, new TransitRegionStateProcedure(env, region, targetServer, forceNewPlan,<a name="line.573"></a>
+<span class="sourceLineNo">574</span> TransitionType.ASSIGN));<a name="line.574"></a>
+<span class="sourceLineNo">575</span> }<a name="line.575"></a>
+<span class="sourceLineNo">576</span><a name="line.576"></a>
+<span class="sourceLineNo">577</span> public static TransitRegionStateProcedure unassign(MasterProcedureEnv env, RegionInfo region) {<a name="line.577"></a>
+<span class="sourceLineNo">578</span> return setOwner(env,<a name="line.578"></a>
+<span class="sourceLineNo">579</span> new TransitRegionStateProcedure(env, region, null, false, TransitionType.UNASSIGN));<a name="line.579"></a>
+<span class="sourceLineNo">580</span> }<a name="line.580"></a>
+<span class="sourceLineNo">581</span><a name="line.581"></a>
+<span class="sourceLineNo">582</span> public static TransitRegionStateProcedure reopen(MasterProcedureEnv env, RegionInfo region) {<a name="line.582"></a>
+<span class="sourceLineNo">583</span> return setOwner(env,<a name="line.583"></a>
+<span class="sourceLineNo">584</span> new TransitRegionStateProcedure(env, region, null, false, TransitionType.REOPEN));<a name="line.584"></a>
+<span class="sourceLineNo">585</span> }<a name="line.585"></a>
+<span class="sourceLineNo">586</span><a name="line.586"></a>
+<span class="sourceLineNo">587</span> public static TransitRegionStateProcedure move(MasterProcedureEnv env, RegionInfo region,<a name="line.587"></a>
+<span class="sourceLineNo">588</span> @Nullable ServerName targetServer) {<a name="line.588"></a>
+<span class="sourceLineNo">589</span> return setOwner(env, new TransitRegionStateProcedure(env, region, targetServer,<a name="line.589"></a>
+<span class="sourceLineNo">590</span> targetServer == null, TransitionType.MOVE));<a name="line.590"></a>
+<span class="sourceLineNo">591</span> }<a name="line.591"></a>
+<span class="sourceLineNo">592</span>}<a name="line.592"></a>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html b/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html
index 3392220..3a56a19 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.html
@@ -25,577 +25,579 @@
<span class="sourceLineNo">017</span> */<a name="line.17"></a>
<span class="sourceLineNo">018</span>package org.apache.hadoop.hbase.master.assignment;<a name="line.18"></a>
<span class="sourceLineNo">019</span><a name="line.19"></a>
-<span class="sourceLineNo">020</span>import edu.umd.cs.findbugs.annotations.Nullable;<a name="line.20"></a>
-<span class="sourceLineNo">021</span>import java.io.IOException;<a name="line.21"></a>
-<span class="sourceLineNo">022</span>import org.apache.hadoop.hbase.HBaseIOException;<a name="line.22"></a>
-<span class="sourceLineNo">023</span>import org.apache.hadoop.hbase.ServerName;<a name="line.23"></a>
-<span class="sourceLineNo">024</span>import org.apache.hadoop.hbase.TableName;<a name="line.24"></a>
-<span class="sourceLineNo">025</span>import org.apache.hadoop.hbase.client.RegionInfo;<a name="line.25"></a>
-<span class="sourceLineNo">026</span>import org.apache.hadoop.hbase.client.RegionReplicaUtil;<a name="line.26"></a>
-<span class="sourceLineNo">027</span>import org.apache.hadoop.hbase.client.RetriesExhaustedException;<a name="line.27"></a>
-<span class="sourceLineNo">028</span>import org.apache.hadoop.hbase.master.MetricsAssignmentManager;<a name="line.28"></a>
-<span class="sourceLineNo">029</span>import org.apache.hadoop.hbase.master.RegionState.State;<a name="line.29"></a>
-<span class="sourceLineNo">030</span>import org.apache.hadoop.hbase.master.procedure.AbstractStateMachineRegionProcedure;<a name="line.30"></a>
-<span class="sourceLineNo">031</span>import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;<a name="line.31"></a>
-<span class="sourceLineNo">032</span>import org.apache.hadoop.hbase.master.procedure.ServerCrashProcedure;<a name="line.32"></a>
-<span class="sourceLineNo">033</span>import org.apache.hadoop.hbase.procedure2.Procedure;<a name="line.33"></a>
-<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.procedure2.ProcedureMetrics;<a name="line.34"></a>
-<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer;<a name="line.35"></a>
-<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.procedure2.ProcedureSuspendedException;<a name="line.36"></a>
-<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.procedure2.ProcedureUtil;<a name="line.37"></a>
-<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.procedure2.ProcedureYieldException;<a name="line.38"></a>
-<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.util.RetryCounter;<a name="line.39"></a>
-<span class="sourceLineNo">040</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.40"></a>
-<span class="sourceLineNo">041</span>import org.slf4j.Logger;<a name="line.41"></a>
-<span class="sourceLineNo">042</span>import org.slf4j.LoggerFactory;<a name="line.42"></a>
-<span class="sourceLineNo">043</span><a name="line.43"></a>
-<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.44"></a>
-<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState;<a name="line.45"></a>
-<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionStateData;<a name="line.46"></a>
-<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionTransitionType;<a name="line.47"></a>
-<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos;<a name="line.48"></a>
-<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionStateTransition.TransitionCode;<a name="line.49"></a>
-<span class="sourceLineNo">050</span><a name="line.50"></a>
-<span class="sourceLineNo">051</span>/**<a name="line.51"></a>
-<span class="sourceLineNo">052</span> * The procedure to deal with the state transition of a region. A region with a TRSP in place is<a name="line.52"></a>
-<span class="sourceLineNo">053</span> * called RIT, i.e, RegionInTransition.<a name="line.53"></a>
-<span class="sourceLineNo">054</span> * <p/><a name="line.54"></a>
-<span class="sourceLineNo">055</span> * It can be used to assign/unassign/reopen/move a region, and for<a name="line.55"></a>
-<span class="sourceLineNo">056</span> * {@link #unassign(MasterProcedureEnv, RegionInfo)} and<a name="line.56"></a>
-<span class="sourceLineNo">057</span> * {@link #reopen(MasterProcedureEnv, RegionInfo)}, you do not need to specify a target server, and<a name="line.57"></a>
-<span class="sourceLineNo">058</span> * for {@link #assign(MasterProcedureEnv, RegionInfo, ServerName)} and<a name="line.58"></a>
-<span class="sourceLineNo">059</span> * {@link #move(MasterProcedureEnv, RegionInfo, ServerName)}, if you want to you can provide a<a name="line.59"></a>
-<span class="sourceLineNo">060</span> * target server. And for {@link #move(MasterProcedureEnv, RegionInfo, ServerName)}, if you do not<a name="line.60"></a>
-<span class="sourceLineNo">061</span> * specify a targetServer, we will select one randomly.<a name="line.61"></a>
-<span class="sourceLineNo">062</span> * <p/><a name="line.62"></a>
-<span class="sourceLineNo">063</span> * <p/><a name="line.63"></a>
-<span class="sourceLineNo">064</span> * The typical state transition for assigning a region is:<a name="line.64"></a>
-<span class="sourceLineNo">065</span> *<a name="line.65"></a>
-<span class="sourceLineNo">066</span> * <pre><a name="line.66"></a>
-<span class="sourceLineNo">067</span> * GET_ASSIGN_CANDIDATE ------> OPEN -----> CONFIRM_OPENED<a name="line.67"></a>
-<span class="sourceLineNo">068</span> * </pre><a name="line.68"></a>
-<span class="sourceLineNo">069</span> *<a name="line.69"></a>
-<span class="sourceLineNo">070</span> * Notice that, if there are failures we may go back to the {@code GET_ASSIGN_CANDIDATE} state to<a name="line.70"></a>
-<span class="sourceLineNo">071</span> * try again.<a name="line.71"></a>
-<span class="sourceLineNo">072</span> * <p/><a name="line.72"></a>
-<span class="sourceLineNo">073</span> * The typical state transition for unassigning a region is:<a name="line.73"></a>
-<span class="sourceLineNo">074</span> *<a name="line.74"></a>
-<span class="sourceLineNo">075</span> * <pre><a name="line.75"></a>
-<span class="sourceLineNo">076</span> * CLOSE -----> CONFIRM_CLOSED<a name="line.76"></a>
-<span class="sourceLineNo">077</span> * </pre><a name="line.77"></a>
-<span class="sourceLineNo">078</span> *<a name="line.78"></a>
-<span class="sourceLineNo">079</span> * Here things go a bit different, if there are failures, especially that if there is a server<a name="line.79"></a>
-<span class="sourceLineNo">080</span> * crash, we will go to the {@code GET_ASSIGN_CANDIDATE} state to bring the region online first, and<a name="line.80"></a>
-<span class="sourceLineNo">081</span> * then go through the normal way to unassign it.<a name="line.81"></a>
-<span class="sourceLineNo">082</span> * <p/><a name="line.82"></a>
-<span class="sourceLineNo">083</span> * The typical state transition for reopening/moving a region is:<a name="line.83"></a>
-<span class="sourceLineNo">084</span> *<a name="line.84"></a>
-<span class="sourceLineNo">085</span> * <pre><a name="line.85"></a>
-<span class="sourceLineNo">086</span> * CLOSE -----> CONFIRM_CLOSED -----> GET_ASSIGN_CANDIDATE ------> OPEN -----> CONFIRM_OPENED<a name="line.86"></a>
-<span class="sourceLineNo">087</span> * </pre><a name="line.87"></a>
-<span class="sourceLineNo">088</span> *<a name="line.88"></a>
-<span class="sourceLineNo">089</span> * The retry logic is the same with the above assign/unassign.<a name="line.89"></a>
-<span class="sourceLineNo">090</span> * <p/><a name="line.90"></a>
-<span class="sourceLineNo">091</span> * Notice that, although we allow specify a target server, it just acts as a candidate, we do not<a name="line.91"></a>
-<span class="sourceLineNo">092</span> * guarantee that the region will finally be on the target server. If this is important for you, you<a name="line.92"></a>
-<span class="sourceLineNo">093</span> * should check whether the region is on the target server after the procedure is finished.<a name="line.93"></a>
-<span class="sourceLineNo">094</span> * <p/><a name="line.94"></a>
-<span class="sourceLineNo">095</span> * When you want to schedule a TRSP, please check whether there is still one for this region, and<a name="line.95"></a>
-<span class="sourceLineNo">096</span> * the check should be under the RegionStateNode lock. We will remove the TRSP from a<a name="line.96"></a>
-<span class="sourceLineNo">097</span> * RegionStateNode when we are done, see the code in {@code reportTransition} method below. There<a name="line.97"></a>
-<span class="sourceLineNo">098</span> * could be at most one TRSP for a give region.<a name="line.98"></a>
-<span class="sourceLineNo">099</span> */<a name="line.99"></a>
-<span class="sourceLineNo">100</span>@InterfaceAudience.Private<a name="line.100"></a>
-<span class="sourceLineNo">101</span>public class TransitRegionStateProcedure<a name="line.101"></a>
-<span class="sourceLineNo">102</span> extends AbstractStateMachineRegionProcedure<RegionStateTransitionState> {<a name="line.102"></a>
-<span class="sourceLineNo">103</span><a name="line.103"></a>
-<span class="sourceLineNo">104</span> private static final Logger LOG = LoggerFactory.getLogger(TransitRegionStateProcedure.class);<a name="line.104"></a>
+<span class="sourceLineNo">020</span>import static org.apache.hadoop.hbase.master.LoadBalancer.BOGUS_SERVER_NAME;<a name="line.20"></a>
+<span class="sourceLineNo">021</span><a name="line.21"></a>
+<span class="sourceLineNo">022</span>import edu.umd.cs.findbugs.annotations.Nullable;<a name="line.22"></a>
+<span class="sourceLineNo">023</span>import java.io.IOException;<a name="line.23"></a>
+<span class="sourceLineNo">024</span>import org.apache.hadoop.hbase.HBaseIOException;<a name="line.24"></a>
+<span class="sourceLineNo">025</span>import org.apache.hadoop.hbase.ServerName;<a name="line.25"></a>
+<span class="sourceLineNo">026</span>import org.apache.hadoop.hbase.TableName;<a name="line.26"></a>
+<span class="sourceLineNo">027</span>import org.apache.hadoop.hbase.client.RegionInfo;<a name="line.27"></a>
+<span class="sourceLineNo">028</span>import org.apache.hadoop.hbase.client.RegionReplicaUtil;<a name="line.28"></a>
+<span class="sourceLineNo">029</span>import org.apache.hadoop.hbase.client.RetriesExhaustedException;<a name="line.29"></a>
+<span class="sourceLineNo">030</span>import org.apache.hadoop.hbase.master.MetricsAssignmentManager;<a name="line.30"></a>
+<span class="sourceLineNo">031</span>import org.apache.hadoop.hbase.master.RegionState.State;<a name="line.31"></a>
+<span class="sourceLineNo">032</span>import org.apache.hadoop.hbase.master.procedure.AbstractStateMachineRegionProcedure;<a name="line.32"></a>
+<span class="sourceLineNo">033</span>import org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv;<a name="line.33"></a>
+<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.master.procedure.ServerCrashProcedure;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.procedure2.Procedure;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.procedure2.ProcedureMetrics;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.procedure2.ProcedureStateSerializer;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.procedure2.ProcedureSuspendedException;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.procedure2.ProcedureUtil;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.procedure2.ProcedureYieldException;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.util.RetryCounter;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.slf4j.Logger;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.slf4j.LoggerFactory;<a name="line.44"></a>
+<span class="sourceLineNo">045</span><a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionState;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionStateTransitionStateData;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MasterProcedureProtos.RegionTransitionType;<a name="line.49"></a>
+<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos;<a name="line.50"></a>
+<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionStateTransition.TransitionCode;<a name="line.51"></a>
+<span class="sourceLineNo">052</span><a name="line.52"></a>
+<span class="sourceLineNo">053</span>/**<a name="line.53"></a>
+<span class="sourceLineNo">054</span> * The procedure to deal with the state transition of a region. A region with a TRSP in place is<a name="line.54"></a>
+<span class="sourceLineNo">055</span> * called RIT, i.e, RegionInTransition.<a name="line.55"></a>
+<span class="sourceLineNo">056</span> * <p/><a name="line.56"></a>
+<span class="sourceLineNo">057</span> * It can be used to assign/unassign/reopen/move a region, and for<a name="line.57"></a>
+<span class="sourceLineNo">058</span> * {@link #unassign(MasterProcedureEnv, RegionInfo)} and<a name="line.58"></a>
+<span class="sourceLineNo">059</span> * {@link #reopen(MasterProcedureEnv, RegionInfo)}, you do not need to specify a target server, and<a name="line.59"></a>
+<span class="sourceLineNo">060</span> * for {@link #assign(MasterProcedureEnv, RegionInfo, ServerName)} and<a name="line.60"></a>
+<span class="sourceLineNo">061</span> * {@link #move(MasterProcedureEnv, RegionInfo, ServerName)}, if you want to you can provide a<a name="line.61"></a>
+<span class="sourceLineNo">062</span> * target server. And for {@link #move(MasterProcedureEnv, RegionInfo, ServerName)}, if you do not<a name="line.62"></a>
+<span class="sourceLineNo">063</span> * specify a targetServer, we will select one randomly.<a name="line.63"></a>
+<span class="sourceLineNo">064</span> * <p/><a name="line.64"></a>
+<span class="sourceLineNo">065</span> * <p/><a name="line.65"></a>
+<span class="sourceLineNo">066</span> * The typical state transition for assigning a region is:<a name="line.66"></a>
+<span class="sourceLineNo">067</span> *<a name="line.67"></a>
+<span class="sourceLineNo">068</span> * <pre><a name="line.68"></a>
+<span class="sourceLineNo">069</span> * GET_ASSIGN_CANDIDATE ------> OPEN -----> CONFIRM_OPENED<a name="line.69"></a>
+<span class="sourceLineNo">070</span> * </pre><a name="line.70"></a>
+<span class="sourceLineNo">071</span> *<a name="line.71"></a>
+<span class="sourceLineNo">072</span> * Notice that, if there are failures we may go back to the {@code GET_ASSIGN_CANDIDATE} state to<a name="line.72"></a>
+<span class="sourceLineNo">073</span> * try again.<a name="line.73"></a>
+<span class="sourceLineNo">074</span> * <p/><a name="line.74"></a>
+<span class="sourceLineNo">075</span> * The typical state transition for unassigning a region is:<a name="line.75"></a>
+<span class="sourceLineNo">076</span> *<a name="line.76"></a>
+<span class="sourceLineNo">077</span> * <pre><a name="line.77"></a>
+<span class="sourceLineNo">078</span> * CLOSE -----> CONFIRM_CLOSED<a name="line.78"></a>
+<span class="sourceLineNo">079</span> * </pre><a name="line.79"></a>
+<span class="sourceLineNo">080</span> *<a name="line.80"></a>
+<span class="sourceLineNo">081</span> * Here things go a bit different, if there are failures, especially that if there is a server<a name="line.81"></a>
+<span class="sourceLineNo">082</span> * crash, we will go to the {@code GET_ASSIGN_CANDIDATE} state to bring the region online first, and<a name="line.82"></a>
+<span class="sourceLineNo">083</span> * then go through the normal way to unassign it.<a name="line.83"></a>
+<span class="sourceLineNo">084</span> * <p/><a name="line.84"></a>
+<span class="sourceLineNo">085</span> * The typical state transition for reopening/moving a region is:<a name="line.85"></a>
+<span class="sourceLineNo">086</span> *<a name="line.86"></a>
+<span class="sourceLineNo">087</span> * <pre><a name="line.87"></a>
+<span class="sourceLineNo">088</span> * CLOSE -----> CONFIRM_CLOSED -----> GET_ASSIGN_CANDIDATE ------> OPEN -----> CONFIRM_OPENED<a name="line.88"></a>
+<span class="sourceLineNo">089</span> * </pre><a name="line.89"></a>
+<span class="sourceLineNo">090</span> *<a name="line.90"></a>
+<span class="sourceLineNo">091</span> * The retry logic is the same with the above assign/unassign.<a name="line.91"></a>
+<span class="sourceLineNo">092</span> * <p/><a name="line.92"></a>
+<span class="sourceLineNo">093</span> * Notice that, although we allow specify a target server, it just acts as a candidate, we do not<a name="line.93"></a>
+<span class="sourceLineNo">094</span> * guarantee that the region will finally be on the target server. If this is important for you, you<a name="line.94"></a>
+<span class="sourceLineNo">095</span> * should check whether the region is on the target server after the procedure is finished.<a name="line.95"></a>
+<span class="sourceLineNo">096</span> * <p/><a name="line.96"></a>
+<span class="sourceLineNo">097</span> * When you want to schedule a TRSP, please check whether there is still one for this region, and<a name="line.97"></a>
+<span class="sourceLineNo">098</span> * the check should be under the RegionStateNode lock. We will remove the TRSP from a<a name="line.98"></a>
+<span class="sourceLineNo">099</span> * RegionStateNode when we are done, see the code in {@code reportTransition} method below. There<a name="line.99"></a>
+<span class="sourceLineNo">100</span> * could be at most one TRSP for a give region.<a name="line.100"></a>
+<span class="sourceLineNo">101</span> */<a name="line.101"></a>
+<span class="sourceLineNo">102</span>@InterfaceAudience.Private<a name="line.102"></a>
+<span class="sourceLineNo">103</span>public class TransitRegionStateProcedure<a name="line.103"></a>
+<span class="sourceLineNo">104</span> extends AbstractStateMachineRegionProcedure<RegionStateTransitionState> {<a name="line.104"></a>
<span class="sourceLineNo">105</span><a name="line.105"></a>
-<span class="sourceLineNo">106</span> private TransitionType type;<a name="line.106"></a>
+<span class="sourceLineNo">106</span> private static final Logger LOG = LoggerFactory.getLogger(TransitRegionStateProcedure.class);<a name="line.106"></a>
<span class="sourceLineNo">107</span><a name="line.107"></a>
-<span class="sourceLineNo">108</span> private RegionStateTransitionState initialState;<a name="line.108"></a>
+<span class="sourceLineNo">108</span> private TransitionType type;<a name="line.108"></a>
<span class="sourceLineNo">109</span><a name="line.109"></a>
-<span class="sourceLineNo">110</span> private RegionStateTransitionState lastState;<a name="line.110"></a>
+<span class="sourceLineNo">110</span> private RegionStateTransitionState initialState;<a name="line.110"></a>
<span class="sourceLineNo">111</span><a name="line.111"></a>
-<span class="sourceLineNo">112</span> // the candidate where we want to assign the region to.<a name="line.112"></a>
-<span class="sourceLineNo">113</span> private ServerName assignCandidate;<a name="line.113"></a>
-<span class="sourceLineNo">114</span><a name="line.114"></a>
-<span class="sourceLineNo">115</span> private boolean forceNewPlan;<a name="line.115"></a>
+<span class="sourceLineNo">112</span> private RegionStateTransitionState lastState;<a name="line.112"></a>
+<span class="sourceLineNo">113</span><a name="line.113"></a>
+<span class="sourceLineNo">114</span> // the candidate where we want to assign the region to.<a name="line.114"></a>
+<span class="sourceLineNo">115</span> private ServerName assignCandidate;<a name="line.115"></a>
<span class="sourceLineNo">116</span><a name="line.116"></a>
-<span class="sourceLineNo">117</span> private RetryCounter retryCounter;<a name="line.117"></a>
+<span class="sourceLineNo">117</span> private boolean forceNewPlan;<a name="line.117"></a>
<span class="sourceLineNo">118</span><a name="line.118"></a>
-<span class="sourceLineNo">119</span> private RegionRemoteProcedureBase remoteProc;<a name="line.119"></a>
+<span class="sourceLineNo">119</span> private RetryCounter retryCounter;<a name="line.119"></a>
<span class="sourceLineNo">120</span><a name="line.120"></a>
-<span class="sourceLineNo">121</span> public TransitRegionStateProcedure() {<a name="line.121"></a>
-<span class="sourceLineNo">122</span> }<a name="line.122"></a>
-<span class="sourceLineNo">123</span><a name="line.123"></a>
-<span class="sourceLineNo">124</span> private void setInitialAndLastState() {<a name="line.124"></a>
-<span class="sourceLineNo">125</span> switch (type) {<a name="line.125"></a>
-<span class="sourceLineNo">126</span> case ASSIGN:<a name="line.126"></a>
-<span class="sourceLineNo">127</span> initialState = RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE;<a name="line.127"></a>
-<span class="sourceLineNo">128</span> lastState = RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED;<a name="line.128"></a>
-<span class="sourceLineNo">129</span> break;<a name="line.129"></a>
-<span class="sourceLineNo">130</span> case UNASSIGN:<a name="line.130"></a>
-<span class="sourceLineNo">131</span> initialState = RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE;<a name="line.131"></a>
-<span class="sourceLineNo">132</span> lastState = RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED;<a name="line.132"></a>
-<span class="sourceLineNo">133</span> break;<a name="line.133"></a>
-<span class="sourceLineNo">134</span> case MOVE:<a name="line.134"></a>
-<span class="sourceLineNo">135</span> case REOPEN:<a name="line.135"></a>
-<span class="sourceLineNo">136</span> initialState = RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE;<a name="line.136"></a>
-<span class="sourceLineNo">137</span> lastState = RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED;<a name="line.137"></a>
-<span class="sourceLineNo">138</span> break;<a name="line.138"></a>
-<span class="sourceLineNo">139</span> default:<a name="line.139"></a>
-<span class="sourceLineNo">140</span> throw new IllegalArgumentException("Unknown TransitionType: " + type);<a name="line.140"></a>
-<span class="sourceLineNo">141</span> }<a name="line.141"></a>
-<span class="sourceLineNo">142</span> }<a name="line.142"></a>
-<span class="sourceLineNo">143</span><a name="line.143"></a>
-<span class="sourceLineNo">144</span> protected TransitRegionStateProcedure(MasterProcedureEnv env, RegionInfo hri,<a name="line.144"></a>
-<span class="sourceLineNo">145</span> ServerName assignCandidate, boolean forceNewPlan, TransitionType type) {<a name="line.145"></a>
-<span class="sourceLineNo">146</span> super(env, hri);<a name="line.146"></a>
-<span class="sourceLineNo">147</span> this.assignCandidate = assignCandidate;<a name="line.147"></a>
-<span class="sourceLineNo">148</span> this.forceNewPlan = forceNewPlan;<a name="line.148"></a>
-<span class="sourceLineNo">149</span> this.type = type;<a name="line.149"></a>
-<span class="sourceLineNo">150</span> setInitialAndLastState();<a name="line.150"></a>
-<span class="sourceLineNo">151</span><a name="line.151"></a>
-<span class="sourceLineNo">152</span> // when do reopen TRSP, let the rs know the targetServer so it can keep some info on close<a name="line.152"></a>
-<span class="sourceLineNo">153</span> if (type == TransitionType.REOPEN) {<a name="line.153"></a>
-<span class="sourceLineNo">154</span> this.assignCandidate = getRegionStateNode(env).getRegionLocation();<a name="line.154"></a>
-<span class="sourceLineNo">155</span> }<a name="line.155"></a>
-<span class="sourceLineNo">156</span> }<a name="line.156"></a>
-<span class="sourceLineNo">157</span><a name="line.157"></a>
-<span class="sourceLineNo">158</span> @Override<a name="line.158"></a>
-<span class="sourceLineNo">159</span> public TableOperationType getTableOperationType() {<a name="line.159"></a>
-<span class="sourceLineNo">160</span> // TODO: maybe we should make another type here, REGION_TRANSITION?<a name="line.160"></a>
-<span class="sourceLineNo">161</span> return TableOperationType.REGION_EDIT;<a name="line.161"></a>
-<span class="sourceLineNo">162</span> }<a name="line.162"></a>
-<span class="sourceLineNo">163</span><a name="line.163"></a>
-<span class="sourceLineNo">164</span> @Override<a name="line.164"></a>
-<span class="sourceLineNo">165</span> protected boolean waitInitialized(MasterProcedureEnv env) {<a name="line.165"></a>
-<span class="sourceLineNo">166</span> if (TableName.isMetaTableName(getTableName())) {<a name="line.166"></a>
-<span class="sourceLineNo">167</span> return false;<a name="line.167"></a>
-<span class="sourceLineNo">168</span> }<a name="line.168"></a>
-<span class="sourceLineNo">169</span> // First we need meta to be loaded, and second, if meta is not online then we will likely to<a name="line.169"></a>
-<span class="sourceLineNo">170</span> // fail when updating meta so we wait until it is assigned.<a name="line.170"></a>
-<span class="sourceLineNo">171</span> AssignmentManager am = env.getAssignmentManager();<a name="line.171"></a>
-<span class="sourceLineNo">172</span> return am.waitMetaLoaded(this) || am.waitMetaAssigned(this, getRegion());<a name="line.172"></a>
-<span class="sourceLineNo">173</span> }<a name="line.173"></a>
-<span class="sourceLineNo">174</span><a name="line.174"></a>
-<span class="sourceLineNo">175</span> private void queueAssign(MasterProcedureEnv env, RegionStateNode regionNode)<a name="line.175"></a>
-<span class="sourceLineNo">176</span> throws ProcedureSuspendedException {<a name="line.176"></a>
-<span class="sourceLineNo">177</span> boolean retain = false;<a name="line.177"></a>
-<span class="sourceLineNo">178</span> if (forceNewPlan) {<a name="line.178"></a>
-<span class="sourceLineNo">179</span> // set the region location to null if forceNewPlan is true<a name="line.179"></a>
-<span class="sourceLineNo">180</span> regionNode.setRegionLocation(null);<a name="line.180"></a>
-<span class="sourceLineNo">181</span> } else {<a name="line.181"></a>
-<span class="sourceLineNo">182</span> if (assignCandidate != null) {<a name="line.182"></a>
-<span class="sourceLineNo">183</span> retain = assignCandidate.equals(regionNode.getLastHost());<a name="line.183"></a>
-<span class="sourceLineNo">184</span> regionNode.setRegionLocation(assignCandidate);<a name="line.184"></a>
-<span class="sourceLineNo">185</span> } else if (regionNode.getLastHost() != null) {<a name="line.185"></a>
-<span class="sourceLineNo">186</span> retain = true;<a name="line.186"></a>
-<span class="sourceLineNo">187</span> LOG.info("Setting lastHost as the region location {}", regionNode.getLastHost());<a name="line.187"></a>
-<span class="sourceLineNo">188</span> regionNode.setRegionLocation(regionNode.getLastHost());<a name="line.188"></a>
-<span class="sourceLineNo">189</span> }<a name="line.189"></a>
-<span class="sourceLineNo">190</span> }<a name="line.190"></a>
-<span class="sourceLineNo">191</span> LOG.info("Starting {}; {}; forceNewPlan={}, retain={}", this, regionNode.toShortString(),<a name="line.191"></a>
-<span class="sourceLineNo">192</span> forceNewPlan, retain);<a name="line.192"></a>
-<span class="sourceLineNo">193</span> env.getAssignmentManager().queueAssign(regionNode);<a name="line.193"></a>
-<span class="sourceLineNo">194</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_OPEN);<a name="line.194"></a>
-<span class="sourceLineNo">195</span> if (regionNode.getProcedureEvent().suspendIfNotReady(this)) {<a name="line.195"></a>
-<span class="sourceLineNo">196</span> throw new ProcedureSuspendedException();<a name="line.196"></a>
-<span class="sourceLineNo">197</span> }<a name="line.197"></a>
-<span class="sourceLineNo">198</span> }<a name="line.198"></a>
-<span class="sourceLineNo">199</span><a name="line.199"></a>
-<span class="sourceLineNo">200</span> private void openRegion(MasterProcedureEnv env, RegionStateNode regionNode) throws IOException {<a name="line.200"></a>
-<span class="sourceLineNo">201</span> ServerName loc = regionNode.getRegionLocation();<a name="line.201"></a>
-<span class="sourceLineNo">202</span> if (loc == null) {<a name="line.202"></a>
-<span class="sourceLineNo">203</span> LOG.warn("No location specified for {}, jump back to state {} to get one", getRegion(),<a name="line.203"></a>
-<span class="sourceLineNo">204</span> RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.204"></a>
-<span class="sourceLineNo">205</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.205"></a>
-<span class="sourceLineNo">206</span> return;<a name="line.206"></a>
-<span class="sourceLineNo">207</span> }<a name="line.207"></a>
-<span class="sourceLineNo">208</span> env.getAssignmentManager().regionOpening(regionNode);<a name="line.208"></a>
-<span class="sourceLineNo">209</span> addChildProcedure(new OpenRegionProcedure(this, getRegion(), loc));<a name="line.209"></a>
-<span class="sourceLineNo">210</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED);<a name="line.210"></a>
-<span class="sourceLineNo">211</span> }<a name="line.211"></a>
-<span class="sourceLineNo">212</span><a name="line.212"></a>
-<span class="sourceLineNo">213</span> private Flow confirmOpened(MasterProcedureEnv env, RegionStateNode regionNode)<a name="line.213"></a>
-<span class="sourceLineNo">214</span> throws IOException {<a name="line.214"></a>
-<span class="sourceLineNo">215</span> if (regionNode.isInState(State.OPEN)) {<a name="line.215"></a>
-<span class="sourceLineNo">216</span> retryCounter = null;<a name="line.216"></a>
-<span class="sourceLineNo">217</span> if (lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED) {<a name="line.217"></a>
-<span class="sourceLineNo">218</span> // we are the last state, finish<a name="line.218"></a>
-<span class="sourceLineNo">219</span> regionNode.unsetProcedure(this);<a name="line.219"></a>
-<span class="sourceLineNo">220</span> ServerCrashProcedure.updateProgress(env, getParentProcId());<a name="line.220"></a>
-<span class="sourceLineNo">221</span> return Flow.NO_MORE_STATE;<a name="line.221"></a>
-<span class="sourceLineNo">222</span> }<a name="line.222"></a>
-<span class="sourceLineNo">223</span> // It is possible that we arrive here but confirm opened is not the last state, for example,<a name="line.223"></a>
-<span class="sourceLineNo">224</span> // when merging or splitting a region, we unassign the region from a RS and the RS is crashed,<a name="line.224"></a>
-<span class="sourceLineNo">225</span> // then there will be recovered edits for this region, we'd better make the region online<a name="line.225"></a>
-<span class="sourceLineNo">226</span> // again and then unassign it, otherwise we have to fail the merge/split procedure as we may<a name="line.226"></a>
-<span class="sourceLineNo">227</span> // loss data.<a name="line.227"></a>
-<span class="sourceLineNo">228</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE);<a name="line.228"></a>
-<span class="sourceLineNo">229</span> return Flow.HAS_MORE_STATE;<a name="line.229"></a>
-<span class="sourceLineNo">230</span> }<a name="line.230"></a>
-<span class="sourceLineNo">231</span><a name="line.231"></a>
-<span class="sourceLineNo">232</span> int retries = env.getAssignmentManager().getRegionStates().addToFailedOpen(regionNode)<a name="line.232"></a>
-<span class="sourceLineNo">233</span> .incrementAndGetRetries();<a name="line.233"></a>
-<span class="sourceLineNo">234</span> int maxAttempts = env.getAssignmentManager().getAssignMaxAttempts();<a name="line.234"></a>
-<span class="sourceLineNo">235</span> LOG.info("Retry={} of max={}; {}; {}", retries, maxAttempts, this, regionNode.toShortString());<a name="line.235"></a>
-<span class="sourceLineNo">236</span><a name="line.236"></a>
-<span class="sourceLineNo">237</span> if (retries >= maxAttempts) {<a name="line.237"></a>
-<span class="sourceLineNo">238</span> env.getAssignmentManager().regionFailedOpen(regionNode, true);<a name="line.238"></a>
-<span class="sourceLineNo">239</span> setFailure(getClass().getSimpleName(), new RetriesExhaustedException(<a name="line.239"></a>
-<span class="sourceLineNo">240</span> "Max attempts " + env.getAssignmentManager().getAssignMaxAttempts() + " exceeded"));<a name="line.240"></a>
-<span class="sourceLineNo">241</span> regionNode.unsetProcedure(this);<a name="line.241"></a>
-<span class="sourceLineNo">242</span> return Flow.NO_MORE_STATE;<a name="line.242"></a>
-<span class="sourceLineNo">243</span> }<a name="line.243"></a>
-<span class="sourceLineNo">244</span><a name="line.244"></a>
-<span class="sourceLineNo">245</span> env.getAssignmentManager().regionFailedOpen(regionNode, false);<a name="line.245"></a>
-<span class="sourceLineNo">246</span> // we failed to assign the region, force a new plan<a name="line.246"></a>
-<span class="sourceLineNo">247</span> forceNewPlan = true;<a name="line.247"></a>
-<span class="sourceLineNo">248</span> regionNode.setRegionLocation(null);<a name="line.248"></a>
-<span class="sourceLineNo">249</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.249"></a>
-<span class="sourceLineNo">250</span><a name="line.250"></a>
-<span class="sourceLineNo">251</span> if (retries > env.getAssignmentManager().getAssignRetryImmediatelyMaxAttempts()) {<a name="line.251"></a>
-<span class="sourceLineNo">252</span> // Throw exception to backoff and retry when failed open too many times<a name="line.252"></a>
-<span class="sourceLineNo">253</span> throw new HBaseIOException("Failed confirm OPEN of " + regionNode +<a name="line.253"></a>
-<span class="sourceLineNo">254</span> " (remote log may yield more detail on why).");<a name="line.254"></a>
-<span class="sourceLineNo">255</span> } else {<a name="line.255"></a>
-<span class="sourceLineNo">256</span> // Here we do not throw exception because we want to the region to be online ASAP<a name="line.256"></a>
-<span class="sourceLineNo">257</span> return Flow.HAS_MORE_STATE;<a name="line.257"></a>
-<span class="sourceLineNo">258</span> }<a name="line.258"></a>
-<span class="sourceLineNo">259</span> }<a name="line.259"></a>
-<span class="sourceLineNo">260</span><a name="line.260"></a>
-<span class="sourceLineNo">261</span> private void closeRegion(MasterProcedureEnv env, RegionStateNode regionNode) throws IOException {<a name="line.261"></a>
-<span class="sourceLineNo">262</span> if (regionNode.isInState(State.OPEN, State.CLOSING, State.MERGING, State.SPLITTING)) {<a name="line.262"></a>
-<span class="sourceLineNo">263</span> // this is the normal case<a name="line.263"></a>
-<span class="sourceLineNo">264</span> env.getAssignmentManager().regionClosing(regionNode);<a name="line.264"></a>
-<span class="sourceLineNo">265</span> addChildProcedure(new CloseRegionProcedure(this, getRegion(), regionNode.getRegionLocation(),<a name="line.265"></a>
-<span class="sourceLineNo">266</span> assignCandidate));<a name="line.266"></a>
-<span class="sourceLineNo">267</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED);<a name="line.267"></a>
-<span class="sourceLineNo">268</span> } else {<a name="line.268"></a>
-<span class="sourceLineNo">269</span> forceNewPlan = true;<a name="line.269"></a>
-<span class="sourceLineNo">270</span> regionNode.setRegionLocation(null);<a name="line.270"></a>
-<span class="sourceLineNo">271</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.271"></a>
-<span class="sourceLineNo">272</span> }<a name="line.272"></a>
-<span class="sourceLineNo">273</span> }<a name="line.273"></a>
-<span class="sourceLineNo">274</span><a name="line.274"></a>
-<span class="sourceLineNo">275</span> private Flow confirmClosed(MasterProcedureEnv env, RegionStateNode regionNode)<a name="line.275"></a>
-<span class="sourceLineNo">276</span> throws IOException {<a name="line.276"></a>
-<span class="sourceLineNo">277</span> if (regionNode.isInState(State.CLOSED)) {<a name="line.277"></a>
-<span class="sourceLineNo">278</span> retryCounter = null;<a name="line.278"></a>
-<span class="sourceLineNo">279</span> if (lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED) {<a name="line.279"></a>
-<span class="sourceLineNo">280</span> // we are the last state, finish<a name="line.280"></a>
-<span class="sourceLineNo">281</span> regionNode.unsetProcedure(this);<a name="line.281"></a>
-<span class="sourceLineNo">282</span> return Flow.NO_MORE_STATE;<a name="line.282"></a>
-<span class="sourceLineNo">283</span> }<a name="line.283"></a>
-<span class="sourceLineNo">284</span> // This means we need to open the region again, should be a move or reopen<a name="line.284"></a>
-<span class="sourceLineNo">285</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.285"></a>
-<span class="sourceLineNo">286</span> return Flow.HAS_MORE_STATE;<a name="line.286"></a>
-<span class="sourceLineNo">287</span> }<a name="line.287"></a>
-<span class="sourceLineNo">288</span> if (regionNode.isInState(State.CLOSING)) {<a name="line.288"></a>
-<span class="sourceLineNo">289</span> // This is possible, think the target RS crashes and restarts immediately, the close region<a name="line.289"></a>
-<span class="sourceLineNo">290</span> // operation will return a NotServingRegionException soon, we can only recover after SCP takes<a name="line.290"></a>
-<span class="sourceLineNo">291</span> // care of this RS. So here we throw an IOException to let upper layer to retry with backoff.<a name="line.291"></a>
-<span class="sourceLineNo">292</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE);<a name="line.292"></a>
-<span class="sourceLineNo">293</span> throw new HBaseIOException("Failed to close region");<a name="line.293"></a>
-<span class="sourceLineNo">294</span> }<a name="line.294"></a>
-<span class="sourceLineNo">295</span> // abnormally closed, need to reopen it, no matter what is the last state, see the comment in<a name="line.295"></a>
-<span class="sourceLineNo">296</span> // confirmOpened for more details that why we need to reopen the region first even if we just<a name="line.296"></a>
-<span class="sourceLineNo">297</span> // want to close it.<a name="line.297"></a>
-<span class="sourceLineNo">298</span> // The only exception is for non-default replica, where we do not need to deal with recovered<a name="line.298"></a>
-<span class="sourceLineNo">299</span> // edits. Notice that the region will remain in ABNORMALLY_CLOSED state, the upper layer need to<a name="line.299"></a>
-<span class="sourceLineNo">300</span> // deal with this state. For non-default replica, this is usually the same with CLOSED.<a name="line.300"></a>
-<span class="sourceLineNo">301</span> assert regionNode.isInState(State.ABNORMALLY_CLOSED);<a name="line.301"></a>
-<span class="sourceLineNo">302</span> if (!RegionReplicaUtil.isDefaultReplica(getRegion()) &&<a name="line.302"></a>
-<span class="sourceLineNo">303</span> lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED) {<a name="line.303"></a>
-<span class="sourceLineNo">304</span> regionNode.unsetProcedure(this);<a name="line.304"></a>
-<span class="sourceLineNo">305</span> return Flow.NO_MORE_STATE;<a name="line.305"></a>
-<span class="sourceLineNo">306</span> }<a name="line.306"></a>
-<span class="sourceLineNo">307</span> retryCounter = null;<a name="line.307"></a>
-<span class="sourceLineNo">308</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.308"></a>
-<span class="sourceLineNo">309</span> return Flow.HAS_MORE_STATE;<a name="line.309"></a>
-<span class="sourceLineNo">310</span> }<a name="line.310"></a>
-<span class="sourceLineNo">311</span><a name="line.311"></a>
-<span class="sourceLineNo">312</span> // Override to lock RegionStateNode<a name="line.312"></a>
-<span class="sourceLineNo">313</span> @SuppressWarnings("rawtypes")<a name="line.313"></a>
-<span class="sourceLineNo">314</span> @Override<a name="line.314"></a>
-<span class="sourceLineNo">315</span> protected Procedure[] execute(MasterProcedureEnv env)<a name="line.315"></a>
-<span class="sourceLineNo">316</span> throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException {<a name="line.316"></a>
-<span class="sourceLineNo">317</span> RegionStateNode regionNode =<a name="line.317"></a>
-<span class="sourceLineNo">318</span> env.getAssignmentManager().getRegionStates().getOrCreateRegionStateNode(getRegion());<a name="line.318"></a>
-<span class="sourceLineNo">319</span> regionNode.lock();<a name="line.319"></a>
-<span class="sourceLineNo">320</span> try {<a name="line.320"></a>
-<span class="sourceLineNo">321</span> return super.execute(env);<a name="line.321"></a>
-<span class="sourceLineNo">322</span> } finally {<a name="line.322"></a>
-<span class="sourceLineNo">323</span> regionNode.unlock();<a name="line.323"></a>
-<span class="sourceLineNo">324</span> }<a name="line.324"></a>
-<span class="sourceLineNo">325</span> }<a name="line.325"></a>
-<span class="sourceLineNo">326</span><a name="line.326"></a>
-<span class="sourceLineNo">327</span> private RegionStateNode getRegionStateNode(MasterProcedureEnv env) {<a name="line.327"></a>
-<span class="sourceLineNo">328</span> return env.getAssignmentManager().getRegionStates().getOrCreateRegionStateNode(getRegion());<a name="line.328"></a>
-<span class="sourceLineNo">329</span> }<a name="line.329"></a>
-<span class="sourceLineNo">330</span><a name="line.330"></a>
-<span class="sourceLineNo">331</span> @Override<a name="line.331"></a>
-<span class="sourceLineNo">332</span> protected Flow executeFromState(MasterProcedureEnv env, RegionStateTransitionState state)<a name="line.332"></a>
-<span class="sourceLineNo">333</span> throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException {<a name="line.333"></a>
-<span class="sourceLineNo">334</span> RegionStateNode regionNode = getRegionStateNode(env);<a name="line.334"></a>
-<span class="sourceLineNo">335</span> try {<a name="line.335"></a>
-<span class="sourceLineNo">336</span> switch (state) {<a name="line.336"></a>
-<span class="sourceLineNo">337</span> case REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE:<a name="line.337"></a>
-<span class="sourceLineNo">338</span> // Need to do some sanity check for replica region, if the region does not exist at<a name="line.338"></a>
-<span class="sourceLineNo">339</span> // master, do not try to assign the replica region, log error and return.<a name="line.339"></a>
-<span class="sourceLineNo">340</span> if (!RegionReplicaUtil.isDefaultReplica(regionNode.getRegionInfo())) {<a name="line.340"></a>
-<span class="sourceLineNo">341</span> RegionInfo defaultRI =<a name="line.341"></a>
-<span class="sourceLineNo">342</span> RegionReplicaUtil.getRegionInfoForDefaultReplica(regionNode.getRegionInfo());<a name="line.342"></a>
-<span class="sourceLineNo">343</span> if (env.getMasterServices().getAssignmentManager().getRegionStates().<a name="line.343"></a>
-<span class="sourceLineNo">344</span> getRegionStateNode(defaultRI) == null) {<a name="line.344"></a>
-<span class="sourceLineNo">345</span> LOG.error(<a name="line.345"></a>
-<span class="sourceLineNo">346</span> "Cannot assign replica region {} because its primary region {} does not exist.",<a name="line.346"></a>
-<span class="sourceLineNo">347</span> regionNode.getRegionInfo(), defaultRI);<a name="line.347"></a>
-<span class="sourceLineNo">348</span> regionNode.unsetProcedure(this);<a name="line.348"></a>
-<span class="sourceLineNo">349</span> return Flow.NO_MORE_STATE;<a name="line.349"></a>
-<span class="sourceLineNo">350</span> }<a name="line.350"></a>
-<span class="sourceLineNo">351</span> }<a name="line.351"></a>
-<span class="sourceLineNo">352</span> queueAssign(env, regionNode);<a name="line.352"></a>
-<span class="sourceLineNo">353</span> return Flow.HAS_MORE_STATE;<a name="line.353"></a>
-<span class="sourceLineNo">354</span> case REGION_STATE_TRANSITION_OPEN:<a name="line.354"></a>
-<span class="sourceLineNo">355</span> openRegion(env, regionNode);<a name="line.355"></a>
-<span class="sourceLineNo">356</span> return Flow.HAS_MORE_STATE;<a name="line.356"></a>
-<span class="sourceLineNo">357</span> case REGION_STATE_TRANSITION_CONFIRM_OPENED:<a name="line.357"></a>
-<span class="sourceLineNo">358</span> return confirmOpened(env, regionNode);<a name="line.358"></a>
-<span class="sourceLineNo">359</span> case REGION_STATE_TRANSITION_CLOSE:<a name="line.359"></a>
-<span class="sourceLineNo">360</span> closeRegion(env, regionNode);<a name="line.360"></a>
-<span class="sourceLineNo">361</span> return Flow.HAS_MORE_STATE;<a name="line.361"></a>
-<span class="sourceLineNo">362</span> case REGION_STATE_TRANSITION_CONFIRM_CLOSED:<a name="line.362"></a>
-<span class="sourceLineNo">363</span> return confirmClosed(env, regionNode);<a name="line.363"></a>
-<span class="sourceLineNo">364</span> default:<a name="line.364"></a>
-<span class="sourceLineNo">365</span> throw new UnsupportedOperationException("unhandled state=" + state);<a name="line.365"></a>
-<span class="sourceLineNo">366</span> }<a name="line.366"></a>
-<span class="sourceLineNo">367</span> } catch (IOException e) {<a name="line.367"></a>
-<span class="sourceLineNo">368</span> if (retryCounter == null) {<a name="line.368"></a>
-<span class="sourceLineNo">369</span> retryCounter = ProcedureUtil.createRetryCounter(env.getMasterConfiguration());<a name="line.369"></a>
-<span class="sourceLineNo">370</span> }<a name="line.370"></a>
-<span class="sourceLineNo">371</span> long backoff = retryCounter.getBackoffTimeAndIncrementAttempts();<a name="line.371"></a>
-<span class="sourceLineNo">372</span> LOG.warn(<a name="line.372"></a>
-<span class="sourceLineNo">373</span> "Failed transition, suspend {}secs {}; {}; waiting on rectified condition fixed " +<a name="line.373"></a>
-<span class="sourceLineNo">374</span> "by other Procedure or operator intervention",<a name="line.374"></a>
-<span class="sourceLineNo">375</span> backoff / 1000, this, regionNode.toShortString(), e);<a name="line.375"></a>
-<span class="sourceLineNo">376</span> setTimeout(Math.toIntExact(backoff));<a name="line.376"></a>
-<span class="sourceLineNo">377</span> setState(ProcedureProtos.ProcedureState.WAITING_TIMEOUT);<a name="line.377"></a>
-<span class="sourceLineNo">378</span> skipPersistence();<a name="line.378"></a>
-<span class="sourceLineNo">379</span> throw new ProcedureSuspendedException();<a name="line.379"></a>
-<span class="sourceLineNo">380</span> }<a name="line.380"></a>
-<span class="sourceLineNo">381</span> }<a name="line.381"></a>
-<span class="sourceLineNo">382</span><a name="line.382"></a>
-<span class="sourceLineNo">383</span> /**<a name="line.383"></a>
-<span class="sourceLineNo">384</span> * At end of timeout, wake ourselves up so we run again.<a name="line.384"></a>
-<span class="sourceLineNo">385</span> */<a name="line.385"></a>
-<span class="sourceLineNo">386</span> @Override<a name="line.386"></a>
-<span class="sourceLineNo">387</span> protected synchronized boolean setTimeoutFailure(MasterProcedureEnv env) {<a name="line.387"></a>
-<span class="sourceLineNo">388</span> setState(ProcedureProtos.ProcedureState.RUNNABLE);<a name="line.388"></a>
-<span class="sourceLineNo">389</span> env.getProcedureScheduler().addFront(this);<a name="line.389"></a>
-<span class="sourceLineNo">390</span> return false; // 'false' means that this procedure handled the timeout<a name="line.390"></a>
-<span class="sourceLineNo">391</span> }<a name="line.391"></a>
-<span class="sourceLineNo">392</span><a name="line.392"></a>
-<span class="sourceLineNo">393</span> // Should be called with RegionStateNode locked<a name="line.393"></a>
-<span class="sourceLineNo">394</span> public void reportTransition(MasterProcedureEnv env, RegionStateNode regionNode,<a name="line.394"></a>
-<span class="sourceLineNo">395</span> ServerName serverName, TransitionCode code, long seqId, long procId) throws IOException {<a name="line.395"></a>
-<span class="sourceLineNo">396</span> if (remoteProc == null) {<a name="line.396"></a>
-<span class="sourceLineNo">397</span> LOG.warn(<a name="line.397"></a>
-<span class="sourceLineNo">398</span> "There is no outstanding remote region procedure for {}, serverName={}, code={}," +<a name="line.398"></a>
-<span class="sourceLineNo">399</span> " seqId={}, proc={}, should be a retry, ignore",<a name="line.399"></a>
-<span class="sourceLineNo">400</span> regionNode, serverName, code, seqId, this);<a name="line.400"></a>
-<span class="sourceLineNo">401</span> return;<a name="line.401"></a>
-<span class="sourceLineNo">402</span> }<a name="line.402"></a>
-<span class="sourceLineNo">403</span> // The procId could be -1 if it is from an old region server, we need to deal with it so that we<a name="line.403"></a>
-<span class="sourceLineNo">404</span> // can do rolling upgraing.<a name="line.404"></a>
-<span class="sourceLineNo">405</span> if (procId >= 0 && remoteProc.getProcId() != procId) {<a name="line.405"></a>
-<span class="sourceLineNo">406</span> LOG.warn(<a name="line.406"></a>
-<span class="sourceLineNo">407</span> "The pid of remote region procedure for {} is {}, the reported pid={}, serverName={}," +<a name="line.407"></a>
-<span class="sourceLineNo">408</span> " code={}, seqId={}, proc={}, should be a retry, ignore",<a name="line.408"></a>
-<span class="sourceLineNo">409</span> regionNode, remoteProc.getProcId(), procId, serverName, code, seqId, this);<a name="line.409"></a>
-<span class="sourceLineNo">410</span> return;<a name="line.410"></a>
-<span class="sourceLineNo">411</span> }<a name="line.411"></a>
-<span class="sourceLineNo">412</span> remoteProc.reportTransition(env, regionNode, serverName, code, seqId);<a name="line.412"></a>
-<span class="sourceLineNo">413</span> }<a name="line.413"></a>
-<span class="sourceLineNo">414</span><a name="line.414"></a>
-<span class="sourceLineNo">415</span> // Should be called with RegionStateNode locked<a name="line.415"></a>
-<span class="sourceLineNo">416</span> public void serverCrashed(MasterProcedureEnv env, RegionStateNode regionNode,<a name="line.416"></a>
-<span class="sourceLineNo">417</span> ServerName serverName, boolean forceNewPlan) throws IOException {<a name="line.417"></a>
-<span class="sourceLineNo">418</span> this.forceNewPlan = forceNewPlan;<a name="line.418"></a>
-<span class="sourceLineNo">419</span> if (remoteProc != null) {<a name="line.419"></a>
-<span class="sourceLineNo">420</span> // this means we are waiting for the sub procedure, so wake it up<a name="line.420"></a>
-<span class="sourceLineNo">421</span> remoteProc.serverCrashed(env, regionNode, serverName);<a name="line.421"></a>
-<span class="sourceLineNo">422</span> } else {<a name="line.422"></a>
-<span class="sourceLineNo">423</span> // we are in RUNNING state, just update the region state, and we will process it later.<a name="line.423"></a>
-<span class="sourceLineNo">424</span> env.getAssignmentManager().regionClosedAbnormally(regionNode);<a name="line.424"></a>
-<span class="sourceLineNo">425</span> }<a name="line.425"></a>
-<span class="sourceLineNo">426</span> }<a name="line.426"></a>
-<span class="sourceLineNo">427</span><a name="line.427"></a>
-<span class="sourceLineNo">428</span> void attachRemoteProc(RegionRemoteProcedureBase proc) {<a name="line.428"></a>
-<span class="sourceLineNo">429</span> this.remoteProc = proc;<a name="line.429"></a>
-<span class="sourceLineNo">430</span> }<a name="line.430"></a>
-<span class="sourceLineNo">431</span><a name="line.431"></a>
-<span class="sourceLineNo">432</span> void unattachRemoteProc(RegionRemoteProcedureBase proc) {<a name="line.432"></a>
-<span class="sourceLineNo">433</span> assert this.remoteProc == proc;<a name="line.433"></a>
-<span class="sourceLineNo">434</span> this.remoteProc = null;<a name="line.434"></a>
-<span class="sourceLineNo">435</span> }<a name="line.435"></a>
-<span class="sourceLineNo">436</span><a name="line.436"></a>
-<span class="sourceLineNo">437</span> // will be called after we finish loading the meta entry for this region.<a name="line.437"></a>
-<span class="sourceLineNo">438</span> // used to change the state of the region node if we have a sub procedure, as we may not persist<a name="line.438"></a>
-<span class="sourceLineNo">439</span> // the state to meta yet. See the code in RegionRemoteProcedureBase.execute for more details.<a name="line.439"></a>
-<span class="sourceLineNo">440</span> void stateLoaded(AssignmentManager am, RegionStateNode regionNode) {<a name="line.440"></a>
-<span class="sourceLineNo">441</span> if (remoteProc != null) {<a name="line.441"></a>
-<span class="sourceLineNo">442</span> remoteProc.stateLoaded(am, regionNode);<a name="line.442"></a>
-<span class="sourceLineNo">443</span> }<a name="line.443"></a>
-<span class="sourceLineNo">444</span> }<a name="line.444"></a>
-<span class="sourceLineNo">445</span><a name="line.445"></a>
-<span class="sourceLineNo">446</span> @Override<a name="line.446"></a>
-<span class="sourceLineNo">447</span> protected void rollbackState(MasterProcedureEnv env, RegionStateTransitionState state)<a name="line.447"></a>
-<span class="sourceLineNo">448</span> throws IOException, InterruptedException {<a name="line.448"></a>
-<span class="sourceLineNo">449</span> // no rollback<a name="line.449"></a>
-<span class="sourceLineNo">450</span> throw new UnsupportedOperationException();<a name="line.450"></a>
-<span class="sourceLineNo">451</span> }<a name="line.451"></a>
-<span class="sourceLineNo">452</span><a name="line.452"></a>
-<span class="sourceLineNo">453</span> @Override<a name="line.453"></a>
-<span class="sourceLineNo">454</span> protected RegionStateTransitionState getState(int stateId) {<a name="line.454"></a>
-<span class="sourceLineNo">455</span> return RegionStateTransitionState.forNumber(stateId);<a name="line.455"></a>
-<span class="sourceLineNo">456</span> }<a name="line.456"></a>
-<span class="sourceLineNo">457</span><a name="line.457"></a>
-<span class="sourceLineNo">458</span> @Override<a name="line.458"></a>
-<span class="sourceLineNo">459</span> protected int getStateId(RegionStateTransitionState state) {<a name="line.459"></a>
-<span class="sourceLineNo">460</span> return state.getNumber();<a name="line.460"></a>
-<span class="sourceLineNo">461</span> }<a name="line.461"></a>
-<span class="sourceLineNo">462</span><a name="line.462"></a>
-<span class="sourceLineNo">463</span> @Override<a name="line.463"></a>
-<span class="sourceLineNo">464</span> protected RegionStateTransitionState getInitialState() {<a name="line.464"></a>
-<span class="sourceLineNo">465</span> return initialState;<a name="line.465"></a>
-<span class="sourceLineNo">466</span> }<a name="line.466"></a>
-<span class="sourceLineNo">467</span><a name="line.467"></a>
-<span class="sourceLineNo">468</span> private static TransitionType convert(RegionTransitionType type) {<a name="line.468"></a>
-<span class="sourceLineNo">469</span> switch (type) {<a name="line.469"></a>
-<span class="sourceLineNo">470</span> case ASSIGN:<a name="line.470"></a>
-<span class="sourceLineNo">471</span> return TransitionType.ASSIGN;<a name="line.471"></a>
-<span class="sourceLineNo">472</span> case UNASSIGN:<a name="line.472"></a>
-<span class="sourceLineNo">473</span> return TransitionType.UNASSIGN;<a name="line.473"></a>
-<span class="sourceLineNo">474</span> case MOVE:<a name="line.474"></a>
-<span class="sourceLineNo">475</span> return TransitionType.MOVE;<a name="line.475"></a>
-<span class="sourceLineNo">476</span> case REOPEN:<a name="line.476"></a>
-<span class="sourceLineNo">477</span> return TransitionType.REOPEN;<a name="line.477"></a>
-<span class="sourceLineNo">478</span> default:<a name="line.478"></a>
-<span class="sourceLineNo">479</span> throw new IllegalArgumentException("Unknown RegionTransitionType: " + type);<a name="line.479"></a>
-<span class="sourceLineNo">480</span> }<a name="line.480"></a>
-<span class="sourceLineNo">481</span> }<a name="line.481"></a>
-<span class="sourceLineNo">482</span><a name="line.482"></a>
-<span class="sourceLineNo">483</span> private static RegionTransitionType convert(TransitionType type) {<a name="line.483"></a>
-<span class="sourceLineNo">484</span> switch (type) {<a name="line.484"></a>
-<span class="sourceLineNo">485</span> case ASSIGN:<a name="line.485"></a>
-<span class="sourceLineNo">486</span> return RegionTransitionType.ASSIGN;<a name="line.486"></a>
-<span class="sourceLineNo">487</span> case UNASSIGN:<a name="line.487"></a>
-<span class="sourceLineNo">488</span> return RegionTransitionType.UNASSIGN;<a name="line.488"></a>
-<span class="sourceLineNo">489</span> case MOVE:<a name="line.489"></a>
-<span class="sourceLineNo">490</span> return RegionTransitionType.MOVE;<a name="line.490"></a>
-<span class="sourceLineNo">491</span> case REOPEN:<a name="line.491"></a>
-<span class="sourceLineNo">492</span> return RegionTransitionType.REOPEN;<a name="line.492"></a>
-<span class="sourceLineNo">493</span> default:<a name="line.493"></a>
-<span class="sourceLineNo">494</span> throw new IllegalArgumentException("Unknown TransitionType: " + type);<a name="line.494"></a>
-<span class="sourceLineNo">495</span> }<a name="line.495"></a>
-<span class="sourceLineNo">496</span> }<a name="line.496"></a>
-<span class="sourceLineNo">497</span><a name="line.497"></a>
-<span class="sourceLineNo">498</span> @Override<a name="line.498"></a>
-<span class="sourceLineNo">499</span> protected void serializeStateData(ProcedureStateSerializer serializer) throws IOException {<a name="line.499"></a>
-<span class="sourceLineNo">500</span> super.serializeStateData(serializer);<a name="line.500"></a>
-<span class="sourceLineNo">501</span> RegionStateTransitionStateData.Builder builder = RegionStateTransitionStateData.newBuilder()<a name="line.501"></a>
-<span class="sourceLineNo">502</span> .setType(convert(type)).setForceNewPlan(forceNewPlan);<a name="line.502"></a>
-<span class="sourceLineNo">503</span> if (assignCandidate != null) {<a name="line.503"></a>
-<span class="sourceLineNo">504</span> builder.setAssignCandidate(ProtobufUtil.toServerName(assignCandidate));<a name="line.504"></a>
-<span class="sourceLineNo">505</span> }<a name="line.505"></a>
-<span class="sourceLineNo">506</span> serializer.serialize(builder.build());<a name="line.506"></a>
-<span class="sourceLineNo">507</span> }<a name="line.507"></a>
-<span class="sourceLineNo">508</span><a name="line.508"></a>
-<span class="sourceLineNo">509</span> @Override<a name="line.509"></a>
-<span class="sourceLineNo">510</span> protected void deserializeStateData(ProcedureStateSerializer serializer) throws IOException {<a name="line.510"></a>
-<span class="sourceLineNo">511</span> super.deserializeStateData(serializer);<a name="line.511"></a>
-<span class="sourceLineNo">512</span> RegionStateTransitionStateData data =<a name="line.512"></a>
-<span class="sourceLineNo">513</span> serializer.deserialize(RegionStateTransitionStateData.class);<a name="line.513"></a>
-<span class="sourceLineNo">514</span> type = convert(data.getType());<a name="line.514"></a>
-<span class="sourceLineNo">515</span> setInitialAndLastState();<a name="line.515"></a>
-<span class="sourceLineNo">516</span> forceNewPlan = data.getForceNewPlan();<a name="line.516"></a>
-<span class="sourceLineNo">517</span> if (data.hasAssignCandidate()) {<a name="line.517"></a>
-<span class="sourceLineNo">518</span> assignCandidate = ProtobufUtil.toServerName(data.getAssignCandidate());<a name="line.518"></a>
-<span class="sourceLineNo">519</span> }<a name="line.519"></a>
-<span class="sourceLineNo">520</span> }<a name="line.520"></a>
-<span class="sourceLineNo">521</span><a name="line.521"></a>
-<span class="sourceLineNo">522</span> @Override<a name="line.522"></a>
-<span class="sourceLineNo">523</span> protected ProcedureMetrics getProcedureMetrics(MasterProcedureEnv env) {<a name="line.523"></a>
-<span class="sourceLineNo">524</span> MetricsAssignmentManager metrics = env.getAssignmentManager().getAssignmentManagerMetrics();<a name="line.524"></a>
-<span class="sourceLineNo">525</span> switch (type) {<a name="line.525"></a>
-<span class="sourceLineNo">526</span> case ASSIGN:<a name="line.526"></a>
-<span class="sourceLineNo">527</span> return metrics.getAssignProcMetrics();<a name="line.527"></a>
-<span class="sourceLineNo">528</span> case UNASSIGN:<a name="line.528"></a>
-<span class="sourceLineNo">529</span> return metrics.getUnassignProcMetrics();<a name="line.529"></a>
-<span class="sourceLineNo">530</span> case MOVE:<a name="line.530"></a>
-<span class="sourceLineNo">531</span> return metrics.getMoveProcMetrics();<a name="line.531"></a>
-<span class="sourceLineNo">532</span> case REOPEN:<a name="line.532"></a>
-<span class="sourceLineNo">533</span> return metrics.getReopenProcMetrics();<a name="line.533"></a>
-<span class="sourceLineNo">534</span> default:<a name="line.534"></a>
-<span class="sourceLineNo">535</span> throw new IllegalArgumentException("Unknown transition type: " + type);<a name="line.535"></a>
-<span class="sourceLineNo">536</span> }<a name="line.536"></a>
-<span class="sourceLineNo">537</span> }<a name="line.537"></a>
-<span class="sourceLineNo">538</span><a name="line.538"></a>
-<span class="sourceLineNo">539</span> @Override<a name="line.539"></a>
-<span class="sourceLineNo">540</span> public void toStringClassDetails(StringBuilder sb) {<a name="line.540"></a>
-<span class="sourceLineNo">541</span> super.toStringClassDetails(sb);<a name="line.541"></a>
-<span class="sourceLineNo">542</span> if (initialState == RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE) {<a name="line.542"></a>
-<span class="sourceLineNo">543</span> sb.append(", ASSIGN");<a name="line.543"></a>
-<span class="sourceLineNo">544</span> } else if (lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED) {<a name="line.544"></a>
-<span class="sourceLineNo">545</span> sb.append(", UNASSIGN");<a name="line.545"></a>
-<span class="sourceLineNo">546</span> } else {<a name="line.546"></a>
-<span class="sourceLineNo">547</span> sb.append(", REOPEN/MOVE");<a name="line.547"></a>
-<span class="sourceLineNo">548</span> }<a name="line.548"></a>
-<span class="sourceLineNo">549</span> }<a name="line.549"></a>
-<span class="sourceLineNo">550</span><a name="line.550"></a>
-<span class="sourceLineNo">551</span> private static TransitRegionStateProcedure setOwner(MasterProcedureEnv env,<a name="line.551"></a>
-<span class="sourceLineNo">552</span> TransitRegionStateProcedure proc) {<a name="line.552"></a>
-<span class="sourceLineNo">553</span> proc.setOwner(env.getRequestUser().getShortName());<a name="line.553"></a>
-<span class="sourceLineNo">554</span> return proc;<a name="line.554"></a>
-<span class="sourceLineNo">555</span> }<a name="line.555"></a>
-<span class="sourceLineNo">556</span><a name="line.556"></a>
-<span class="sourceLineNo">557</span> public enum TransitionType {<a name="line.557"></a>
-<span class="sourceLineNo">558</span> ASSIGN, UNASSIGN, MOVE, REOPEN<a name="line.558"></a>
-<span class="sourceLineNo">559</span> }<a name="line.559"></a>
-<span class="sourceLineNo">560</span><a name="line.560"></a>
-<span class="sourceLineNo">561</span> // Be careful that, when you call these 4 methods below, you need to manually attach the returned<a name="line.561"></a>
-<span class="sourceLineNo">562</span> // procedure with the RegionStateNode, otherwise the procedure will quit immediately without doing<a name="line.562"></a>
-<span class="sourceLineNo">563</span> // anything. See the comment in executeFromState to find out why we need this assumption.<a name="line.563"></a>
-<span class="sourceLineNo">564</span> public static TransitRegionStateProcedure assign(MasterProcedureEnv env, RegionInfo region,<a name="line.564"></a>
-<span class="sourceLineNo">565</span> @Nullable ServerName targetServer) {<a name="line.565"></a>
-<span class="sourceLineNo">566</span> return assign(env, region, false, targetServer);<a name="line.566"></a>
-<span class="sourceLineNo">567</span> }<a name="line.567"></a>
-<span class="sourceLineNo">568</span><a name="line.568"></a>
-<span class="sourceLineNo">569</span> public static TransitRegionStateProcedure assign(MasterProcedureEnv env, RegionInfo region,<a name="line.569"></a>
-<span class="sourceLineNo">570</span> boolean forceNewPlan, @Nullable ServerName targetServer) {<a name="line.570"></a>
-<span class="sourceLineNo">571</span> return setOwner(env, new TransitRegionStateProcedure(env, region, targetServer, forceNewPlan,<a name="line.571"></a>
-<span class="sourceLineNo">572</span> TransitionType.ASSIGN));<a name="line.572"></a>
-<span class="sourceLineNo">573</span> }<a name="line.573"></a>
-<span class="sourceLineNo">574</span><a name="line.574"></a>
-<span class="sourceLineNo">575</span> public static TransitRegionStateProcedure unassign(MasterProcedureEnv env, RegionInfo region) {<a name="line.575"></a>
-<span class="sourceLineNo">576</span> return setOwner(env,<a name="line.576"></a>
-<span class="sourceLineNo">577</span> new TransitRegionStateProcedure(env, region, null, false, TransitionType.UNASSIGN));<a name="line.577"></a>
-<span class="sourceLineNo">578</span> }<a name="line.578"></a>
-<span class="sourceLineNo">579</span><a name="line.579"></a>
-<span class="sourceLineNo">580</span> public static TransitRegionStateProcedure reopen(MasterProcedureEnv env, RegionInfo region) {<a name="line.580"></a>
-<span class="sourceLineNo">581</span> return setOwner(env,<a name="line.581"></a>
-<span class="sourceLineNo">582</span> new TransitRegionStateProcedure(env, region, null, false, TransitionType.REOPEN));<a name="line.582"></a>
-<span class="sourceLineNo">583</span> }<a name="line.583"></a>
-<span class="sourceLineNo">584</span><a name="line.584"></a>
-<span class="sourceLineNo">585</span> public static TransitRegionStateProcedure move(MasterProcedureEnv env, RegionInfo region,<a name="line.585"></a>
-<span class="sourceLineNo">586</span> @Nullable ServerName targetServer) {<a name="line.586"></a>
-<span class="sourceLineNo">587</span> return setOwner(env, new TransitRegionStateProcedure(env, region, targetServer,<a name="line.587"></a>
-<span class="sourceLineNo">588</span> targetServer == null, TransitionType.MOVE));<a name="line.588"></a>
-<span class="sourceLineNo">589</span> }<a name="line.589"></a>
-<span class="sourceLineNo">590</span>}<a name="line.590"></a>
+<span class="sourceLineNo">121</span> private RegionRemoteProcedureBase remoteProc;<a name="line.121"></a>
+<span class="sourceLineNo">122</span><a name="line.122"></a>
+<span class="sourceLineNo">123</span> public TransitRegionStateProcedure() {<a name="line.123"></a>
+<span class="sourceLineNo">124</span> }<a name="line.124"></a>
+<span class="sourceLineNo">125</span><a name="line.125"></a>
+<span class="sourceLineNo">126</span> private void setInitialAndLastState() {<a name="line.126"></a>
+<span class="sourceLineNo">127</span> switch (type) {<a name="line.127"></a>
+<span class="sourceLineNo">128</span> case ASSIGN:<a name="line.128"></a>
+<span class="sourceLineNo">129</span> initialState = RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE;<a name="line.129"></a>
+<span class="sourceLineNo">130</span> lastState = RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED;<a name="line.130"></a>
+<span class="sourceLineNo">131</span> break;<a name="line.131"></a>
+<span class="sourceLineNo">132</span> case UNASSIGN:<a name="line.132"></a>
+<span class="sourceLineNo">133</span> initialState = RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE;<a name="line.133"></a>
+<span class="sourceLineNo">134</span> lastState = RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED;<a name="line.134"></a>
+<span class="sourceLineNo">135</span> break;<a name="line.135"></a>
+<span class="sourceLineNo">136</span> case MOVE:<a name="line.136"></a>
+<span class="sourceLineNo">137</span> case REOPEN:<a name="line.137"></a>
+<span class="sourceLineNo">138</span> initialState = RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE;<a name="line.138"></a>
+<span class="sourceLineNo">139</span> lastState = RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED;<a name="line.139"></a>
+<span class="sourceLineNo">140</span> break;<a name="line.140"></a>
+<span class="sourceLineNo">141</span> default:<a name="line.141"></a>
+<span class="sourceLineNo">142</span> throw new IllegalArgumentException("Unknown TransitionType: " + type);<a name="line.142"></a>
+<span class="sourceLineNo">143</span> }<a name="line.143"></a>
+<span class="sourceLineNo">144</span> }<a name="line.144"></a>
+<span class="sourceLineNo">145</span><a name="line.145"></a>
+<span class="sourceLineNo">146</span> protected TransitRegionStateProcedure(MasterProcedureEnv env, RegionInfo hri,<a name="line.146"></a>
+<span class="sourceLineNo">147</span> ServerName assignCandidate, boolean forceNewPlan, TransitionType type) {<a name="line.147"></a>
+<span class="sourceLineNo">148</span> super(env, hri);<a name="line.148"></a>
+<span class="sourceLineNo">149</span> this.assignCandidate = assignCandidate;<a name="line.149"></a>
+<span class="sourceLineNo">150</span> this.forceNewPlan = forceNewPlan;<a name="line.150"></a>
+<span class="sourceLineNo">151</span> this.type = type;<a name="line.151"></a>
+<span class="sourceLineNo">152</span> setInitialAndLastState();<a name="line.152"></a>
+<span class="sourceLineNo">153</span><a name="line.153"></a>
+<span class="sourceLineNo">154</span> // when do reopen TRSP, let the rs know the targetServer so it can keep some info on close<a name="line.154"></a>
+<span class="sourceLineNo">155</span> if (type == TransitionType.REOPEN) {<a name="line.155"></a>
+<span class="sourceLineNo">156</span> this.assignCandidate = getRegionStateNode(env).getRegionLocation();<a name="line.156"></a>
+<span class="sourceLineNo">157</span> }<a name="line.157"></a>
+<span class="sourceLineNo">158</span> }<a name="line.158"></a>
+<span class="sourceLineNo">159</span><a name="line.159"></a>
+<span class="sourceLineNo">160</span> @Override<a name="line.160"></a>
+<span class="sourceLineNo">161</span> public TableOperationType getTableOperationType() {<a name="line.161"></a>
+<span class="sourceLineNo">162</span> // TODO: maybe we should make another type here, REGION_TRANSITION?<a name="line.162"></a>
+<span class="sourceLineNo">163</span> return TableOperationType.REGION_EDIT;<a name="line.163"></a>
+<span class="sourceLineNo">164</span> }<a name="line.164"></a>
+<span class="sourceLineNo">165</span><a name="line.165"></a>
+<span class="sourceLineNo">166</span> @Override<a name="line.166"></a>
+<span class="sourceLineNo">167</span> protected boolean waitInitialized(MasterProcedureEnv env) {<a name="line.167"></a>
+<span class="sourceLineNo">168</span> if (TableName.isMetaTableName(getTableName())) {<a name="line.168"></a>
+<span class="sourceLineNo">169</span> return false;<a name="line.169"></a>
+<span class="sourceLineNo">170</span> }<a name="line.170"></a>
+<span class="sourceLineNo">171</span> // First we need meta to be loaded, and second, if meta is not online then we will likely to<a name="line.171"></a>
+<span class="sourceLineNo">172</span> // fail when updating meta so we wait until it is assigned.<a name="line.172"></a>
+<span class="sourceLineNo">173</span> AssignmentManager am = env.getAssignmentManager();<a name="line.173"></a>
+<span class="sourceLineNo">174</span> return am.waitMetaLoaded(this) || am.waitMetaAssigned(this, getRegion());<a name="line.174"></a>
+<span class="sourceLineNo">175</span> }<a name="line.175"></a>
+<span class="sourceLineNo">176</span><a name="line.176"></a>
+<span class="sourceLineNo">177</span> private void queueAssign(MasterProcedureEnv env, RegionStateNode regionNode)<a name="line.177"></a>
+<span class="sourceLineNo">178</span> throws ProcedureSuspendedException {<a name="line.178"></a>
+<span class="sourceLineNo">179</span> boolean retain = false;<a name="line.179"></a>
+<span class="sourceLineNo">180</span> if (forceNewPlan) {<a name="line.180"></a>
+<span class="sourceLineNo">181</span> // set the region location to null if forceNewPlan is true<a name="line.181"></a>
+<span class="sourceLineNo">182</span> regionNode.setRegionLocation(null);<a name="line.182"></a>
+<span class="sourceLineNo">183</span> } else {<a name="line.183"></a>
+<span class="sourceLineNo">184</span> if (assignCandidate != null) {<a name="line.184"></a>
+<span class="sourceLineNo">185</span> retain = assignCandidate.equals(regionNode.getLastHost());<a name="line.185"></a>
+<span class="sourceLineNo">186</span> regionNode.setRegionLocation(assignCandidate);<a name="line.186"></a>
+<span class="sourceLineNo">187</span> } else if (regionNode.getLastHost() != null) {<a name="line.187"></a>
+<span class="sourceLineNo">188</span> retain = true;<a name="line.188"></a>
+<span class="sourceLineNo">189</span> LOG.info("Setting lastHost as the region location {}", regionNode.getLastHost());<a name="line.189"></a>
+<span class="sourceLineNo">190</span> regionNode.setRegionLocation(regionNode.getLastHost());<a name="line.190"></a>
+<span class="sourceLineNo">191</span> }<a name="line.191"></a>
+<span class="sourceLineNo">192</span> }<a name="line.192"></a>
+<span class="sourceLineNo">193</span> LOG.info("Starting {}; {}; forceNewPlan={}, retain={}", this, regionNode.toShortString(),<a name="line.193"></a>
+<span class="sourceLineNo">194</span> forceNewPlan, retain);<a name="line.194"></a>
+<span class="sourceLineNo">195</span> env.getAssignmentManager().queueAssign(regionNode);<a name="line.195"></a>
+<span class="sourceLineNo">196</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_OPEN);<a name="line.196"></a>
+<span class="sourceLineNo">197</span> if (regionNode.getProcedureEvent().suspendIfNotReady(this)) {<a name="line.197"></a>
+<span class="sourceLineNo">198</span> throw new ProcedureSuspendedException();<a name="line.198"></a>
+<span class="sourceLineNo">199</span> }<a name="line.199"></a>
+<span class="sourceLineNo">200</span> }<a name="line.200"></a>
+<span class="sourceLineNo">201</span><a name="line.201"></a>
+<span class="sourceLineNo">202</span> private void openRegion(MasterProcedureEnv env, RegionStateNode regionNode) throws IOException {<a name="line.202"></a>
+<span class="sourceLineNo">203</span> ServerName loc = regionNode.getRegionLocation();<a name="line.203"></a>
+<span class="sourceLineNo">204</span> if (loc == null || BOGUS_SERVER_NAME.equals(loc)) {<a name="line.204"></a>
+<span class="sourceLineNo">205</span> LOG.warn("No location specified for {}, jump back to state {} to get one", getRegion(),<a name="line.205"></a>
+<span class="sourceLineNo">206</span> RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.206"></a>
+<span class="sourceLineNo">207</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.207"></a>
+<span class="sourceLineNo">208</span> return;<a name="line.208"></a>
+<span class="sourceLineNo">209</span> }<a name="line.209"></a>
+<span class="sourceLineNo">210</span> env.getAssignmentManager().regionOpening(regionNode);<a name="line.210"></a>
+<span class="sourceLineNo">211</span> addChildProcedure(new OpenRegionProcedure(this, getRegion(), loc));<a name="line.211"></a>
+<span class="sourceLineNo">212</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED);<a name="line.212"></a>
+<span class="sourceLineNo">213</span> }<a name="line.213"></a>
+<span class="sourceLineNo">214</span><a name="line.214"></a>
+<span class="sourceLineNo">215</span> private Flow confirmOpened(MasterProcedureEnv env, RegionStateNode regionNode)<a name="line.215"></a>
+<span class="sourceLineNo">216</span> throws IOException {<a name="line.216"></a>
+<span class="sourceLineNo">217</span> if (regionNode.isInState(State.OPEN)) {<a name="line.217"></a>
+<span class="sourceLineNo">218</span> retryCounter = null;<a name="line.218"></a>
+<span class="sourceLineNo">219</span> if (lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_OPENED) {<a name="line.219"></a>
+<span class="sourceLineNo">220</span> // we are the last state, finish<a name="line.220"></a>
+<span class="sourceLineNo">221</span> regionNode.unsetProcedure(this);<a name="line.221"></a>
+<span class="sourceLineNo">222</span> ServerCrashProcedure.updateProgress(env, getParentProcId());<a name="line.222"></a>
+<span class="sourceLineNo">223</span> return Flow.NO_MORE_STATE;<a name="line.223"></a>
+<span class="sourceLineNo">224</span> }<a name="line.224"></a>
+<span class="sourceLineNo">225</span> // It is possible that we arrive here but confirm opened is not the last state, for example,<a name="line.225"></a>
+<span class="sourceLineNo">226</span> // when merging or splitting a region, we unassign the region from a RS and the RS is crashed,<a name="line.226"></a>
+<span class="sourceLineNo">227</span> // then there will be recovered edits for this region, we'd better make the region online<a name="line.227"></a>
+<span class="sourceLineNo">228</span> // again and then unassign it, otherwise we have to fail the merge/split procedure as we may<a name="line.228"></a>
+<span class="sourceLineNo">229</span> // loss data.<a name="line.229"></a>
+<span class="sourceLineNo">230</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE);<a name="line.230"></a>
+<span class="sourceLineNo">231</span> return Flow.HAS_MORE_STATE;<a name="line.231"></a>
+<span class="sourceLineNo">232</span> }<a name="line.232"></a>
+<span class="sourceLineNo">233</span><a name="line.233"></a>
+<span class="sourceLineNo">234</span> int retries = env.getAssignmentManager().getRegionStates().addToFailedOpen(regionNode)<a name="line.234"></a>
+<span class="sourceLineNo">235</span> .incrementAndGetRetries();<a name="line.235"></a>
+<span class="sourceLineNo">236</span> int maxAttempts = env.getAssignmentManager().getAssignMaxAttempts();<a name="line.236"></a>
+<span class="sourceLineNo">237</span> LOG.info("Retry={} of max={}; {}; {}", retries, maxAttempts, this, regionNode.toShortString());<a name="line.237"></a>
+<span class="sourceLineNo">238</span><a name="line.238"></a>
+<span class="sourceLineNo">239</span> if (retries >= maxAttempts) {<a name="line.239"></a>
+<span class="sourceLineNo">240</span> env.getAssignmentManager().regionFailedOpen(regionNode, true);<a name="line.240"></a>
+<span class="sourceLineNo">241</span> setFailure(getClass().getSimpleName(), new RetriesExhaustedException(<a name="line.241"></a>
+<span class="sourceLineNo">242</span> "Max attempts " + env.getAssignmentManager().getAssignMaxAttempts() + " exceeded"));<a name="line.242"></a>
+<span class="sourceLineNo">243</span> regionNode.unsetProcedure(this);<a name="line.243"></a>
+<span class="sourceLineNo">244</span> return Flow.NO_MORE_STATE;<a name="line.244"></a>
+<span class="sourceLineNo">245</span> }<a name="line.245"></a>
+<span class="sourceLineNo">246</span><a name="line.246"></a>
+<span class="sourceLineNo">247</span> env.getAssignmentManager().regionFailedOpen(regionNode, false);<a name="line.247"></a>
+<span class="sourceLineNo">248</span> // we failed to assign the region, force a new plan<a name="line.248"></a>
+<span class="sourceLineNo">249</span> forceNewPlan = true;<a name="line.249"></a>
+<span class="sourceLineNo">250</span> regionNode.setRegionLocation(null);<a name="line.250"></a>
+<span class="sourceLineNo">251</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.251"></a>
+<span class="sourceLineNo">252</span><a name="line.252"></a>
+<span class="sourceLineNo">253</span> if (retries > env.getAssignmentManager().getAssignRetryImmediatelyMaxAttempts()) {<a name="line.253"></a>
+<span class="sourceLineNo">254</span> // Throw exception to backoff and retry when failed open too many times<a name="line.254"></a>
+<span class="sourceLineNo">255</span> throw new HBaseIOException("Failed confirm OPEN of " + regionNode +<a name="line.255"></a>
+<span class="sourceLineNo">256</span> " (remote log may yield more detail on why).");<a name="line.256"></a>
+<span class="sourceLineNo">257</span> } else {<a name="line.257"></a>
+<span class="sourceLineNo">258</span> // Here we do not throw exception because we want to the region to be online ASAP<a name="line.258"></a>
+<span class="sourceLineNo">259</span> return Flow.HAS_MORE_STATE;<a name="line.259"></a>
+<span class="sourceLineNo">260</span> }<a name="line.260"></a>
+<span class="sourceLineNo">261</span> }<a name="line.261"></a>
+<span class="sourceLineNo">262</span><a name="line.262"></a>
+<span class="sourceLineNo">263</span> private void closeRegion(MasterProcedureEnv env, RegionStateNode regionNode) throws IOException {<a name="line.263"></a>
+<span class="sourceLineNo">264</span> if (regionNode.isInState(State.OPEN, State.CLOSING, State.MERGING, State.SPLITTING)) {<a name="line.264"></a>
+<span class="sourceLineNo">265</span> // this is the normal case<a name="line.265"></a>
+<span class="sourceLineNo">266</span> env.getAssignmentManager().regionClosing(regionNode);<a name="line.266"></a>
+<span class="sourceLineNo">267</span> addChildProcedure(new CloseRegionProcedure(this, getRegion(), regionNode.getRegionLocation(),<a name="line.267"></a>
+<span class="sourceLineNo">268</span> assignCandidate));<a name="line.268"></a>
+<span class="sourceLineNo">269</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED);<a name="line.269"></a>
+<span class="sourceLineNo">270</span> } else {<a name="line.270"></a>
+<span class="sourceLineNo">271</span> forceNewPlan = true;<a name="line.271"></a>
+<span class="sourceLineNo">272</span> regionNode.setRegionLocation(null);<a name="line.272"></a>
+<span class="sourceLineNo">273</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.273"></a>
+<span class="sourceLineNo">274</span> }<a name="line.274"></a>
+<span class="sourceLineNo">275</span> }<a name="line.275"></a>
+<span class="sourceLineNo">276</span><a name="line.276"></a>
+<span class="sourceLineNo">277</span> private Flow confirmClosed(MasterProcedureEnv env, RegionStateNode regionNode)<a name="line.277"></a>
+<span class="sourceLineNo">278</span> throws IOException {<a name="line.278"></a>
+<span class="sourceLineNo">279</span> if (regionNode.isInState(State.CLOSED)) {<a name="line.279"></a>
+<span class="sourceLineNo">280</span> retryCounter = null;<a name="line.280"></a>
+<span class="sourceLineNo">281</span> if (lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED) {<a name="line.281"></a>
+<span class="sourceLineNo">282</span> // we are the last state, finish<a name="line.282"></a>
+<span class="sourceLineNo">283</span> regionNode.unsetProcedure(this);<a name="line.283"></a>
+<span class="sourceLineNo">284</span> return Flow.NO_MORE_STATE;<a name="line.284"></a>
+<span class="sourceLineNo">285</span> }<a name="line.285"></a>
+<span class="sourceLineNo">286</span> // This means we need to open the region again, should be a move or reopen<a name="line.286"></a>
+<span class="sourceLineNo">287</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.287"></a>
+<span class="sourceLineNo">288</span> return Flow.HAS_MORE_STATE;<a name="line.288"></a>
+<span class="sourceLineNo">289</span> }<a name="line.289"></a>
+<span class="sourceLineNo">290</span> if (regionNode.isInState(State.CLOSING)) {<a name="line.290"></a>
+<span class="sourceLineNo">291</span> // This is possible, think the target RS crashes and restarts immediately, the close region<a name="line.291"></a>
+<span class="sourceLineNo">292</span> // operation will return a NotServingRegionException soon, we can only recover after SCP takes<a name="line.292"></a>
+<span class="sourceLineNo">293</span> // care of this RS. So here we throw an IOException to let upper layer to retry with backoff.<a name="line.293"></a>
+<span class="sourceLineNo">294</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_CLOSE);<a name="line.294"></a>
+<span class="sourceLineNo">295</span> throw new HBaseIOException("Failed to close region");<a name="line.295"></a>
+<span class="sourceLineNo">296</span> }<a name="line.296"></a>
+<span class="sourceLineNo">297</span> // abnormally closed, need to reopen it, no matter what is the last state, see the comment in<a name="line.297"></a>
+<span class="sourceLineNo">298</span> // confirmOpened for more details that why we need to reopen the region first even if we just<a name="line.298"></a>
+<span class="sourceLineNo">299</span> // want to close it.<a name="line.299"></a>
+<span class="sourceLineNo">300</span> // The only exception is for non-default replica, where we do not need to deal with recovered<a name="line.300"></a>
+<span class="sourceLineNo">301</span> // edits. Notice that the region will remain in ABNORMALLY_CLOSED state, the upper layer need to<a name="line.301"></a>
+<span class="sourceLineNo">302</span> // deal with this state. For non-default replica, this is usually the same with CLOSED.<a name="line.302"></a>
+<span class="sourceLineNo">303</span> assert regionNode.isInState(State.ABNORMALLY_CLOSED);<a name="line.303"></a>
+<span class="sourceLineNo">304</span> if (!RegionReplicaUtil.isDefaultReplica(getRegion()) &&<a name="line.304"></a>
+<span class="sourceLineNo">305</span> lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED) {<a name="line.305"></a>
+<span class="sourceLineNo">306</span> regionNode.unsetProcedure(this);<a name="line.306"></a>
+<span class="sourceLineNo">307</span> return Flow.NO_MORE_STATE;<a name="line.307"></a>
+<span class="sourceLineNo">308</span> }<a name="line.308"></a>
+<span class="sourceLineNo">309</span> retryCounter = null;<a name="line.309"></a>
+<span class="sourceLineNo">310</span> setNextState(RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE);<a name="line.310"></a>
+<span class="sourceLineNo">311</span> return Flow.HAS_MORE_STATE;<a name="line.311"></a>
+<span class="sourceLineNo">312</span> }<a name="line.312"></a>
+<span class="sourceLineNo">313</span><a name="line.313"></a>
+<span class="sourceLineNo">314</span> // Override to lock RegionStateNode<a name="line.314"></a>
+<span class="sourceLineNo">315</span> @SuppressWarnings("rawtypes")<a name="line.315"></a>
+<span class="sourceLineNo">316</span> @Override<a name="line.316"></a>
+<span class="sourceLineNo">317</span> protected Procedure[] execute(MasterProcedureEnv env)<a name="line.317"></a>
+<span class="sourceLineNo">318</span> throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException {<a name="line.318"></a>
+<span class="sourceLineNo">319</span> RegionStateNode regionNode =<a name="line.319"></a>
+<span class="sourceLineNo">320</span> env.getAssignmentManager().getRegionStates().getOrCreateRegionStateNode(getRegion());<a name="line.320"></a>
+<span class="sourceLineNo">321</span> regionNode.lock();<a name="line.321"></a>
+<span class="sourceLineNo">322</span> try {<a name="line.322"></a>
+<span class="sourceLineNo">323</span> return super.execute(env);<a name="line.323"></a>
+<span class="sourceLineNo">324</span> } finally {<a name="line.324"></a>
+<span class="sourceLineNo">325</span> regionNode.unlock();<a name="line.325"></a>
+<span class="sourceLineNo">326</span> }<a name="line.326"></a>
+<span class="sourceLineNo">327</span> }<a name="line.327"></a>
+<span class="sourceLineNo">328</span><a name="line.328"></a>
+<span class="sourceLineNo">329</span> private RegionStateNode getRegionStateNode(MasterProcedureEnv env) {<a name="line.329"></a>
+<span class="sourceLineNo">330</span> return env.getAssignmentManager().getRegionStates().getOrCreateRegionStateNode(getRegion());<a name="line.330"></a>
+<span class="sourceLineNo">331</span> }<a name="line.331"></a>
+<span class="sourceLineNo">332</span><a name="line.332"></a>
+<span class="sourceLineNo">333</span> @Override<a name="line.333"></a>
+<span class="sourceLineNo">334</span> protected Flow executeFromState(MasterProcedureEnv env, RegionStateTransitionState state)<a name="line.334"></a>
+<span class="sourceLineNo">335</span> throws ProcedureSuspendedException, ProcedureYieldException, InterruptedException {<a name="line.335"></a>
+<span class="sourceLineNo">336</span> RegionStateNode regionNode = getRegionStateNode(env);<a name="line.336"></a>
+<span class="sourceLineNo">337</span> try {<a name="line.337"></a>
+<span class="sourceLineNo">338</span> switch (state) {<a name="line.338"></a>
+<span class="sourceLineNo">339</span> case REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE:<a name="line.339"></a>
+<span class="sourceLineNo">340</span> // Need to do some sanity check for replica region, if the region does not exist at<a name="line.340"></a>
+<span class="sourceLineNo">341</span> // master, do not try to assign the replica region, log error and return.<a name="line.341"></a>
+<span class="sourceLineNo">342</span> if (!RegionReplicaUtil.isDefaultReplica(regionNode.getRegionInfo())) {<a name="line.342"></a>
+<span class="sourceLineNo">343</span> RegionInfo defaultRI =<a name="line.343"></a>
+<span class="sourceLineNo">344</span> RegionReplicaUtil.getRegionInfoForDefaultReplica(regionNode.getRegionInfo());<a name="line.344"></a>
+<span class="sourceLineNo">345</span> if (env.getMasterServices().getAssignmentManager().getRegionStates().<a name="line.345"></a>
+<span class="sourceLineNo">346</span> getRegionStateNode(defaultRI) == null) {<a name="line.346"></a>
+<span class="sourceLineNo">347</span> LOG.error(<a name="line.347"></a>
+<span class="sourceLineNo">348</span> "Cannot assign replica region {} because its primary region {} does not exist.",<a name="line.348"></a>
+<span class="sourceLineNo">349</span> regionNode.getRegionInfo(), defaultRI);<a name="line.349"></a>
+<span class="sourceLineNo">350</span> regionNode.unsetProcedure(this);<a name="line.350"></a>
+<span class="sourceLineNo">351</span> return Flow.NO_MORE_STATE;<a name="line.351"></a>
+<span class="sourceLineNo">352</span> }<a name="line.352"></a>
+<span class="sourceLineNo">353</span> }<a name="line.353"></a>
+<span class="sourceLineNo">354</span> queueAssign(env, regionNode);<a name="line.354"></a>
+<span class="sourceLineNo">355</span> return Flow.HAS_MORE_STATE;<a name="line.355"></a>
+<span class="sourceLineNo">356</span> case REGION_STATE_TRANSITION_OPEN:<a name="line.356"></a>
+<span class="sourceLineNo">357</span> openRegion(env, regionNode);<a name="line.357"></a>
+<span class="sourceLineNo">358</span> return Flow.HAS_MORE_STATE;<a name="line.358"></a>
+<span class="sourceLineNo">359</span> case REGION_STATE_TRANSITION_CONFIRM_OPENED:<a name="line.359"></a>
+<span class="sourceLineNo">360</span> return confirmOpened(env, regionNode);<a name="line.360"></a>
+<span class="sourceLineNo">361</span> case REGION_STATE_TRANSITION_CLOSE:<a name="line.361"></a>
+<span class="sourceLineNo">362</span> closeRegion(env, regionNode);<a name="line.362"></a>
+<span class="sourceLineNo">363</span> return Flow.HAS_MORE_STATE;<a name="line.363"></a>
+<span class="sourceLineNo">364</span> case REGION_STATE_TRANSITION_CONFIRM_CLOSED:<a name="line.364"></a>
+<span class="sourceLineNo">365</span> return confirmClosed(env, regionNode);<a name="line.365"></a>
+<span class="sourceLineNo">366</span> default:<a name="line.366"></a>
+<span class="sourceLineNo">367</span> throw new UnsupportedOperationException("unhandled state=" + state);<a name="line.367"></a>
+<span class="sourceLineNo">368</span> }<a name="line.368"></a>
+<span class="sourceLineNo">369</span> } catch (IOException e) {<a name="line.369"></a>
+<span class="sourceLineNo">370</span> if (retryCounter == null) {<a name="line.370"></a>
+<span class="sourceLineNo">371</span> retryCounter = ProcedureUtil.createRetryCounter(env.getMasterConfiguration());<a name="line.371"></a>
+<span class="sourceLineNo">372</span> }<a name="line.372"></a>
+<span class="sourceLineNo">373</span> long backoff = retryCounter.getBackoffTimeAndIncrementAttempts();<a name="line.373"></a>
+<span class="sourceLineNo">374</span> LOG.warn(<a name="line.374"></a>
+<span class="sourceLineNo">375</span> "Failed transition, suspend {}secs {}; {}; waiting on rectified condition fixed " +<a name="line.375"></a>
+<span class="sourceLineNo">376</span> "by other Procedure or operator intervention",<a name="line.376"></a>
+<span class="sourceLineNo">377</span> backoff / 1000, this, regionNode.toShortString(), e);<a name="line.377"></a>
+<span class="sourceLineNo">378</span> setTimeout(Math.toIntExact(backoff));<a name="line.378"></a>
+<span class="sourceLineNo">379</span> setState(ProcedureProtos.ProcedureState.WAITING_TIMEOUT);<a name="line.379"></a>
+<span class="sourceLineNo">380</span> skipPersistence();<a name="line.380"></a>
+<span class="sourceLineNo">381</span> throw new ProcedureSuspendedException();<a name="line.381"></a>
+<span class="sourceLineNo">382</span> }<a name="line.382"></a>
+<span class="sourceLineNo">383</span> }<a name="line.383"></a>
+<span class="sourceLineNo">384</span><a name="line.384"></a>
+<span class="sourceLineNo">385</span> /**<a name="line.385"></a>
+<span class="sourceLineNo">386</span> * At end of timeout, wake ourselves up so we run again.<a name="line.386"></a>
+<span class="sourceLineNo">387</span> */<a name="line.387"></a>
+<span class="sourceLineNo">388</span> @Override<a name="line.388"></a>
+<span class="sourceLineNo">389</span> protected synchronized boolean setTimeoutFailure(MasterProcedureEnv env) {<a name="line.389"></a>
+<span class="sourceLineNo">390</span> setState(ProcedureProtos.ProcedureState.RUNNABLE);<a name="line.390"></a>
+<span class="sourceLineNo">391</span> env.getProcedureScheduler().addFront(this);<a name="line.391"></a>
+<span class="sourceLineNo">392</span> return false; // 'false' means that this procedure handled the timeout<a name="line.392"></a>
+<span class="sourceLineNo">393</span> }<a name="line.393"></a>
+<span class="sourceLineNo">394</span><a name="line.394"></a>
+<span class="sourceLineNo">395</span> // Should be called with RegionStateNode locked<a name="line.395"></a>
+<span class="sourceLineNo">396</span> public void reportTransition(MasterProcedureEnv env, RegionStateNode regionNode,<a name="line.396"></a>
+<span class="sourceLineNo">397</span> ServerName serverName, TransitionCode code, long seqId, long procId) throws IOException {<a name="line.397"></a>
+<span class="sourceLineNo">398</span> if (remoteProc == null) {<a name="line.398"></a>
+<span class="sourceLineNo">399</span> LOG.warn(<a name="line.399"></a>
+<span class="sourceLineNo">400</span> "There is no outstanding remote region procedure for {}, serverName={}, code={}," +<a name="line.400"></a>
+<span class="sourceLineNo">401</span> " seqId={}, proc={}, should be a retry, ignore",<a name="line.401"></a>
+<span class="sourceLineNo">402</span> regionNode, serverName, code, seqId, this);<a name="line.402"></a>
+<span class="sourceLineNo">403</span> return;<a name="line.403"></a>
+<span class="sourceLineNo">404</span> }<a name="line.404"></a>
+<span class="sourceLineNo">405</span> // The procId could be -1 if it is from an old region server, we need to deal with it so that we<a name="line.405"></a>
+<span class="sourceLineNo">406</span> // can do rolling upgraing.<a name="line.406"></a>
+<span class="sourceLineNo">407</span> if (procId >= 0 && remoteProc.getProcId() != procId) {<a name="line.407"></a>
+<span class="sourceLineNo">408</span> LOG.warn(<a name="line.408"></a>
+<span class="sourceLineNo">409</span> "The pid of remote region procedure for {} is {}, the reported pid={}, serverName={}," +<a name="line.409"></a>
+<span class="sourceLineNo">410</span> " code={}, seqId={}, proc={}, should be a retry, ignore",<a name="line.410"></a>
+<span class="sourceLineNo">411</span> regionNode, remoteProc.getProcId(), procId, serverName, code, seqId, this);<a name="line.411"></a>
+<span class="sourceLineNo">412</span> return;<a name="line.412"></a>
+<span class="sourceLineNo">413</span> }<a name="line.413"></a>
+<span class="sourceLineNo">414</span> remoteProc.reportTransition(env, regionNode, serverName, code, seqId);<a name="line.414"></a>
+<span class="sourceLineNo">415</span> }<a name="line.415"></a>
+<span class="sourceLineNo">416</span><a name="line.416"></a>
+<span class="sourceLineNo">417</span> // Should be called with RegionStateNode locked<a name="line.417"></a>
+<span class="sourceLineNo">418</span> public void serverCrashed(MasterProcedureEnv env, RegionStateNode regionNode,<a name="line.418"></a>
+<span class="sourceLineNo">419</span> ServerName serverName, boolean forceNewPlan) throws IOException {<a name="line.419"></a>
+<span class="sourceLineNo">420</span> this.forceNewPlan = forceNewPlan;<a name="line.420"></a>
+<span class="sourceLineNo">421</span> if (remoteProc != null) {<a name="line.421"></a>
+<span class="sourceLineNo">422</span> // this means we are waiting for the sub procedure, so wake it up<a name="line.422"></a>
+<span class="sourceLineNo">423</span> remoteProc.serverCrashed(env, regionNode, serverName);<a name="line.423"></a>
+<span class="sourceLineNo">424</span> } else {<a name="line.424"></a>
+<span class="sourceLineNo">425</span> // we are in RUNNING state, just update the region state, and we will process it later.<a name="line.425"></a>
+<span class="sourceLineNo">426</span> env.getAssignmentManager().regionClosedAbnormally(regionNode);<a name="line.426"></a>
+<span class="sourceLineNo">427</span> }<a name="line.427"></a>
+<span class="sourceLineNo">428</span> }<a name="line.428"></a>
+<span class="sourceLineNo">429</span><a name="line.429"></a>
+<span class="sourceLineNo">430</span> void attachRemoteProc(RegionRemoteProcedureBase proc) {<a name="line.430"></a>
+<span class="sourceLineNo">431</span> this.remoteProc = proc;<a name="line.431"></a>
+<span class="sourceLineNo">432</span> }<a name="line.432"></a>
+<span class="sourceLineNo">433</span><a name="line.433"></a>
+<span class="sourceLineNo">434</span> void unattachRemoteProc(RegionRemoteProcedureBase proc) {<a name="line.434"></a>
+<span class="sourceLineNo">435</span> assert this.remoteProc == proc;<a name="line.435"></a>
+<span class="sourceLineNo">436</span> this.remoteProc = null;<a name="line.436"></a>
+<span class="sourceLineNo">437</span> }<a name="line.437"></a>
+<span class="sourceLineNo">438</span><a name="line.438"></a>
+<span class="sourceLineNo">439</span> // will be called after we finish loading the meta entry for this region.<a name="line.439"></a>
+<span class="sourceLineNo">440</span> // used to change the state of the region node if we have a sub procedure, as we may not persist<a name="line.440"></a>
+<span class="sourceLineNo">441</span> // the state to meta yet. See the code in RegionRemoteProcedureBase.execute for more details.<a name="line.441"></a>
+<span class="sourceLineNo">442</span> void stateLoaded(AssignmentManager am, RegionStateNode regionNode) {<a name="line.442"></a>
+<span class="sourceLineNo">443</span> if (remoteProc != null) {<a name="line.443"></a>
+<span class="sourceLineNo">444</span> remoteProc.stateLoaded(am, regionNode);<a name="line.444"></a>
+<span class="sourceLineNo">445</span> }<a name="line.445"></a>
+<span class="sourceLineNo">446</span> }<a name="line.446"></a>
+<span class="sourceLineNo">447</span><a name="line.447"></a>
+<span class="sourceLineNo">448</span> @Override<a name="line.448"></a>
+<span class="sourceLineNo">449</span> protected void rollbackState(MasterProcedureEnv env, RegionStateTransitionState state)<a name="line.449"></a>
+<span class="sourceLineNo">450</span> throws IOException, InterruptedException {<a name="line.450"></a>
+<span class="sourceLineNo">451</span> // no rollback<a name="line.451"></a>
+<span class="sourceLineNo">452</span> throw new UnsupportedOperationException();<a name="line.452"></a>
+<span class="sourceLineNo">453</span> }<a name="line.453"></a>
+<span class="sourceLineNo">454</span><a name="line.454"></a>
+<span class="sourceLineNo">455</span> @Override<a name="line.455"></a>
+<span class="sourceLineNo">456</span> protected RegionStateTransitionState getState(int stateId) {<a name="line.456"></a>
+<span class="sourceLineNo">457</span> return RegionStateTransitionState.forNumber(stateId);<a name="line.457"></a>
+<span class="sourceLineNo">458</span> }<a name="line.458"></a>
+<span class="sourceLineNo">459</span><a name="line.459"></a>
+<span class="sourceLineNo">460</span> @Override<a name="line.460"></a>
+<span class="sourceLineNo">461</span> protected int getStateId(RegionStateTransitionState state) {<a name="line.461"></a>
+<span class="sourceLineNo">462</span> return state.getNumber();<a name="line.462"></a>
+<span class="sourceLineNo">463</span> }<a name="line.463"></a>
+<span class="sourceLineNo">464</span><a name="line.464"></a>
+<span class="sourceLineNo">465</span> @Override<a name="line.465"></a>
+<span class="sourceLineNo">466</span> protected RegionStateTransitionState getInitialState() {<a name="line.466"></a>
+<span class="sourceLineNo">467</span> return initialState;<a name="line.467"></a>
+<span class="sourceLineNo">468</span> }<a name="line.468"></a>
+<span class="sourceLineNo">469</span><a name="line.469"></a>
+<span class="sourceLineNo">470</span> private static TransitionType convert(RegionTransitionType type) {<a name="line.470"></a>
+<span class="sourceLineNo">471</span> switch (type) {<a name="line.471"></a>
+<span class="sourceLineNo">472</span> case ASSIGN:<a name="line.472"></a>
+<span class="sourceLineNo">473</span> return TransitionType.ASSIGN;<a name="line.473"></a>
+<span class="sourceLineNo">474</span> case UNASSIGN:<a name="line.474"></a>
+<span class="sourceLineNo">475</span> return TransitionType.UNASSIGN;<a name="line.475"></a>
+<span class="sourceLineNo">476</span> case MOVE:<a name="line.476"></a>
+<span class="sourceLineNo">477</span> return TransitionType.MOVE;<a name="line.477"></a>
+<span class="sourceLineNo">478</span> case REOPEN:<a name="line.478"></a>
+<span class="sourceLineNo">479</span> return TransitionType.REOPEN;<a name="line.479"></a>
+<span class="sourceLineNo">480</span> default:<a name="line.480"></a>
+<span class="sourceLineNo">481</span> throw new IllegalArgumentException("Unknown RegionTransitionType: " + type);<a name="line.481"></a>
+<span class="sourceLineNo">482</span> }<a name="line.482"></a>
+<span class="sourceLineNo">483</span> }<a name="line.483"></a>
+<span class="sourceLineNo">484</span><a name="line.484"></a>
+<span class="sourceLineNo">485</span> private static RegionTransitionType convert(TransitionType type) {<a name="line.485"></a>
+<span class="sourceLineNo">486</span> switch (type) {<a name="line.486"></a>
+<span class="sourceLineNo">487</span> case ASSIGN:<a name="line.487"></a>
+<span class="sourceLineNo">488</span> return RegionTransitionType.ASSIGN;<a name="line.488"></a>
+<span class="sourceLineNo">489</span> case UNASSIGN:<a name="line.489"></a>
+<span class="sourceLineNo">490</span> return RegionTransitionType.UNASSIGN;<a name="line.490"></a>
+<span class="sourceLineNo">491</span> case MOVE:<a name="line.491"></a>
+<span class="sourceLineNo">492</span> return RegionTransitionType.MOVE;<a name="line.492"></a>
+<span class="sourceLineNo">493</span> case REOPEN:<a name="line.493"></a>
+<span class="sourceLineNo">494</span> return RegionTransitionType.REOPEN;<a name="line.494"></a>
+<span class="sourceLineNo">495</span> default:<a name="line.495"></a>
+<span class="sourceLineNo">496</span> throw new IllegalArgumentException("Unknown TransitionType: " + type);<a name="line.496"></a>
+<span class="sourceLineNo">497</span> }<a name="line.497"></a>
+<span class="sourceLineNo">498</span> }<a name="line.498"></a>
+<span class="sourceLineNo">499</span><a name="line.499"></a>
+<span class="sourceLineNo">500</span> @Override<a name="line.500"></a>
+<span class="sourceLineNo">501</span> protected void serializeStateData(ProcedureStateSerializer serializer) throws IOException {<a name="line.501"></a>
+<span class="sourceLineNo">502</span> super.serializeStateData(serializer);<a name="line.502"></a>
+<span class="sourceLineNo">503</span> RegionStateTransitionStateData.Builder builder = RegionStateTransitionStateData.newBuilder()<a name="line.503"></a>
+<span class="sourceLineNo">504</span> .setType(convert(type)).setForceNewPlan(forceNewPlan);<a name="line.504"></a>
+<span class="sourceLineNo">505</span> if (assignCandidate != null) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span> builder.setAssignCandidate(ProtobufUtil.toServerName(assignCandidate));<a name="line.506"></a>
+<span class="sourceLineNo">507</span> }<a name="line.507"></a>
+<span class="sourceLineNo">508</span> serializer.serialize(builder.build());<a name="line.508"></a>
+<span class="sourceLineNo">509</span> }<a name="line.509"></a>
+<span class="sourceLineNo">510</span><a name="line.510"></a>
+<span class="sourceLineNo">511</span> @Override<a name="line.511"></a>
+<span class="sourceLineNo">512</span> protected void deserializeStateData(ProcedureStateSerializer serializer) throws IOException {<a name="line.512"></a>
+<span class="sourceLineNo">513</span> super.deserializeStateData(serializer);<a name="line.513"></a>
+<span class="sourceLineNo">514</span> RegionStateTransitionStateData data =<a name="line.514"></a>
+<span class="sourceLineNo">515</span> serializer.deserialize(RegionStateTransitionStateData.class);<a name="line.515"></a>
+<span class="sourceLineNo">516</span> type = convert(data.getType());<a name="line.516"></a>
+<span class="sourceLineNo">517</span> setInitialAndLastState();<a name="line.517"></a>
+<span class="sourceLineNo">518</span> forceNewPlan = data.getForceNewPlan();<a name="line.518"></a>
+<span class="sourceLineNo">519</span> if (data.hasAssignCandidate()) {<a name="line.519"></a>
+<span class="sourceLineNo">520</span> assignCandidate = ProtobufUtil.toServerName(data.getAssignCandidate());<a name="line.520"></a>
+<span class="sourceLineNo">521</span> }<a name="line.521"></a>
+<span class="sourceLineNo">522</span> }<a name="line.522"></a>
+<span class="sourceLineNo">523</span><a name="line.523"></a>
+<span class="sourceLineNo">524</span> @Override<a name="line.524"></a>
+<span class="sourceLineNo">525</span> protected ProcedureMetrics getProcedureMetrics(MasterProcedureEnv env) {<a name="line.525"></a>
+<span class="sourceLineNo">526</span> MetricsAssignmentManager metrics = env.getAssignmentManager().getAssignmentManagerMetrics();<a name="line.526"></a>
+<span class="sourceLineNo">527</span> switch (type) {<a name="line.527"></a>
+<span class="sourceLineNo">528</span> case ASSIGN:<a name="line.528"></a>
+<span class="sourceLineNo">529</span> return metrics.getAssignProcMetrics();<a name="line.529"></a>
+<span class="sourceLineNo">530</span> case UNASSIGN:<a name="line.530"></a>
+<span class="sourceLineNo">531</span> return metrics.getUnassignProcMetrics();<a name="line.531"></a>
+<span class="sourceLineNo">532</span> case MOVE:<a name="line.532"></a>
+<span class="sourceLineNo">533</span> return metrics.getMoveProcMetrics();<a name="line.533"></a>
+<span class="sourceLineNo">534</span> case REOPEN:<a name="line.534"></a>
+<span class="sourceLineNo">535</span> return metrics.getReopenProcMetrics();<a name="line.535"></a>
+<span class="sourceLineNo">536</span> default:<a name="line.536"></a>
+<span class="sourceLineNo">537</span> throw new IllegalArgumentException("Unknown transition type: " + type);<a name="line.537"></a>
+<span class="sourceLineNo">538</span> }<a name="line.538"></a>
+<span class="sourceLineNo">539</span> }<a name="line.539"></a>
+<span class="sourceLineNo">540</span><a name="line.540"></a>
+<span class="sourceLineNo">541</span> @Override<a name="line.541"></a>
+<span class="sourceLineNo">542</span> public void toStringClassDetails(StringBuilder sb) {<a name="line.542"></a>
+<span class="sourceLineNo">543</span> super.toStringClassDetails(sb);<a name="line.543"></a>
+<span class="sourceLineNo">544</span> if (initialState == RegionStateTransitionState.REGION_STATE_TRANSITION_GET_ASSIGN_CANDIDATE) {<a name="line.544"></a>
+<span class="sourceLineNo">545</span> sb.append(", ASSIGN");<a name="line.545"></a>
+<span class="sourceLineNo">546</span> } else if (lastState == RegionStateTransitionState.REGION_STATE_TRANSITION_CONFIRM_CLOSED) {<a name="line.546"></a>
+<span class="sourceLineNo">547</span> sb.append(", UNASSIGN");<a name="line.547"></a>
+<span class="sourceLineNo">548</span> } else {<a name="line.548"></a>
+<span class="sourceLineNo">549</span> sb.append(", REOPEN/MOVE");<a name="line.549"></a>
+<span class="sourceLineNo">550</span> }<a name="line.550"></a>
+<span class="sourceLineNo">551</span> }<a name="line.551"></a>
+<span class="sourceLineNo">552</span><a name="line.552"></a>
+<span class="sourceLineNo">553</span> private static TransitRegionStateProcedure setOwner(MasterProcedureEnv env,<a name="line.553"></a>
+<span class="sourceLineNo">554</span> TransitRegionStateProcedure proc) {<a name="line.554"></a>
+<span class="sourceLineNo">555</span> proc.setOwner(env.getRequestUser().getShortName());<a name="line.555"></a>
+<span class="sourceLineNo">556</span> return proc;<a name="line.556"></a>
+<span class="sourceLineNo">557</span> }<a name="line.557"></a>
+<span class="sourceLineNo">558</span><a name="line.558"></a>
+<span class="sourceLineNo">559</span> public enum TransitionType {<a name="line.559"></a>
+<span class="sourceLineNo">560</span> ASSIGN, UNASSIGN, MOVE, REOPEN<a name="line.560"></a>
+<span class="sourceLineNo">561</span> }<a name="line.561"></a>
+<span class="sourceLineNo">562</span><a name="line.562"></a>
+<span class="sourceLineNo">563</span> // Be careful that, when you call these 4 methods below, you need to manually attach the returned<a name="line.563"></a>
+<span class="sourceLineNo">564</span> // procedure with the RegionStateNode, otherwise the procedure will quit immediately without doing<a name="line.564"></a>
+<span class="sourceLineNo">565</span> // anything. See the comment in executeFromState to find out why we need this assumption.<a name="line.565"></a>
+<span class="sourceLineNo">566</span> public static TransitRegionStateProcedure assign(MasterProcedureEnv env, RegionInfo region,<a name="line.566"></a>
+<span class="sourceLineNo">567</span> @Nullable ServerName targetServer) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span> return assign(env, region, false, targetServer);<a name="line.568"></a>
+<span class="sourceLineNo">569</span> }<a name="line.569"></a>
+<span class="sourceLineNo">570</span><a name="line.570"></a>
+<span class="sourceLineNo">571</span> public static TransitRegionStateProcedure assign(MasterProcedureEnv env, RegionInfo region,<a name="line.571"></a>
+<span class="sourceLineNo">572</span> boolean forceNewPlan, @Nullable ServerName targetServer) {<a name="line.572"></a>
+<span class="sourceLineNo">573</span> return setOwner(env, new TransitRegionStateProcedure(env, region, targetServer, forceNewPlan,<a name="line.573"></a>
+<span class="sourceLineNo">574</span> TransitionType.ASSIGN));<a name="line.574"></a>
+<span class="sourceLineNo">575</span> }<a name="line.575"></a>
+<span class="sourceLineNo">576</span><a name="line.576"></a>
+<span class="sourceLineNo">577</span> public static TransitRegionStateProcedure unassign(MasterProcedureEnv env, RegionInfo region) {<a name="line.577"></a>
+<span class="sourceLineNo">578</span> return setOwner(env,<a name="line.578"></a>
+<span class="sourceLineNo">579</span> new TransitRegionStateProcedure(env, region, null, false, TransitionType.UNASSIGN));<a name="line.579"></a>
+<span class="sourceLineNo">580</span> }<a name="line.580"></a>
+<span class="sourceLineNo">581</span><a name="line.581"></a>
+<span class="sourceLineNo">582</span> public static TransitRegionStateProcedure reopen(MasterProcedureEnv env, RegionInfo region) {<a name="line.582"></a>
+<span class="sourceLineNo">583</span> return setOwner(env,<a name="line.583"></a>
+<span class="sourceLineNo">584</span> new TransitRegionStateProcedure(env, region, null, false, TransitionType.REOPEN));<a name="line.584"></a>
+<span class="sourceLineNo">585</span> }<a name="line.585"></a>
+<span class="sourceLineNo">586</span><a name="line.586"></a>
+<span class="sourceLineNo">587</span> public static TransitRegionStateProcedure move(MasterProcedureEnv env, RegionInfo region,<a name="line.587"></a>
+<span class="sourceLineNo">588</span> @Nullable ServerName targetServer) {<a name="line.588"></a>
+<span class="sourceLineNo">589</span> return setOwner(env, new TransitRegionStateProcedure(env, region, targetServer,<a name="line.589"></a>
+<span class="sourceLineNo">590</span> targetServer == null, TransitionType.MOVE));<a name="line.590"></a>
+<span class="sourceLineNo">591</span> }<a name="line.591"></a>
+<span class="sourceLineNo">592</span>}<a name="line.592"></a>
diff --git a/downloads.html b/downloads.html
index 9226f11..443ed97 100644
--- a/downloads.html
+++ b/downloads.html
@@ -395,7 +395,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/export_control.html b/export_control.html
index 1b5abaa..d02fb67 100644
--- a/export_control.html
+++ b/export_control.html
@@ -185,7 +185,7 @@ for more details.</p>
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/index.html b/index.html
index defc722..4a94ffc 100644
--- a/index.html
+++ b/index.html
@@ -263,7 +263,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/issue-management.html b/issue-management.html
index 3e871d6..e31d564 100644
--- a/issue-management.html
+++ b/issue-management.html
@@ -157,7 +157,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/licenses.html b/licenses.html
index 0d3d9d0..726f34e 100644
--- a/licenses.html
+++ b/licenses.html
@@ -360,7 +360,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/mailing-lists.html b/mailing-lists.html
index bcd271a..fd57a3e 100644
--- a/mailing-lists.html
+++ b/mailing-lists.html
@@ -203,7 +203,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/metrics.html b/metrics.html
index a12521d..4fa2f9d 100644
--- a/metrics.html
+++ b/metrics.html
@@ -313,7 +313,7 @@ export HBASE_REGIONSERVER_OPTS="$HBASE_JMX_OPTS -Dcom.sun.management.jmxrem
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/old_news.html b/old_news.html
index af13844..4026080 100644
--- a/old_news.html
+++ b/old_news.html
@@ -304,7 +304,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/plugin-management.html b/plugin-management.html
index 0122976..0e154c7 100644
--- a/plugin-management.html
+++ b/plugin-management.html
@@ -309,7 +309,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/plugins.html b/plugins.html
index 9ae466b..1f2680d 100644
--- a/plugins.html
+++ b/plugins.html
@@ -240,7 +240,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/poweredbyhbase.html b/poweredbyhbase.html
index cdf242c..6a03cd6 100644
--- a/poweredbyhbase.html
+++ b/poweredbyhbase.html
@@ -638,7 +638,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/project-info.html b/project-info.html
index 57c464e..642561b 100644
--- a/project-info.html
+++ b/project-info.html
@@ -201,7 +201,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/project-reports.html b/project-reports.html
index e7dc879..322abd5 100644
--- a/project-reports.html
+++ b/project-reports.html
@@ -174,7 +174,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/pseudo-distributed.html b/pseudo-distributed.html
index 6498003..bcc6646 100644
--- a/pseudo-distributed.html
+++ b/pseudo-distributed.html
@@ -162,7 +162,7 @@ Running Apache HBase (TM) in pseudo-distributed mode
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/replication.html b/replication.html
index cb37b3a..4d131cb 100644
--- a/replication.html
+++ b/replication.html
@@ -157,7 +157,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/resources.html b/resources.html
index 2dd02d3..22a06c8 100644
--- a/resources.html
+++ b/resources.html
@@ -185,7 +185,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/scm.html b/scm.html
index 0e7245b..d2f8bba 100644
--- a/scm.html
+++ b/scm.html
@@ -168,7 +168,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/sponsors.html b/sponsors.html
index 5e44b11..eae6ec7 100644
--- a/sponsors.html
+++ b/sponsors.html
@@ -187,7 +187,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/summary.html b/summary.html
index f43d3ba..b082d96 100644
--- a/summary.html
+++ b/summary.html
@@ -200,7 +200,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/supportingprojects.html b/supportingprojects.html
index 0d8225d..c16f9a5 100644
--- a/supportingprojects.html
+++ b/supportingprojects.html
@@ -378,7 +378,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/team.html b/team.html
index 1398f7e..c5af60d 100644
--- a/team.html
+++ b/team.html
@@ -749,7 +749,7 @@
<div class="row">
<p>Copyright ©2007–2022
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-28</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2022-03-30</li>
</p>
</div>
<p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/testdevapidocs/index-all.html b/testdevapidocs/index-all.html
index 94c2b62..7833911 100644
--- a/testdevapidocs/index-all.html
+++ b/testdevapidocs/index-all.html
@@ -55345,6 +55345,14 @@
<dd> </dd>
<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystems-java.lang.String-java.lang.String-org.apache.hadoop.hbase.backup.TestHFileArchiving.ArchivingFunction-">testArchiveStoreFilesDifferentFileSystems(String, String, TestHFileArchiving.ArchivingFunction<Configuration, FileSystem, RegionInfo, Path, byte[], Collection<HStoreFile>>)</a></span> - Method in class org.apache.hadoop.hbase.backup.<a h [...]
<dd> </dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystems-java.lang.String-java.lang.String-boolean-boolean-boolean-org.apache.hadoop.hbase.backup.TestHFileArchiving.ArchivingFunction-">testArchiveStoreFilesDifferentFileSystems(String, String, boolean, boolean, boolean, TestHFileArchiving.ArchivingFunction<Configuration, FileSystem, RegionInfo, Path, byte[], Collection<HStoreFile>>)</a></span> - [...]
+<dd> </dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystemsArchiveFileMatchCurrent--">testArchiveStoreFilesDifferentFileSystemsArchiveFileMatchCurrent()</a></span> - Method in class org.apache.hadoop.hbase.backup.<a href="org/apache/hadoop/hbase/backup/TestHFileArchiving.html" title="class in org.apache.hadoop.hbase.backup">TestHFileArchiving</a></dt>
+<dd> </dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystemsArchiveFileMismatch--">testArchiveStoreFilesDifferentFileSystemsArchiveFileMismatch()</a></span> - Method in class org.apache.hadoop.hbase.backup.<a href="org/apache/hadoop/hbase/backup/TestHFileArchiving.html" title="class in org.apache.hadoop.hbase.backup">TestHFileArchiving</a></dt>
+<dd> </dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystemsFileAlreadyArchived--">testArchiveStoreFilesDifferentFileSystemsFileAlreadyArchived()</a></span> - Method in class org.apache.hadoop.hbase.backup.<a href="org/apache/hadoop/hbase/backup/TestHFileArchiving.html" title="class in org.apache.hadoop.hbase.backup">TestHFileArchiving</a></dt>
+<dd> </dd>
<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystemsWallAndRootSame--">testArchiveStoreFilesDifferentFileSystemsWallAndRootSame()</a></span> - Method in class org.apache.hadoop.hbase.backup.<a href="org/apache/hadoop/hbase/backup/TestHFileArchiving.html" title="class in org.apache.hadoop.hbase.backup">TestHFileArchiving</a></dt>
<dd> </dd>
<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystemsWallNullPlainRoot--">testArchiveStoreFilesDifferentFileSystemsWallNullPlainRoot()</a></span> - Method in class org.apache.hadoop.hbase.backup.<a href="org/apache/hadoop/hbase/backup/TestHFileArchiving.html" title="class in org.apache.hadoop.hbase.backup">TestHFileArchiving</a></dt>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html b/testdevapidocs/org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html
index a81998e..36213fc 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html
@@ -110,7 +110,7 @@ var activeTableTab = "activeTableTab";
<hr>
<br>
<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html?is-external=true" title="class or interface in java.lang">@FunctionalInterface</a>
-private static interface <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.196">TestHFileArchiving.ArchivingFunction</a><Configuration,FS,Region,Dir,Family,Files></pre>
+private static interface <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.255">TestHFileArchiving.ArchivingFunction</a><Configuration,FS,Region,Dir,Family,Files></pre>
</li>
</ul>
</div>
@@ -161,7 +161,7 @@ private static interface <a href="../../../../../src-html/org/apache/hadoop/hbas
<ul class="blockListLast">
<li class="blockList">
<h4>apply</h4>
-<pre>void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html#line.197">apply</a>(<a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html" title="type parameter in TestHFileArchiving.ArchivingFunction">Configuration</a> config,
+<pre>void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html#line.256">apply</a>(<a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html" title="type parameter in TestHFileArchiving.ArchivingFunction">Configuration</a> config,
<a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html" title="type parameter in TestHFileArchiving.ArchivingFunction">FS</a> fs,
<a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html" title="type parameter in TestHFileArchiving.ArchivingFunction">Region</a> region,
<a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html" title="type parameter in TestHFileArchiving.ArchivingFunction">Dir</a> dir,
diff --git a/testdevapidocs/org/apache/hadoop/hbase/backup/TestHFileArchiving.html b/testdevapidocs/org/apache/hadoop/hbase/backup/TestHFileArchiving.html
index b482df9..b778afa 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/backup/TestHFileArchiving.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/backup/TestHFileArchiving.html
@@ -18,7 +18,7 @@
catch(err) {
}
//-->
-var methods = {"i0":10,"i1":9,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":9,"i8":9,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":10,"i24":10,"i25":10,"i26":10,"i27":10,"i28":10};
+var methods = {"i0":10,"i1":9,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":9,"i8":9,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10,"i17":10,"i18":10,"i19":10,"i20":10,"i21":10,"i22":10,"i23":10,"i24":10,"i25":10,"i26":10,"i27":10,"i28":10,"i29":10,"i30":10,"i31":10,"i32":10};
var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]};
var altColor = "altColor";
var rowColor = "rowColor";
@@ -109,7 +109,7 @@ var activeTableTab = "activeTableTab";
<li class="blockList">
<hr>
<br>
-<pre>public class <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.89">TestHFileArchiving</a>
+<pre>public class <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.91">TestHFileArchiving</a>
extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a></pre>
<div class="block">Test that the <code>HFileArchiver</code> correctly removes all the parts of a region when cleaning up
a region</div>
@@ -312,36 +312,57 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
</tr>
<tr id="i22" class="altColor">
<td class="colFirst"><code>private void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystems-java.lang.String-java.lang.String-org.apache.hadoop.hbase.backup.TestHFileArchiving.ArchivingFunction-">testArchiveStoreFilesDifferentFileSystems</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> walDir,
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystems-java.lang.String-java.lang.String-boolean-boolean-boolean-org.apache.hadoop.hbase.backup.TestHFileArchiving.ArchivingFunction-">testArchiveStoreFilesDifferentFileSystems</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">Stri [...]
<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> expectedBase,
+ boolean archiveFileExists,
+ boolean sourceFileExists,
+ boolean archiveFileDifferentLength,
<a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html" title="interface in org.apache.hadoop.hbase.backup">TestHFileArchiving.ArchivingFunction</a><org.apache.hadoop.conf.Configuration,org.apache.hadoop.fs.FileSystem,org.apache.hadoop.hbase.client.RegionInfo,org.apache.hadoop.fs.Path,byte[],<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html?is-external=true" title="class or in [...]
</tr>
<tr id="i23" class="rowColor">
+<td class="colFirst"><code>private void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystems-java.lang.String-java.lang.String-org.apache.hadoop.hbase.backup.TestHFileArchiving.ArchivingFunction-">testArchiveStoreFilesDifferentFileSystems</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> walDir,
+ <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> expectedBase,
+ <a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html" title="interface in org.apache.hadoop.hbase.backup">TestHFileArchiving.ArchivingFunction</a><org.apache.hadoop.conf.Configuration,org.apache.hadoop.fs.FileSystem,org.apache.hadoop.hbase.client.RegionInfo,org.apache.hadoop.fs.Path,byte[],<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html?is-external=true" title="class or in [...]
+</tr>
+<tr id="i24" class="altColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystemsArchiveFileMatchCurrent--">testArchiveStoreFilesDifferentFileSystemsArchiveFileMatchCurrent</a></span>()</code> </td>
+</tr>
+<tr id="i25" class="rowColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystemsArchiveFileMismatch--">testArchiveStoreFilesDifferentFileSystemsArchiveFileMismatch</a></span>()</code> </td>
+</tr>
+<tr id="i26" class="altColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystemsFileAlreadyArchived--">testArchiveStoreFilesDifferentFileSystemsFileAlreadyArchived</a></span>()</code> </td>
+</tr>
+<tr id="i27" class="rowColor">
<td class="colFirst"><code>void</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystemsWallAndRootSame--">testArchiveStoreFilesDifferentFileSystemsWallAndRootSame</a></span>()</code> </td>
</tr>
-<tr id="i24" class="altColor">
+<tr id="i28" class="altColor">
<td class="colFirst"><code>void</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystemsWallNullPlainRoot--">testArchiveStoreFilesDifferentFileSystemsWallNullPlainRoot</a></span>()</code> </td>
</tr>
-<tr id="i25" class="rowColor">
+<tr id="i29" class="rowColor">
<td class="colFirst"><code>void</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystemsWallWithSchemaPlainRoot--">testArchiveStoreFilesDifferentFileSystemsWallWithSchemaPlainRoot</a></span>()</code> </td>
</tr>
-<tr id="i26" class="altColor">
+<tr id="i30" class="altColor">
<td class="colFirst"><code>void</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testCleaningRace--">testCleaningRace</a></span>()</code>
<div class="block">Test HFileArchiver.resolveAndArchive() race condition HBASE-7643</div>
</td>
</tr>
-<tr id="i27" class="rowColor">
+<tr id="i31" class="rowColor">
<td class="colFirst"><code>void</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testDeleteRegionWithNoStoreFiles--">testDeleteRegionWithNoStoreFiles</a></span>()</code>
<div class="block">Test that the region directory is removed when we archive a region without store files, but
still has hidden files.</div>
</td>
</tr>
-<tr id="i28" class="altColor">
+<tr id="i32" class="altColor">
<td class="colFirst"><code>void</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testRemoveRegionDirOnArchive--">testRemoveRegionDirOnArchive</a></span>()</code> </td>
</tr>
@@ -373,7 +394,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>CLASS_RULE</h4>
-<pre>public static final <a href="../../../../../org/apache/hadoop/hbase/HBaseClassTestRule.html" title="class in org.apache.hadoop.hbase">HBaseClassTestRule</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.92">CLASS_RULE</a></pre>
+<pre>public static final <a href="../../../../../org/apache/hadoop/hbase/HBaseClassTestRule.html" title="class in org.apache.hadoop.hbase">HBaseClassTestRule</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.94">CLASS_RULE</a></pre>
</li>
</ul>
<a name="LOG">
@@ -382,7 +403,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>LOG</h4>
-<pre>private static final org.slf4j.Logger <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.95">LOG</a></pre>
+<pre>private static final org.slf4j.Logger <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.97">LOG</a></pre>
</li>
</ul>
<a name="UTIL">
@@ -391,7 +412,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>UTIL</h4>
-<pre>private static final <a href="../../../../../org/apache/hadoop/hbase/HBaseTestingUtil.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtil</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.96">UTIL</a></pre>
+<pre>private static final <a href="../../../../../org/apache/hadoop/hbase/HBaseTestingUtil.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtil</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.98">UTIL</a></pre>
</li>
</ul>
<a name="TEST_FAM">
@@ -400,7 +421,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>TEST_FAM</h4>
-<pre>private static final byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.97">TEST_FAM</a></pre>
+<pre>private static final byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.99">TEST_FAM</a></pre>
</li>
</ul>
<a name="POOL">
@@ -409,7 +430,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>POOL</h4>
-<pre>private static org.apache.hadoop.hbase.master.cleaner.DirScanPool <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.99">POOL</a></pre>
+<pre>private static org.apache.hadoop.hbase.master.cleaner.DirScanPool <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.101">POOL</a></pre>
</li>
</ul>
<a name="name">
@@ -418,7 +439,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>name</h4>
-<pre>public org.junit.rules.TestName <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.101">name</a></pre>
+<pre>public org.junit.rules.TestName <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.103">name</a></pre>
</li>
</ul>
</li>
@@ -435,7 +456,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>TestHFileArchiving</h4>
-<pre>public <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.89">TestHFileArchiving</a>()</pre>
+<pre>public <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.91">TestHFileArchiving</a>()</pre>
</li>
</ul>
</li>
@@ -452,7 +473,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>setupCluster</h4>
-<pre>public static void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.107">setupCluster</a>()
+<pre>public static void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.109">setupCluster</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<div class="block">Setup the config for the cluster</div>
<dl>
@@ -467,7 +488,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>setupConf</h4>
-<pre>private static void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.117">setupConf</a>(org.apache.hadoop.conf.Configuration conf)</pre>
+<pre>private static void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.119">setupConf</a>(org.apache.hadoop.conf.Configuration conf)</pre>
</li>
</ul>
<a name="tearDown--">
@@ -476,7 +497,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>tearDown</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.131">tearDown</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.133">tearDown</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -490,7 +511,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>cleanupTest</h4>
-<pre>public static void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.137">cleanupTest</a>()
+<pre>public static void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.139">cleanupTest</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -504,7 +525,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testArchiveStoreFilesDifferentFileSystemsWallWithSchemaPlainRoot</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.143">testArchiveStoreFilesDifferentFileSystemsWallWithSchemaPlainRoot</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.145">testArchiveStoreFilesDifferentFileSystemsWallWithSchemaPlainRoot</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -518,7 +539,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testArchiveStoreFilesDifferentFileSystemsWallNullPlainRoot</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.151">testArchiveStoreFilesDifferentFileSystemsWallNullPlainRoot</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.153">testArchiveStoreFilesDifferentFileSystemsWallNullPlainRoot</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -532,7 +553,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testArchiveStoreFilesDifferentFileSystemsWallAndRootSame</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.158">testArchiveStoreFilesDifferentFileSystemsWallAndRootSame</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.160">testArchiveStoreFilesDifferentFileSystemsWallAndRootSame</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -540,14 +561,75 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
</dl>
</li>
</ul>
+<a name="testArchiveStoreFilesDifferentFileSystemsFileAlreadyArchived--">
+<!-- -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>testArchiveStoreFilesDifferentFileSystemsFileAlreadyArchived</h4>
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.167">testArchiveStoreFilesDifferentFileSystemsFileAlreadyArchived</a>()
+ throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
+<dl>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></code></dd>
+</dl>
+</li>
+</ul>
+<a name="testArchiveStoreFilesDifferentFileSystemsArchiveFileMatchCurrent--">
+<!-- -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>testArchiveStoreFilesDifferentFileSystemsArchiveFileMatchCurrent</h4>
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.174">testArchiveStoreFilesDifferentFileSystemsArchiveFileMatchCurrent</a>()
+ throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
+<dl>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></code></dd>
+</dl>
+</li>
+</ul>
+<a name="testArchiveStoreFilesDifferentFileSystemsArchiveFileMismatch--">
+<!-- -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>testArchiveStoreFilesDifferentFileSystemsArchiveFileMismatch</h4>
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.181">testArchiveStoreFilesDifferentFileSystemsArchiveFileMismatch</a>()
+ throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
+<dl>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></code></dd>
+</dl>
+</li>
+</ul>
<a name="testArchiveStoreFilesDifferentFileSystems-java.lang.String-java.lang.String-org.apache.hadoop.hbase.backup.TestHFileArchiving.ArchivingFunction-">
<!-- -->
</a>
<ul class="blockList">
<li class="blockList">
<h4>testArchiveStoreFilesDifferentFileSystems</h4>
-<pre>private void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.164">testArchiveStoreFilesDifferentFileSystems</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> walDir,
+<pre>private void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.187">testArchiveStoreFilesDifferentFileSystems</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> walDir,
+ <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> expectedBase,
+ <a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html" title="interface in org.apache.hadoop.hbase.backup">TestHFileArchiving.ArchivingFunction</a><org.apache.hadoop.conf.Configuration,org.apache.hadoop.fs.FileSystem,org.apache.hadoop.hbase.client.RegionInfo,org.apache.hadoop.fs.Path,byte[],<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html?is-external=true" titl [...]
+ throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
+<dl>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></code></dd>
+</dl>
+</li>
+</ul>
+<a name="testArchiveStoreFilesDifferentFileSystems-java.lang.String-java.lang.String-boolean-boolean-boolean-org.apache.hadoop.hbase.backup.TestHFileArchiving.ArchivingFunction-">
+<!-- -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>testArchiveStoreFilesDifferentFileSystems</h4>
+<pre>private void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.194">testArchiveStoreFilesDifferentFileSystems</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> walDir,
<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> expectedBase,
+ boolean archiveFileExists,
+ boolean sourceFileExists,
+ boolean archiveFileDifferentLength,
<a href="../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html" title="interface in org.apache.hadoop.hbase.backup">TestHFileArchiving.ArchivingFunction</a><org.apache.hadoop.conf.Configuration,org.apache.hadoop.fs.FileSystem,org.apache.hadoop.hbase.client.RegionInfo,org.apache.hadoop.fs.Path,byte[],<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html?is-external=true" titl [...]
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<dl>
@@ -562,7 +644,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testArchiveRecoveredEditsWalDirNull</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.202">testArchiveRecoveredEditsWalDirNull</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.261">testArchiveRecoveredEditsWalDirNull</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -576,7 +658,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testArchiveRecoveredEditsWalDirSameFsStoreFiles</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.207">testArchiveRecoveredEditsWalDirSameFsStoreFiles</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.266">testArchiveRecoveredEditsWalDirSameFsStoreFiles</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -590,7 +672,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testArchiveRecoveredEditsWalDirNullOrSame</h4>
-<pre>private void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.211">testArchiveRecoveredEditsWalDirNullOrSame</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> walDir)
+<pre>private void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.270">testArchiveRecoveredEditsWalDirNullOrSame</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> walDir)
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -604,7 +686,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testArchiveRecoveredEditsWrongFS</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.225">testArchiveRecoveredEditsWrongFS</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.284">testArchiveRecoveredEditsWrongFS</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -618,7 +700,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testArchiveRecoveredEditsWalDirDifferentFS</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.236">testArchiveRecoveredEditsWalDirDifferentFS</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.295">testArchiveRecoveredEditsWalDirDifferentFS</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -632,7 +714,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testRemoveRegionDirOnArchive</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.244">testRemoveRegionDirOnArchive</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.303">testRemoveRegionDirOnArchive</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -646,7 +728,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testDeleteRegionWithNoStoreFiles</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.303">testDeleteRegionWithNoStoreFiles</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.362">testDeleteRegionWithNoStoreFiles</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<div class="block">Test that the region directory is removed when we archive a region without store files, but
still has hidden files.</div>
@@ -663,7 +745,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>initTableForArchivingRegions</h4>
-<pre>private <a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a><org.apache.hadoop.hbase.regionserver.HRegion> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.350">initTableForArchivingRegions</a>(org.apache.hadoop.hbase.TableName tableName)
+<pre>private <a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a><org.apache.hadoop.hbase.regionserver.HRegion> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.409">initTableForArchivingRegions</a>(org.apache.hadoop.hbase.TableName tableName)
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -677,7 +759,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testArchiveRegions</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.374">testArchiveRegions</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.433">testArchiveRegions</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -691,7 +773,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testArchiveRegionsWhenPermissionDenied</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.414">testArchiveRegionsWhenPermissionDenied</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.473">testArchiveRegionsWhenPermissionDenied</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -705,7 +787,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testArchiveOnTableDelete</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.445">testArchiveOnTableDelete</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.504">testArchiveOnTableDelete</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -719,7 +801,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>assertArchiveFiles</h4>
-<pre>private void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.488">assertArchiveFiles</a>(org.apache.hadoop.fs.FileSystem fs,
+<pre>private void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.547">assertArchiveFiles</a>(org.apache.hadoop.fs.FileSystem fs,
<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a><<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>> storeFiles,
long timeout)
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
@@ -735,7 +817,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testArchiveOnTableFamilyDelete</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.527">testArchiveOnTableFamilyDelete</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.586">testArchiveOnTableFamilyDelete</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a>,
<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InterruptedException.html?is-external=true" title="class or interface in java.lang">InterruptedException</a></pre>
<div class="block">Test that the store files are archived when a column family is removed.</div>
@@ -752,7 +834,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testCleaningRace</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.575">testCleaningRace</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.634">testCleaningRace</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
<div class="block">Test HFileArchiver.resolveAndArchive() race condition HBASE-7643</div>
<dl>
@@ -767,7 +849,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testArchiveRegionTableAndRegionDirsNull</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.638">testArchiveRegionTableAndRegionDirsNull</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.697">testArchiveRegionTableAndRegionDirsNull</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -781,7 +863,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testArchiveRegionWithTableDirNull</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.646">testArchiveRegionWithTableDirNull</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.705">testArchiveRegionWithTableDirNull</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -795,7 +877,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>testArchiveRegionWithRegionDirNull</h4>
-<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.663">testArchiveRegionWithRegionDirNull</a>()
+<pre>public void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.722">testArchiveRegionWithRegionDirNull</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -809,7 +891,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getHFileCleaner</h4>
-<pre>private org.apache.hadoop.hbase.master.cleaner.HFileCleaner <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.682">getHFileCleaner</a>(org.apache.hadoop.hbase.Stoppable stoppable,
+<pre>private org.apache.hadoop.hbase.master.cleaner.HFileCleaner <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.741">getHFileCleaner</a>(org.apache.hadoop.hbase.Stoppable stoppable,
org.apache.hadoop.conf.Configuration conf,
org.apache.hadoop.fs.FileSystem fs,
org.apache.hadoop.fs.Path archiveDir)
@@ -826,7 +908,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>clearArchiveDirectory</h4>
-<pre>private void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.690">clearArchiveDirectory</a>()
+<pre>private void <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.749">clearArchiveDirectory</a>()
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<dl>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -840,7 +922,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getAllFileNames</h4>
-<pre>private <a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a><<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.702">getAllFileNames</a>(org.apache.hadoop.fs.FileSystem fs,
+<pre>private <a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a><<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.761">getAllFileNames</a>(org.apache.hadoop.fs.FileSystem fs,
org.apache.hadoop.fs.Path archiveDir)
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
<div class="block">Get the names of all the files below the given directory</div>
@@ -861,7 +943,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>recurseOnFiles</h4>
-<pre>private <a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a><<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.716">recurseOnFiles</a>(org.apache.hadoop.fs.FileSystem fs,
+<pre>private <a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a><<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>> <a href="../../../../../src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.html#line.775">recurseOnFiles</a>(org.apache.hadoop.fs.FileSystem fs,
org.apache.hadoop.fs.FileStatus[] files,
<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a><<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>> fileNames)
throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/backup/class-use/TestHFileArchiving.ArchivingFunction.html b/testdevapidocs/org/apache/hadoop/hbase/backup/class-use/TestHFileArchiving.ArchivingFunction.html
index e8eae53..8a532e3 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/backup/class-use/TestHFileArchiving.ArchivingFunction.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/backup/class-use/TestHFileArchiving.ArchivingFunction.html
@@ -104,6 +104,15 @@
<tbody>
<tr class="altColor">
<td class="colFirst"><code>private void</code></td>
+<td class="colLast"><span class="typeNameLabel">TestHFileArchiving.</span><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystems-java.lang.String-java.lang.String-boolean-boolean-boolean-org.apache.hadoop.hbase.backup.TestHFileArchiving.ArchivingFunction-">testArchiveStoreFilesDifferentFileSystems</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-ex [...]
+ <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> expectedBase,
+ boolean archiveFileExists,
+ boolean sourceFileExists,
+ boolean archiveFileDifferentLength,
+ <a href="../../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html" title="interface in org.apache.hadoop.hbase.backup">TestHFileArchiving.ArchivingFunction</a><org.apache.hadoop.conf.Configuration,org.apache.hadoop.fs.FileSystem,org.apache.hadoop.hbase.client.RegionInfo,org.apache.hadoop.fs.Path,byte[],<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html?is-external=true" title="class or [...]
+</tr>
+<tr class="rowColor">
+<td class="colFirst"><code>private void</code></td>
<td class="colLast"><span class="typeNameLabel">TestHFileArchiving.</span><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.html#testArchiveStoreFilesDifferentFileSystems-java.lang.String-java.lang.String-org.apache.hadoop.hbase.backup.TestHFileArchiving.ArchivingFunction-">testArchiveStoreFilesDifferentFileSystems</a></span>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="clas [...]
<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> expectedBase,
<a href="../../../../../../org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html" title="interface in org.apache.hadoop.hbase.backup">TestHFileArchiving.ArchivingFunction</a><org.apache.hadoop.conf.Configuration,org.apache.hadoop.fs.FileSystem,org.apache.hadoop.hbase.client.RegionInfo,org.apache.hadoop.fs.Path,byte[],<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Collection.html?is-external=true" title="class or [...]
diff --git a/testdevapidocs/org/apache/hadoop/hbase/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/package-tree.html
index 07229ba..dd89d66 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/package-tree.html
@@ -668,18 +668,18 @@
<ul>
<li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a><E> (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a><T>, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
<ul>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.Service.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.Service</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/IntegrationTestDDLMasterFailover.ACTION.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">IntegrationTestDDLMasterFailover.ACTION</span></a></li>
<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/IntegrationTestRegionReplicaPerf.Stat.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">IntegrationTestRegionReplicaPerf.Stat</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HBaseClusterManager.Signal.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HBaseClusterManager.Signal</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.RoleState.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.RoleState</span></a></li>
<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ResourceChecker.Phase.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ResourceChecker.Phase</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.Service.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.Service</span></a></li>
<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/PerformanceEvaluation.Counter.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">PerformanceEvaluation.Counter</span></a></li>
<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.RoleCommand.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.RoleCommand</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/IntegrationTestDDLMasterFailover.ACTION.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">IntegrationTestDDLMasterFailover.ACTION</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.RoleState.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.RoleState</span></a></li>
<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.HealthSummary.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.HealthSummary</span></a></li>
<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HBaseClusterManager.CommandProvider.Operation.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HBaseClusterManager.CommandProvider.Operation</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ClusterManager.ServiceType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ClusterManager.ServiceType</span></a></li>
<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ZNodeClusterManager.CmdType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ZNodeClusterManager.CmdType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ClusterManager.ServiceType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ClusterManager.ServiceType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HBaseClusterManager.Signal.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HBaseClusterManager.Signal</span></a></li>
<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ScanPerformanceEvaluation.ScanCounter.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ScanPerformanceEvaluation.ScanCounter</span></a></li>
</ul>
</li>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
index 1d5e3ee..36ba9e7 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
@@ -241,10 +241,10 @@
<ul>
<li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a><E> (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a><T>, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
<ul>
-<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestYieldProcedures.TestStateMachineProcedure.State.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestYieldProcedures.TestStateMachineProcedure.State</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestStateMachineProcedure.TestSMProcedureState.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestStateMachineProcedure.TestSMProcedureState</span></a></li>
<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestProcedureBypass.StuckStateMachineState.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestProcedureBypass.StuckStateMachineState</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestStateMachineProcedure.TestSMProcedureState.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestStateMachineProcedure.TestSMProcedureState</span></a></li>
<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestProcedureRecovery.TestStateMachineProcedure.State.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestProcedureRecovery.TestStateMachineProcedure.State</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestYieldProcedures.TestStateMachineProcedure.State.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestYieldProcedures.TestStateMachineProcedure.State</span></a></li>
</ul>
</li>
</ul>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
index 9c06d5b..a6a165d 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
@@ -763,12 +763,12 @@
<ul>
<li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a><E> (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a><T>, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
<ul>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestCompactionState.StateSource.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestCompactionState.StateSource</span></a></li>
<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/DataBlockEncodingTool.Manipulation.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">DataBlockEncodingTool.Manipulation</span></a></li>
<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestCacheOnWriteInSchema.CacheOnWriteType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestCacheOnWriteInSchema.CacheOnWriteType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestCompactionState.StateSource.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestCompactionState.StateSource</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestMultiLogThreshold.ActionType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestMultiLogThreshold.ActionType</span></a></li>
<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestRegionServerReadRequestMetrics.Metric.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestRegionServerReadRequestMetrics.Metric</span></a></li>
<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestAtomicOperation.TestStep.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestAtomicOperation.TestStep</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestMultiLogThreshold.ActionType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestMultiLogThreshold.ActionType</span></a></li>
</ul>
</li>
</ul>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html
index c8c6e84..92fb3a2 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html
@@ -260,11 +260,11 @@
<ul>
<li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a><E> (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a><T>, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
<ul>
-<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestLoadCommonCrawl.Counts.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestLoadCommonCrawl.Counts</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.Counters.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestWithCellVisibilityLoadAndVerify.Counters</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestBigLinkedList.Generator.Counts.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestBigLinkedList.Generator.Counts</span></a></li>
<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestLoadAndVerify.Counters.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestLoadAndVerify.Counters</span></a></li>
<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestBigLinkedList.Verify.Counts.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestBigLinkedList.Verify.Counts</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestBigLinkedList.Generator.Counts.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestBigLinkedList.Generator.Counts</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.Counters.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestWithCellVisibilityLoadAndVerify.Counters</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestLoadCommonCrawl.Counts.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestLoadCommonCrawl.Counts</span></a></li>
</ul>
</li>
</ul>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html
index ef1e9d6..464c534 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html
@@ -206,9 +206,9 @@
<ul>
<li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a><E> (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a><T>, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
<ul>
+<li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/FaultyFSLog.FailureType.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">FaultyFSLog.FailureType</span></a></li>
<li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/TestWALSplit.Corruptions.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">TestWALSplit.Corruptions</span></a></li>
<li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/IOTestProvider.AllowedOperations.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">IOTestProvider.AllowedOperations</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/FaultyFSLog.FailureType.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">FaultyFSLog.FailureType</span></a></li>
</ul>
</li>
</ul>
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html
index 2fe5299..5620b33 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/backup/TestHFileArchiving.ArchivingFunction.html
@@ -29,714 +29,773 @@
<span class="sourceLineNo">021</span>import static org.junit.Assert.assertFalse;<a name="line.21"></a>
<span class="sourceLineNo">022</span>import static org.junit.Assert.assertNotNull;<a name="line.22"></a>
<span class="sourceLineNo">023</span>import static org.junit.Assert.assertTrue;<a name="line.23"></a>
-<span class="sourceLineNo">024</span>import static org.mockito.ArgumentMatchers.any;<a name="line.24"></a>
-<span class="sourceLineNo">025</span>import static org.mockito.Mockito.mock;<a name="line.25"></a>
-<span class="sourceLineNo">026</span>import static org.mockito.Mockito.times;<a name="line.26"></a>
-<span class="sourceLineNo">027</span>import static org.mockito.Mockito.verify;<a name="line.27"></a>
-<span class="sourceLineNo">028</span>import static org.mockito.Mockito.when;<a name="line.28"></a>
-<span class="sourceLineNo">029</span><a name="line.29"></a>
-<span class="sourceLineNo">030</span>import java.io.IOException;<a name="line.30"></a>
-<span class="sourceLineNo">031</span>import java.security.PrivilegedExceptionAction;<a name="line.31"></a>
-<span class="sourceLineNo">032</span>import java.util.ArrayList;<a name="line.32"></a>
-<span class="sourceLineNo">033</span>import java.util.Collection;<a name="line.33"></a>
-<span class="sourceLineNo">034</span>import java.util.Collections;<a name="line.34"></a>
-<span class="sourceLineNo">035</span>import java.util.HashMap;<a name="line.35"></a>
-<span class="sourceLineNo">036</span>import java.util.List;<a name="line.36"></a>
-<span class="sourceLineNo">037</span>import java.util.Map;<a name="line.37"></a>
-<span class="sourceLineNo">038</span>import java.util.Objects;<a name="line.38"></a>
-<span class="sourceLineNo">039</span>import java.util.stream.Collectors;<a name="line.39"></a>
-<span class="sourceLineNo">040</span>import org.apache.hadoop.conf.Configuration;<a name="line.40"></a>
-<span class="sourceLineNo">041</span>import org.apache.hadoop.fs.FileStatus;<a name="line.41"></a>
-<span class="sourceLineNo">042</span>import org.apache.hadoop.fs.FileSystem;<a name="line.42"></a>
-<span class="sourceLineNo">043</span>import org.apache.hadoop.fs.Path;<a name="line.43"></a>
-<span class="sourceLineNo">044</span>import org.apache.hadoop.fs.PathFilter;<a name="line.44"></a>
-<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.ChoreService;<a name="line.45"></a>
-<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.46"></a>
-<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.HBaseTestingUtil;<a name="line.47"></a>
-<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.HConstants;<a name="line.48"></a>
-<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.Stoppable;<a name="line.49"></a>
-<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.TableName;<a name="line.50"></a>
-<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.client.Admin;<a name="line.51"></a>
-<span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.client.RegionInfo;<a name="line.52"></a>
-<span class="sourceLineNo">053</span>import org.apache.hadoop.hbase.client.Table;<a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.apache.hadoop.hbase.master.HMaster;<a name="line.54"></a>
-<span class="sourceLineNo">055</span>import org.apache.hadoop.hbase.master.cleaner.DirScanPool;<a name="line.55"></a>
-<span class="sourceLineNo">056</span>import org.apache.hadoop.hbase.master.cleaner.HFileCleaner;<a name="line.56"></a>
-<span class="sourceLineNo">057</span>import org.apache.hadoop.hbase.regionserver.ConstantSizeRegionSplitPolicy;<a name="line.57"></a>
-<span class="sourceLineNo">058</span>import org.apache.hadoop.hbase.regionserver.HRegion;<a name="line.58"></a>
-<span class="sourceLineNo">059</span>import org.apache.hadoop.hbase.regionserver.HRegionServer;<a name="line.59"></a>
-<span class="sourceLineNo">060</span>import org.apache.hadoop.hbase.regionserver.HStoreFile;<a name="line.60"></a>
-<span class="sourceLineNo">061</span>import org.apache.hadoop.hbase.testclassification.LargeTests;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>import org.apache.hadoop.hbase.testclassification.MiscTests;<a name="line.62"></a>
-<span class="sourceLineNo">063</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.63"></a>
-<span class="sourceLineNo">064</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.64"></a>
-<span class="sourceLineNo">065</span>import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;<a name="line.65"></a>
-<span class="sourceLineNo">066</span>import org.apache.hadoop.hbase.util.FSUtils;<a name="line.66"></a>
-<span class="sourceLineNo">067</span>import org.apache.hadoop.hbase.util.HFileArchiveTestingUtil;<a name="line.67"></a>
-<span class="sourceLineNo">068</span>import org.apache.hadoop.hbase.util.HFileArchiveUtil;<a name="line.68"></a>
-<span class="sourceLineNo">069</span>import org.apache.hadoop.hbase.util.StoppableImplementation;<a name="line.69"></a>
-<span class="sourceLineNo">070</span>import org.apache.hadoop.security.UserGroupInformation;<a name="line.70"></a>
-<span class="sourceLineNo">071</span>import org.junit.After;<a name="line.71"></a>
-<span class="sourceLineNo">072</span>import org.junit.AfterClass;<a name="line.72"></a>
-<span class="sourceLineNo">073</span>import org.junit.Assert;<a name="line.73"></a>
-<span class="sourceLineNo">074</span>import org.junit.BeforeClass;<a name="line.74"></a>
-<span class="sourceLineNo">075</span>import org.junit.ClassRule;<a name="line.75"></a>
-<span class="sourceLineNo">076</span>import org.junit.Rule;<a name="line.76"></a>
-<span class="sourceLineNo">077</span>import org.junit.Test;<a name="line.77"></a>
-<span class="sourceLineNo">078</span>import org.junit.experimental.categories.Category;<a name="line.78"></a>
-<span class="sourceLineNo">079</span>import org.junit.rules.TestName;<a name="line.79"></a>
-<span class="sourceLineNo">080</span>import org.mockito.ArgumentCaptor;<a name="line.80"></a>
-<span class="sourceLineNo">081</span>import org.slf4j.Logger;<a name="line.81"></a>
-<span class="sourceLineNo">082</span>import org.slf4j.LoggerFactory;<a name="line.82"></a>
-<span class="sourceLineNo">083</span><a name="line.83"></a>
-<span class="sourceLineNo">084</span>/**<a name="line.84"></a>
-<span class="sourceLineNo">085</span> * Test that the {@link HFileArchiver} correctly removes all the parts of a region when cleaning up<a name="line.85"></a>
-<span class="sourceLineNo">086</span> * a region<a name="line.86"></a>
-<span class="sourceLineNo">087</span> */<a name="line.87"></a>
-<span class="sourceLineNo">088</span>@Category({LargeTests.class, MiscTests.class})<a name="line.88"></a>
-<span class="sourceLineNo">089</span>public class TestHFileArchiving {<a name="line.89"></a>
-<span class="sourceLineNo">090</span><a name="line.90"></a>
-<span class="sourceLineNo">091</span> @ClassRule<a name="line.91"></a>
-<span class="sourceLineNo">092</span> public static final HBaseClassTestRule CLASS_RULE =<a name="line.92"></a>
-<span class="sourceLineNo">093</span> HBaseClassTestRule.forClass(TestHFileArchiving.class);<a name="line.93"></a>
-<span class="sourceLineNo">094</span><a name="line.94"></a>
-<span class="sourceLineNo">095</span> private static final Logger LOG = LoggerFactory.getLogger(TestHFileArchiving.class);<a name="line.95"></a>
-<span class="sourceLineNo">096</span> private static final HBaseTestingUtil UTIL = new HBaseTestingUtil();<a name="line.96"></a>
-<span class="sourceLineNo">097</span> private static final byte[] TEST_FAM = Bytes.toBytes("fam");<a name="line.97"></a>
-<span class="sourceLineNo">098</span><a name="line.98"></a>
-<span class="sourceLineNo">099</span> private static DirScanPool POOL;<a name="line.99"></a>
-<span class="sourceLineNo">100</span> @Rule<a name="line.100"></a>
-<span class="sourceLineNo">101</span> public TestName name = new TestName();<a name="line.101"></a>
-<span class="sourceLineNo">102</span><a name="line.102"></a>
-<span class="sourceLineNo">103</span> /**<a name="line.103"></a>
-<span class="sourceLineNo">104</span> * Setup the config for the cluster<a name="line.104"></a>
-<span class="sourceLineNo">105</span> */<a name="line.105"></a>
-<span class="sourceLineNo">106</span> @BeforeClass<a name="line.106"></a>
-<span class="sourceLineNo">107</span> public static void setupCluster() throws Exception {<a name="line.107"></a>
-<span class="sourceLineNo">108</span> setupConf(UTIL.getConfiguration());<a name="line.108"></a>
-<span class="sourceLineNo">109</span> UTIL.startMiniCluster();<a name="line.109"></a>
-<span class="sourceLineNo">110</span><a name="line.110"></a>
-<span class="sourceLineNo">111</span> // We don't want the cleaner to remove files. The tests do that.<a name="line.111"></a>
-<span class="sourceLineNo">112</span> UTIL.getMiniHBaseCluster().getMaster().getHFileCleaner().cancel(true);<a name="line.112"></a>
-<span class="sourceLineNo">113</span><a name="line.113"></a>
-<span class="sourceLineNo">114</span> POOL = DirScanPool.getHFileCleanerScanPool(UTIL.getConfiguration());<a name="line.114"></a>
-<span class="sourceLineNo">115</span> }<a name="line.115"></a>
-<span class="sourceLineNo">116</span><a name="line.116"></a>
-<span class="sourceLineNo">117</span> private static void setupConf(Configuration conf) {<a name="line.117"></a>
-<span class="sourceLineNo">118</span> // disable the ui<a name="line.118"></a>
-<span class="sourceLineNo">119</span> conf.setInt("hbase.regionsever.info.port", -1);<a name="line.119"></a>
-<span class="sourceLineNo">120</span> // drop the memstore size so we get flushes<a name="line.120"></a>
-<span class="sourceLineNo">121</span> conf.setInt("hbase.hregion.memstore.flush.size", 25000);<a name="line.121"></a>
-<span class="sourceLineNo">122</span> // disable major compactions<a name="line.122"></a>
-<span class="sourceLineNo">123</span> conf.setInt(HConstants.MAJOR_COMPACTION_PERIOD, 0);<a name="line.123"></a>
-<span class="sourceLineNo">124</span><a name="line.124"></a>
-<span class="sourceLineNo">125</span> // prevent aggressive region split<a name="line.125"></a>
-<span class="sourceLineNo">126</span> conf.set(HConstants.HBASE_REGION_SPLIT_POLICY_KEY,<a name="line.126"></a>
-<span class="sourceLineNo">127</span> ConstantSizeRegionSplitPolicy.class.getName());<a name="line.127"></a>
-<span class="sourceLineNo">128</span> }<a name="line.128"></a>
-<span class="sourceLineNo">129</span><a name="line.129"></a>
-<span class="sourceLineNo">130</span> @After<a name="line.130"></a>
-<span class="sourceLineNo">131</span> public void tearDown() throws Exception {<a name="line.131"></a>
-<span class="sourceLineNo">132</span> // cleanup the archive directory<a name="line.132"></a>
-<span class="sourceLineNo">133</span> clearArchiveDirectory();<a name="line.133"></a>
-<span class="sourceLineNo">134</span> }<a name="line.134"></a>
-<span class="sourceLineNo">135</span><a name="line.135"></a>
-<span class="sourceLineNo">136</span> @AfterClass<a name="line.136"></a>
-<span class="sourceLineNo">137</span> public static void cleanupTest() throws Exception {<a name="line.137"></a>
-<span class="sourceLineNo">138</span> UTIL.shutdownMiniCluster();<a name="line.138"></a>
-<span class="sourceLineNo">139</span> POOL.shutdownNow();<a name="line.139"></a>
-<span class="sourceLineNo">140</span> }<a name="line.140"></a>
-<span class="sourceLineNo">141</span><a name="line.141"></a>
-<span class="sourceLineNo">142</span> @Test<a name="line.142"></a>
-<span class="sourceLineNo">143</span> public void testArchiveStoreFilesDifferentFileSystemsWallWithSchemaPlainRoot() throws Exception {<a name="line.143"></a>
-<span class="sourceLineNo">144</span> String walDir = "mockFS://mockFSAuthority:9876/mockDir/wals/";<a name="line.144"></a>
-<span class="sourceLineNo">145</span> String baseDir = CommonFSUtils.getRootDir(UTIL.getConfiguration()).toString() + "/";<a name="line.145"></a>
-<span class="sourceLineNo">146</span> testArchiveStoreFilesDifferentFileSystems(walDir, baseDir,<a name="line.146"></a>
-<span class="sourceLineNo">147</span> HFileArchiver::archiveStoreFiles);<a name="line.147"></a>
-<span class="sourceLineNo">148</span> }<a name="line.148"></a>
-<span class="sourceLineNo">149</span><a name="line.149"></a>
-<span class="sourceLineNo">150</span> @Test<a name="line.150"></a>
-<span class="sourceLineNo">151</span> public void testArchiveStoreFilesDifferentFileSystemsWallNullPlainRoot() throws Exception {<a name="line.151"></a>
-<span class="sourceLineNo">152</span> String baseDir = CommonFSUtils.getRootDir(UTIL.getConfiguration()).toString() + "/";<a name="line.152"></a>
-<span class="sourceLineNo">153</span> testArchiveStoreFilesDifferentFileSystems(null, baseDir,<a name="line.153"></a>
-<span class="sourceLineNo">154</span> HFileArchiver::archiveStoreFiles);<a name="line.154"></a>
-<span class="sourceLineNo">155</span> }<a name="line.155"></a>
-<span class="sourceLineNo">156</span><a name="line.156"></a>
-<span class="sourceLineNo">157</span> @Test<a name="line.157"></a>
-<span class="sourceLineNo">158</span> public void testArchiveStoreFilesDifferentFileSystemsWallAndRootSame() throws Exception {<a name="line.158"></a>
-<span class="sourceLineNo">159</span> String baseDir = CommonFSUtils.getRootDir(UTIL.getConfiguration()).toString() + "/";<a name="line.159"></a>
-<span class="sourceLineNo">160</span> testArchiveStoreFilesDifferentFileSystems("/hbase/wals/", baseDir,<a name="line.160"></a>
-<span class="sourceLineNo">161</span> HFileArchiver::archiveStoreFiles);<a name="line.161"></a>
-<span class="sourceLineNo">162</span> }<a name="line.162"></a>
-<span class="sourceLineNo">163</span><a name="line.163"></a>
-<span class="sourceLineNo">164</span> private void testArchiveStoreFilesDifferentFileSystems(String walDir, String expectedBase,<a name="line.164"></a>
-<span class="sourceLineNo">165</span> ArchivingFunction<Configuration, FileSystem, RegionInfo, Path, byte[],<a name="line.165"></a>
-<span class="sourceLineNo">166</span> Collection<HStoreFile>> archivingFunction) throws IOException {<a name="line.166"></a>
-<span class="sourceLineNo">167</span> FileSystem mockedFileSystem = mock(FileSystem.class);<a name="line.167"></a>
-<span class="sourceLineNo">168</span> Configuration conf = new Configuration(UTIL.getConfiguration());<a name="line.168"></a>
-<span class="sourceLineNo">169</span> if(walDir != null) {<a name="line.169"></a>
-<span class="sourceLineNo">170</span> conf.set(CommonFSUtils.HBASE_WAL_DIR, walDir);<a name="line.170"></a>
-<span class="sourceLineNo">171</span> }<a name="line.171"></a>
-<span class="sourceLineNo">172</span> Path filePath = new Path("/mockDir/wals/mockFile");<a name="line.172"></a>
-<span class="sourceLineNo">173</span> when(mockedFileSystem.getScheme()).thenReturn("mockFS");<a name="line.173"></a>
-<span class="sourceLineNo">174</span> when(mockedFileSystem.mkdirs(any())).thenReturn(true);<a name="line.174"></a>
-<span class="sourceLineNo">175</span> when(mockedFileSystem.exists(any())).thenReturn(true);<a name="line.175"></a>
-<span class="sourceLineNo">176</span> RegionInfo mockedRegion = mock(RegionInfo.class);<a name="line.176"></a>
-<span class="sourceLineNo">177</span> TableName tableName = TableName.valueOf("mockTable");<a name="line.177"></a>
-<span class="sourceLineNo">178</span> when(mockedRegion.getTable()).thenReturn(tableName);<a name="line.178"></a>
-<span class="sourceLineNo">179</span> when(mockedRegion.getEncodedName()).thenReturn("mocked-region-encoded-name");<a name="line.179"></a>
-<span class="sourceLineNo">180</span> Path tableDir = new Path("mockFS://mockDir/tabledir");<a name="line.180"></a>
-<span class="sourceLineNo">181</span> byte[] family = Bytes.toBytes("testfamily");<a name="line.181"></a>
-<span class="sourceLineNo">182</span> HStoreFile mockedFile = mock(HStoreFile.class);<a name="line.182"></a>
-<span class="sourceLineNo">183</span> List<HStoreFile> list = new ArrayList<>();<a name="line.183"></a>
-<span class="sourceLineNo">184</span> list.add(mockedFile);<a name="line.184"></a>
-<span class="sourceLineNo">185</span> when(mockedFile.getPath()).thenReturn(filePath);<a name="line.185"></a>
-<span class="sourceLineNo">186</span> when(mockedFileSystem.rename(any(),any())).thenReturn(true);<a name="line.186"></a>
-<span class="sourceLineNo">187</span> archivingFunction.apply(conf, mockedFileSystem, mockedRegion, tableDir, family, list);<a name="line.187"></a>
-<span class="sourceLineNo">188</span> ArgumentCaptor<Path> pathCaptor = ArgumentCaptor.forClass(Path.class);<a name="line.188"></a>
-<span class="sourceLineNo">189</span> verify(mockedFileSystem, times(2)).rename(pathCaptor.capture(), any());<a name="line.189"></a>
-<span class="sourceLineNo">190</span> String expectedDir = expectedBase +<a name="line.190"></a>
-<span class="sourceLineNo">191</span> "archive/data/default/mockTable/mocked-region-encoded-name/testfamily/mockFile";<a name="line.191"></a>
-<span class="sourceLineNo">192</span> assertTrue(pathCaptor.getAllValues().get(0).toString().equals(expectedDir));<a name="line.192"></a>
-<span class="sourceLineNo">193</span> }<a name="line.193"></a>
-<span class="sourceLineNo">194</span><a name="line.194"></a>
-<span class="sourceLineNo">195</span> @FunctionalInterface<a name="line.195"></a>
-<span class="sourceLineNo">196</span> private interface ArchivingFunction<Configuration, FS, Region, Dir, Family, Files> {<a name="line.196"></a>
-<span class="sourceLineNo">197</span> void apply(Configuration config, FS fs, Region region, Dir dir, Family family, Files files)<a name="line.197"></a>
-<span class="sourceLineNo">198</span> throws IOException;<a name="line.198"></a>
-<span class="sourceLineNo">199</span> }<a name="line.199"></a>
-<span class="sourceLineNo">200</span><a name="line.200"></a>
-<span class="sourceLineNo">201</span> @Test<a name="line.201"></a>
-<span class="sourceLineNo">202</span> public void testArchiveRecoveredEditsWalDirNull() throws Exception {<a name="line.202"></a>
-<span class="sourceLineNo">203</span> testArchiveRecoveredEditsWalDirNullOrSame(null);<a name="line.203"></a>
-<span class="sourceLineNo">204</span> }<a name="line.204"></a>
-<span class="sourceLineNo">205</span><a name="line.205"></a>
-<span class="sourceLineNo">206</span> @Test<a name="line.206"></a>
-<span class="sourceLineNo">207</span> public void testArchiveRecoveredEditsWalDirSameFsStoreFiles() throws Exception {<a name="line.207"></a>
-<span class="sourceLineNo">208</span> testArchiveRecoveredEditsWalDirNullOrSame("/wal-dir");<a name="line.208"></a>
-<span class="sourceLineNo">209</span> }<a name="line.209"></a>
-<span class="sourceLineNo">210</span><a name="line.210"></a>
-<span class="sourceLineNo">211</span> private void testArchiveRecoveredEditsWalDirNullOrSame(String walDir) throws Exception {<a name="line.211"></a>
-<span class="sourceLineNo">212</span> String originalRootDir = UTIL.getConfiguration().get(HConstants.HBASE_DIR);<a name="line.212"></a>
-<span class="sourceLineNo">213</span> try {<a name="line.213"></a>
-<span class="sourceLineNo">214</span> String baseDir = "mockFS://mockFSAuthority:9876/hbase/";<a name="line.214"></a>
-<span class="sourceLineNo">215</span> UTIL.getConfiguration().set(HConstants.HBASE_DIR, baseDir);<a name="line.215"></a>
-<span class="sourceLineNo">216</span> testArchiveStoreFilesDifferentFileSystems(walDir, baseDir,<a name="line.216"></a>
-<span class="sourceLineNo">217</span> (conf, fs, region, dir, family, list) -> HFileArchiver<a name="line.217"></a>
-<span class="sourceLineNo">218</span> .archiveRecoveredEdits(conf, fs, region, family, list));<a name="line.218"></a>
-<span class="sourceLineNo">219</span> } finally {<a name="line.219"></a>
-<span class="sourceLineNo">220</span> UTIL.getConfiguration().set(HConstants.HBASE_DIR, originalRootDir);<a name="line.220"></a>
-<span class="sourceLineNo">221</span> }<a name="line.221"></a>
-<span class="sourceLineNo">222</span> }<a name="line.222"></a>
-<span class="sourceLineNo">223</span><a name="line.223"></a>
-<span class="sourceLineNo">224</span> @Test(expected = IOException.class)<a name="line.224"></a>
-<span class="sourceLineNo">225</span> public void testArchiveRecoveredEditsWrongFS() throws Exception {<a name="line.225"></a>
-<span class="sourceLineNo">226</span> String baseDir = CommonFSUtils.getRootDir(UTIL.getConfiguration()).toString() + "/";<a name="line.226"></a>
-<span class="sourceLineNo">227</span> //Internally, testArchiveStoreFilesDifferentFileSystems will pass a "mockedFS"<a name="line.227"></a>
-<span class="sourceLineNo">228</span> // to HFileArchiver.archiveRecoveredEdits, but since wal-dir is supposedly on same FS<a name="line.228"></a>
-<span class="sourceLineNo">229</span> // as root dir it would lead to conflicting FSes and an IOException is expected.<a name="line.229"></a>
-<span class="sourceLineNo">230</span> testArchiveStoreFilesDifferentFileSystems("/wal-dir", baseDir,<a name="line.230"></a>
-<span class="sourceLineNo">231</span> (conf, fs, region, dir, family, list) -> HFileArchiver<a name="line.231"></a>
-<span class="sourceLineNo">232</span> .archiveRecoveredEdits(conf, fs, region, family, list));<a name="line.232"></a>
-<span class="sourceLineNo">233</span> }<a name="line.233"></a>
-<span class="sourceLineNo">234</span><a name="line.234"></a>
-<span class="sourceLineNo">235</span> @Test<a name="line.235"></a>
-<span class="sourceLineNo">236</span> public void testArchiveRecoveredEditsWalDirDifferentFS() throws Exception {<a name="line.236"></a>
-<span class="sourceLineNo">237</span> String walDir = "mockFS://mockFSAuthority:9876/mockDir/wals/";<a name="line.237"></a>
-<span class="sourceLineNo">238</span> testArchiveStoreFilesDifferentFileSystems(walDir, walDir,<a name="line.238"></a>
-<span class="sourceLineNo">239</span> (conf, fs, region, dir, family, list) -><a name="line.239"></a>
-<span class="sourceLineNo">240</span> HFileArchiver.archiveRecoveredEdits(conf, fs, region, family, list));<a name="line.240"></a>
-<span class="sourceLineNo">241</span> }<a name="line.241"></a>
-<span class="sourceLineNo">242</span><a name="line.242"></a>
-<span class="sourceLineNo">243</span> @Test<a name="line.243"></a>
-<span class="sourceLineNo">244</span> public void testRemoveRegionDirOnArchive() throws Exception {<a name="line.244"></a>
-<span class="sourceLineNo">245</span> final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.245"></a>
-<span class="sourceLineNo">246</span> UTIL.createTable(tableName, TEST_FAM);<a name="line.246"></a>
-<span class="sourceLineNo">247</span><a name="line.247"></a>
-<span class="sourceLineNo">248</span> final Admin admin = UTIL.getAdmin();<a name="line.248"></a>
-<span class="sourceLineNo">249</span><a name="line.249"></a>
-<span class="sourceLineNo">250</span> // get the current store files for the region<a name="line.250"></a>
-<span class="sourceLineNo">251</span> List<HRegion> servingRegions = UTIL.getHBaseCluster().getRegions(tableName);<a name="line.251"></a>
-<span class="sourceLineNo">252</span> // make sure we only have 1 region serving this table<a name="line.252"></a>
-<span class="sourceLineNo">253</span> assertEquals(1, servingRegions.size());<a name="line.253"></a>
-<span class="sourceLineNo">254</span> HRegion region = servingRegions.get(0);<a name="line.254"></a>
-<span class="sourceLineNo">255</span><a name="line.255"></a>
-<span class="sourceLineNo">256</span> // and load the table<a name="line.256"></a>
-<span class="sourceLineNo">257</span> UTIL.loadRegion(region, TEST_FAM);<a name="line.257"></a>
-<span class="sourceLineNo">258</span><a name="line.258"></a>
-<span class="sourceLineNo">259</span> // shutdown the table so we can manipulate the files<a name="line.259"></a>
-<span class="sourceLineNo">260</span> admin.disableTable(tableName);<a name="line.260"></a>
-<span class="sourceLineNo">261</span><a name="line.261"></a>
-<span class="sourceLineNo">262</span> FileSystem fs = UTIL.getTestFileSystem();<a name="line.262"></a>
-<span class="sourceLineNo">263</span><a name="line.263"></a>
-<span class="sourceLineNo">264</span> // now attempt to depose the region<a name="line.264"></a>
-<span class="sourceLineNo">265</span> Path rootDir = region.getRegionFileSystem().getTableDir().getParent();<a name="line.265"></a>
-<span class="sourceLineNo">266</span> Path regionDir = FSUtils.getRegionDirFromRootDir(rootDir, region.getRegionInfo());<a name="line.266"></a>
-<span class="sourceLineNo">267</span><a name="line.267"></a>
-<span class="sourceLineNo">268</span> HFileArchiver.archiveRegion(UTIL.getConfiguration(), fs, region.getRegionInfo());<a name="line.268"></a>
+<span class="sourceLineNo">024</span>import static org.junit.Assert.fail;<a name="line.24"></a>
+<span class="sourceLineNo">025</span>import static org.mockito.ArgumentMatchers.any;<a name="line.25"></a>
+<span class="sourceLineNo">026</span>import static org.mockito.Mockito.mock;<a name="line.26"></a>
+<span class="sourceLineNo">027</span>import static org.mockito.Mockito.never;<a name="line.27"></a>
+<span class="sourceLineNo">028</span>import static org.mockito.Mockito.times;<a name="line.28"></a>
+<span class="sourceLineNo">029</span>import static org.mockito.Mockito.verify;<a name="line.29"></a>
+<span class="sourceLineNo">030</span>import static org.mockito.Mockito.when;<a name="line.30"></a>
+<span class="sourceLineNo">031</span><a name="line.31"></a>
+<span class="sourceLineNo">032</span>import java.io.IOException;<a name="line.32"></a>
+<span class="sourceLineNo">033</span>import java.security.PrivilegedExceptionAction;<a name="line.33"></a>
+<span class="sourceLineNo">034</span>import java.util.ArrayList;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import java.util.Collection;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import java.util.Collections;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import java.util.HashMap;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import java.util.List;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import java.util.Map;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import java.util.Objects;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import java.util.stream.Collectors;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.apache.hadoop.conf.Configuration;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.apache.hadoop.fs.FileStatus;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.apache.hadoop.fs.FileSystem;<a name="line.44"></a>
+<span class="sourceLineNo">045</span>import org.apache.hadoop.fs.Path;<a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.apache.hadoop.fs.PathFilter;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.ChoreService;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.HBaseTestingUtil;<a name="line.49"></a>
+<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.HConstants;<a name="line.50"></a>
+<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.Stoppable;<a name="line.51"></a>
+<span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.TableName;<a name="line.52"></a>
+<span class="sourceLineNo">053</span>import org.apache.hadoop.hbase.client.Admin;<a name="line.53"></a>
+<span class="sourceLineNo">054</span>import org.apache.hadoop.hbase.client.RegionInfo;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>import org.apache.hadoop.hbase.client.Table;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>import org.apache.hadoop.hbase.master.HMaster;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>import org.apache.hadoop.hbase.master.cleaner.DirScanPool;<a name="line.57"></a>
+<span class="sourceLineNo">058</span>import org.apache.hadoop.hbase.master.cleaner.HFileCleaner;<a name="line.58"></a>
+<span class="sourceLineNo">059</span>import org.apache.hadoop.hbase.regionserver.ConstantSizeRegionSplitPolicy;<a name="line.59"></a>
+<span class="sourceLineNo">060</span>import org.apache.hadoop.hbase.regionserver.HRegion;<a name="line.60"></a>
+<span class="sourceLineNo">061</span>import org.apache.hadoop.hbase.regionserver.HRegionServer;<a name="line.61"></a>
+<span class="sourceLineNo">062</span>import org.apache.hadoop.hbase.regionserver.HStoreFile;<a name="line.62"></a>
+<span class="sourceLineNo">063</span>import org.apache.hadoop.hbase.testclassification.LargeTests;<a name="line.63"></a>
+<span class="sourceLineNo">064</span>import org.apache.hadoop.hbase.testclassification.MiscTests;<a name="line.64"></a>
+<span class="sourceLineNo">065</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.65"></a>
+<span class="sourceLineNo">066</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.66"></a>
+<span class="sourceLineNo">067</span>import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;<a name="line.67"></a>
+<span class="sourceLineNo">068</span>import org.apache.hadoop.hbase.util.FSUtils;<a name="line.68"></a>
+<span class="sourceLineNo">069</span>import org.apache.hadoop.hbase.util.HFileArchiveTestingUtil;<a name="line.69"></a>
+<span class="sourceLineNo">070</span>import org.apache.hadoop.hbase.util.HFileArchiveUtil;<a name="line.70"></a>
+<span class="sourceLineNo">071</span>import org.apache.hadoop.hbase.util.StoppableImplementation;<a name="line.71"></a>
+<span class="sourceLineNo">072</span>import org.apache.hadoop.security.UserGroupInformation;<a name="line.72"></a>
+<span class="sourceLineNo">073</span>import org.junit.After;<a name="line.73"></a>
+<span class="sourceLineNo">074</span>import org.junit.AfterClass;<a name="line.74"></a>
+<span class="sourceLineNo">075</span>import org.junit.Assert;<a name="line.75"></a>
+<span class="sourceLineNo">076</span>import org.junit.BeforeClass;<a name="line.76"></a>
+<span class="sourceLineNo">077</span>import org.junit.ClassRule;<a name="line.77"></a>
+<span class="sourceLineNo">078</span>import org.junit.Rule;<a name="line.78"></a>
+<span class="sourceLineNo">079</span>import org.junit.Test;<a name="line.79"></a>
+<span class="sourceLineNo">080</span>import org.junit.experimental.categories.Category;<a name="line.80"></a>
+<span class="sourceLineNo">081</span>import org.junit.rules.TestName;<a name="line.81"></a>
+<span class="sourceLineNo">082</span>import org.mockito.ArgumentCaptor;<a name="line.82"></a>
+<span class="sourceLineNo">083</span>import org.slf4j.Logger;<a name="line.83"></a>
+<span class="sourceLineNo">084</span>import org.slf4j.LoggerFactory;<a name="line.84"></a>
+<span class="sourceLineNo">085</span><a name="line.85"></a>
+<span class="sourceLineNo">086</span>/**<a name="line.86"></a>
+<span class="sourceLineNo">087</span> * Test that the {@link HFileArchiver} correctly removes all the parts of a region when cleaning up<a name="line.87"></a>
+<span class="sourceLineNo">088</span> * a region<a name="line.88"></a>
+<span class="sourceLineNo">089</span> */<a name="line.89"></a>
+<span class="sourceLineNo">090</span>@Category({LargeTests.class, MiscTests.class})<a name="line.90"></a>
+<span class="sourceLineNo">091</span>public class TestHFileArchiving {<a name="line.91"></a>
+<span class="sourceLineNo">092</span><a name="line.92"></a>
+<span class="sourceLineNo">093</span> @ClassRule<a name="line.93"></a>
+<span class="sourceLineNo">094</span> public static final HBaseClassTestRule CLASS_RULE =<a name="line.94"></a>
+<span class="sourceLineNo">095</span> HBaseClassTestRule.forClass(TestHFileArchiving.class);<a name="line.95"></a>
+<span class="sourceLineNo">096</span><a name="line.96"></a>
+<span class="sourceLineNo">097</span> private static final Logger LOG = LoggerFactory.getLogger(TestHFileArchiving.class);<a name="line.97"></a>
+<span class="sourceLineNo">098</span> private static final HBaseTestingUtil UTIL = new HBaseTestingUtil();<a name="line.98"></a>
+<span class="sourceLineNo">099</span> private static final byte[] TEST_FAM = Bytes.toBytes("fam");<a name="line.99"></a>
+<span class="sourceLineNo">100</span><a name="line.100"></a>
+<span class="sourceLineNo">101</span> private static DirScanPool POOL;<a name="line.101"></a>
+<span class="sourceLineNo">102</span> @Rule<a name="line.102"></a>
+<span class="sourceLineNo">103</span> public TestName name = new TestName();<a name="line.103"></a>
+<span class="sourceLineNo">104</span><a name="line.104"></a>
+<span class="sourceLineNo">105</span> /**<a name="line.105"></a>
+<span class="sourceLineNo">106</span> * Setup the config for the cluster<a name="line.106"></a>
+<span class="sourceLineNo">107</span> */<a name="line.107"></a>
+<span class="sourceLineNo">108</span> @BeforeClass<a name="line.108"></a>
+<span class="sourceLineNo">109</span> public static void setupCluster() throws Exception {<a name="line.109"></a>
+<span class="sourceLineNo">110</span> setupConf(UTIL.getConfiguration());<a name="line.110"></a>
+<span class="sourceLineNo">111</span> UTIL.startMiniCluster();<a name="line.111"></a>
+<span class="sourceLineNo">112</span><a name="line.112"></a>
+<span class="sourceLineNo">113</span> // We don't want the cleaner to remove files. The tests do that.<a name="line.113"></a>
+<span class="sourceLineNo">114</span> UTIL.getMiniHBaseCluster().getMaster().getHFileCleaner().cancel(true);<a name="line.114"></a>
+<span class="sourceLineNo">115</span><a name="line.115"></a>
+<span class="sourceLineNo">116</span> POOL = DirScanPool.getHFileCleanerScanPool(UTIL.getConfiguration());<a name="line.116"></a>
+<span class="sourceLineNo">117</span> }<a name="line.117"></a>
+<span class="sourceLineNo">118</span><a name="line.118"></a>
+<span class="sourceLineNo">119</span> private static void setupConf(Configuration conf) {<a name="line.119"></a>
+<span class="sourceLineNo">120</span> // disable the ui<a name="line.120"></a>
+<span class="sourceLineNo">121</span> conf.setInt("hbase.regionsever.info.port", -1);<a name="line.121"></a>
+<span class="sourceLineNo">122</span> // drop the memstore size so we get flushes<a name="line.122"></a>
+<span class="sourceLineNo">123</span> conf.setInt("hbase.hregion.memstore.flush.size", 25000);<a name="line.123"></a>
+<span class="sourceLineNo">124</span> // disable major compactions<a name="line.124"></a>
+<span class="sourceLineNo">125</span> conf.setInt(HConstants.MAJOR_COMPACTION_PERIOD, 0);<a name="line.125"></a>
+<span class="sourceLineNo">126</span><a name="line.126"></a>
+<span class="sourceLineNo">127</span> // prevent aggressive region split<a name="line.127"></a>
+<span class="sourceLineNo">128</span> conf.set(HConstants.HBASE_REGION_SPLIT_POLICY_KEY,<a name="line.128"></a>
+<span class="sourceLineNo">129</span> ConstantSizeRegionSplitPolicy.class.getName());<a name="line.129"></a>
+<span class="sourceLineNo">130</span> }<a name="line.130"></a>
+<span class="sourceLineNo">131</span><a name="line.131"></a>
+<span class="sourceLineNo">132</span> @After<a name="line.132"></a>
+<span class="sourceLineNo">133</span> public void tearDown() throws Exception {<a name="line.133"></a>
+<span class="sourceLineNo">134</span> // cleanup the archive directory<a name="line.134"></a>
+<span class="sourceLineNo">135</span> clearArchiveDirectory();<a name="line.135"></a>
+<span class="sourceLineNo">136</span> }<a name="line.136"></a>
+<span class="sourceLineNo">137</span><a name="line.137"></a>
+<span class="sourceLineNo">138</span> @AfterClass<a name="line.138"></a>
+<span class="sourceLineNo">139</span> public static void cleanupTest() throws Exception {<a name="line.139"></a>
+<span class="sourceLineNo">140</span> UTIL.shutdownMiniCluster();<a name="line.140"></a>
+<span class="sourceLineNo">141</span> POOL.shutdownNow();<a name="line.141"></a>
+<span class="sourceLineNo">142</span> }<a name="line.142"></a>
+<span class="sourceLineNo">143</span><a name="line.143"></a>
+<span class="sourceLineNo">144</span> @Test<a name="line.144"></a>
+<span class="sourceLineNo">145</span> public void testArchiveStoreFilesDifferentFileSystemsWallWithSchemaPlainRoot() throws Exception {<a name="line.145"></a>
+<span class="sourceLineNo">146</span> String walDir = "mockFS://mockFSAuthority:9876/mockDir/wals/";<a name="line.146"></a>
+<span class="sourceLineNo">147</span> String baseDir = CommonFSUtils.getRootDir(UTIL.getConfiguration()).toString() + "/";<a name="line.147"></a>
+<span class="sourceLineNo">148</span> testArchiveStoreFilesDifferentFileSystems(walDir, baseDir,<a name="line.148"></a>
+<span class="sourceLineNo">149</span> HFileArchiver::archiveStoreFiles);<a name="line.149"></a>
+<span class="sourceLineNo">150</span> }<a name="line.150"></a>
+<span class="sourceLineNo">151</span><a name="line.151"></a>
+<span class="sourceLineNo">152</span> @Test<a name="line.152"></a>
+<span class="sourceLineNo">153</span> public void testArchiveStoreFilesDifferentFileSystemsWallNullPlainRoot() throws Exception {<a name="line.153"></a>
+<span class="sourceLineNo">154</span> String baseDir = CommonFSUtils.getRootDir(UTIL.getConfiguration()).toString() + "/";<a name="line.154"></a>
+<span class="sourceLineNo">155</span> testArchiveStoreFilesDifferentFileSystems(null, baseDir,<a name="line.155"></a>
+<span class="sourceLineNo">156</span> HFileArchiver::archiveStoreFiles);<a name="line.156"></a>
+<span class="sourceLineNo">157</span> }<a name="line.157"></a>
+<span class="sourceLineNo">158</span><a name="line.158"></a>
+<span class="sourceLineNo">159</span> @Test<a name="line.159"></a>
+<span class="sourceLineNo">160</span> public void testArchiveStoreFilesDifferentFileSystemsWallAndRootSame() throws Exception {<a name="line.160"></a>
+<span class="sourceLineNo">161</span> String baseDir = CommonFSUtils.getRootDir(UTIL.getConfiguration()).toString() + "/";<a name="line.161"></a>
+<span class="sourceLineNo">162</span> testArchiveStoreFilesDifferentFileSystems("/hbase/wals/", baseDir,<a name="line.162"></a>
+<span class="sourceLineNo">163</span> HFileArchiver::archiveStoreFiles);<a name="line.163"></a>
+<span class="sourceLineNo">164</span> }<a name="line.164"></a>
+<span class="sourceLineNo">165</span><a name="line.165"></a>
+<span class="sourceLineNo">166</span> @Test<a name="line.166"></a>
+<span class="sourceLineNo">167</span> public void testArchiveStoreFilesDifferentFileSystemsFileAlreadyArchived() throws Exception {<a name="line.167"></a>
+<span class="sourceLineNo">168</span> String baseDir = CommonFSUtils.getRootDir(UTIL.getConfiguration()).toString() + "/";<a name="line.168"></a>
+<span class="sourceLineNo">169</span> testArchiveStoreFilesDifferentFileSystems("/hbase/wals/", baseDir, true, false, false,<a name="line.169"></a>
+<span class="sourceLineNo">170</span> HFileArchiver::archiveStoreFiles);<a name="line.170"></a>
+<span class="sourceLineNo">171</span> }<a name="line.171"></a>
+<span class="sourceLineNo">172</span><a name="line.172"></a>
+<span class="sourceLineNo">173</span> @Test<a name="line.173"></a>
+<span class="sourceLineNo">174</span> public void testArchiveStoreFilesDifferentFileSystemsArchiveFileMatchCurrent() throws Exception {<a name="line.174"></a>
+<span class="sourceLineNo">175</span> String baseDir = CommonFSUtils.getRootDir(UTIL.getConfiguration()).toString() + "/";<a name="line.175"></a>
+<span class="sourceLineNo">176</span> testArchiveStoreFilesDifferentFileSystems("/hbase/wals/", baseDir, true, true, false,<a name="line.176"></a>
+<span class="sourceLineNo">177</span> HFileArchiver::archiveStoreFiles);<a name="line.177"></a>
+<span class="sourceLineNo">178</span> }<a name="line.178"></a>
+<span class="sourceLineNo">179</span><a name="line.179"></a>
+<span class="sourceLineNo">180</span> @Test(expected = IOException.class)<a name="line.180"></a>
+<span class="sourceLineNo">181</span> public void testArchiveStoreFilesDifferentFileSystemsArchiveFileMismatch() throws Exception {<a name="line.181"></a>
+<span class="sourceLineNo">182</span> String baseDir = CommonFSUtils.getRootDir(UTIL.getConfiguration()).toString() + "/";<a name="line.182"></a>
+<span class="sourceLineNo">183</span> testArchiveStoreFilesDifferentFileSystems("/hbase/wals/", baseDir, true, true, true,<a name="line.183"></a>
+<span class="sourceLineNo">184</span> HFileArchiver::archiveStoreFiles);<a name="line.184"></a>
+<span class="sourceLineNo">185</span> }<a name="line.185"></a>
+<span class="sourceLineNo">186</span><a name="line.186"></a>
+<span class="sourceLineNo">187</span> private void testArchiveStoreFilesDifferentFileSystems(String walDir, String expectedBase,<a name="line.187"></a>
+<span class="sourceLineNo">188</span> ArchivingFunction<Configuration, FileSystem, RegionInfo, Path, byte[],<a name="line.188"></a>
+<span class="sourceLineNo">189</span> Collection<HStoreFile>> archivingFunction) throws IOException {<a name="line.189"></a>
+<span class="sourceLineNo">190</span> testArchiveStoreFilesDifferentFileSystems(walDir, expectedBase, false, true, false,<a name="line.190"></a>
+<span class="sourceLineNo">191</span> archivingFunction);<a name="line.191"></a>
+<span class="sourceLineNo">192</span> }<a name="line.192"></a>
+<span class="sourceLineNo">193</span><a name="line.193"></a>
+<span class="sourceLineNo">194</span> private void testArchiveStoreFilesDifferentFileSystems(String walDir, String expectedBase,<a name="line.194"></a>
+<span class="sourceLineNo">195</span> boolean archiveFileExists, boolean sourceFileExists, boolean archiveFileDifferentLength,<a name="line.195"></a>
+<span class="sourceLineNo">196</span> ArchivingFunction<Configuration, FileSystem, RegionInfo, Path, byte[],<a name="line.196"></a>
+<span class="sourceLineNo">197</span> Collection<HStoreFile>> archivingFunction) throws IOException {<a name="line.197"></a>
+<span class="sourceLineNo">198</span> FileSystem mockedFileSystem = mock(FileSystem.class);<a name="line.198"></a>
+<span class="sourceLineNo">199</span> Configuration conf = new Configuration(UTIL.getConfiguration());<a name="line.199"></a>
+<span class="sourceLineNo">200</span> if(walDir != null) {<a name="line.200"></a>
+<span class="sourceLineNo">201</span> conf.set(CommonFSUtils.HBASE_WAL_DIR, walDir);<a name="line.201"></a>
+<span class="sourceLineNo">202</span> }<a name="line.202"></a>
+<span class="sourceLineNo">203</span> when(mockedFileSystem.getScheme()).thenReturn("mockFS");<a name="line.203"></a>
+<span class="sourceLineNo">204</span> when(mockedFileSystem.mkdirs(any())).thenReturn(true);<a name="line.204"></a>
+<span class="sourceLineNo">205</span> HashMap<Path,Boolean> existsTracker = new HashMap<>();<a name="line.205"></a>
+<span class="sourceLineNo">206</span> Path filePath = new Path("/mockDir/wals/mockFile");<a name="line.206"></a>
+<span class="sourceLineNo">207</span> String expectedDir = expectedBase +<a name="line.207"></a>
+<span class="sourceLineNo">208</span> "archive/data/default/mockTable/mocked-region-encoded-name/testfamily/mockFile";<a name="line.208"></a>
+<span class="sourceLineNo">209</span> existsTracker.put(new Path(expectedDir), archiveFileExists);<a name="line.209"></a>
+<span class="sourceLineNo">210</span> existsTracker.put(filePath, sourceFileExists);<a name="line.210"></a>
+<span class="sourceLineNo">211</span> when(mockedFileSystem.exists(any())).thenAnswer(invocation -><a name="line.211"></a>
+<span class="sourceLineNo">212</span> existsTracker.getOrDefault((Path)invocation.getArgument(0), true));<a name="line.212"></a>
+<span class="sourceLineNo">213</span> FileStatus mockedStatus = mock(FileStatus.class);<a name="line.213"></a>
+<span class="sourceLineNo">214</span> when(mockedStatus.getLen()).thenReturn(12L).thenReturn(archiveFileDifferentLength ? 34L : 12L);<a name="line.214"></a>
+<span class="sourceLineNo">215</span> when(mockedFileSystem.getFileStatus(any())).thenReturn(mockedStatus);<a name="line.215"></a>
+<span class="sourceLineNo">216</span> RegionInfo mockedRegion = mock(RegionInfo.class);<a name="line.216"></a>
+<span class="sourceLineNo">217</span> TableName tableName = TableName.valueOf("mockTable");<a name="line.217"></a>
+<span class="sourceLineNo">218</span> when(mockedRegion.getTable()).thenReturn(tableName);<a name="line.218"></a>
+<span class="sourceLineNo">219</span> when(mockedRegion.getEncodedName()).thenReturn("mocked-region-encoded-name");<a name="line.219"></a>
+<span class="sourceLineNo">220</span> Path tableDir = new Path("mockFS://mockDir/tabledir");<a name="line.220"></a>
+<span class="sourceLineNo">221</span> byte[] family = Bytes.toBytes("testfamily");<a name="line.221"></a>
+<span class="sourceLineNo">222</span> HStoreFile mockedFile = mock(HStoreFile.class);<a name="line.222"></a>
+<span class="sourceLineNo">223</span> List<HStoreFile> list = new ArrayList<>();<a name="line.223"></a>
+<span class="sourceLineNo">224</span> list.add(mockedFile);<a name="line.224"></a>
+<span class="sourceLineNo">225</span> when(mockedFile.getPath()).thenReturn(filePath);<a name="line.225"></a>
+<span class="sourceLineNo">226</span> when(mockedFileSystem.rename(any(),any())).thenReturn(true);<a name="line.226"></a>
+<span class="sourceLineNo">227</span> archivingFunction.apply(conf, mockedFileSystem, mockedRegion, tableDir, family, list);<a name="line.227"></a>
+<span class="sourceLineNo">228</span><a name="line.228"></a>
+<span class="sourceLineNo">229</span> if (sourceFileExists) {<a name="line.229"></a>
+<span class="sourceLineNo">230</span> ArgumentCaptor<Path> srcPath = ArgumentCaptor.forClass(Path.class);<a name="line.230"></a>
+<span class="sourceLineNo">231</span> ArgumentCaptor<Path> destPath = ArgumentCaptor.forClass(Path.class);<a name="line.231"></a>
+<span class="sourceLineNo">232</span> if (archiveFileExists) {<a name="line.232"></a>
+<span class="sourceLineNo">233</span> // Verify we renamed the archived file to sideline, and then renamed the source file.<a name="line.233"></a>
+<span class="sourceLineNo">234</span> verify(mockedFileSystem, times(2)).rename(srcPath.capture(), destPath.capture());<a name="line.234"></a>
+<span class="sourceLineNo">235</span> assertEquals(expectedDir, srcPath.getAllValues().get(0).toString());<a name="line.235"></a>
+<span class="sourceLineNo">236</span> assertEquals(filePath, srcPath.getAllValues().get(1));<a name="line.236"></a>
+<span class="sourceLineNo">237</span> assertEquals(expectedDir, destPath.getAllValues().get(1).toString());<a name="line.237"></a>
+<span class="sourceLineNo">238</span> } else {<a name="line.238"></a>
+<span class="sourceLineNo">239</span> // Verify we renamed the source file to the archived file.<a name="line.239"></a>
+<span class="sourceLineNo">240</span> verify(mockedFileSystem, times(1)).rename(srcPath.capture(), destPath.capture());<a name="line.240"></a>
+<span class="sourceLineNo">241</span> assertEquals(filePath, srcPath.getAllValues().get(0));<a name="line.241"></a>
+<span class="sourceLineNo">242</span> assertEquals(expectedDir, destPath.getAllValues().get(0).toString());<a name="line.242"></a>
+<span class="sourceLineNo">243</span> }<a name="line.243"></a>
+<span class="sourceLineNo">244</span> } else {<a name="line.244"></a>
+<span class="sourceLineNo">245</span> if (archiveFileExists) {<a name="line.245"></a>
+<span class="sourceLineNo">246</span> // Verify we did not rename. No source file with a present archive file should be a no-op.<a name="line.246"></a>
+<span class="sourceLineNo">247</span> verify(mockedFileSystem, never()).rename(any(), any());<a name="line.247"></a>
+<span class="sourceLineNo">248</span> } else {<a name="line.248"></a>
+<span class="sourceLineNo">249</span> fail("Unsupported test conditions: sourceFileExists and archiveFileExists both false.");<a name="line.249"></a>
+<span class="sourceLineNo">250</span> }<a name="line.250"></a>
+<span class="sourceLineNo">251</span> }<a name="line.251"></a>
+<span class="sourceLineNo">252</span> }<a name="line.252"></a>
+<span class="sourceLineNo">253</span><a name="line.253"></a>
+<span class="sourceLineNo">254</span> @FunctionalInterface<a name="line.254"></a>
+<span class="sourceLineNo">255</span> private interface ArchivingFunction<Configuration, FS, Region, Dir, Family, Files> {<a name="line.255"></a>
+<span class="sourceLineNo">256</span> void apply(Configuration config, FS fs, Region region, Dir dir, Family family, Files files)<a name="line.256"></a>
+<span class="sourceLineNo">257</span> throws IOException;<a name="line.257"></a>
+<span class="sourceLineNo">258</span> }<a name="line.258"></a>
+<span class="sourceLineNo">259</span><a name="line.259"></a>
+<span class="sourceLineNo">260</span> @Test<a name="line.260"></a>
+<span class="sourceLineNo">261</span> public void testArchiveRecoveredEditsWalDirNull() throws Exception {<a name="line.261"></a>
+<span class="sourceLineNo">262</span> testArchiveRecoveredEditsWalDirNullOrSame(null);<a name="line.262"></a>
+<span class="sourceLineNo">263</span> }<a name="line.263"></a>
+<span class="sourceLineNo">264</span><a name="line.264"></a>
+<span class="sourceLineNo">265</span> @Test<a name="line.265"></a>
+<span class="sourceLineNo">266</span> public void testArchiveRecoveredEditsWalDirSameFsStoreFiles() throws Exception {<a name="line.266"></a>
+<span class="sourceLineNo">267</span> testArchiveRecoveredEditsWalDirNullOrSame("/wal-dir");<a name="line.267"></a>
+<span class="sourceLineNo">268</span> }<a name="line.268"></a>
<span class="sourceLineNo">269</span><a name="line.269"></a>
-<span class="sourceLineNo">270</span> // check for the existence of the archive directory and some files in it<a name="line.270"></a>
-<span class="sourceLineNo">271</span> Path archiveDir = HFileArchiveTestingUtil.getRegionArchiveDir(UTIL.getConfiguration(), region);<a name="line.271"></a>
-<span class="sourceLineNo">272</span> assertTrue(fs.exists(archiveDir));<a name="line.272"></a>
-<span class="sourceLineNo">273</span><a name="line.273"></a>
-<span class="sourceLineNo">274</span> // check to make sure the store directory was copied<a name="line.274"></a>
-<span class="sourceLineNo">275</span> FileStatus[] stores = fs.listStatus(archiveDir, new PathFilter() {<a name="line.275"></a>
-<span class="sourceLineNo">276</span> @Override<a name="line.276"></a>
-<span class="sourceLineNo">277</span> public boolean accept(Path p) {<a name="line.277"></a>
-<span class="sourceLineNo">278</span> if (p.getName().contains(HConstants.RECOVERED_EDITS_DIR)) {<a name="line.278"></a>
-<span class="sourceLineNo">279</span> return false;<a name="line.279"></a>
-<span class="sourceLineNo">280</span> }<a name="line.280"></a>
-<span class="sourceLineNo">281</span> return true;<a name="line.281"></a>
-<span class="sourceLineNo">282</span> }<a name="line.282"></a>
-<span class="sourceLineNo">283</span> });<a name="line.283"></a>
-<span class="sourceLineNo">284</span> assertTrue(stores.length == 1);<a name="line.284"></a>
-<span class="sourceLineNo">285</span><a name="line.285"></a>
-<span class="sourceLineNo">286</span> // make sure we archived the store files<a name="line.286"></a>
-<span class="sourceLineNo">287</span> FileStatus[] storeFiles = fs.listStatus(stores[0].getPath());<a name="line.287"></a>
-<span class="sourceLineNo">288</span> assertTrue(storeFiles.length > 0);<a name="line.288"></a>
-<span class="sourceLineNo">289</span><a name="line.289"></a>
-<span class="sourceLineNo">290</span> // then ensure the region's directory isn't present<a name="line.290"></a>
-<span class="sourceLineNo">291</span> assertFalse(fs.exists(regionDir));<a name="line.291"></a>
-<span class="sourceLineNo">292</span><a name="line.292"></a>
-<span class="sourceLineNo">293</span> UTIL.deleteTable(tableName);<a name="line.293"></a>
-<span class="sourceLineNo">294</span> }<a name="line.294"></a>
-<span class="sourceLineNo">295</span><a name="line.295"></a>
-<span class="sourceLineNo">296</span> /**<a name="line.296"></a>
-<span class="sourceLineNo">297</span> * Test that the region directory is removed when we archive a region without store files, but<a name="line.297"></a>
-<span class="sourceLineNo">298</span> * still has hidden files.<a name="line.298"></a>
-<span class="sourceLineNo">299</span> * @throws IOException throws an IOException if there's problem creating a table<a name="line.299"></a>
-<span class="sourceLineNo">300</span> * or if there's an issue with accessing FileSystem.<a name="line.300"></a>
-<span class="sourceLineNo">301</span> */<a name="line.301"></a>
+<span class="sourceLineNo">270</span> private void testArchiveRecoveredEditsWalDirNullOrSame(String walDir) throws Exception {<a name="line.270"></a>
+<span class="sourceLineNo">271</span> String originalRootDir = UTIL.getConfiguration().get(HConstants.HBASE_DIR);<a name="line.271"></a>
+<span class="sourceLineNo">272</span> try {<a name="line.272"></a>
+<span class="sourceLineNo">273</span> String baseDir = "mockFS://mockFSAuthority:9876/hbase/";<a name="line.273"></a>
+<span class="sourceLineNo">274</span> UTIL.getConfiguration().set(HConstants.HBASE_DIR, baseDir);<a name="line.274"></a>
+<span class="sourceLineNo">275</span> testArchiveStoreFilesDifferentFileSystems(walDir, baseDir,<a name="line.275"></a>
+<span class="sourceLineNo">276</span> (conf, fs, region, dir, family, list) -> HFileArchiver<a name="line.276"></a>
+<span class="sourceLineNo">277</span> .archiveRecoveredEdits(conf, fs, region, family, list));<a name="line.277"></a>
+<span class="sourceLineNo">278</span> } finally {<a name="line.278"></a>
+<span class="sourceLineNo">279</span> UTIL.getConfiguration().set(HConstants.HBASE_DIR, originalRootDir);<a name="line.279"></a>
+<span class="sourceLineNo">280</span> }<a name="line.280"></a>
+<span class="sourceLineNo">281</span> }<a name="line.281"></a>
+<span class="sourceLineNo">282</span><a name="line.282"></a>
+<span class="sourceLineNo">283</span> @Test(expected = IOException.class)<a name="line.283"></a>
+<span class="sourceLineNo">284</span> public void testArchiveRecoveredEditsWrongFS() throws Exception {<a name="line.284"></a>
+<span class="sourceLineNo">285</span> String baseDir = CommonFSUtils.getRootDir(UTIL.getConfiguration()).toString() + "/";<a name="line.285"></a>
+<span class="sourceLineNo">286</span> //Internally, testArchiveStoreFilesDifferentFileSystems will pass a "mockedFS"<a name="line.286"></a>
+<span class="sourceLineNo">287</span> // to HFileArchiver.archiveRecoveredEdits, but since wal-dir is supposedly on same FS<a name="line.287"></a>
+<span class="sourceLineNo">288</span> // as root dir it would lead to conflicting FSes and an IOException is expected.<a name="line.288"></a>
+<span class="sourceLineNo">289</span> testArchiveStoreFilesDifferentFileSystems("/wal-dir", baseDir,<a name="line.289"></a>
+<span class="sourceLineNo">290</span> (conf, fs, region, dir, family, list) -> HFileArchiver<a name="line.290"></a>
+<span class="sourceLineNo">291</span> .archiveRecoveredEdits(conf, fs, region, family, list));<a name="line.291"></a>
+<span class="sourceLineNo">292</span> }<a name="line.292"></a>
+<span class="sourceLineNo">293</span><a name="line.293"></a>
+<span class="sourceLineNo">294</span> @Test<a name="line.294"></a>
+<span class="sourceLineNo">295</span> public void testArchiveRecoveredEditsWalDirDifferentFS() throws Exception {<a name="line.295"></a>
+<span class="sourceLineNo">296</span> String walDir = "mockFS://mockFSAuthority:9876/mockDir/wals/";<a name="line.296"></a>
+<span class="sourceLineNo">297</span> testArchiveStoreFilesDifferentFileSystems(walDir, walDir,<a name="line.297"></a>
+<span class="sourceLineNo">298</span> (conf, fs, region, dir, family, list) -><a name="line.298"></a>
+<span class="sourceLineNo">299</span> HFileArchiver.archiveRecoveredEdits(conf, fs, region, family, list));<a name="line.299"></a>
+<span class="sourceLineNo">300</span> }<a name="line.300"></a>
+<span class="sourceLineNo">301</span><a name="line.301"></a>
<span class="sourceLineNo">302</span> @Test<a name="line.302"></a>
-<span class="sourceLineNo">303</span> public void testDeleteRegionWithNoStoreFiles() throws IOException {<a name="line.303"></a>
+<span class="sourceLineNo">303</span> public void testRemoveRegionDirOnArchive() throws Exception {<a name="line.303"></a>
<span class="sourceLineNo">304</span> final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.304"></a>
<span class="sourceLineNo">305</span> UTIL.createTable(tableName, TEST_FAM);<a name="line.305"></a>
<span class="sourceLineNo">306</span><a name="line.306"></a>
-<span class="sourceLineNo">307</span> // get the current store files for the region<a name="line.307"></a>
-<span class="sourceLineNo">308</span> List<HRegion> servingRegions = UTIL.getHBaseCluster().getRegions(tableName);<a name="line.308"></a>
-<span class="sourceLineNo">309</span> // make sure we only have 1 region serving this table<a name="line.309"></a>
-<span class="sourceLineNo">310</span> assertEquals(1, servingRegions.size());<a name="line.310"></a>
-<span class="sourceLineNo">311</span> HRegion region = servingRegions.get(0);<a name="line.311"></a>
-<span class="sourceLineNo">312</span><a name="line.312"></a>
-<span class="sourceLineNo">313</span> FileSystem fs = region.getRegionFileSystem().getFileSystem();<a name="line.313"></a>
+<span class="sourceLineNo">307</span> final Admin admin = UTIL.getAdmin();<a name="line.307"></a>
+<span class="sourceLineNo">308</span><a name="line.308"></a>
+<span class="sourceLineNo">309</span> // get the current store files for the region<a name="line.309"></a>
+<span class="sourceLineNo">310</span> List<HRegion> servingRegions = UTIL.getHBaseCluster().getRegions(tableName);<a name="line.310"></a>
+<span class="sourceLineNo">311</span> // make sure we only have 1 region serving this table<a name="line.311"></a>
+<span class="sourceLineNo">312</span> assertEquals(1, servingRegions.size());<a name="line.312"></a>
+<span class="sourceLineNo">313</span> HRegion region = servingRegions.get(0);<a name="line.313"></a>
<span class="sourceLineNo">314</span><a name="line.314"></a>
-<span class="sourceLineNo">315</span> // make sure there are some files in the regiondir<a name="line.315"></a>
-<span class="sourceLineNo">316</span> Path rootDir = CommonFSUtils.getRootDir(fs.getConf());<a name="line.316"></a>
-<span class="sourceLineNo">317</span> Path regionDir = FSUtils.getRegionDirFromRootDir(rootDir, region.getRegionInfo());<a name="line.317"></a>
-<span class="sourceLineNo">318</span> FileStatus[] regionFiles = CommonFSUtils.listStatus(fs, regionDir, null);<a name="line.318"></a>
-<span class="sourceLineNo">319</span> Assert.assertNotNull("No files in the region directory", regionFiles);<a name="line.319"></a>
-<span class="sourceLineNo">320</span> if (LOG.isDebugEnabled()) {<a name="line.320"></a>
-<span class="sourceLineNo">321</span> List<Path> files = new ArrayList<>();<a name="line.321"></a>
-<span class="sourceLineNo">322</span> for (FileStatus file : regionFiles) {<a name="line.322"></a>
-<span class="sourceLineNo">323</span> files.add(file.getPath());<a name="line.323"></a>
-<span class="sourceLineNo">324</span> }<a name="line.324"></a>
-<span class="sourceLineNo">325</span> LOG.debug("Current files:" + files);<a name="line.325"></a>
-<span class="sourceLineNo">326</span> }<a name="line.326"></a>
-<span class="sourceLineNo">327</span> // delete the visible folders so we just have hidden files/folders<a name="line.327"></a>
-<span class="sourceLineNo">328</span> final PathFilter dirFilter = new FSUtils.DirFilter(fs);<a name="line.328"></a>
-<span class="sourceLineNo">329</span> PathFilter nonHidden = new PathFilter() {<a name="line.329"></a>
-<span class="sourceLineNo">330</span> @Override<a name="line.330"></a>
-<span class="sourceLineNo">331</span> public boolean accept(Path file) {<a name="line.331"></a>
-<span class="sourceLineNo">332</span> return dirFilter.accept(file) && !file.getName().startsWith(".");<a name="line.332"></a>
-<span class="sourceLineNo">333</span> }<a name="line.333"></a>
-<span class="sourceLineNo">334</span> };<a name="line.334"></a>
-<span class="sourceLineNo">335</span> FileStatus[] storeDirs = CommonFSUtils.listStatus(fs, regionDir, nonHidden);<a name="line.335"></a>
-<span class="sourceLineNo">336</span> for (FileStatus store : storeDirs) {<a name="line.336"></a>
-<span class="sourceLineNo">337</span> LOG.debug("Deleting store for test");<a name="line.337"></a>
-<span class="sourceLineNo">338</span> fs.delete(store.getPath(), true);<a name="line.338"></a>
-<span class="sourceLineNo">339</span> }<a name="line.339"></a>
-<span class="sourceLineNo">340</span><a name="line.340"></a>
-<span class="sourceLineNo">341</span> // then archive the region<a name="line.341"></a>
-<span class="sourceLineNo">342</span> HFileArchiver.archiveRegion(UTIL.getConfiguration(), fs, region.getRegionInfo());<a name="line.342"></a>
-<span class="sourceLineNo">343</span><a name="line.343"></a>
-<span class="sourceLineNo">344</span> // and check to make sure the region directoy got deleted<a name="line.344"></a>
-<span class="sourceLineNo">345</span> assertFalse("Region directory (" + regionDir + "), still exists.", fs.exists(regionDir));<a name="line.345"></a>
-<span class="sourceLineNo">346</span><a name="line.346"></a>
-<span class="sourceLineNo">347</span> UTIL.deleteTable(tableName);<a name="line.347"></a>
-<span class="sourceLineNo">348</span> }<a name="line.348"></a>
-<span class="sourceLineNo">349</span><a name="line.349"></a>
-<span class="sourceLineNo">350</span> private List<HRegion> initTableForArchivingRegions(TableName tableName) throws IOException {<a name="line.350"></a>
-<span class="sourceLineNo">351</span> final byte[][] splitKeys = new byte[][] {<a name="line.351"></a>
-<span class="sourceLineNo">352</span> Bytes.toBytes("b"), Bytes.toBytes("c"), Bytes.toBytes("d")<a name="line.352"></a>
-<span class="sourceLineNo">353</span> };<a name="line.353"></a>
+<span class="sourceLineNo">315</span> // and load the table<a name="line.315"></a>
+<span class="sourceLineNo">316</span> UTIL.loadRegion(region, TEST_FAM);<a name="line.316"></a>
+<span class="sourceLineNo">317</span><a name="line.317"></a>
+<span class="sourceLineNo">318</span> // shutdown the table so we can manipulate the files<a name="line.318"></a>
+<span class="sourceLineNo">319</span> admin.disableTable(tableName);<a name="line.319"></a>
+<span class="sourceLineNo">320</span><a name="line.320"></a>
+<span class="sourceLineNo">321</span> FileSystem fs = UTIL.getTestFileSystem();<a name="line.321"></a>
+<span class="sourceLineNo">322</span><a name="line.322"></a>
+<span class="sourceLineNo">323</span> // now attempt to depose the region<a name="line.323"></a>
+<span class="sourceLineNo">324</span> Path rootDir = region.getRegionFileSystem().getTableDir().getParent();<a name="line.324"></a>
+<span class="sourceLineNo">325</span> Path regionDir = FSUtils.getRegionDirFromRootDir(rootDir, region.getRegionInfo());<a name="line.325"></a>
+<span class="sourceLineNo">326</span><a name="line.326"></a>
+<span class="sourceLineNo">327</span> HFileArchiver.archiveRegion(UTIL.getConfiguration(), fs, region.getRegionInfo());<a name="line.327"></a>
+<span class="sourceLineNo">328</span><a name="line.328"></a>
+<span class="sourceLineNo">329</span> // check for the existence of the archive directory and some files in it<a name="line.329"></a>
+<span class="sourceLineNo">330</span> Path archiveDir = HFileArchiveTestingUtil.getRegionArchiveDir(UTIL.getConfiguration(), region);<a name="line.330"></a>
+<span class="sourceLineNo">331</span> assertTrue(fs.exists(archiveDir));<a name="line.331"></a>
+<span class="sourceLineNo">332</span><a name="line.332"></a>
+<span class="sourceLineNo">333</span> // check to make sure the store directory was copied<a name="line.333"></a>
+<span class="sourceLineNo">334</span> FileStatus[] stores = fs.listStatus(archiveDir, new PathFilter() {<a name="line.334"></a>
+<span class="sourceLineNo">335</span> @Override<a name="line.335"></a>
+<span class="sourceLineNo">336</span> public boolean accept(Path p) {<a name="line.336"></a>
+<span class="sourceLineNo">337</span> if (p.getName().contains(HConstants.RECOVERED_EDITS_DIR)) {<a name="line.337"></a>
+<span class="sourceLineNo">338</span> return false;<a name="line.338"></a>
+<span class="sourceLineNo">339</span> }<a name="line.339"></a>
+<span class="sourceLineNo">340</span> return true;<a name="line.340"></a>
+<span class="sourceLineNo">341</span> }<a name="line.341"></a>
+<span class="sourceLineNo">342</span> });<a name="line.342"></a>
+<span class="sourceLineNo">343</span> assertTrue(stores.length == 1);<a name="line.343"></a>
+<span class="sourceLineNo">344</span><a name="line.344"></a>
+<span class="sourceLineNo">345</span> // make sure we archived the store files<a name="line.345"></a>
+<span class="sourceLineNo">346</span> FileStatus[] storeFiles = fs.listStatus(stores[0].getPath());<a name="line.346"></a>
+<span class="sourceLineNo">347</span> assertTrue(storeFiles.length > 0);<a name="line.347"></a>
+<span class="sourceLineNo">348</span><a name="line.348"></a>
+<span class="sourceLineNo">349</span> // then ensure the region's directory isn't present<a name="line.349"></a>
+<span class="sourceLineNo">350</span> assertFalse(fs.exists(regionDir));<a name="line.350"></a>
+<span class="sourceLineNo">351</span><a name="line.351"></a>
+<span class="sourceLineNo">352</span> UTIL.deleteTable(tableName);<a name="line.352"></a>
+<span class="sourceLineNo">353</span> }<a name="line.353"></a>
<span class="sourceLineNo">354</span><a name="line.354"></a>
-<span class="sourceLineNo">355</span> UTIL.createTable(tableName, TEST_FAM, splitKeys);<a name="line.355"></a>
-<span class="sourceLineNo">356</span><a name="line.356"></a>
-<span class="sourceLineNo">357</span> // get the current store files for the regions<a name="line.357"></a>
-<span class="sourceLineNo">358</span> List<HRegion> regions = UTIL.getHBaseCluster().getRegions(tableName);<a name="line.358"></a>
-<span class="sourceLineNo">359</span> // make sure we have 4 regions serving this table<a name="line.359"></a>
-<span class="sourceLineNo">360</span> assertEquals(4, regions.size());<a name="line.360"></a>
-<span class="sourceLineNo">361</span><a name="line.361"></a>
-<span class="sourceLineNo">362</span> // and load the table<a name="line.362"></a>
-<span class="sourceLineNo">363</span> try (Table table = UTIL.getConnection().getTable(tableName)) {<a name="line.363"></a>
-<span class="sourceLineNo">364</span> UTIL.loadTable(table, TEST_FAM);<a name="line.364"></a>
-<span class="sourceLineNo">365</span> }<a name="line.365"></a>
-<span class="sourceLineNo">366</span><a name="line.366"></a>
-<span class="sourceLineNo">367</span> // disable the table so that we can manipulate the files<a name="line.367"></a>
-<span class="sourceLineNo">368</span> UTIL.getAdmin().disableTable(tableName);<a name="line.368"></a>
-<span class="sourceLineNo">369</span><a name="line.369"></a>
-<span class="sourceLineNo">370</span> return regions;<a name="line.370"></a>
-<span class="sourceLineNo">371</span> }<a name="line.371"></a>
-<span class="sourceLineNo">372</span><a name="line.372"></a>
-<span class="sourceLineNo">373</span> @Test<a name="line.373"></a>
-<span class="sourceLineNo">374</span> public void testArchiveRegions() throws Exception {<a name="line.374"></a>
-<span class="sourceLineNo">375</span> final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.375"></a>
-<span class="sourceLineNo">376</span> List<HRegion> regions = initTableForArchivingRegions(tableName);<a name="line.376"></a>
-<span class="sourceLineNo">377</span><a name="line.377"></a>
-<span class="sourceLineNo">378</span> FileSystem fs = UTIL.getTestFileSystem();<a name="line.378"></a>
-<span class="sourceLineNo">379</span><a name="line.379"></a>
-<span class="sourceLineNo">380</span> // now attempt to depose the regions<a name="line.380"></a>
-<span class="sourceLineNo">381</span> Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.381"></a>
-<span class="sourceLineNo">382</span> Path tableDir = CommonFSUtils.getTableDir(rootDir, regions.get(0).getRegionInfo().getTable());<a name="line.382"></a>
-<span class="sourceLineNo">383</span> List<Path> regionDirList = regions.stream()<a name="line.383"></a>
-<span class="sourceLineNo">384</span> .map(region -> FSUtils.getRegionDirFromTableDir(tableDir, region.getRegionInfo()))<a name="line.384"></a>
-<span class="sourceLineNo">385</span> .collect(Collectors.toList());<a name="line.385"></a>
-<span class="sourceLineNo">386</span><a name="line.386"></a>
-<span class="sourceLineNo">387</span> HFileArchiver.archiveRegions(UTIL.getConfiguration(), fs, rootDir, tableDir, regionDirList);<a name="line.387"></a>
-<span class="sourceLineNo">388</span><a name="line.388"></a>
-<span class="sourceLineNo">389</span> // check for the existence of the archive directory and some files in it<a name="line.389"></a>
-<span class="sourceLineNo">390</span> for (HRegion region : regions) {<a name="line.390"></a>
-<span class="sourceLineNo">391</span> Path archiveDir = HFileArchiveTestingUtil.getRegionArchiveDir(UTIL.getConfiguration(),<a name="line.391"></a>
-<span class="sourceLineNo">392</span> region);<a name="line.392"></a>
-<span class="sourceLineNo">393</span> assertTrue(fs.exists(archiveDir));<a name="line.393"></a>
-<span class="sourceLineNo">394</span><a name="line.394"></a>
-<span class="sourceLineNo">395</span> // check to make sure the store directory was copied<a name="line.395"></a>
-<span class="sourceLineNo">396</span> FileStatus[] stores = fs.listStatus(archiveDir,<a name="line.396"></a>
-<span class="sourceLineNo">397</span> p -> !p.getName().contains(HConstants.RECOVERED_EDITS_DIR));<a name="line.397"></a>
-<span class="sourceLineNo">398</span> assertTrue(stores.length == 1);<a name="line.398"></a>
+<span class="sourceLineNo">355</span> /**<a name="line.355"></a>
+<span class="sourceLineNo">356</span> * Test that the region directory is removed when we archive a region without store files, but<a name="line.356"></a>
+<span class="sourceLineNo">357</span> * still has hidden files.<a name="line.357"></a>
+<span class="sourceLineNo">358</span> * @throws IOException throws an IOException if there's problem creating a table<a name="line.358"></a>
+<span class="sourceLineNo">359</span> * or if there's an issue with accessing FileSystem.<a name="line.359"></a>
+<span class="sourceLineNo">360</span> */<a name="line.360"></a>
+<span class="sourceLineNo">361</span> @Test<a name="line.361"></a>
+<span class="sourceLineNo">362</span> public void testDeleteRegionWithNoStoreFiles() throws IOException {<a name="line.362"></a>
+<span class="sourceLineNo">363</span> final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.363"></a>
+<span class="sourceLineNo">364</span> UTIL.createTable(tableName, TEST_FAM);<a name="line.364"></a>
+<span class="sourceLineNo">365</span><a name="line.365"></a>
+<span class="sourceLineNo">366</span> // get the current store files for the region<a name="line.366"></a>
+<span class="sourceLineNo">367</span> List<HRegion> servingRegions = UTIL.getHBaseCluster().getRegions(tableName);<a name="line.367"></a>
+<span class="sourceLineNo">368</span> // make sure we only have 1 region serving this table<a name="line.368"></a>
+<span class="sourceLineNo">369</span> assertEquals(1, servingRegions.size());<a name="line.369"></a>
+<span class="sourceLineNo">370</span> HRegion region = servingRegions.get(0);<a name="line.370"></a>
+<span class="sourceLineNo">371</span><a name="line.371"></a>
+<span class="sourceLineNo">372</span> FileSystem fs = region.getRegionFileSystem().getFileSystem();<a name="line.372"></a>
+<span class="sourceLineNo">373</span><a name="line.373"></a>
+<span class="sourceLineNo">374</span> // make sure there are some files in the regiondir<a name="line.374"></a>
+<span class="sourceLineNo">375</span> Path rootDir = CommonFSUtils.getRootDir(fs.getConf());<a name="line.375"></a>
+<span class="sourceLineNo">376</span> Path regionDir = FSUtils.getRegionDirFromRootDir(rootDir, region.getRegionInfo());<a name="line.376"></a>
+<span class="sourceLineNo">377</span> FileStatus[] regionFiles = CommonFSUtils.listStatus(fs, regionDir, null);<a name="line.377"></a>
+<span class="sourceLineNo">378</span> Assert.assertNotNull("No files in the region directory", regionFiles);<a name="line.378"></a>
+<span class="sourceLineNo">379</span> if (LOG.isDebugEnabled()) {<a name="line.379"></a>
+<span class="sourceLineNo">380</span> List<Path> files = new ArrayList<>();<a name="line.380"></a>
+<span class="sourceLineNo">381</span> for (FileStatus file : regionFiles) {<a name="line.381"></a>
+<span class="sourceLineNo">382</span> files.add(file.getPath());<a name="line.382"></a>
+<span class="sourceLineNo">383</span> }<a name="line.383"></a>
+<span class="sourceLineNo">384</span> LOG.debug("Current files:" + files);<a name="line.384"></a>
+<span class="sourceLineNo">385</span> }<a name="line.385"></a>
+<span class="sourceLineNo">386</span> // delete the visible folders so we just have hidden files/folders<a name="line.386"></a>
+<span class="sourceLineNo">387</span> final PathFilter dirFilter = new FSUtils.DirFilter(fs);<a name="line.387"></a>
+<span class="sourceLineNo">388</span> PathFilter nonHidden = new PathFilter() {<a name="line.388"></a>
+<span class="sourceLineNo">389</span> @Override<a name="line.389"></a>
+<span class="sourceLineNo">390</span> public boolean accept(Path file) {<a name="line.390"></a>
+<span class="sourceLineNo">391</span> return dirFilter.accept(file) && !file.getName().startsWith(".");<a name="line.391"></a>
+<span class="sourceLineNo">392</span> }<a name="line.392"></a>
+<span class="sourceLineNo">393</span> };<a name="line.393"></a>
+<span class="sourceLineNo">394</span> FileStatus[] storeDirs = CommonFSUtils.listStatus(fs, regionDir, nonHidden);<a name="line.394"></a>
+<span class="sourceLineNo">395</span> for (FileStatus store : storeDirs) {<a name="line.395"></a>
+<span class="sourceLineNo">396</span> LOG.debug("Deleting store for test");<a name="line.396"></a>
+<span class="sourceLineNo">397</span> fs.delete(store.getPath(), true);<a name="line.397"></a>
+<span class="sourceLineNo">398</span> }<a name="line.398"></a>
<span class="sourceLineNo">399</span><a name="line.399"></a>
-<span class="sourceLineNo">400</span> // make sure we archived the store files<a name="line.400"></a>
-<span class="sourceLineNo">401</span> FileStatus[] storeFiles = fs.listStatus(stores[0].getPath());<a name="line.401"></a>
-<span class="sourceLineNo">402</span> assertTrue(storeFiles.length > 0);<a name="line.402"></a>
-<span class="sourceLineNo">403</span> }<a name="line.403"></a>
-<span class="sourceLineNo">404</span><a name="line.404"></a>
-<span class="sourceLineNo">405</span> // then ensure the region's directories aren't present<a name="line.405"></a>
-<span class="sourceLineNo">406</span> for (Path regionDir: regionDirList) {<a name="line.406"></a>
-<span class="sourceLineNo">407</span> assertFalse(fs.exists(regionDir));<a name="line.407"></a>
-<span class="sourceLineNo">408</span> }<a name="line.408"></a>
-<span class="sourceLineNo">409</span><a name="line.409"></a>
-<span class="sourceLineNo">410</span> UTIL.deleteTable(tableName);<a name="line.410"></a>
-<span class="sourceLineNo">411</span> }<a name="line.411"></a>
-<span class="sourceLineNo">412</span><a name="line.412"></a>
-<span class="sourceLineNo">413</span> @Test(expected=IOException.class)<a name="line.413"></a>
-<span class="sourceLineNo">414</span> public void testArchiveRegionsWhenPermissionDenied() throws Exception {<a name="line.414"></a>
-<span class="sourceLineNo">415</span> final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.415"></a>
-<span class="sourceLineNo">416</span> List<HRegion> regions = initTableForArchivingRegions(tableName);<a name="line.416"></a>
-<span class="sourceLineNo">417</span><a name="line.417"></a>
-<span class="sourceLineNo">418</span> // now attempt to depose the regions<a name="line.418"></a>
-<span class="sourceLineNo">419</span> Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.419"></a>
-<span class="sourceLineNo">420</span> Path tableDir = CommonFSUtils.getTableDir(rootDir, regions.get(0).getRegionInfo().getTable());<a name="line.420"></a>
-<span class="sourceLineNo">421</span> List<Path> regionDirList = regions.stream()<a name="line.421"></a>
-<span class="sourceLineNo">422</span> .map(region -> FSUtils.getRegionDirFromTableDir(tableDir, region.getRegionInfo()))<a name="line.422"></a>
-<span class="sourceLineNo">423</span> .collect(Collectors.toList());<a name="line.423"></a>
-<span class="sourceLineNo">424</span><a name="line.424"></a>
-<span class="sourceLineNo">425</span> // To create a permission denied error, we do archive regions as a non-current user<a name="line.425"></a>
-<span class="sourceLineNo">426</span> UserGroupInformation<a name="line.426"></a>
-<span class="sourceLineNo">427</span> ugi = UserGroupInformation.createUserForTesting("foo1234", new String[]{"group1"});<a name="line.427"></a>
+<span class="sourceLineNo">400</span> // then archive the region<a name="line.400"></a>
+<span class="sourceLineNo">401</span> HFileArchiver.archiveRegion(UTIL.getConfiguration(), fs, region.getRegionInfo());<a name="line.401"></a>
+<span class="sourceLineNo">402</span><a name="line.402"></a>
+<span class="sourceLineNo">403</span> // and check to make sure the region directoy got deleted<a name="line.403"></a>
+<span class="sourceLineNo">404</span> assertFalse("Region directory (" + regionDir + "), still exists.", fs.exists(regionDir));<a name="line.404"></a>
+<span class="sourceLineNo">405</span><a name="line.405"></a>
+<span class="sourceLineNo">406</span> UTIL.deleteTable(tableName);<a name="line.406"></a>
+<span class="sourceLineNo">407</span> }<a name="line.407"></a>
+<span class="sourceLineNo">408</span><a name="line.408"></a>
+<span class="sourceLineNo">409</span> private List<HRegion> initTableForArchivingRegions(TableName tableName) throws IOException {<a name="line.409"></a>
+<span class="sourceLineNo">410</span> final byte[][] splitKeys = new byte[][] {<a name="line.410"></a>
+<span class="sourceLineNo">411</span> Bytes.toBytes("b"), Bytes.toBytes("c"), Bytes.toBytes("d")<a name="line.411"></a>
+<span class="sourceLineNo">412</span> };<a name="line.412"></a>
+<span class="sourceLineNo">413</span><a name="line.413"></a>
+<span class="sourceLineNo">414</span> UTIL.createTable(tableName, TEST_FAM, splitKeys);<a name="line.414"></a>
+<span class="sourceLineNo">415</span><a name="line.415"></a>
+<span class="sourceLineNo">416</span> // get the current store files for the regions<a name="line.416"></a>
+<span class="sourceLineNo">417</span> List<HRegion> regions = UTIL.getHBaseCluster().getRegions(tableName);<a name="line.417"></a>
+<span class="sourceLineNo">418</span> // make sure we have 4 regions serving this table<a name="line.418"></a>
+<span class="sourceLineNo">419</span> assertEquals(4, regions.size());<a name="line.419"></a>
+<span class="sourceLineNo">420</span><a name="line.420"></a>
+<span class="sourceLineNo">421</span> // and load the table<a name="line.421"></a>
+<span class="sourceLineNo">422</span> try (Table table = UTIL.getConnection().getTable(tableName)) {<a name="line.422"></a>
+<span class="sourceLineNo">423</span> UTIL.loadTable(table, TEST_FAM);<a name="line.423"></a>
+<span class="sourceLineNo">424</span> }<a name="line.424"></a>
+<span class="sourceLineNo">425</span><a name="line.425"></a>
+<span class="sourceLineNo">426</span> // disable the table so that we can manipulate the files<a name="line.426"></a>
+<span class="sourceLineNo">427</span> UTIL.getAdmin().disableTable(tableName);<a name="line.427"></a>
<span class="sourceLineNo">428</span><a name="line.428"></a>
-<span class="sourceLineNo">429</span> try {<a name="line.429"></a>
-<span class="sourceLineNo">430</span> ugi.doAs((PrivilegedExceptionAction<Void>) () -> {<a name="line.430"></a>
-<span class="sourceLineNo">431</span> FileSystem fs = UTIL.getTestFileSystem();<a name="line.431"></a>
-<span class="sourceLineNo">432</span> HFileArchiver.archiveRegions(UTIL.getConfiguration(), fs, rootDir, tableDir,<a name="line.432"></a>
-<span class="sourceLineNo">433</span> regionDirList);<a name="line.433"></a>
-<span class="sourceLineNo">434</span> return null;<a name="line.434"></a>
-<span class="sourceLineNo">435</span> });<a name="line.435"></a>
-<span class="sourceLineNo">436</span> } catch (IOException e) {<a name="line.436"></a>
-<span class="sourceLineNo">437</span> assertTrue(e.getCause().getMessage().contains("Permission denied"));<a name="line.437"></a>
-<span class="sourceLineNo">438</span> throw e;<a name="line.438"></a>
-<span class="sourceLineNo">439</span> } finally {<a name="line.439"></a>
-<span class="sourceLineNo">440</span> UTIL.deleteTable(tableName);<a name="line.440"></a>
-<span class="sourceLineNo">441</span> }<a name="line.441"></a>
-<span class="sourceLineNo">442</span> }<a name="line.442"></a>
-<span class="sourceLineNo">443</span><a name="line.443"></a>
-<span class="sourceLineNo">444</span> @Test<a name="line.444"></a>
-<span class="sourceLineNo">445</span> public void testArchiveOnTableDelete() throws Exception {<a name="line.445"></a>
-<span class="sourceLineNo">446</span> final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.446"></a>
-<span class="sourceLineNo">447</span> UTIL.createTable(tableName, TEST_FAM);<a name="line.447"></a>
-<span class="sourceLineNo">448</span><a name="line.448"></a>
-<span class="sourceLineNo">449</span> List<HRegion> servingRegions = UTIL.getHBaseCluster().getRegions(tableName);<a name="line.449"></a>
-<span class="sourceLineNo">450</span> // make sure we only have 1 region serving this table<a name="line.450"></a>
-<span class="sourceLineNo">451</span> assertEquals(1, servingRegions.size());<a name="line.451"></a>
-<span class="sourceLineNo">452</span> HRegion region = servingRegions.get(0);<a name="line.452"></a>
+<span class="sourceLineNo">429</span> return regions;<a name="line.429"></a>
+<span class="sourceLineNo">430</span> }<a name="line.430"></a>
+<span class="sourceLineNo">431</span><a name="line.431"></a>
+<span class="sourceLineNo">432</span> @Test<a name="line.432"></a>
+<span class="sourceLineNo">433</span> public void testArchiveRegions() throws Exception {<a name="line.433"></a>
+<span class="sourceLineNo">434</span> final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.434"></a>
+<span class="sourceLineNo">435</span> List<HRegion> regions = initTableForArchivingRegions(tableName);<a name="line.435"></a>
+<span class="sourceLineNo">436</span><a name="line.436"></a>
+<span class="sourceLineNo">437</span> FileSystem fs = UTIL.getTestFileSystem();<a name="line.437"></a>
+<span class="sourceLineNo">438</span><a name="line.438"></a>
+<span class="sourceLineNo">439</span> // now attempt to depose the regions<a name="line.439"></a>
+<span class="sourceLineNo">440</span> Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.440"></a>
+<span class="sourceLineNo">441</span> Path tableDir = CommonFSUtils.getTableDir(rootDir, regions.get(0).getRegionInfo().getTable());<a name="line.441"></a>
+<span class="sourceLineNo">442</span> List<Path> regionDirList = regions.stream()<a name="line.442"></a>
+<span class="sourceLineNo">443</span> .map(region -> FSUtils.getRegionDirFromTableDir(tableDir, region.getRegionInfo()))<a name="line.443"></a>
+<span class="sourceLineNo">444</span> .collect(Collectors.toList());<a name="line.444"></a>
+<span class="sourceLineNo">445</span><a name="line.445"></a>
+<span class="sourceLineNo">446</span> HFileArchiver.archiveRegions(UTIL.getConfiguration(), fs, rootDir, tableDir, regionDirList);<a name="line.446"></a>
+<span class="sourceLineNo">447</span><a name="line.447"></a>
+<span class="sourceLineNo">448</span> // check for the existence of the archive directory and some files in it<a name="line.448"></a>
+<span class="sourceLineNo">449</span> for (HRegion region : regions) {<a name="line.449"></a>
+<span class="sourceLineNo">450</span> Path archiveDir = HFileArchiveTestingUtil.getRegionArchiveDir(UTIL.getConfiguration(),<a name="line.450"></a>
+<span class="sourceLineNo">451</span> region);<a name="line.451"></a>
+<span class="sourceLineNo">452</span> assertTrue(fs.exists(archiveDir));<a name="line.452"></a>
<span class="sourceLineNo">453</span><a name="line.453"></a>
-<span class="sourceLineNo">454</span> // get the parent RS and monitor<a name="line.454"></a>
-<span class="sourceLineNo">455</span> HRegionServer hrs = UTIL.getRSForFirstRegionInTable(tableName);<a name="line.455"></a>
-<span class="sourceLineNo">456</span> FileSystem fs = hrs.getFileSystem();<a name="line.456"></a>
-<span class="sourceLineNo">457</span><a name="line.457"></a>
-<span class="sourceLineNo">458</span> // put some data on the region<a name="line.458"></a>
-<span class="sourceLineNo">459</span> LOG.debug("-------Loading table");<a name="line.459"></a>
-<span class="sourceLineNo">460</span> UTIL.loadRegion(region, TEST_FAM);<a name="line.460"></a>
-<span class="sourceLineNo">461</span><a name="line.461"></a>
-<span class="sourceLineNo">462</span> // get the hfiles in the region<a name="line.462"></a>
-<span class="sourceLineNo">463</span> List<HRegion> regions = hrs.getRegions(tableName);<a name="line.463"></a>
-<span class="sourceLineNo">464</span> assertEquals("More that 1 region for test table.", 1, regions.size());<a name="line.464"></a>
-<span class="sourceLineNo">465</span><a name="line.465"></a>
-<span class="sourceLineNo">466</span> region = regions.get(0);<a name="line.466"></a>
-<span class="sourceLineNo">467</span> // wait for all the compactions to complete<a name="line.467"></a>
-<span class="sourceLineNo">468</span> region.waitForFlushesAndCompactions();<a name="line.468"></a>
-<span class="sourceLineNo">469</span><a name="line.469"></a>
-<span class="sourceLineNo">470</span> // disable table to prevent new updates<a name="line.470"></a>
-<span class="sourceLineNo">471</span> UTIL.getAdmin().disableTable(tableName);<a name="line.471"></a>
-<span class="sourceLineNo">472</span> LOG.debug("Disabled table");<a name="line.472"></a>
-<span class="sourceLineNo">473</span><a name="line.473"></a>
-<span class="sourceLineNo">474</span> // remove all the files from the archive to get a fair comparison<a name="line.474"></a>
-<span class="sourceLineNo">475</span> clearArchiveDirectory();<a name="line.475"></a>
+<span class="sourceLineNo">454</span> // check to make sure the store directory was copied<a name="line.454"></a>
+<span class="sourceLineNo">455</span> FileStatus[] stores = fs.listStatus(archiveDir,<a name="line.455"></a>
+<span class="sourceLineNo">456</span> p -> !p.getName().contains(HConstants.RECOVERED_EDITS_DIR));<a name="line.456"></a>
+<span class="sourceLineNo">457</span> assertTrue(stores.length == 1);<a name="line.457"></a>
+<span class="sourceLineNo">458</span><a name="line.458"></a>
+<span class="sourceLineNo">459</span> // make sure we archived the store files<a name="line.459"></a>
+<span class="sourceLineNo">460</span> FileStatus[] storeFiles = fs.listStatus(stores[0].getPath());<a name="line.460"></a>
+<span class="sourceLineNo">461</span> assertTrue(storeFiles.length > 0);<a name="line.461"></a>
+<span class="sourceLineNo">462</span> }<a name="line.462"></a>
+<span class="sourceLineNo">463</span><a name="line.463"></a>
+<span class="sourceLineNo">464</span> // then ensure the region's directories aren't present<a name="line.464"></a>
+<span class="sourceLineNo">465</span> for (Path regionDir: regionDirList) {<a name="line.465"></a>
+<span class="sourceLineNo">466</span> assertFalse(fs.exists(regionDir));<a name="line.466"></a>
+<span class="sourceLineNo">467</span> }<a name="line.467"></a>
+<span class="sourceLineNo">468</span><a name="line.468"></a>
+<span class="sourceLineNo">469</span> UTIL.deleteTable(tableName);<a name="line.469"></a>
+<span class="sourceLineNo">470</span> }<a name="line.470"></a>
+<span class="sourceLineNo">471</span><a name="line.471"></a>
+<span class="sourceLineNo">472</span> @Test(expected=IOException.class)<a name="line.472"></a>
+<span class="sourceLineNo">473</span> public void testArchiveRegionsWhenPermissionDenied() throws Exception {<a name="line.473"></a>
+<span class="sourceLineNo">474</span> final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.474"></a>
+<span class="sourceLineNo">475</span> List<HRegion> regions = initTableForArchivingRegions(tableName);<a name="line.475"></a>
<span class="sourceLineNo">476</span><a name="line.476"></a>
-<span class="sourceLineNo">477</span> // then get the current store files<a name="line.477"></a>
-<span class="sourceLineNo">478</span> byte[][]columns = region.getTableDescriptor().getColumnFamilyNames().toArray(new byte[0][]);<a name="line.478"></a>
-<span class="sourceLineNo">479</span> List<String> storeFiles = region.getStoreFileList(columns);<a name="line.479"></a>
-<span class="sourceLineNo">480</span><a name="line.480"></a>
-<span class="sourceLineNo">481</span> // then delete the table so the hfiles get archived<a name="line.481"></a>
-<span class="sourceLineNo">482</span> UTIL.deleteTable(tableName);<a name="line.482"></a>
-<span class="sourceLineNo">483</span> LOG.debug("Deleted table");<a name="line.483"></a>
-<span class="sourceLineNo">484</span><a name="line.484"></a>
-<span class="sourceLineNo">485</span> assertArchiveFiles(fs, storeFiles, 30000);<a name="line.485"></a>
-<span class="sourceLineNo">486</span> }<a name="line.486"></a>
+<span class="sourceLineNo">477</span> // now attempt to depose the regions<a name="line.477"></a>
+<span class="sourceLineNo">478</span> Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.478"></a>
+<span class="sourceLineNo">479</span> Path tableDir = CommonFSUtils.getTableDir(rootDir, regions.get(0).getRegionInfo().getTable());<a name="line.479"></a>
+<span class="sourceLineNo">480</span> List<Path> regionDirList = regions.stream()<a name="line.480"></a>
+<span class="sourceLineNo">481</span> .map(region -> FSUtils.getRegionDirFromTableDir(tableDir, region.getRegionInfo()))<a name="line.481"></a>
+<span class="sourceLineNo">482</span> .collect(Collectors.toList());<a name="line.482"></a>
+<span class="sourceLineNo">483</span><a name="line.483"></a>
+<span class="sourceLineNo">484</span> // To create a permission denied error, we do archive regions as a non-current user<a name="line.484"></a>
+<span class="sourceLineNo">485</span> UserGroupInformation<a name="line.485"></a>
+<span class="sourceLineNo">486</span> ugi = UserGroupInformation.createUserForTesting("foo1234", new String[]{"group1"});<a name="line.486"></a>
<span class="sourceLineNo">487</span><a name="line.487"></a>
-<span class="sourceLineNo">488</span> private void assertArchiveFiles(FileSystem fs, List<String> storeFiles, long timeout)<a name="line.488"></a>
-<span class="sourceLineNo">489</span> throws IOException {<a name="line.489"></a>
-<span class="sourceLineNo">490</span> long end = EnvironmentEdgeManager.currentTime() + timeout;<a name="line.490"></a>
-<span class="sourceLineNo">491</span> Path archiveDir = HFileArchiveUtil.getArchivePath(UTIL.getConfiguration());<a name="line.491"></a>
-<span class="sourceLineNo">492</span> List<String> archivedFiles = new ArrayList<>();<a name="line.492"></a>
-<span class="sourceLineNo">493</span><a name="line.493"></a>
-<span class="sourceLineNo">494</span> // We have to ensure that the DeleteTableHandler is finished. HBaseAdmin.deleteXXX()<a name="line.494"></a>
-<span class="sourceLineNo">495</span> // can return before all files<a name="line.495"></a>
-<span class="sourceLineNo">496</span> // are archived. We should fix HBASE-5487 and fix synchronous operations from admin.<a name="line.496"></a>
-<span class="sourceLineNo">497</span> while (EnvironmentEdgeManager.currentTime() < end) {<a name="line.497"></a>
-<span class="sourceLineNo">498</span> archivedFiles = getAllFileNames(fs, archiveDir);<a name="line.498"></a>
-<span class="sourceLineNo">499</span> if (archivedFiles.size() >= storeFiles.size()) {<a name="line.499"></a>
-<span class="sourceLineNo">500</span> break;<a name="line.500"></a>
-<span class="sourceLineNo">501</span> }<a name="line.501"></a>
-<span class="sourceLineNo">502</span> }<a name="line.502"></a>
-<span class="sourceLineNo">503</span><a name="line.503"></a>
-<span class="sourceLineNo">504</span> Collections.sort(storeFiles);<a name="line.504"></a>
-<span class="sourceLineNo">505</span> Collections.sort(archivedFiles);<a name="line.505"></a>
-<span class="sourceLineNo">506</span><a name="line.506"></a>
-<span class="sourceLineNo">507</span> LOG.debug("Store files:");<a name="line.507"></a>
-<span class="sourceLineNo">508</span> for (int i = 0; i < storeFiles.size(); i++) {<a name="line.508"></a>
-<span class="sourceLineNo">509</span> LOG.debug(i + " - " + storeFiles.get(i));<a name="line.509"></a>
-<span class="sourceLineNo">510</span> }<a name="line.510"></a>
-<span class="sourceLineNo">511</span> LOG.debug("Archive files:");<a name="line.511"></a>
-<span class="sourceLineNo">512</span> for (int i = 0; i < archivedFiles.size(); i++) {<a name="line.512"></a>
-<span class="sourceLineNo">513</span> LOG.debug(i + " - " + archivedFiles.get(i));<a name="line.513"></a>
-<span class="sourceLineNo">514</span> }<a name="line.514"></a>
-<span class="sourceLineNo">515</span><a name="line.515"></a>
-<span class="sourceLineNo">516</span> assertTrue("Archived files are missing some of the store files!",<a name="line.516"></a>
-<span class="sourceLineNo">517</span> archivedFiles.containsAll(storeFiles));<a name="line.517"></a>
-<span class="sourceLineNo">518</span> }<a name="line.518"></a>
-<span class="sourceLineNo">519</span><a name="line.519"></a>
+<span class="sourceLineNo">488</span> try {<a name="line.488"></a>
+<span class="sourceLineNo">489</span> ugi.doAs((PrivilegedExceptionAction<Void>) () -> {<a name="line.489"></a>
+<span class="sourceLineNo">490</span> FileSystem fs = UTIL.getTestFileSystem();<a name="line.490"></a>
+<span class="sourceLineNo">491</span> HFileArchiver.archiveRegions(UTIL.getConfiguration(), fs, rootDir, tableDir,<a name="line.491"></a>
+<span class="sourceLineNo">492</span> regionDirList);<a name="line.492"></a>
+<span class="sourceLineNo">493</span> return null;<a name="line.493"></a>
+<span class="sourceLineNo">494</span> });<a name="line.494"></a>
+<span class="sourceLineNo">495</span> } catch (IOException e) {<a name="line.495"></a>
+<span class="sourceLineNo">496</span> assertTrue(e.getCause().getMessage().contains("Permission denied"));<a name="line.496"></a>
+<span class="sourceLineNo">497</span> throw e;<a name="line.497"></a>
+<span class="sourceLineNo">498</span> } finally {<a name="line.498"></a>
+<span class="sourceLineNo">499</span> UTIL.deleteTable(tableName);<a name="line.499"></a>
+<span class="sourceLineNo">500</span> }<a name="line.500"></a>
+<span class="sourceLineNo">501</span> }<a name="line.501"></a>
+<span class="sourceLineNo">502</span><a name="line.502"></a>
+<span class="sourceLineNo">503</span> @Test<a name="line.503"></a>
+<span class="sourceLineNo">504</span> public void testArchiveOnTableDelete() throws Exception {<a name="line.504"></a>
+<span class="sourceLineNo">505</span> final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.505"></a>
+<span class="sourceLineNo">506</span> UTIL.createTable(tableName, TEST_FAM);<a name="line.506"></a>
+<span class="sourceLineNo">507</span><a name="line.507"></a>
+<span class="sourceLineNo">508</span> List<HRegion> servingRegions = UTIL.getHBaseCluster().getRegions(tableName);<a name="line.508"></a>
+<span class="sourceLineNo">509</span> // make sure we only have 1 region serving this table<a name="line.509"></a>
+<span class="sourceLineNo">510</span> assertEquals(1, servingRegions.size());<a name="line.510"></a>
+<span class="sourceLineNo">511</span> HRegion region = servingRegions.get(0);<a name="line.511"></a>
+<span class="sourceLineNo">512</span><a name="line.512"></a>
+<span class="sourceLineNo">513</span> // get the parent RS and monitor<a name="line.513"></a>
+<span class="sourceLineNo">514</span> HRegionServer hrs = UTIL.getRSForFirstRegionInTable(tableName);<a name="line.514"></a>
+<span class="sourceLineNo">515</span> FileSystem fs = hrs.getFileSystem();<a name="line.515"></a>
+<span class="sourceLineNo">516</span><a name="line.516"></a>
+<span class="sourceLineNo">517</span> // put some data on the region<a name="line.517"></a>
+<span class="sourceLineNo">518</span> LOG.debug("-------Loading table");<a name="line.518"></a>
+<span class="sourceLineNo">519</span> UTIL.loadRegion(region, TEST_FAM);<a name="line.519"></a>
<span class="sourceLineNo">520</span><a name="line.520"></a>
-<span class="sourceLineNo">521</span> /**<a name="line.521"></a>
-<span class="sourceLineNo">522</span> * Test that the store files are archived when a column family is removed.<a name="line.522"></a>
-<span class="sourceLineNo">523</span> * @throws java.io.IOException if there's a problem creating a table.<a name="line.523"></a>
-<span class="sourceLineNo">524</span> * @throws java.lang.InterruptedException problem getting a RegionServer.<a name="line.524"></a>
-<span class="sourceLineNo">525</span> */<a name="line.525"></a>
-<span class="sourceLineNo">526</span> @Test<a name="line.526"></a>
-<span class="sourceLineNo">527</span> public void testArchiveOnTableFamilyDelete() throws IOException, InterruptedException {<a name="line.527"></a>
-<span class="sourceLineNo">528</span> final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.528"></a>
-<span class="sourceLineNo">529</span> UTIL.createTable(tableName, new byte[][] {TEST_FAM, Bytes.toBytes("fam2")});<a name="line.529"></a>
-<span class="sourceLineNo">530</span><a name="line.530"></a>
-<span class="sourceLineNo">531</span> List<HRegion> servingRegions = UTIL.getHBaseCluster().getRegions(tableName);<a name="line.531"></a>
-<span class="sourceLineNo">532</span> // make sure we only have 1 region serving this table<a name="line.532"></a>
-<span class="sourceLineNo">533</span> assertEquals(1, servingRegions.size());<a name="line.533"></a>
-<span class="sourceLineNo">534</span> HRegion region = servingRegions.get(0);<a name="line.534"></a>
+<span class="sourceLineNo">521</span> // get the hfiles in the region<a name="line.521"></a>
+<span class="sourceLineNo">522</span> List<HRegion> regions = hrs.getRegions(tableName);<a name="line.522"></a>
+<span class="sourceLineNo">523</span> assertEquals("More that 1 region for test table.", 1, regions.size());<a name="line.523"></a>
+<span class="sourceLineNo">524</span><a name="line.524"></a>
+<span class="sourceLineNo">525</span> region = regions.get(0);<a name="line.525"></a>
+<span class="sourceLineNo">526</span> // wait for all the compactions to complete<a name="line.526"></a>
+<span class="sourceLineNo">527</span> region.waitForFlushesAndCompactions();<a name="line.527"></a>
+<span class="sourceLineNo">528</span><a name="line.528"></a>
+<span class="sourceLineNo">529</span> // disable table to prevent new updates<a name="line.529"></a>
+<span class="sourceLineNo">530</span> UTIL.getAdmin().disableTable(tableName);<a name="line.530"></a>
+<span class="sourceLineNo">531</span> LOG.debug("Disabled table");<a name="line.531"></a>
+<span class="sourceLineNo">532</span><a name="line.532"></a>
+<span class="sourceLineNo">533</span> // remove all the files from the archive to get a fair comparison<a name="line.533"></a>
+<span class="sourceLineNo">534</span> clearArchiveDirectory();<a name="line.534"></a>
<span class="sourceLineNo">535</span><a name="line.535"></a>
-<span class="sourceLineNo">536</span> // get the parent RS and monitor<a name="line.536"></a>
-<span class="sourceLineNo">537</span> HRegionServer hrs = UTIL.getRSForFirstRegionInTable(tableName);<a name="line.537"></a>
-<span class="sourceLineNo">538</span> FileSystem fs = hrs.getFileSystem();<a name="line.538"></a>
+<span class="sourceLineNo">536</span> // then get the current store files<a name="line.536"></a>
+<span class="sourceLineNo">537</span> byte[][]columns = region.getTableDescriptor().getColumnFamilyNames().toArray(new byte[0][]);<a name="line.537"></a>
+<span class="sourceLineNo">538</span> List<String> storeFiles = region.getStoreFileList(columns);<a name="line.538"></a>
<span class="sourceLineNo">539</span><a name="line.539"></a>
-<span class="sourceLineNo">540</span> // put some data on the region<a name="line.540"></a>
-<span class="sourceLineNo">541</span> LOG.debug("-------Loading table");<a name="line.541"></a>
-<span class="sourceLineNo">542</span> UTIL.loadRegion(region, TEST_FAM);<a name="line.542"></a>
+<span class="sourceLineNo">540</span> // then delete the table so the hfiles get archived<a name="line.540"></a>
+<span class="sourceLineNo">541</span> UTIL.deleteTable(tableName);<a name="line.541"></a>
+<span class="sourceLineNo">542</span> LOG.debug("Deleted table");<a name="line.542"></a>
<span class="sourceLineNo">543</span><a name="line.543"></a>
-<span class="sourceLineNo">544</span> // get the hfiles in the region<a name="line.544"></a>
-<span class="sourceLineNo">545</span> List<HRegion> regions = hrs.getRegions(tableName);<a name="line.545"></a>
-<span class="sourceLineNo">546</span> assertEquals("More that 1 region for test table.", 1, regions.size());<a name="line.546"></a>
-<span class="sourceLineNo">547</span><a name="line.547"></a>
-<span class="sourceLineNo">548</span> region = regions.get(0);<a name="line.548"></a>
-<span class="sourceLineNo">549</span> // wait for all the compactions to complete<a name="line.549"></a>
-<span class="sourceLineNo">550</span> region.waitForFlushesAndCompactions();<a name="line.550"></a>
-<span class="sourceLineNo">551</span><a name="line.551"></a>
-<span class="sourceLineNo">552</span> // disable table to prevent new updates<a name="line.552"></a>
-<span class="sourceLineNo">553</span> UTIL.getAdmin().disableTable(tableName);<a name="line.553"></a>
-<span class="sourceLineNo">554</span> LOG.debug("Disabled table");<a name="line.554"></a>
-<span class="sourceLineNo">555</span><a name="line.555"></a>
-<span class="sourceLineNo">556</span> // remove all the files from the archive to get a fair comparison<a name="line.556"></a>
-<span class="sourceLineNo">557</span> clearArchiveDirectory();<a name="line.557"></a>
-<span class="sourceLineNo">558</span><a name="line.558"></a>
-<span class="sourceLineNo">559</span> // then get the current store files<a name="line.559"></a>
-<span class="sourceLineNo">560</span> byte[][]columns = region.getTableDescriptor().getColumnFamilyNames().toArray(new byte[0][]);<a name="line.560"></a>
... 1879 lines suppressed ...