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 2021/05/04 20:19:23 UTC
[hbase-site] branch asf-site updated: Published site at
432d14147495cbac82f68310a55b2007cde44891.
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 a80a89e Published site at 432d14147495cbac82f68310a55b2007cde44891.
a80a89e is described below
commit a80a89ef589500be6043650b6e49bb5f548eb05d
Author: jenkins <bu...@apache.org>
AuthorDate: Tue May 4 20:19:08 2021 +0000
Published site at 432d14147495cbac82f68310a55b2007cde44891.
---
acid-semantics.html | 2 +-
apache_hbase_reference_guide.pdf | 4 +-
book.html | 2 +-
bulk-loads.html | 2 +-
checkstyle-aggregate.html | 14 +-
checkstyle.rss | 114 +-
coc.html | 2 +-
dependencies.html | 2 +-
dependency-convergence.html | 2 +-
dependency-info.html | 2 +-
dependency-management.html | 2 +-
devapidocs/index-all.html | 2 +-
.../apache/hadoop/hbase/class-use/TableName.html | 6 +-
...ignmentManager.DeadServerMetricRegionChore.html | 6 +-
.../AssignmentManager.RegionInTransitionChore.html | 6 +-
.../AssignmentManager.RegionInTransitionStat.html | 40 +-
...AssignmentManager.RegionMetaLoadingVisitor.html | 6 +-
.../hbase/master/assignment/AssignmentManager.html | 112 +-
.../assignment/RegionStates.RegionFailedOpen.html | 22 +-
.../hbase/master/assignment/RegionStates.html | 44 +-
.../master/balancer/StochasticLoadBalancer.html | 24 +-
.../CatalogJanitor.SplitParentFirstComparator.html | 8 +-
.../hbase/master/janitor/CatalogJanitor.html | 22 +-
...ignmentManager.DeadServerMetricRegionChore.html | 2400 ++++++++++----------
.../AssignmentManager.RegionInTransitionChore.html | 2400 ++++++++++----------
.../AssignmentManager.RegionInTransitionStat.html | 2400 ++++++++++----------
...AssignmentManager.RegionMetaLoadingVisitor.html | 2400 ++++++++++----------
.../hbase/master/assignment/AssignmentManager.html | 2400 ++++++++++----------
.../assignment/RegionStates.RegionFailedOpen.html | 442 ++--
.../RegionStates.RegionStateStampComparator.html | 442 ++--
.../hbase/master/assignment/RegionStates.html | 442 ++--
.../master/balancer/StochasticLoadBalancer.html | 16 +-
.../CatalogJanitor.SplitParentFirstComparator.html | 568 +++--
.../hbase/master/janitor/CatalogJanitor.html | 568 +++--
downloads.html | 2 +-
export_control.html | 2 +-
index.html | 2 +-
issue-tracking.html | 2 +-
mail-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 +-
project-summary.html | 2 +-
pseudo-distributed.html | 2 +-
replication.html | 2 +-
resources.html | 2 +-
source-repository.html | 2 +-
sponsors.html | 2 +-
supportingprojects.html | 2 +-
team-list.html | 2 +-
testapidocs/index-all.html | 4 +
.../apache/hadoop/hbase/test/package-summary.html | 4 +-
.../org/apache/hadoop/hbase/test/package-tree.html | 4 +-
.../hadoop/hbase/test/util/package-frame.html | 14 +
.../hbase/test/{ => util}/package-summary.html | 42 +-
.../hadoop/hbase/test/{ => util}/package-tree.html | 44 +-
.../package-use.html} | 55 +-
.../hadoop/hbase/test/util/warc/package-frame.html | 14 +
.../test/{ => util/warc}/package-summary.html | 42 +-
.../hbase/test/{ => util/warc}/package-tree.html | 44 +-
.../warc/package-use.html} | 55 +-
.../hbase/testclassification/package-summary.html | 4 +-
.../hbase/testclassification/package-tree.html | 4 +-
testapidocs/overview-frame.html | 2 +
testapidocs/overview-summary.html | 8 +
testapidocs/overview-tree.html | 2 +
testapidocs/package-list | 2 +
testdevapidocs/allclasses-frame.html | 17 +
testdevapidocs/allclasses-noframe.html | 17 +
testdevapidocs/constant-values.html | 113 +
testdevapidocs/index-all.html | 542 +++++
.../apache/hadoop/hbase/IntegrationTestBase.html | 2 +-
.../hbase/class-use/IntegrationTestBase.html | 14 +-
.../org/apache/hadoop/hbase/package-tree.html | 18 +-
.../hadoop/hbase/procedure/package-tree.html | 8 +-
.../hadoop/hbase/procedure2/package-tree.html | 4 +-
.../hadoop/hbase/regionserver/package-tree.html | 4 +-
...oadAndVerify.WALSearcher.WALMapperSearcher.html | 4 +-
.../IntegrationTestLoadCommonCrawl.Counts.html | 358 +++
...rationTestLoadCommonCrawl.HBaseKeyWritable.html | 797 +++++++
...ionTestLoadCommonCrawl.Loader.LoaderMapper.html | 442 ++++
... => IntegrationTestLoadCommonCrawl.Loader.html} | 194 +-
...nTestLoadCommonCrawl.OneFilePerMapperSFIF.html} | 168 +-
...onTestLoadCommonCrawl.Verify.VerifyMapper.html} | 122 +-
... => IntegrationTestLoadCommonCrawl.Verify.html} | 176 +-
.../hbase/test/IntegrationTestLoadCommonCrawl.html | 835 +++++++
.../hadoop/hbase/test/IntegrationTestMonkeys.html | 4 +-
.../IntegrationTestLoadCommonCrawl.Counts.html | 174 ++
...rationTestLoadCommonCrawl.HBaseKeyWritable.html | 167 ++
...ionTestLoadCommonCrawl.Loader.LoaderMapper.html | 125 +
.../IntegrationTestLoadCommonCrawl.Loader.html | 125 +
...onTestLoadCommonCrawl.OneFilePerMapperSFIF.html | 125 +
...ionTestLoadCommonCrawl.Verify.VerifyMapper.html | 125 +
.../IntegrationTestLoadCommonCrawl.Verify.html | 125 +
.../class-use/IntegrationTestLoadCommonCrawl.html | 125 +
.../apache/hadoop/hbase/test/package-frame.html | 8 +
.../apache/hadoop/hbase/test/package-summary.html | 58 +-
.../org/apache/hadoop/hbase/test/package-tree.html | 14 +-
.../org/apache/hadoop/hbase/test/package-use.html | 6 +
.../org/apache/hadoop/hbase/test/util/CRC64.html | 213 +-
.../hadoop/hbase/test/util/class-use/CRC64.html | 125 +
.../hadoop/hbase/test/util/package-frame.html | 20 +
.../hadoop/hbase/test/util}/package-summary.html | 61 +-
.../hadoop/hbase/test/util}/package-tree.html | 54 +-
.../apache/hadoop/hbase/test/util/package-use.html | 55 +-
.../warc/WARCFileReader.CountingInputStream.html | 363 +++
.../hbase/test/util/warc/WARCFileReader.html | 493 ++++
.../warc/WARCFileWriter.CountingOutputStream.html | 367 +++
.../hbase/test/util/warc/WARCFileWriter.html | 658 ++++++
.../test/util/warc/WARCInputFormat.WARCReader.html | 468 ++++
.../hbase/test/util/warc/WARCInputFormat.html | 380 ++++
.../warc/WARCOutputFormat.WARCWriter.html} | 162 +-
.../warc/WARCOutputFormat.html} | 214 +-
.../hbase/test/util/warc/WARCRecord.Header.html | 597 +++++
.../hadoop/hbase/test/util/warc/WARCRecord.html | 562 +++++
.../hadoop/hbase/test/util/warc/WARCWritable.html | 402 ++++
.../WARCFileReader.CountingInputStream.html | 165 ++
.../test/util/warc/class-use/WARCFileReader.html | 165 ++
.../WARCFileWriter.CountingOutputStream.html | 165 ++
.../test/util/warc/class-use/WARCFileWriter.html | 165 ++
.../warc/class-use/WARCInputFormat.WARCReader.html | 125 +
.../test/util/warc/class-use/WARCInputFormat.html | 125 +
.../class-use/WARCOutputFormat.WARCWriter.html | 125 +
.../test/util/warc/class-use/WARCOutputFormat.html | 125 +
.../util/warc/class-use/WARCRecord.Header.html | 184 ++
.../hbase/test/util/warc/class-use/WARCRecord.html | 220 ++
.../test/util/warc/class-use/WARCWritable.html | 245 ++
.../hadoop/hbase/test/util/warc/package-frame.html | 27 +
.../hbase/test/util/warc/package-summary.html | 185 ++
.../hadoop/hbase/test/util/warc/package-tree.html | 188 ++
.../hadoop/hbase/test/util/warc/package-use.html | 207 ++
.../hbase/testclassification/package-summary.html | 4 +-
.../hbase/testclassification/package-tree.html | 4 +-
.../org/apache/hadoop/hbase/wal/package-tree.html | 2 +-
testdevapidocs/overview-frame.html | 2 +
testdevapidocs/overview-summary.html | 8 +
testdevapidocs/overview-tree.html | 34 +
testdevapidocs/package-list | 2 +
.../IntegrationTestLoadCommonCrawl.Counts.html | 910 ++++++++
...rationTestLoadCommonCrawl.HBaseKeyWritable.html | 910 ++++++++
...ionTestLoadCommonCrawl.Loader.LoaderMapper.html | 910 ++++++++
.../IntegrationTestLoadCommonCrawl.Loader.html | 910 ++++++++
...onTestLoadCommonCrawl.OneFilePerMapperSFIF.html | 910 ++++++++
...ionTestLoadCommonCrawl.Verify.VerifyMapper.html | 910 ++++++++
.../IntegrationTestLoadCommonCrawl.Verify.html | 910 ++++++++
.../hbase/test/IntegrationTestLoadCommonCrawl.html | 910 ++++++++
.../org/apache/hadoop/hbase/test/util/CRC64.html | 136 ++
.../warc/WARCFileReader.CountingInputStream.html | 237 ++
.../hbase/test/util/warc/WARCFileReader.html | 237 ++
.../warc/WARCFileWriter.CountingOutputStream.html | 317 +++
.../hbase/test/util/warc/WARCFileWriter.html | 317 +++
.../test/util/warc/WARCInputFormat.WARCReader.html | 206 ++
.../hbase/test/util/warc/WARCInputFormat.html | 206 ++
.../util/warc/WARCOutputFormat.WARCWriter.html | 175 ++
.../hbase/test/util/warc/WARCOutputFormat.html | 175 ++
.../hbase/test/util/warc/WARCRecord.Header.html | 468 ++++
.../hadoop/hbase/test/util/warc/WARCRecord.html | 468 ++++
.../hadoop/hbase/test/util/warc/WARCWritable.html | 168 ++
162 files changed, 30158 insertions(+), 8222 deletions(-)
diff --git a/acid-semantics.html b/acid-semantics.html
index 3b85e4e..5e013b3 100644
--- a/acid-semantics.html
+++ b/acid-semantics.html
@@ -467,7 +467,7 @@
<div class="row">
<p>Copyright ©2007–2021
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2021-05-03</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2021-05-04</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 029765f..1804c8c 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:20210503200552+00'00')
-/CreationDate (D:20210503201710+00'00')
+/ModDate (D:20210504200602+00'00')
+/CreationDate (D:20210504201716+00'00')
>>
endobj
2 0 obj
diff --git a/book.html b/book.html
index 31c6174..e0763c0 100644
--- a/book.html
+++ b/book.html
@@ -46194,7 +46194,7 @@ org/apache/hadoop/hbase/security/access/AccessControlClient.revoke:(Lorg/apache/
<div id="footer">
<div id="footer-text">
Version 3.0.0-SNAPSHOT<br>
-Last updated 2021-05-03 20:05:52 UTC
+Last updated 2021-05-04 20:06:02 UTC
</div>
</div>
<link rel="stylesheet" href="./coderay-asciidoctor.css">
diff --git a/bulk-loads.html b/bulk-loads.html
index 8b30cfa..81278ac 100644
--- a/bulk-loads.html
+++ b/bulk-loads.html
@@ -172,7 +172,7 @@
<div class="row">
<p>Copyright ©2007–2021
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2021-05-03</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2021-05-04</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 0c68bbe..256d34c 100644
--- a/checkstyle-aggregate.html
+++ b/checkstyle-aggregate.html
@@ -166,7 +166,7 @@
<th><img src="images/icon_warning_sml.gif" alt="" /> Warnings</th>
<th><img src="images/icon_error_sml.gif" alt="" /> Errors</th></tr>
<tr class="b">
-<td>4398</td>
+<td>4406</td>
<td>0</td>
<td>0</td>
<td>8912</td></tr></table></div>
@@ -7319,7 +7319,7 @@
<tr class="a">
<td>annotation</td>
<td><a class="externalLink" href="http://checkstyle.sourceforge.net/config_annotation.html#MissingDeprecated">MissingDeprecated</a></td>
-<td>5</td>
+<td>6</td>
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td></tr>
<tr class="b">
<td>blocks</td>
@@ -7418,7 +7418,7 @@
<td><a class="externalLink" href="http://checkstyle.sourceforge.net/config_javadoc.html#JavadocTagContinuationIndentation">JavadocTagContinuationIndentation</a>
<ul>
<li>offset: <tt>"2"</tt></li></ul></td>
-<td>526</td>
+<td>525</td>
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td></tr>
<tr class="b">
<td></td>
@@ -34980,8 +34980,8 @@
<th>Line</th></tr>
<tr class="a">
<td><img src="images/icon_error_sml.gif" alt="" /> Error</td>
-<td>javadoc</td>
-<td>JavadocTagContinuationIndentation</td>
+<td>annotation</td>
+<td>MissingDeprecated</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">
@@ -40314,7 +40314,7 @@
<td>blocks</td>
<td>NeedBraces</td>
<td>'if' construct must use '{}'s.</td>
-<td>731</td></tr></table></div>
+<td>745</td></tr></table></div>
<div class="section">
<h3 id="org.apache.hadoop.hbase.master.assignment.RegionTransitionProcedure.java">org/apache/hadoop/hbase/master/assignment/RegionTransitionProcedure.java</h3>
<table border="0" class="table table-striped">
@@ -73779,7 +73779,7 @@
<div class="row">
<p>Copyright ©2007–2021
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2021-05-03</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2021-05-04</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.rss b/checkstyle.rss
index c1c9a99..c4341ce 100644
--- a/checkstyle.rss
+++ b/checkstyle.rss
@@ -25,7 +25,7 @@ under the License.
<language>en-us</language>
<copyright>©2007 - 2021 The Apache Software Foundation</copyright>
<item>
- <title>File: 4398,
+ <title>File: 4406,
Errors: 8912,
Warnings: 0,
Infos: 0
@@ -5310,6 +5310,20 @@ under the License.
</tr>
<tr>
<td>
+ <a href="https://hbase.apache.org/checkstyle.html#org.apache.hadoop.hbase.test.util.warc.WARCRecord.java">org/apache/hadoop/hbase/test/util/warc/WARCRecord.java</a>
+ </td>
+ <td>
+ 0
+ </td>
+ <td>
+ 0
+ </td>
+ <td>
+ 0
+ </td>
+ </tr>
+ <tr>
+ <td>
<a href="https://hbase.apache.org/checkstyle.html#org.apache.hadoop.hbase.util.LauncherSecurityManager.java">org/apache/hadoop/hbase/util/LauncherSecurityManager.java</a>
</td>
<td>
@@ -19982,6 +19996,20 @@ under the License.
</tr>
<tr>
<td>
+ <a href="https://hbase.apache.org/checkstyle.html#org.apache.hadoop.hbase.test.util.warc.WARCInputFormat.java">org/apache/hadoop/hbase/test/util/warc/WARCInputFormat.java</a>
+ </td>
+ <td>
+ 0
+ </td>
+ <td>
+ 0
+ </td>
+ <td>
+ 0
+ </td>
+ </tr>
+ <tr>
+ <td>
<a href="https://hbase.apache.org/checkstyle.html#org.apache.hadoop.hbase.regionserver.compactions.DateTieredCompactionPolicy.java">org/apache/hadoop/hbase/regionserver/compactions/DateTieredCompactionPolicy.java</a>
</td>
<td>
@@ -20122,6 +20150,20 @@ under the License.
</tr>
<tr>
<td>
+ <a href="https://hbase.apache.org/checkstyle.html#org.apache.hadoop.hbase.test.util.warc.WARCWritable.java">org/apache/hadoop/hbase/test/util/warc/WARCWritable.java</a>
+ </td>
+ <td>
+ 0
+ </td>
+ <td>
+ 0
+ </td>
+ <td>
+ 0
+ </td>
+ </tr>
+ <tr>
+ <td>
<a href="https://hbase.apache.org/checkstyle.html#org.apache.hadoop.hbase.regionserver.DisabledRegionSplitPolicy.java">org/apache/hadoop/hbase/regionserver/DisabledRegionSplitPolicy.java</a>
</td>
<td>
@@ -28536,6 +28578,20 @@ under the License.
</tr>
<tr>
<td>
+ <a href="https://hbase.apache.org/checkstyle.html#org.apache.hadoop.hbase.test.IntegrationTestLoadCommonCrawl.java">org/apache/hadoop/hbase/test/IntegrationTestLoadCommonCrawl.java</a>
+ </td>
+ <td>
+ 0
+ </td>
+ <td>
+ 0
+ </td>
+ <td>
+ 0
+ </td>
+ </tr>
+ <tr>
+ <td>
<a href="https://hbase.apache.org/checkstyle.html#org.apache.hadoop.hbase.ConnectionRule.java">org/apache/hadoop/hbase/ConnectionRule.java</a>
</td>
<td>
@@ -34570,6 +34626,20 @@ under the License.
</tr>
<tr>
<td>
+ <a href="https://hbase.apache.org/checkstyle.html#org.apache.hadoop.hbase.test.util.warc.WARCFileReader.java">org/apache/hadoop/hbase/test/util/warc/WARCFileReader.java</a>
+ </td>
+ <td>
+ 0
+ </td>
+ <td>
+ 0
+ </td>
+ <td>
+ 0
+ </td>
+ </tr>
+ <tr>
+ <td>
<a href="https://hbase.apache.org/checkstyle.html#org.apache.hadoop.hbase.util.JVMClusterUtil.java">org/apache/hadoop/hbase/util/JVMClusterUtil.java</a>
</td>
<td>
@@ -43908,6 +43978,20 @@ under the License.
</tr>
<tr>
<td>
+ <a href="https://hbase.apache.org/checkstyle.html#org.apache.hadoop.hbase.test.util.CRC64.java">org/apache/hadoop/hbase/test/util/CRC64.java</a>
+ </td>
+ <td>
+ 0
+ </td>
+ <td>
+ 0
+ </td>
+ <td>
+ 0
+ </td>
+ </tr>
+ <tr>
+ <td>
<a href="https://hbase.apache.org/checkstyle.html#org.apache.hadoop.hbase.client.ClientSideRegionScanner.java">org/apache/hadoop/hbase/client/ClientSideRegionScanner.java</a>
</td>
<td>
@@ -55318,6 +55402,20 @@ under the License.
</tr>
<tr>
<td>
+ <a href="https://hbase.apache.org/checkstyle.html#org.apache.hadoop.hbase.test.util.warc.WARCFileWriter.java">org/apache/hadoop/hbase/test/util/warc/WARCFileWriter.java</a>
+ </td>
+ <td>
+ 0
+ </td>
+ <td>
+ 0
+ </td>
+ <td>
+ 0
+ </td>
+ </tr>
+ <tr>
+ <td>
<a href="https://hbase.apache.org/checkstyle.html#org.apache.hadoop.hbase.regionserver.TestRegionSplitPolicy.java">org/apache/hadoop/hbase/regionserver/TestRegionSplitPolicy.java</a>
</td>
<td>
@@ -59756,6 +59854,20 @@ under the License.
</tr>
<tr>
<td>
+ <a href="https://hbase.apache.org/checkstyle.html#org.apache.hadoop.hbase.test.util.warc.WARCOutputFormat.java">org/apache/hadoop/hbase/test/util/warc/WARCOutputFormat.java</a>
+ </td>
+ <td>
+ 0
+ </td>
+ <td>
+ 0
+ </td>
+ <td>
+ 0
+ </td>
+ </tr>
+ <tr>
+ <td>
<a href="https://hbase.apache.org/checkstyle.html#org.apache.hadoop.hbase.io.hfile.BlockType.java">org/apache/hadoop/hbase/io/hfile/BlockType.java</a>
</td>
<td>
diff --git a/coc.html b/coc.html
index 45368e0..99034a3 100644
--- a/coc.html
+++ b/coc.html
@@ -241,7 +241,7 @@ email to <a class="externalLink" href="mailto:private@hbase.apache.org">the priv
<div class="row">
<p>Copyright ©2007–2021
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2021-05-03</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2021-05-04</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 9d20d1d..8d9fd0b 100644
--- a/dependencies.html
+++ b/dependencies.html
@@ -313,7 +313,7 @@
<div class="row">
<p>Copyright ©2007–2021
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2021-05-03</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2021-05-04</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 ccc2f05..88a126a 100644
--- a/dependency-convergence.html
+++ b/dependency-convergence.html
@@ -824,7 +824,7 @@
<div class="row">
<p>Copyright ©2007–2021
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2021-05-03</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2021-05-04</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 b975385..359255b 100644
--- a/dependency-info.html
+++ b/dependency-info.html
@@ -194,7 +194,7 @@
<div class="row">
<p>Copyright ©2007–2021
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2021-05-03</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2021-05-04</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 0703673..458f5ec 100644
--- a/dependency-management.html
+++ b/dependency-management.html
@@ -1201,7 +1201,7 @@
<div class="row">
<p>Copyright ©2007–2021
<a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2021-05-03</li>
+All rights reserved. <li id="publishDate" class="pull-right">Last Published: 2021-05-04</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/index-all.html b/devapidocs/index-all.html
index 0c1f43f..425ffa7 100644
--- a/devapidocs/index-all.html
+++ b/devapidocs/index-all.html
@@ -126720,7 +126720,7 @@ service.</div>
<dd>
<div class="block">Reports stochastic load balancer costs to JMX</div>
</dd>
-<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#updateStochasticCosts-org.apache.hadoop.hbase.TableName-java.lang.Double-java.lang.Double:A-">updateStochasticCosts(TableName, Double, Double[])</a></span> - Method in class org.apache.hadoop.hbase.master.balancer.<a href="org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html" title="class in org.apache.hadoop.hbase.master.balancer">StochasticLoadBalancer</a></dt>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#updateStochasticCosts-org.apache.hadoop.hbase.TableName-double-double:A-">updateStochasticCosts(TableName, double, double[])</a></span> - Method in class org.apache.hadoop.hbase.master.balancer.<a href="org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html" title="class in org.apache.hadoop.hbase.master.balancer">StochasticLoadBalancer</a></dt>
<dd>
<div class="block">update costs to JMX</div>
</dd>
diff --git a/devapidocs/org/apache/hadoop/hbase/class-use/TableName.html b/devapidocs/org/apache/hadoop/hbase/class-use/TableName.html
index 5a15980..976c0c1 100644
--- a/devapidocs/org/apache/hadoop/hbase/class-use/TableName.html
+++ b/devapidocs/org/apache/hadoop/hbase/class-use/TableName.html
@@ -6320,9 +6320,9 @@ service.</div>
</tr>
<tr class="altColor">
<td class="colFirst"><code>private void</code></td>
-<td class="colLast"><span class="typeNameLabel">StochasticLoadBalancer.</span><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#updateStochasticCosts-org.apache.hadoop.hbase.TableName-java.lang.Double-java.lang.Double:A-">updateStochasticCosts</a></span>(<a href="../../../../../org/apache/hadoop/hbase/TableName.html" title="class in org.apache.hadoop.hbase">TableName</a> tableName,
- <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang">Double</a> overall,
- <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang">Double</a>[] subCosts)</code>
+<td class="colLast"><span class="typeNameLabel">StochasticLoadBalancer.</span><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#updateStochasticCosts-org.apache.hadoop.hbase.TableName-double-double:A-">updateStochasticCosts</a></span>(<a href="../../../../../org/apache/hadoop/hbase/TableName.html" title="class in org.apache.hadoop.hbase">TableName</a> tableName,
+ double overall,
+ double[] subCosts)</code>
<div class="block">update costs to JMX</div>
</td>
</tr>
diff --git a/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.DeadServerMetricRegionChore.html b/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.DeadServerMetricRegionChore.html
index 27cc939..36288b8 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.DeadServerMetricRegionChore.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.DeadServerMetricRegionChore.html
@@ -127,7 +127,7 @@ var activeTableTab = "activeTableTab";
</dl>
<hr>
<br>
-<pre>private static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1305">AssignmentManager.DeadServerMetricRegionChore</a>
+<pre>private static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1321">AssignmentManager.DeadServerMetricRegionChore</a>
extends <a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureInMemoryChore.html" title="class in org.apache.hadoop.hbase.procedure2">ProcedureInMemoryChore</a><<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a>></pre>
</li>
</ul>
@@ -240,7 +240,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureI
<ul class="blockListLast">
<li class="blockList">
<h4>DeadServerMetricRegionChore</h4>
-<pre>public <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.DeadServerMetricRegionChore.html#line.1307">DeadServerMetricRegionChore</a>(int timeoutMsec)</pre>
+<pre>public <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.DeadServerMetricRegionChore.html#line.1323">DeadServerMetricRegionChore</a>(int timeoutMsec)</pre>
</li>
</ul>
</li>
@@ -257,7 +257,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureI
<ul class="blockListLast">
<li class="blockList">
<h4>periodicExecute</h4>
-<pre>protected void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.DeadServerMetricRegionChore.html#line.1312">periodicExecute</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 void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.DeadServerMetricRegionChore.html#line.1328">periodicExecute</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env)</pre>
<dl>
<dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
<dd><code><a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureInMemoryChore.html#periodicExecute-TEnvironment-">periodicExecute</a></code> in class <code><a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureInMemoryChore.html" title="class in org.apache.hadoop.hbase.procedure2">ProcedureInMemoryChore</a><<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.mas [...]
diff --git a/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionChore.html b/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionChore.html
index 887d650..739665d 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionChore.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionChore.html
@@ -127,7 +127,7 @@ var activeTableTab = "activeTableTab";
</dl>
<hr>
<br>
-<pre>private static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1284">AssignmentManager.RegionInTransitionChore</a>
+<pre>private static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1300">AssignmentManager.RegionInTransitionChore</a>
extends <a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureInMemoryChore.html" title="class in org.apache.hadoop.hbase.procedure2">ProcedureInMemoryChore</a><<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a>></pre>
</li>
</ul>
@@ -240,7 +240,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureI
<ul class="blockListLast">
<li class="blockList">
<h4>RegionInTransitionChore</h4>
-<pre>public <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionChore.html#line.1285">RegionInTransitionChore</a>(int timeoutMsec)</pre>
+<pre>public <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionChore.html#line.1301">RegionInTransitionChore</a>(int timeoutMsec)</pre>
</li>
</ul>
</li>
@@ -257,7 +257,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureI
<ul class="blockListLast">
<li class="blockList">
<h4>periodicExecute</h4>
-<pre>protected void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionChore.html#line.1290">periodicExecute</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 void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionChore.html#line.1306">periodicExecute</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.master.procedure">MasterProcedureEnv</a> env)</pre>
<dl>
<dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
<dd><code><a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureInMemoryChore.html#periodicExecute-TEnvironment-">periodicExecute</a></code> in class <code><a href="../../../../../../org/apache/hadoop/hbase/procedure2/ProcedureInMemoryChore.html" title="class in org.apache.hadoop.hbase.procedure2">ProcedureInMemoryChore</a><<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MasterProcedureEnv.html" title="class in org.apache.hadoop.hbase.mas [...]
diff --git a/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html b/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html
index 8d2a8ad..27093aa 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html
@@ -113,7 +113,7 @@ var activeTableTab = "activeTableTab";
</dl>
<hr>
<br>
-<pre>public static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1368">AssignmentManager.RegionInTransitionStat</a>
+<pre>public static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1384">AssignmentManager.RegionInTransitionStat</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>
</li>
</ul>
@@ -266,7 +266,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>ritThreshold</h4>
-<pre>private final int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1369">ritThreshold</a></pre>
+<pre>private final int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1385">ritThreshold</a></pre>
</li>
</ul>
<a name="ritsOverThreshold">
@@ -275,7 +275,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>ritsOverThreshold</h4>
-<pre>private <a href="https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html?is-external=true" title="class or interface in java.util">HashMap</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="../../../../../../org/apache/hadoop/hbase/master/RegionState.html" title="class in org.apache.hadoop.hbase.master">RegionState</a>> <a href="../../../../../../src-html/org/a [...]
+<pre>private <a href="https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html?is-external=true" title="class or interface in java.util">HashMap</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="../../../../../../org/apache/hadoop/hbase/master/RegionState.html" title="class in org.apache.hadoop.hbase.master">RegionState</a>> <a href="../../../../../../src-html/org/a [...]
</li>
</ul>
<a name="statTimestamp">
@@ -284,7 +284,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>statTimestamp</h4>
-<pre>private long <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1372">statTimestamp</a></pre>
+<pre>private long <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1388">statTimestamp</a></pre>
</li>
</ul>
<a name="oldestRITTime">
@@ -293,7 +293,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>oldestRITTime</h4>
-<pre>private long <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1373">oldestRITTime</a></pre>
+<pre>private long <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1389">oldestRITTime</a></pre>
</li>
</ul>
<a name="totalRITsTwiceThreshold">
@@ -302,7 +302,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>totalRITsTwiceThreshold</h4>
-<pre>private int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1374">totalRITsTwiceThreshold</a></pre>
+<pre>private int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1390">totalRITsTwiceThreshold</a></pre>
</li>
</ul>
<a name="totalRITs">
@@ -311,7 +311,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>totalRITs</h4>
-<pre>private int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1375">totalRITs</a></pre>
+<pre>private int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1391">totalRITs</a></pre>
</li>
</ul>
</li>
@@ -328,7 +328,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>RegionInTransitionStat</h4>
-<pre>public <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1377">RegionInTransitionStat</a>(org.apache.hadoop.conf.Configuration conf)</pre>
+<pre>public <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1393">RegionInTransitionStat</a>(org.apache.hadoop.conf.Configuration conf)</pre>
</li>
</ul>
</li>
@@ -345,7 +345,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getRITThreshold</h4>
-<pre>public int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1382">getRITThreshold</a>()</pre>
+<pre>public int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1398">getRITThreshold</a>()</pre>
</li>
</ul>
<a name="getTimestamp--">
@@ -354,7 +354,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getTimestamp</h4>
-<pre>public long <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1386">getTimestamp</a>()</pre>
+<pre>public long <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1402">getTimestamp</a>()</pre>
</li>
</ul>
<a name="getTotalRITs--">
@@ -363,7 +363,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getTotalRITs</h4>
-<pre>public int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1390">getTotalRITs</a>()</pre>
+<pre>public int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1406">getTotalRITs</a>()</pre>
</li>
</ul>
<a name="getOldestRITTime--">
@@ -372,7 +372,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getOldestRITTime</h4>
-<pre>public long <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1394">getOldestRITTime</a>()</pre>
+<pre>public long <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1410">getOldestRITTime</a>()</pre>
</li>
</ul>
<a name="getTotalRITsOverThreshold--">
@@ -381,7 +381,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getTotalRITsOverThreshold</h4>
-<pre>public int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1398">getTotalRITsOverThreshold</a>()</pre>
+<pre>public int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1414">getTotalRITsOverThreshold</a>()</pre>
</li>
</ul>
<a name="hasRegionsTwiceOverThreshold--">
@@ -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>hasRegionsTwiceOverThreshold</h4>
-<pre>public boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1403">hasRegionsTwiceOverThreshold</a>()</pre>
+<pre>public boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1419">hasRegionsTwiceOverThreshold</a>()</pre>
</li>
</ul>
<a name="hasRegionsOverThreshold--">
@@ -399,7 +399,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>hasRegionsOverThreshold</h4>
-<pre>public boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1407">hasRegionsOverThreshold</a>()</pre>
+<pre>public boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1423">hasRegionsOverThreshold</a>()</pre>
</li>
</ul>
<a name="getRegionOverThreshold--">
@@ -408,7 +408,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getRegionOverThreshold</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/master/RegionState.html" title="class in org.apache.hadoop.hbase.master">RegionState</a>> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1412">getRegionOverThreshold</a>()</pre>
+<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/master/RegionState.html" title="class in org.apache.hadoop.hbase.master">RegionState</a>> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1428">getRegionOverThreshold</a>()</pre>
</li>
</ul>
<a name="isRegionOverThreshold-org.apache.hadoop.hbase.client.RegionInfo-">
@@ -417,7 +417,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>isRegionOverThreshold</h4>
-<pre>public boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1417">isRegionOverThreshold</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo)</pre>
+<pre>public boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1433">isRegionOverThreshold</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo)</pre>
</li>
</ul>
<a name="isRegionTwiceOverThreshold-org.apache.hadoop.hbase.client.RegionInfo-">
@@ -426,7 +426,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>isRegionTwiceOverThreshold</h4>
-<pre>public boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1422">isRegionTwiceOverThreshold</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo)</pre>
+<pre>public boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1438">isRegionTwiceOverThreshold</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo)</pre>
</li>
</ul>
<a name="update-org.apache.hadoop.hbase.master.assignment.AssignmentManager-">
@@ -435,7 +435,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>update</h4>
-<pre>protected void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1434">update</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/AssignmentManager.html" title="class in org.apache.hadoop.hbase.master.assignment">AssignmentManager</a> am)</pre>
+<pre>protected void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1450">update</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/AssignmentManager.html" title="class in org.apache.hadoop.hbase.master.assignment">AssignmentManager</a> am)</pre>
</li>
</ul>
<a name="update-java.util.Collection-long-">
@@ -444,7 +444,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>update</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1448">update</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/master/RegionState.html" title="class in org.apache.hadoop.hbase.master">RegionState</a>> regions,
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html#line.1464">update</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/master/RegionState.html" title="class in org.apache.hadoop.hbase.master">RegionState</a>> regions,
long currentTime)</pre>
</li>
</ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionMetaLoadingVisitor.html b/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionMetaLoadingVisitor.html
index 088d174..f7818e8 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionMetaLoadingVisitor.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionMetaLoadingVisitor.html
@@ -117,7 +117,7 @@ var activeTableTab = "activeTableTab";
</dl>
<hr>
<br>
-<pre>private class <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1555">AssignmentManager.RegionMetaLoadingVisitor</a>
+<pre>private class <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1571">AssignmentManager.RegionMetaLoadingVisitor</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>
implements <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateStore.RegionStateVisitor.html" title="interface in org.apache.hadoop.hbase.master.assignment">RegionStateStore.RegionStateVisitor</a></pre>
</li>
@@ -194,7 +194,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/
<ul class="blockListLast">
<li class="blockList">
<h4>RegionMetaLoadingVisitor</h4>
-<pre>private <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionMetaLoadingVisitor.html#line.1555">RegionMetaLoadingVisitor</a>()</pre>
+<pre>private <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionMetaLoadingVisitor.html#line.1571">RegionMetaLoadingVisitor</a>()</pre>
</li>
</ul>
</li>
@@ -211,7 +211,7 @@ implements <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/
<ul class="blockListLast">
<li class="blockList">
<h4>visitRegionState</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionMetaLoadingVisitor.html#line.1558">visitRegionState</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/Result.html" title="class in org.apache.hadoop.hbase.client">Result</a> result,
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionMetaLoadingVisitor.html#line.1574">visitRegionState</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/Result.html" title="class in org.apache.hadoop.hbase.client">Result</a> result,
<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo,
<a href="../../../../../../org/apache/hadoop/hbase/master/RegionState.State.html" title="enum in org.apache.hadoop.hbase.master">RegionState.State</a> state,
<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> regionLocation,
diff --git a/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html b/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html
index d7c1a12..6dd3ff6 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html
@@ -1374,7 +1374,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>STATES_EXPECTED_ON_OPEN</h4>
-<pre>private static final <a href="../../../../../../org/apache/hadoop/hbase/master/RegionState.State.html" title="enum in org.apache.hadoop.hbase.master">RegionState.State</a>[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1784">STATES_EXPECTED_ON_OPEN</a></pre>
+<pre>private static final <a href="../../../../../../org/apache/hadoop/hbase/master/RegionState.State.html" title="enum in org.apache.hadoop.hbase.master">RegionState.State</a>[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1800">STATES_EXPECTED_ON_OPEN</a></pre>
</li>
</ul>
<a name="STATES_EXPECTED_ON_CLOSING">
@@ -1383,7 +1383,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>STATES_EXPECTED_ON_CLOSING</h4>
-<pre>private static final <a href="../../../../../../org/apache/hadoop/hbase/master/RegionState.State.html" title="enum in org.apache.hadoop.hbase.master">RegionState.State</a>[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1789">STATES_EXPECTED_ON_CLOSING</a></pre>
+<pre>private static final <a href="../../../../../../org/apache/hadoop/hbase/master/RegionState.State.html" title="enum in org.apache.hadoop.hbase.master">RegionState.State</a>[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1805">STATES_EXPECTED_ON_CLOSING</a></pre>
</li>
</ul>
<a name="STATES_EXPECTED_ON_CLOSED">
@@ -1392,7 +1392,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>STATES_EXPECTED_ON_CLOSED</h4>
-<pre>private static final <a href="../../../../../../org/apache/hadoop/hbase/master/RegionState.State.html" title="enum in org.apache.hadoop.hbase.master">RegionState.State</a>[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1796">STATES_EXPECTED_ON_CLOSED</a></pre>
+<pre>private static final <a href="../../../../../../org/apache/hadoop/hbase/master/RegionState.State.html" title="enum in org.apache.hadoop.hbase.master">RegionState.State</a>[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1812">STATES_EXPECTED_ON_CLOSED</a></pre>
</li>
</ul>
<a name="STATES_EXPECTED_ON_ASSIGN">
@@ -1401,7 +1401,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>STATES_EXPECTED_ON_ASSIGN</h4>
-<pre>private static final <a href="../../../../../../org/apache/hadoop/hbase/master/RegionState.State.html" title="enum in org.apache.hadoop.hbase.master">RegionState.State</a>[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1803">STATES_EXPECTED_ON_ASSIGN</a></pre>
+<pre>private static final <a href="../../../../../../org/apache/hadoop/hbase/master/RegionState.State.html" title="enum in org.apache.hadoop.hbase.master">RegionState.State</a>[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1819">STATES_EXPECTED_ON_ASSIGN</a></pre>
</li>
</ul>
<a name="STATES_EXPECTED_ON_UNASSIGN_OR_MOVE">
@@ -1410,7 +1410,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>STATES_EXPECTED_ON_UNASSIGN_OR_MOVE</h4>
-<pre>private static final <a href="../../../../../../org/apache/hadoop/hbase/master/RegionState.State.html" title="enum in org.apache.hadoop.hbase.master">RegionState.State</a>[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1806">STATES_EXPECTED_ON_UNASSIGN_OR_MOVE</a></pre>
+<pre>private static final <a href="../../../../../../org/apache/hadoop/hbase/master/RegionState.State.html" title="enum in org.apache.hadoop.hbase.master">RegionState.State</a>[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1822">STATES_EXPECTED_ON_UNASSIGN_OR_MOVE</a></pre>
</li>
</ul>
<a name="pendingAssignQueue">
@@ -1419,7 +1419,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>pendingAssignQueue</h4>
-<pre>private final <a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html?is-external=true" title="class or interface in java.util">ArrayList</a><<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/AssignmentManager.html#line.2012">pendingAssignQueue</a></pre>
+<pre>private final <a href="https://docs.oracle.com/javase/8/docs/api/java/util/ArrayList.html?is-external=true" title="class or interface in java.util">ArrayList</a><<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/AssignmentManager.html#line.2028">pendingAssignQueue</a></pre>
</li>
</ul>
<a name="assignQueueLock">
@@ -1428,7 +1428,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>assignQueueLock</h4>
-<pre>private final <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/ReentrantLock.html?is-external=true" title="class or interface in java.util.concurrent.locks">ReentrantLock</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2013">assignQueueLock</a></pre>
+<pre>private final <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/ReentrantLock.html?is-external=true" title="class or interface in java.util.concurrent.locks">ReentrantLock</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2029">assignQueueLock</a></pre>
</li>
</ul>
<a name="assignQueueFullCond">
@@ -1437,7 +1437,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>assignQueueFullCond</h4>
-<pre>private final <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Condition.html?is-external=true" title="class or interface in java.util.concurrent.locks">Condition</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2014">assignQueueFullCond</a></pre>
+<pre>private final <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/Condition.html?is-external=true" title="class or interface in java.util.concurrent.locks">Condition</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2030">assignQueueFullCond</a></pre>
</li>
</ul>
</li>
@@ -2335,7 +2335,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>updateRegionMergeTransition</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1138">updateRegionMergeTransition</a>(<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName,
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1154">updateRegionMergeTransition</a>(<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 state,
<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> merged,
<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> hriA,
@@ -2353,7 +2353,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>reportOnlineRegions</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1181">reportOnlineRegions</a>(<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName,
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1197">reportOnlineRegions</a>(<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName,
<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Set.html?is-external=true" title="class or interface in java.util">Set</a><byte[]> regionNames)</pre>
<div class="block">The master will call this method when the RS send the regionServerReport(). The report will
contains the "online regions". This method will check the the online regions against the
@@ -2371,7 +2371,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>closeRegionSilently</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1223">closeRegionSilently</a>(<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> sn,
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1239">closeRegionSilently</a>(<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> sn,
byte[] regionName)</pre>
<div class="block">Close <code>regionName</code> on <code>sn</code> silently and immediately without
using a Procedure or going via hbase:meta. For case where a RegionServer's hosting
@@ -2385,7 +2385,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>checkOnlineRegionsReport</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1238">checkOnlineRegionsReport</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/ServerStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">ServerStateNode</a> serverNode,
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1254">checkOnlineRegionsReport</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/ServerStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">ServerStateNode</a> serverNode,
<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Set.html?is-external=true" title="class or interface in java.util">Set</a><byte[]> regionNames)</pre>
<div class="block">Check that what the RegionServer reports aligns with the Master's image.
If disagreement, we will tell the RegionServer to expediently close
@@ -2398,7 +2398,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>computeRegionInTransitionStat</h4>
-<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html" title="class in org.apache.hadoop.hbase.master.assignment">AssignmentManager.RegionInTransitionStat</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1362">computeRegionInTransitionStat</a>()</pre>
+<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html" title="class in org.apache.hadoop.hbase.master.assignment">AssignmentManager.RegionInTransitionStat</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1378">computeRegionInTransitionStat</a>()</pre>
</li>
</ul>
<a name="updateRegionsInTransitionMetrics-org.apache.hadoop.hbase.master.assignment.AssignmentManager.RegionInTransitionStat-">
@@ -2407,7 +2407,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>updateRegionsInTransitionMetrics</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1472">updateRegionsInTransitionMetrics</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html" title="class in org.apache.hadoop.hbase.master.assignment">AssignmentManager.RegionInTransitionStat</a> ritStat)</pre>
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1488">updateRegionsInTransitionMetrics</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html" title="class in org.apache.hadoop.hbase.master.assignment">AssignmentManager.RegionInTransitionStat</a> ritStat)</pre>
</li>
</ul>
<a name="updateDeadServerRegionMetrics-int-int-">
@@ -2416,7 +2416,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>updateDeadServerRegionMetrics</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1478">updateDeadServerRegionMetrics</a>(int deadRegions,
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1494">updateDeadServerRegionMetrics</a>(int deadRegions,
int unknownRegions)</pre>
</li>
</ul>
@@ -2426,7 +2426,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>handleRegionOverStuckWarningThreshold</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1483">handleRegionOverStuckWarningThreshold</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo)</pre>
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1499">handleRegionOverStuckWarningThreshold</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo)</pre>
</li>
</ul>
<a name="joinCluster--">
@@ -2435,7 +2435,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>joinCluster</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1492">joinCluster</a>()
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1508">joinCluster</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>
@@ -2449,7 +2449,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>processOfflineRegions</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1527">processOfflineRegions</a>()</pre>
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1543">processOfflineRegions</a>()</pre>
<div class="block">Create assign procedure for offline regions.
Just follow the old processofflineServersWithOnlineRegions method. Since now we do not need to
deal with dead server any more, we only deal with the regions in OFFLINE state in this method.
@@ -2465,7 +2465,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>loadRegionFromMeta</h4>
-<pre>public <a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1609">loadRegionFromMeta</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> regionEncodedName)
+<pre>public <a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1625">loadRegionFromMeta</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> regionEncodedName)
throws <a href="../../../../../../org/apache/hadoop/hbase/UnknownRegionException.html" title="class in org.apache.hadoop.hbase">UnknownRegionException</a></pre>
<div class="block">Query META if the given <code>RegionInfo</code> exists, adding to
<code>AssignmentManager.regionStateStore</code> cache if the region is found in META.</div>
@@ -2488,7 +2488,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>loadMeta</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1621">loadMeta</a>()
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1637">loadMeta</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>
@@ -2502,7 +2502,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>checkMetaLoaded</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1633">checkMetaLoaded</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> hri)
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1649">checkMetaLoaded</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> hri)
throws <a href="../../../../../../org/apache/hadoop/hbase/PleaseHoldException.html" title="class in org.apache.hadoop.hbase">PleaseHoldException</a></pre>
<div class="block">Used to check if the meta loading is done.
<p/>
@@ -2521,7 +2521,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getNumRegionsOpened</h4>
-<pre>public int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1648">getNumRegionsOpened</a>()</pre>
+<pre>public int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1664">getNumRegionsOpened</a>()</pre>
</li>
</ul>
<a name="submitServerCrash-org.apache.hadoop.hbase.ServerName-boolean-boolean-">
@@ -2530,7 +2530,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>submitServerCrash</h4>
-<pre>public long <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1665">submitServerCrash</a>(<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName,
+<pre>public long <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1681">submitServerCrash</a>(<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName,
boolean shouldSplitWal,
boolean force)</pre>
<div class="block">Usually run by the Master in reaction to server crash during normal processing.
@@ -2555,7 +2555,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>offlineRegion</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1720">offlineRegion</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo)</pre>
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1736">offlineRegion</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo)</pre>
</li>
</ul>
<a name="onlineRegion-org.apache.hadoop.hbase.client.RegionInfo-org.apache.hadoop.hbase.ServerName-">
@@ -2564,7 +2564,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>onlineRegion</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1728">onlineRegion</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo,
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1744">onlineRegion</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo,
<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName)</pre>
</li>
</ul>
@@ -2574,7 +2574,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getSnapShotOfAssignment</h4>
-<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.html?is-external=true" title="class or interface in java.util">Map</a><<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>,<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="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.ht [...]
+<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.html?is-external=true" title="class or interface in java.util">Map</a><<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>,<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="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.ht [...]
</li>
</ul>
<a name="getReopenStatus-org.apache.hadoop.hbase.TableName-">
@@ -2583,7 +2583,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getReopenStatus</h4>
-<pre>public <a href="../../../../../../org/apache/hadoop/hbase/util/Pair.html" title="class in org.apache.hadoop.hbase.util">Pair</a><<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang">Integer</a>,<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang">Integer</a>> <a href="../../../../../../src-html/org/apache/hadoop [...]
+<pre>public <a href="../../../../../../org/apache/hadoop/hbase/util/Pair.html" title="class in org.apache.hadoop.hbase.util">Pair</a><<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang">Integer</a>,<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Integer.html?is-external=true" title="class or interface in java.lang">Integer</a>> <a href="../../../../../../src-html/org/apache/hadoop [...]
<div class="block">Used by the client (via master) to identify if all regions have the schema updates</div>
<dl>
<dt><span class="returnLabel">Returns:</span></dt>
@@ -2597,7 +2597,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>hasRegionsInTransition</h4>
-<pre>public boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1762">hasRegionsInTransition</a>()</pre>
+<pre>public boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1778">hasRegionsInTransition</a>()</pre>
</li>
</ul>
<a name="getRegionsInTransition--">
@@ -2606,7 +2606,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getRegionsInTransition</h4>
-<pre>public <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="../../../../../../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/AssignmentManager.html#line.1766">getRegionsInTransition</a>()</pre>
+<pre>public <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="../../../../../../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/AssignmentManager.html#line.1782">getRegionsInTransition</a>()</pre>
</li>
</ul>
<a name="getAssignedRegions--">
@@ -2615,7 +2615,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getAssignedRegions</h4>
-<pre>public <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="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1770">getAssignedRegions</a>()</pre>
+<pre>public <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="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1786">getAssignedRegions</a>()</pre>
</li>
</ul>
<a name="getRegionInfo-byte:A-">
@@ -2624,7 +2624,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getRegionInfo</h4>
-<pre>public <a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1774">getRegionInfo</a>(byte[] regionName)</pre>
+<pre>public <a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1790">getRegionInfo</a>(byte[] regionName)</pre>
</li>
</ul>
<a name="transitStateAndUpdate-org.apache.hadoop.hbase.master.assignment.RegionStateNode-org.apache.hadoop.hbase.master.RegionState.State-org.apache.hadoop.hbase.master.RegionState.State...-">
@@ -2633,7 +2633,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>transitStateAndUpdate</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1813">transitStateAndUpdate</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode,
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1829">transitStateAndUpdate</a>(<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/master/RegionState.State.html" title="enum in org.apache.hadoop.hbase.master">RegionState.State</a> newState,
<a href="../../../../../../org/apache/hadoop/hbase/master/RegionState.State.html" title="enum in org.apache.hadoop.hbase.master">RegionState.State</a>... expectedStates)
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>
@@ -2649,7 +2649,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>regionOpening</h4>
-<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1830">regionOpening</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode)
+<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1846">regionOpening</a>(<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>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -2663,7 +2663,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>regionFailedOpen</h4>
-<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1843">regionFailedOpen</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode,
+<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1859">regionFailedOpen</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode,
boolean giveUp)
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>
@@ -2678,7 +2678,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>regionClosing</h4>
-<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1867">regionClosing</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode)
+<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1883">regionClosing</a>(<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>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -2692,7 +2692,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>regionOpenedWithoutPersistingToMeta</h4>
-<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1886">regionOpenedWithoutPersistingToMeta</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode)
+<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1902">regionOpenedWithoutPersistingToMeta</a>(<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>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -2706,7 +2706,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>regionClosedWithoutPersistingToMeta</h4>
-<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1894">regionClosedWithoutPersistingToMeta</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode)
+<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1910">regionClosedWithoutPersistingToMeta</a>(<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>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -2720,7 +2720,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>regionClosedAbnormally</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1906">regionClosedAbnormally</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode)
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1922">regionClosedAbnormally</a>(<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>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -2734,7 +2734,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>persistToMeta</h4>
-<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1928">persistToMeta</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode)
+<pre>void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1944">persistToMeta</a>(<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>
<dt><span class="throwsLabel">Throws:</span></dt>
@@ -2748,7 +2748,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>markRegionAsSplit</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1944">markRegionAsSplit</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> parent,
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1960">markRegionAsSplit</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> parent,
<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName,
<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> daughterA,
<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> daughterB)
@@ -2765,7 +2765,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>markRegionAsMerged</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.1985">markRegionAsMerged</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> child,
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2001">markRegionAsMerged</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> child,
<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName,
<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>[] mergeParents)
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>
@@ -2789,7 +2789,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>shouldAssignFavoredNodes</h4>
-<pre>private boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2004">shouldAssignFavoredNodes</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> region)</pre>
+<pre>private boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2020">shouldAssignFavoredNodes</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> region)</pre>
</li>
</ul>
<a name="queueAssign-org.apache.hadoop.hbase.master.assignment.RegionStateNode-">
@@ -2798,7 +2798,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>queueAssign</h4>
-<pre>protected void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2021">queueAssign</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode)</pre>
+<pre>protected void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2037">queueAssign</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode)</pre>
<div class="block">Add the assign operation to the assignment queue.
The pending assignment operation will be processed,
and each region will be assigned by a server using the balancer.</div>
@@ -2810,7 +2810,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>startAssignmentThread</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2038">startAssignmentThread</a>()</pre>
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2054">startAssignmentThread</a>()</pre>
</li>
</ul>
<a name="stopAssignmentThread--">
@@ -2819,7 +2819,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>stopAssignmentThread</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2052">stopAssignmentThread</a>()</pre>
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2068">stopAssignmentThread</a>()</pre>
</li>
</ul>
<a name="assignQueueSignal--">
@@ -2828,7 +2828,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>assignQueueSignal</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2065">assignQueueSignal</a>()</pre>
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2081">assignQueueSignal</a>()</pre>
</li>
</ul>
<a name="waitOnAssignQueue--">
@@ -2837,7 +2837,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>waitOnAssignQueue</h4>
-<pre>private <a href="https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html?is-external=true" title="class or interface in java.util">HashMap</a><<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>,<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a>> <a hre [...]
+<pre>private <a href="https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html?is-external=true" title="class or interface in java.util">HashMap</a><<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>,<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a>> <a hre [...]
</li>
</ul>
<a name="processAssignQueue--">
@@ -2846,7 +2846,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>processAssignQueue</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2102">processAssignQueue</a>()</pre>
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2118">processAssignQueue</a>()</pre>
</li>
</ul>
<a name="containsBogusAssignments-java.util.Map-java.util.List-">
@@ -2855,7 +2855,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>containsBogusAssignments</h4>
-<pre>private boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2165">containsBogusAssignments</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.html?is-external=true" title="class or interface in java.util">Map</a><<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>,<a href="../../../../../../org/apache/h [...]
+<pre>private boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2181">containsBogusAssignments</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.html?is-external=true" title="class or interface in java.util">Map</a><<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>,<a href="../../../../../../org/apache/h [...]
<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="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>> hirs)</pre>
</li>
</ul>
@@ -2865,7 +2865,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>processAssignmentPlans</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2176">processAssignmentPlans</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html?is-external=true" title="class or interface in java.util">HashMap</a><<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>,<a href="../../../../../../org/apach [...]
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2192">processAssignmentPlans</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html?is-external=true" title="class or interface in java.util">HashMap</a><<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>,<a href="../../../../../../org/apach [...]
<a href="https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html?is-external=true" title="class or interface in java.util">HashMap</a><<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>,<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>> retainMap,
<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="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>> hris,
<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="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>> servers)</pre>
@@ -2877,7 +2877,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>acceptPlan</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2214">acceptPlan</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html?is-external=true" title="class or interface in java.util">HashMap</a><<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>,<a href="../../../../../../org/apache/hadoop/hba [...]
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2230">acceptPlan</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html?is-external=true" title="class or interface in java.util">HashMap</a><<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>,<a href="../../../../../../org/apache/hadoop/hba [...]
<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.html?is-external=true" title="class or interface in java.util">Map</a><<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>,<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="../../../../../../org/apache/hadoop/hbase/client/Region [...]
throws <a href="../../../../../../org/apache/hadoop/hbase/HBaseIOException.html" title="class in org.apache.hadoop.hbase">HBaseIOException</a></pre>
<dl>
@@ -2892,7 +2892,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>addToPendingAssignment</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2250">addToPendingAssignment</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html?is-external=true" title="class or interface in java.util">HashMap</a><<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>,<a href="../../../../../../org/apach [...]
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2266">addToPendingAssignment</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html?is-external=true" title="class or interface in java.util">HashMap</a><<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>,<a href="../../../../../../org/apach [...]
<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/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>> pendingRegions)</pre>
</li>
</ul>
@@ -2902,7 +2902,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getExcludedServersForSystemTable</h4>
-<pre>public <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="../../../../../../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/AssignmentManager.html#line.2266">getExcludedServersForSystemTable</a>()</pre>
+<pre>public <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="../../../../../../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/AssignmentManager.html#line.2282">getExcludedServersForSystemTable</a>()</pre>
<div class="block">Get a list of servers that this region cannot be assigned to.
For system tables, we must assign them to a server with highest version.</div>
</li>
@@ -2913,7 +2913,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getMaster</h4>
-<pre><a href="../../../../../../org/apache/hadoop/hbase/master/MasterServices.html" title="interface in org.apache.hadoop.hbase.master">MasterServices</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2285">getMaster</a>()</pre>
+<pre><a href="../../../../../../org/apache/hadoop/hbase/master/MasterServices.html" title="interface in org.apache.hadoop.hbase.master">MasterServices</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2301">getMaster</a>()</pre>
</li>
</ul>
<a name="getRSReports--">
@@ -2922,7 +2922,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getRSReports</h4>
-<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.html?is-external=true" title="class or interface in java.util">Map</a><<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>,<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Set.html?is-external=true" title="class or interface in java.util">Set</a><byte[]>> <a href="../../../../../../src-html/org/apache/hadoop [...]
+<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.html?is-external=true" title="class or interface in java.util">Map</a><<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>,<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Set.html?is-external=true" title="class or interface in java.util">Set</a><byte[]>> <a href="../../../../../../src-html/org/apache/hadoop [...]
<dl>
<dt><span class="returnLabel">Returns:</span></dt>
<dd>a snapshot of rsReports</dd>
@@ -2935,7 +2935,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>getRegionStatesCount</h4>
-<pre>public <a href="../../../../../../org/apache/hadoop/hbase/client/RegionStatesCount.html" title="class in org.apache.hadoop.hbase.client">RegionStatesCount</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2307">getRegionStatesCount</a>(<a href="../../../../../../org/apache/hadoop/hbase/TableName.html" title="class in org.apache.hadoop.hbase">TableName</a> tableName)</pre>
+<pre>public <a href="../../../../../../org/apache/hadoop/hbase/client/RegionStatesCount.html" title="class in org.apache.hadoop.hbase.client">RegionStatesCount</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.html#line.2323">getRegionStatesCount</a>(<a href="../../../../../../org/apache/hadoop/hbase/TableName.html" title="class in org.apache.hadoop.hbase">TableName</a> tableName)</pre>
<div class="block">Provide regions state count for given table.
e.g howmany regions of give table are opened/closed/rit etc</div>
<dl>
diff --git a/devapidocs/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html b/devapidocs/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html
index ab5e641..57d2b33 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html
@@ -113,7 +113,7 @@ var activeTableTab = "activeTableTab";
</dl>
<hr>
<br>
-<pre>public static final class <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.682">RegionStates.RegionFailedOpen</a>
+<pre>public static final class <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.696">RegionStates.RegionFailedOpen</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>
</li>
</ul>
@@ -229,7 +229,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>regionNode</h4>
-<pre>private final <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/RegionStates.RegionFailedOpen.html#line.683">regionNode</a></pre>
+<pre>private final <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/RegionStates.RegionFailedOpen.html#line.697">regionNode</a></pre>
</li>
</ul>
<a name="exception">
@@ -238,7 +238,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>exception</h4>
-<pre>private volatile <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> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html#line.685">exception</a></pre>
+<pre>private volatile <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> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html#line.699">exception</a></pre>
</li>
</ul>
<a name="retries">
@@ -247,7 +247,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>retries</h4>
-<pre>private <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicInteger.html?is-external=true" title="class or interface in java.util.concurrent.atomic">AtomicInteger</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html#line.686">retries</a></pre>
+<pre>private <a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicInteger.html?is-external=true" title="class or interface in java.util.concurrent.atomic">AtomicInteger</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html#line.700">retries</a></pre>
</li>
</ul>
</li>
@@ -264,7 +264,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>RegionFailedOpen</h4>
-<pre>public <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html#line.688">RegionFailedOpen</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode)</pre>
+<pre>public <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html#line.702">RegionFailedOpen</a>(<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>
</li>
@@ -281,7 +281,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getRegionStateNode</h4>
-<pre>public <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/RegionStates.RegionFailedOpen.html#line.692">getRegionStateNode</a>()</pre>
+<pre>public <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/RegionStates.RegionFailedOpen.html#line.706">getRegionStateNode</a>()</pre>
</li>
</ul>
<a name="getRegionInfo--">
@@ -290,7 +290,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getRegionInfo</h4>
-<pre>public <a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html#line.696">getRegionInfo</a>()</pre>
+<pre>public <a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html#line.710">getRegionInfo</a>()</pre>
</li>
</ul>
<a name="incrementAndGetRetries--">
@@ -299,7 +299,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>incrementAndGetRetries</h4>
-<pre>public int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html#line.700">incrementAndGetRetries</a>()</pre>
+<pre>public int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html#line.714">incrementAndGetRetries</a>()</pre>
</li>
</ul>
<a name="getRetries--">
@@ -308,7 +308,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getRetries</h4>
-<pre>public int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html#line.704">getRetries</a>()</pre>
+<pre>public int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html#line.718">getRetries</a>()</pre>
</li>
</ul>
<a name="setException-java.lang.Exception-">
@@ -317,7 +317,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>setException</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html#line.708">setException</a>(<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> exception)</pre>
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html#line.722">setException</a>(<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> exception)</pre>
</li>
</ul>
<a name="getException--">
@@ -326,7 +326,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>getException</h4>
-<pre>public <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> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html#line.712">getException</a>()</pre>
+<pre>public <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> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html#line.726">getException</a>()</pre>
</li>
</ul>
</li>
diff --git a/devapidocs/org/apache/hadoop/hbase/master/assignment/RegionStates.html b/devapidocs/org/apache/hadoop/hbase/master/assignment/RegionStates.html
index 02a4c9f..908eb09 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/assignment/RegionStates.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/assignment/RegionStates.html
@@ -1105,7 +1105,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
since all access to this.servers is under a lock on this.regions.</div>
<dl>
<dt><span class="returnLabel">Returns:</span></dt>
-<dd>A clone of current assignments.</dd>
+<dd>A clone of current open or opening assignments.</dd>
</dl>
</li>
</ul>
@@ -1115,7 +1115,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>isTableDisabled</h4>
-<pre>private boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.606">isTableDisabled</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/TableStateManager.html" title="class in org.apache.hadoop.hbase.master">TableStateManager</a> tableStateManager,
+<pre>private boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.620">isTableDisabled</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/TableStateManager.html" title="class in org.apache.hadoop.hbase.master">TableStateManager</a> tableStateManager,
<a href="../../../../../../org/apache/hadoop/hbase/TableName.html" title="class in org.apache.hadoop.hbase">TableName</a> tableName)</pre>
</li>
</ul>
@@ -1125,7 +1125,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>hasRegionsInTransition</h4>
-<pre>public boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.615">hasRegionsInTransition</a>()</pre>
+<pre>public boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.629">hasRegionsInTransition</a>()</pre>
</li>
</ul>
<a name="isRegionInTransition-org.apache.hadoop.hbase.client.RegionInfo-">
@@ -1134,7 +1134,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>isRegionInTransition</h4>
-<pre>public boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.619">isRegionInTransition</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo)</pre>
+<pre>public boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.633">isRegionInTransition</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo)</pre>
</li>
</ul>
<a name="getRegionTransitionState-org.apache.hadoop.hbase.client.RegionInfo-">
@@ -1143,7 +1143,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getRegionTransitionState</h4>
-<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/RegionState.html" title="class in org.apache.hadoop.hbase.master">RegionState</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.624">getRegionTransitionState</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> hri)</pre>
+<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/RegionState.html" title="class in org.apache.hadoop.hbase.master">RegionState</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.638">getRegionTransitionState</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> hri)</pre>
</li>
</ul>
<a name="getRegionsInTransition--">
@@ -1152,7 +1152,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getRegionsInTransition</h4>
-<pre>public <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="../../../../../../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/RegionStates.html#line.638">getRegionsInTransition</a>()</pre>
+<pre>public <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="../../../../../../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/RegionStates.html#line.652">getRegionsInTransition</a>()</pre>
</li>
</ul>
<a name="getRegionsInTransitionCount--">
@@ -1161,7 +1161,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getRegionsInTransitionCount</h4>
-<pre>public int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.645">getRegionsInTransitionCount</a>()</pre>
+<pre>public int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.659">getRegionsInTransitionCount</a>()</pre>
<div class="block">Get the number of regions in transition.</div>
</li>
</ul>
@@ -1171,7 +1171,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getRegionsStateInTransition</h4>
-<pre>public <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="../../../../../../org/apache/hadoop/hbase/master/RegionState.html" title="class in org.apache.hadoop.hbase.master">RegionState</a>> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.649">getRegionsStateInTransition</a>()</pre>
+<pre>public <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="../../../../../../org/apache/hadoop/hbase/master/RegionState.html" title="class in org.apache.hadoop.hbase.master">RegionState</a>> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.663">getRegionsStateInTransition</a>()</pre>
</li>
</ul>
<a name="getRegionsInTransitionOrderedByTimestamp--">
@@ -1180,7 +1180,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getRegionsInTransitionOrderedByTimestamp</h4>
-<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/util/SortedSet.html?is-external=true" title="class or interface in java.util">SortedSet</a><<a href="../../../../../../org/apache/hadoop/hbase/master/RegionState.html" title="class in org.apache.hadoop.hbase.master">RegionState</a>> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.657">getRegionsInTransitionOrderedByTimestamp</a>()</pre>
+<pre>public <a href="https://docs.oracle.com/javase/8/docs/api/java/util/SortedSet.html?is-external=true" title="class or interface in java.util">SortedSet</a><<a href="../../../../../../org/apache/hadoop/hbase/master/RegionState.html" title="class in org.apache.hadoop.hbase.master">RegionState</a>> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.671">getRegionsInTransitionOrderedByTimestamp</a>()</pre>
</li>
</ul>
<a name="addToOfflineRegions-org.apache.hadoop.hbase.master.assignment.RegionStateNode-">
@@ -1189,7 +1189,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>addToOfflineRegions</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.669">addToOfflineRegions</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a> regionNode)</pre>
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.683">addToOfflineRegions</a>(<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>
<a name="removeFromOfflineRegions-org.apache.hadoop.hbase.client.RegionInfo-">
@@ -1198,7 +1198,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>removeFromOfflineRegions</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.675">removeFromOfflineRegions</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo)</pre>
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.689">removeFromOfflineRegions</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo)</pre>
</li>
</ul>
<a name="addToFailedOpen-org.apache.hadoop.hbase.master.assignment.RegionStateNode-">
@@ -1207,7 +1207,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>addToFailedOpen</h4>
-<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStates.RegionFailedOpen</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.717">addToFailedOpen</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignme [...]
+<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStates.RegionFailedOpen</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.731">addToFailedOpen</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignme [...]
</li>
</ul>
<a name="getFailedOpen-org.apache.hadoop.hbase.client.RegionInfo-">
@@ -1216,7 +1216,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getFailedOpen</h4>
-<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStates.RegionFailedOpen</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.722">getFailedOpen</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> r [...]
+<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStates.RegionFailedOpen.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStates.RegionFailedOpen</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.736">getFailedOpen</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> r [...]
</li>
</ul>
<a name="removeFromFailedOpen-org.apache.hadoop.hbase.client.RegionInfo-">
@@ -1225,7 +1225,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>removeFromFailedOpen</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.726">removeFromFailedOpen</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo)</pre>
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.740">removeFromFailedOpen</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> regionInfo)</pre>
</li>
</ul>
<a name="getRegionFailedOpen--">
@@ -1234,7 +1234,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getRegionFailedOpen</h4>
-<pre>public <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="../../../../../../org/apache/hadoop/hbase/master/RegionState.html" title="class in org.apache.hadoop.hbase.master">RegionState</a>> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.730">getRegionFailedOpen</a>()</pre>
+<pre>public <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="../../../../../../org/apache/hadoop/hbase/master/RegionState.html" title="class in org.apache.hadoop.hbase.master">RegionState</a>> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.744">getRegionFailedOpen</a>()</pre>
</li>
</ul>
<a name="getOrCreateServer-org.apache.hadoop.hbase.ServerName-">
@@ -1243,7 +1243,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getOrCreateServer</h4>
-<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/ServerStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">ServerStateNode</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.749">getOrCreateServer</a>(<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName)</pre>
+<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/ServerStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">ServerStateNode</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.763">getOrCreateServer</a>(<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName)</pre>
<div class="block">Be judicious calling this method. Do it on server register ONLY otherwise
you could mess up online server accounting. TOOD: Review usage and convert
to <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStates.html#getServerNode-org.apache.hadoop.hbase.ServerName-"><code>getServerNode(ServerName)</code></a> where we can.</div>
@@ -1255,7 +1255,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>removeServer</h4>
-<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.756">removeServer</a>(<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName)</pre>
+<pre>public void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.770">removeServer</a>(<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName)</pre>
<div class="block">Called by SCP at end of successful processing.</div>
</li>
</ul>
@@ -1265,7 +1265,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getServerNode</h4>
-<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/ServerStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">ServerStateNode</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.763">getServerNode</a>(<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName)</pre>
+<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/ServerStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">ServerStateNode</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.777">getServerNode</a>(<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName)</pre>
<dl>
<dt><span class="returnLabel">Returns:</span></dt>
<dd>Pertinent ServerStateNode or NULL if none found (Do not make modifications).</dd>
@@ -1278,7 +1278,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>getAverageLoad</h4>
-<pre>public double <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.767">getAverageLoad</a>()</pre>
+<pre>public double <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.781">getAverageLoad</a>()</pre>
</li>
</ul>
<a name="addRegionToServer-org.apache.hadoop.hbase.master.assignment.RegionStateNode-">
@@ -1287,7 +1287,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>addRegionToServer</h4>
-<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/ServerStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">ServerStateNode</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.777">addRegionToServer</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a>&nb [...]
+<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/ServerStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">ServerStateNode</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.791">addRegionToServer</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/RegionStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">RegionStateNode</a>&nb [...]
</li>
</ul>
<a name="removeRegionFromServer-org.apache.hadoop.hbase.ServerName-org.apache.hadoop.hbase.master.assignment.RegionStateNode-">
@@ -1296,7 +1296,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockList">
<li class="blockList">
<h4>removeRegionFromServer</h4>
-<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/ServerStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">ServerStateNode</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.783">removeRegionFromServer</a>(<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName,
+<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/assignment/ServerStateNode.html" title="class in org.apache.hadoop.hbase.master.assignment">ServerStateNode</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/assignment/RegionStates.html#line.797">removeRegionFromServer</a>(<a href="../../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a> serverName,
<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>
@@ -1306,7 +1306,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
<ul class="blockListLast">
<li class="blockList">
<h4>regionNamesToString</h4>
-<pre>public static <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/master/assignment/RegionStates.html#line.793">regionNamesToString</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><byte[]> regions)</pre>
+<pre>public static <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/master/assignment/RegionStates.html#line.807">regionNamesToString</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><byte[]> regions)</pre>
</li>
</ul>
</li>
diff --git a/devapidocs/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html b/devapidocs/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html
index 3404b26..87fc5f2 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html
@@ -204,11 +204,11 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/balancer/BaseL
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#costFunctions">costFunctions</a></span></code> </td>
</tr>
<tr class="rowColor">
-<td class="colFirst"><code>private <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang">Double</a>[]</code></td>
+<td class="colFirst"><code>private double[]</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#curFunctionCosts">curFunctionCosts</a></span></code> </td>
</tr>
<tr class="altColor">
-<td class="colFirst"><code>private <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang">Double</a></code></td>
+<td class="colFirst"><code>private double</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#curOverallCost">curOverallCost</a></span></code> </td>
</tr>
<tr class="rowColor">
@@ -310,7 +310,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/balancer/BaseL
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#TABLE_FUNCTION_SEP">TABLE_FUNCTION_SEP</a></span></code> </td>
</tr>
<tr class="rowColor">
-<td class="colFirst"><code>private <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang">Double</a>[]</code></td>
+<td class="colFirst"><code>private double[]</code></td>
<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#tempFunctionCosts">tempFunctionCosts</a></span></code> </td>
</tr>
</table>
@@ -498,9 +498,9 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/balancer/BaseL
</tr>
<tr id="i25" class="rowColor">
<td class="colFirst"><code>private void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#updateStochasticCosts-org.apache.hadoop.hbase.TableName-java.lang.Double-java.lang.Double:A-">updateStochasticCosts</a></span>(<a href="../../../../../../org/apache/hadoop/hbase/TableName.html" title="class in org.apache.hadoop.hbase">TableName</a> tableName,
- <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang">Double</a> overall,
- <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang">Double</a>[] subCosts)</code>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#updateStochasticCosts-org.apache.hadoop.hbase.TableName-double-double:A-">updateStochasticCosts</a></span>(<a href="../../../../../../org/apache/hadoop/hbase/TableName.html" title="class in org.apache.hadoop.hbase">TableName</a> tableName,
+ double overall,
+ double[] subCosts)</code>
<div class="block">update costs to JMX</div>
</td>
</tr>
@@ -760,7 +760,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/balancer/BaseL
<ul class="blockList">
<li class="blockList">
<h4>curOverallCost</h4>
-<pre>private <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang">Double</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#line.142">curOverallCost</a></pre>
+<pre>private double <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#line.142">curOverallCost</a></pre>
</li>
</ul>
<a name="tempFunctionCosts">
@@ -769,7 +769,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/balancer/BaseL
<ul class="blockList">
<li class="blockList">
<h4>tempFunctionCosts</h4>
-<pre>private <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang">Double</a>[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#line.143">tempFunctionCosts</a></pre>
+<pre>private double[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#line.143">tempFunctionCosts</a></pre>
</li>
</ul>
<a name="curFunctionCosts">
@@ -778,7 +778,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/balancer/BaseL
<ul class="blockList">
<li class="blockList">
<h4>curFunctionCosts</h4>
-<pre>private <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang">Double</a>[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#line.144">curFunctionCosts</a></pre>
+<pre>private double[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#line.144">curFunctionCosts</a></pre>
</li>
</ul>
<a name="localityCandidateGenerator">
@@ -1064,15 +1064,15 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/master/balancer/BaseL
long step)</pre>
</li>
</ul>
-<a name="updateStochasticCosts-org.apache.hadoop.hbase.TableName-java.lang.Double-java.lang.Double:A-">
+<a name="updateStochasticCosts-org.apache.hadoop.hbase.TableName-double-double:A-">
<!-- -->
</a>
<ul class="blockList">
<li class="blockList">
<h4>updateStochasticCosts</h4>
<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/balancer/StochasticLoadBalancer.html#line.559">updateStochasticCosts</a>(<a href="../../../../../../org/apache/hadoop/hbase/TableName.html" title="class in org.apache.hadoop.hbase">TableName</a> tableName,
- <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang">Double</a> overall,
- <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html?is-external=true" title="class or interface in java.lang">Double</a>[] subCosts)</pre>
+ double overall,
+ double[] subCosts)</pre>
<div class="block">update costs to JMX</div>
</li>
</ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.SplitParentFirstComparator.html b/devapidocs/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.SplitParentFirstComparator.html
index e0fb6ca..9fcde38 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.SplitParentFirstComparator.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.SplitParentFirstComparator.html
@@ -117,7 +117,7 @@ var activeTableTab = "activeTableTab";
</dl>
<hr>
<br>
-<pre>static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.275">CatalogJanitor.SplitParentFirstComparator</a>
+<pre>static class <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.271">CatalogJanitor.SplitParentFirstComparator</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>
implements <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html?is-external=true" title="class or interface in java.util">Comparator</a><<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>></pre>
<div class="block">Compare HRegionInfos in a way that has split parents sort BEFORE their daughters.</div>
@@ -215,7 +215,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Comparat
<ul class="blockListLast">
<li class="blockList">
<h4>rowEndKeyComparator</h4>
-<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html?is-external=true" title="class or interface in java.util">Comparator</a><byte[]> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.SplitParentFirstComparator.html#line.276">rowEndKeyComparator</a></pre>
+<pre><a href="https://docs.oracle.com/javase/8/docs/api/java/util/Comparator.html?is-external=true" title="class or interface in java.util">Comparator</a><byte[]> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.SplitParentFirstComparator.html#line.272">rowEndKeyComparator</a></pre>
</li>
</ul>
</li>
@@ -232,7 +232,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Comparat
<ul class="blockListLast">
<li class="blockList">
<h4>SplitParentFirstComparator</h4>
-<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.SplitParentFirstComparator.html#line.275">SplitParentFirstComparator</a>()</pre>
+<pre><a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.SplitParentFirstComparator.html#line.271">SplitParentFirstComparator</a>()</pre>
</li>
</ul>
</li>
@@ -249,7 +249,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Comparat
<ul class="blockListLast">
<li class="blockList">
<h4>compare</h4>
-<pre>public int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.SplitParentFirstComparator.html#line.279">compare</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> left,
+<pre>public int <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.SplitParentFirstComparator.html#line.275">compare</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> left,
<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> right)</pre>
<dl>
<dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
diff --git a/devapidocs/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html b/devapidocs/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html
index df39623..4cff0ea 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html
@@ -507,7 +507,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/ScheduledChore.html"
<ul class="blockList">
<li class="blockList">
<h4>scanForReport</h4>
-<pre>protected <a href="../../../../../../org/apache/hadoop/hbase/master/janitor/Report.html" title="class in org.apache.hadoop.hbase.master.janitor">Report</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.220">scanForReport</a>()
+<pre>protected <a href="../../../../../../org/apache/hadoop/hbase/master/janitor/Report.html" title="class in org.apache.hadoop.hbase.master.janitor">Report</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.216">scanForReport</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">Scan hbase:meta.</div>
<dl>
@@ -524,7 +524,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/ScheduledChore.html"
<ul class="blockList">
<li class="blockList">
<h4>getLastReport</h4>
-<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/janitor/Report.html" title="class in org.apache.hadoop.hbase.master.janitor">Report</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.230">getLastReport</a>()</pre>
+<pre>public <a href="../../../../../../org/apache/hadoop/hbase/master/janitor/Report.html" title="class in org.apache.hadoop.hbase.master.janitor">Report</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.226">getLastReport</a>()</pre>
<dl>
<dt><span class="returnLabel">Returns:</span></dt>
<dd>Returns last published Report that comes of last successful scan of hbase:meta.</dd>
@@ -537,7 +537,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/ScheduledChore.html"
<ul class="blockList">
<li class="blockList">
<h4>cleanMergeRegion</h4>
-<pre>private boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.240">cleanMergeRegion</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> mergedRegion,
+<pre>private boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.236">cleanMergeRegion</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> mergedRegion,
<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="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>> parents)
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">If merged region no longer holds reference to the merge regions, archive merge region on hdfs
@@ -557,7 +557,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/ScheduledChore.html"
<ul class="blockList">
<li class="blockList">
<h4>cleanParent</h4>
-<pre>static boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.305">cleanParent</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/MasterServices.html" title="interface in org.apache.hadoop.hbase.master">MasterServices</a> services,
+<pre>static boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.301">cleanParent</a>(<a href="../../../../../../org/apache/hadoop/hbase/master/MasterServices.html" title="interface in org.apache.hadoop.hbase.master">MasterServices</a> services,
<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> parent,
<a href="../../../../../../org/apache/hadoop/hbase/client/Result.html" title="class in org.apache.hadoop.hbase.client">Result</a> rowContent)
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>
@@ -573,7 +573,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/ScheduledChore.html"
<ul class="blockList">
<li class="blockList">
<h4>cleanParent</h4>
-<pre>private boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.339">cleanParent</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> parent,
+<pre>private boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.335">cleanParent</a>(<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> parent,
<a href="../../../../../../org/apache/hadoop/hbase/client/Result.html" title="class in org.apache.hadoop.hbase.client">Result</a> rowContent)
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">If daughters no longer hold reference to the parents, delete the parent.</div>
@@ -594,7 +594,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/ScheduledChore.html"
<ul class="blockList">
<li class="blockList">
<h4>hasNoReferences</h4>
-<pre>private static boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.349">hasNoReferences</a>(<a href="../../../../../../org/apache/hadoop/hbase/util/Pair.html" title="class in org.apache.hadoop.hbase.util">Pair</a><<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang">Boolean</a>,<a href="https://docs.oracle.com/javase/8/docs/api/java/lang [...]
+<pre>private static boolean <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.345">hasNoReferences</a>(<a href="../../../../../../org/apache/hadoop/hbase/util/Pair.html" title="class in org.apache.hadoop.hbase.util">Pair</a><<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang">Boolean</a>,<a href="https://docs.oracle.com/javase/8/docs/api/java/lang [...]
<dl>
<dt><span class="paramLabel">Parameters:</span></dt>
<dd><code>p</code> - A pair where the first boolean says whether or not the daughter region directory
@@ -611,7 +611,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/ScheduledChore.html"
<ul class="blockList">
<li class="blockList">
<h4>checkDaughterInFs</h4>
-<pre>private static <a href="../../../../../../org/apache/hadoop/hbase/util/Pair.html" title="class in org.apache.hadoop.hbase.util">Pair</a><<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang">Boolean</a>,<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang">Boolean</a>> <a href="../../../../../../src-html/org/apach [...]
+<pre>private static <a href="../../../../../../org/apache/hadoop/hbase/util/Pair.html" title="class in org.apache.hadoop.hbase.util">Pair</a><<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang">Boolean</a>,<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Boolean.html?is-external=true" title="class or interface in java.lang">Boolean</a>> <a href="../../../../../../src-html/org/apach [...]
<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> parent,
<a href="../../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> daughter)
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>
@@ -635,7 +635,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/ScheduledChore.html"
<ul class="blockList">
<li class="blockList">
<h4>getDescriptor</h4>
-<pre>private <a href="../../../../../../org/apache/hadoop/hbase/client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client">TableDescriptor</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.405">getDescriptor</a>(<a href="../../../../../../org/apache/hadoop/hbase/TableName.html" title="class in org.apache.hadoop.hbase">TableName</a> tableName)
+<pre>private <a href="../../../../../../org/apache/hadoop/hbase/client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client">TableDescriptor</a> <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.401">getDescriptor</a>(<a href="../../../../../../org/apache/hadoop/hbase/TableName.html" title="class in org.apache.hadoop.hbase">TableName</a> 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>
@@ -649,7 +649,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/ScheduledChore.html"
<ul class="blockList">
<li class="blockList">
<h4>updateAssignmentManagerMetrics</h4>
-<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.409">updateAssignmentManagerMetrics</a>()</pre>
+<pre>private void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.405">updateAssignmentManagerMetrics</a>()</pre>
</li>
</ul>
<a name="checkLog4jProperties--">
@@ -658,7 +658,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/ScheduledChore.html"
<ul class="blockList">
<li class="blockList">
<h4>checkLog4jProperties</h4>
-<pre>private static void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.420">checkLog4jProperties</a>()</pre>
+<pre>private static void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.416">checkLog4jProperties</a>()</pre>
</li>
</ul>
<a name="main-java.lang.String:A-">
@@ -667,7 +667,7 @@ extends <a href="../../../../../../org/apache/hadoop/hbase/ScheduledChore.html"
<ul class="blockListLast">
<li class="blockList">
<h4>main</h4>
-<pre>public static void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.438">main</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>[] args)
+<pre>public static void <a href="../../../../../../src-html/org/apache/hadoop/hbase/master/janitor/CatalogJanitor.html#line.434">main</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>[] args)
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">For testing against a cluster. Doesn't have a MasterServices context so does not report on good
vs bad servers.</div>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.DeadServerMetricRegionChore.html b/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.DeadServerMetricRegionChore.html
index c00cc30..2c789f6 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.DeadServerMetricRegionChore.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.DeadServerMetricRegionChore.html
@@ -1134,1214 +1134,1230 @@
<span class="sourceLineNo">1126</span> LOG.debug("Split request from " + serverName +<a name="line.1126"></a>
<span class="sourceLineNo">1127</span> ", parent=" + parent + " splitKey=" + Bytes.toStringBinary(splitKey));<a name="line.1127"></a>
<span class="sourceLineNo">1128</span> }<a name="line.1128"></a>
-<span class="sourceLineNo">1129</span> master.getMasterProcedureExecutor().submitProcedure(createSplitProcedure(parent, splitKey));<a name="line.1129"></a>
-<span class="sourceLineNo">1130</span><a name="line.1130"></a>
-<span class="sourceLineNo">1131</span> // If the RS is < 2.0 throw an exception to abort the operation, we are handling the split<a name="line.1131"></a>
-<span class="sourceLineNo">1132</span> if (master.getServerManager().getVersionNumber(serverName) < 0x0200000) {<a name="line.1132"></a>
-<span class="sourceLineNo">1133</span> throw new UnsupportedOperationException(String.format("Split handled by the master: " +<a name="line.1133"></a>
-<span class="sourceLineNo">1134</span> "parent=%s hriA=%s hriB=%s", parent.getShortNameToLog(), hriA, hriB));<a name="line.1134"></a>
-<span class="sourceLineNo">1135</span> }<a name="line.1135"></a>
-<span class="sourceLineNo">1136</span> }<a name="line.1136"></a>
-<span class="sourceLineNo">1137</span><a name="line.1137"></a>
-<span class="sourceLineNo">1138</span> private void updateRegionMergeTransition(final ServerName serverName, final TransitionCode state,<a name="line.1138"></a>
-<span class="sourceLineNo">1139</span> final RegionInfo merged, final RegionInfo hriA, final RegionInfo hriB) throws IOException {<a name="line.1139"></a>
-<span class="sourceLineNo">1140</span> checkMetaLoaded(merged);<a name="line.1140"></a>
-<span class="sourceLineNo">1141</span><a name="line.1141"></a>
-<span class="sourceLineNo">1142</span> if (state != TransitionCode.READY_TO_MERGE) {<a name="line.1142"></a>
-<span class="sourceLineNo">1143</span> throw new UnexpectedStateException("Unsupported merge regionState=" + state +<a name="line.1143"></a>
-<span class="sourceLineNo">1144</span> " for regionA=" + hriA + " regionB=" + hriB + " merged=" + merged +<a name="line.1144"></a>
-<span class="sourceLineNo">1145</span> " maybe an old RS (< 2.0) had the operation in progress");<a name="line.1145"></a>
-<span class="sourceLineNo">1146</span> }<a name="line.1146"></a>
-<span class="sourceLineNo">1147</span><a name="line.1147"></a>
-<span class="sourceLineNo">1148</span> if (!master.isSplitOrMergeEnabled(MasterSwitchType.MERGE)) {<a name="line.1148"></a>
-<span class="sourceLineNo">1149</span> LOG.warn("Merge switch is off! skip merge of regionA=" + hriA + " regionB=" + hriB);<a name="line.1149"></a>
-<span class="sourceLineNo">1150</span> throw new DoNotRetryIOException("Merge of regionA=" + hriA + " regionB=" + hriB +<a name="line.1150"></a>
-<span class="sourceLineNo">1151</span> " failed because merge switch is off");<a name="line.1151"></a>
-<span class="sourceLineNo">1152</span> }<a name="line.1152"></a>
+<span class="sourceLineNo">1129</span> // Processing this report happens asynchronously from other activities which can mutate<a name="line.1129"></a>
+<span class="sourceLineNo">1130</span> // the region state. For example, a split procedure may already be running for this parent.<a name="line.1130"></a>
+<span class="sourceLineNo">1131</span> // A split procedure cannot succeed if the parent region is no longer open, so we can<a name="line.1131"></a>
+<span class="sourceLineNo">1132</span> // ignore it in that case.<a name="line.1132"></a>
+<span class="sourceLineNo">1133</span> // Note that submitting more than one split procedure for a given region is<a name="line.1133"></a>
+<span class="sourceLineNo">1134</span> // harmless -- the split is fenced in the procedure handling -- but it would be noisy in<a name="line.1134"></a>
+<span class="sourceLineNo">1135</span> // the logs. Only one procedure can succeed. The other procedure(s) would abort during<a name="line.1135"></a>
+<span class="sourceLineNo">1136</span> // initialization and report failure with WARN level logging.<a name="line.1136"></a>
+<span class="sourceLineNo">1137</span> RegionState parentState = regionStates.getRegionState(parent);<a name="line.1137"></a>
+<span class="sourceLineNo">1138</span> if (parentState != null && parentState.isOpened()) {<a name="line.1138"></a>
+<span class="sourceLineNo">1139</span> master.getMasterProcedureExecutor().submitProcedure(createSplitProcedure(parent,<a name="line.1139"></a>
+<span class="sourceLineNo">1140</span> splitKey));<a name="line.1140"></a>
+<span class="sourceLineNo">1141</span> } else {<a name="line.1141"></a>
+<span class="sourceLineNo">1142</span> LOG.info("Ignoring split request from " + serverName +<a name="line.1142"></a>
+<span class="sourceLineNo">1143</span> ", parent=" + parent + " because parent is unknown or not open");<a name="line.1143"></a>
+<span class="sourceLineNo">1144</span> return;<a name="line.1144"></a>
+<span class="sourceLineNo">1145</span> }<a name="line.1145"></a>
+<span class="sourceLineNo">1146</span><a name="line.1146"></a>
+<span class="sourceLineNo">1147</span> // If the RS is < 2.0 throw an exception to abort the operation, we are handling the split<a name="line.1147"></a>
+<span class="sourceLineNo">1148</span> if (master.getServerManager().getVersionNumber(serverName) < 0x0200000) {<a name="line.1148"></a>
+<span class="sourceLineNo">1149</span> throw new UnsupportedOperationException(String.format("Split handled by the master: " +<a name="line.1149"></a>
+<span class="sourceLineNo">1150</span> "parent=%s hriA=%s hriB=%s", parent.getShortNameToLog(), hriA, hriB));<a name="line.1150"></a>
+<span class="sourceLineNo">1151</span> }<a name="line.1151"></a>
+<span class="sourceLineNo">1152</span> }<a name="line.1152"></a>
<span class="sourceLineNo">1153</span><a name="line.1153"></a>
-<span class="sourceLineNo">1154</span> // Submit the Merge procedure<a name="line.1154"></a>
-<span class="sourceLineNo">1155</span> if (LOG.isDebugEnabled()) {<a name="line.1155"></a>
-<span class="sourceLineNo">1156</span> LOG.debug("Handling merge request from RS=" + merged + ", merged=" + merged);<a name="line.1156"></a>
-<span class="sourceLineNo">1157</span> }<a name="line.1157"></a>
-<span class="sourceLineNo">1158</span> master.getMasterProcedureExecutor().submitProcedure(createMergeProcedure(hriA, hriB));<a name="line.1158"></a>
-<span class="sourceLineNo">1159</span><a name="line.1159"></a>
-<span class="sourceLineNo">1160</span> // If the RS is < 2.0 throw an exception to abort the operation, we are handling the merge<a name="line.1160"></a>
-<span class="sourceLineNo">1161</span> if (master.getServerManager().getVersionNumber(serverName) < 0x0200000) {<a name="line.1161"></a>
-<span class="sourceLineNo">1162</span> throw new UnsupportedOperationException(String.format(<a name="line.1162"></a>
-<span class="sourceLineNo">1163</span> "Merge not handled yet: regionState=%s merged=%s hriA=%s hriB=%s", state, merged, hriA,<a name="line.1163"></a>
-<span class="sourceLineNo">1164</span> hriB));<a name="line.1164"></a>
-<span class="sourceLineNo">1165</span> }<a name="line.1165"></a>
-<span class="sourceLineNo">1166</span> }<a name="line.1166"></a>
-<span class="sourceLineNo">1167</span><a name="line.1167"></a>
-<span class="sourceLineNo">1168</span> // ============================================================================================<a name="line.1168"></a>
-<span class="sourceLineNo">1169</span> // RS Status update (report online regions) helpers<a name="line.1169"></a>
-<span class="sourceLineNo">1170</span> // ============================================================================================<a name="line.1170"></a>
-<span class="sourceLineNo">1171</span> /**<a name="line.1171"></a>
-<span class="sourceLineNo">1172</span> * The master will call this method when the RS send the regionServerReport(). The report will<a name="line.1172"></a>
-<span class="sourceLineNo">1173</span> * contains the "online regions". This method will check the the online regions against the<a name="line.1173"></a>
-<span class="sourceLineNo">1174</span> * in-memory state of the AM, and we will log a warn message if there is a mismatch. This is<a name="line.1174"></a>
-<span class="sourceLineNo">1175</span> * because that there is no fencing between the reportRegionStateTransition method and<a name="line.1175"></a>
-<span class="sourceLineNo">1176</span> * regionServerReport method, so there could be race and introduce inconsistency here, but<a name="line.1176"></a>
-<span class="sourceLineNo">1177</span> * actually there is no problem.<a name="line.1177"></a>
-<span class="sourceLineNo">1178</span> * <p/><a name="line.1178"></a>
-<span class="sourceLineNo">1179</span> * Please see HBASE-21421 and HBASE-21463 for more details.<a name="line.1179"></a>
-<span class="sourceLineNo">1180</span> */<a name="line.1180"></a>
-<span class="sourceLineNo">1181</span> public void reportOnlineRegions(ServerName serverName, Set<byte[]> regionNames) {<a name="line.1181"></a>
-<span class="sourceLineNo">1182</span> if (!isRunning()) {<a name="line.1182"></a>
-<span class="sourceLineNo">1183</span> return;<a name="line.1183"></a>
-<span class="sourceLineNo">1184</span> }<a name="line.1184"></a>
-<span class="sourceLineNo">1185</span> if (LOG.isTraceEnabled()) {<a name="line.1185"></a>
-<span class="sourceLineNo">1186</span> LOG.trace("ReportOnlineRegions {} regionCount={}, metaLoaded={} {}", serverName,<a name="line.1186"></a>
-<span class="sourceLineNo">1187</span> regionNames.size(), isMetaLoaded(),<a name="line.1187"></a>
-<span class="sourceLineNo">1188</span> regionNames.stream().map(Bytes::toStringBinary).collect(Collectors.toList()));<a name="line.1188"></a>
-<span class="sourceLineNo">1189</span> }<a name="line.1189"></a>
-<span class="sourceLineNo">1190</span><a name="line.1190"></a>
-<span class="sourceLineNo">1191</span> ServerStateNode serverNode = regionStates.getOrCreateServer(serverName);<a name="line.1191"></a>
-<span class="sourceLineNo">1192</span> synchronized (serverNode) {<a name="line.1192"></a>
-<span class="sourceLineNo">1193</span> if (!serverNode.isInState(ServerState.ONLINE)) {<a name="line.1193"></a>
-<span class="sourceLineNo">1194</span> LOG.warn("Got a report from a server result in state " + serverNode.getState());<a name="line.1194"></a>
-<span class="sourceLineNo">1195</span> return;<a name="line.1195"></a>
-<span class="sourceLineNo">1196</span> }<a name="line.1196"></a>
-<span class="sourceLineNo">1197</span> }<a name="line.1197"></a>
-<span class="sourceLineNo">1198</span><a name="line.1198"></a>
-<span class="sourceLineNo">1199</span> // Track the regionserver reported online regions in memory.<a name="line.1199"></a>
-<span class="sourceLineNo">1200</span> synchronized (rsReports) {<a name="line.1200"></a>
-<span class="sourceLineNo">1201</span> rsReports.put(serverName, regionNames);<a name="line.1201"></a>
-<span class="sourceLineNo">1202</span> }<a name="line.1202"></a>
-<span class="sourceLineNo">1203</span><a name="line.1203"></a>
-<span class="sourceLineNo">1204</span> if (regionNames.isEmpty()) {<a name="line.1204"></a>
-<span class="sourceLineNo">1205</span> // nothing to do if we don't have regions<a name="line.1205"></a>
-<span class="sourceLineNo">1206</span> LOG.trace("no online region found on {}", serverName);<a name="line.1206"></a>
-<span class="sourceLineNo">1207</span> return;<a name="line.1207"></a>
-<span class="sourceLineNo">1208</span> }<a name="line.1208"></a>
-<span class="sourceLineNo">1209</span> if (!isMetaLoaded()) {<a name="line.1209"></a>
-<span class="sourceLineNo">1210</span> // we are still on startup, skip checking<a name="line.1210"></a>
-<span class="sourceLineNo">1211</span> return;<a name="line.1211"></a>
-<span class="sourceLineNo">1212</span> }<a name="line.1212"></a>
-<span class="sourceLineNo">1213</span> // The Heartbeat tells us of what regions are on the region serve, check the state.<a name="line.1213"></a>
-<span class="sourceLineNo">1214</span> checkOnlineRegionsReport(serverNode, regionNames);<a name="line.1214"></a>
-<span class="sourceLineNo">1215</span> }<a name="line.1215"></a>
-<span class="sourceLineNo">1216</span><a name="line.1216"></a>
-<span class="sourceLineNo">1217</span> /**<a name="line.1217"></a>
-<span class="sourceLineNo">1218</span> * Close <code>regionName</code> on <code>sn</code> silently and immediately without<a name="line.1218"></a>
-<span class="sourceLineNo">1219</span> * using a Procedure or going via hbase:meta. For case where a RegionServer's hosting<a name="line.1219"></a>
-<span class="sourceLineNo">1220</span> * of a Region is not aligned w/ the Master's accounting of Region state. This is for<a name="line.1220"></a>
-<span class="sourceLineNo">1221</span> * cleaning up an error in accounting.<a name="line.1221"></a>
-<span class="sourceLineNo">1222</span> */<a name="line.1222"></a>
-<span class="sourceLineNo">1223</span> private void closeRegionSilently(ServerName sn, byte [] regionName) {<a name="line.1223"></a>
-<span class="sourceLineNo">1224</span> try {<a name="line.1224"></a>
-<span class="sourceLineNo">1225</span> RegionInfo ri = CatalogFamilyFormat.parseRegionInfoFromRegionName(regionName);<a name="line.1225"></a>
-<span class="sourceLineNo">1226</span> // Pass -1 for timeout. Means do not wait.<a name="line.1226"></a>
-<span class="sourceLineNo">1227</span> ServerManager.closeRegionSilentlyAndWait(this.master.getAsyncClusterConnection(), sn, ri, -1);<a name="line.1227"></a>
-<span class="sourceLineNo">1228</span> } catch (Exception e) {<a name="line.1228"></a>
-<span class="sourceLineNo">1229</span> LOG.error("Failed trying to close {} on {}", Bytes.toStringBinary(regionName), sn, e);<a name="line.1229"></a>
-<span class="sourceLineNo">1230</span> }<a name="line.1230"></a>
+<span class="sourceLineNo">1154</span> private void updateRegionMergeTransition(final ServerName serverName, final TransitionCode state,<a name="line.1154"></a>
+<span class="sourceLineNo">1155</span> final RegionInfo merged, final RegionInfo hriA, final RegionInfo hriB) throws IOException {<a name="line.1155"></a>
+<span class="sourceLineNo">1156</span> checkMetaLoaded(merged);<a name="line.1156"></a>
+<span class="sourceLineNo">1157</span><a name="line.1157"></a>
+<span class="sourceLineNo">1158</span> if (state != TransitionCode.READY_TO_MERGE) {<a name="line.1158"></a>
+<span class="sourceLineNo">1159</span> throw new UnexpectedStateException("Unsupported merge regionState=" + state +<a name="line.1159"></a>
+<span class="sourceLineNo">1160</span> " for regionA=" + hriA + " regionB=" + hriB + " merged=" + merged +<a name="line.1160"></a>
+<span class="sourceLineNo">1161</span> " maybe an old RS (< 2.0) had the operation in progress");<a name="line.1161"></a>
+<span class="sourceLineNo">1162</span> }<a name="line.1162"></a>
+<span class="sourceLineNo">1163</span><a name="line.1163"></a>
+<span class="sourceLineNo">1164</span> if (!master.isSplitOrMergeEnabled(MasterSwitchType.MERGE)) {<a name="line.1164"></a>
+<span class="sourceLineNo">1165</span> LOG.warn("Merge switch is off! skip merge of regionA=" + hriA + " regionB=" + hriB);<a name="line.1165"></a>
+<span class="sourceLineNo">1166</span> throw new DoNotRetryIOException("Merge of regionA=" + hriA + " regionB=" + hriB +<a name="line.1166"></a>
+<span class="sourceLineNo">1167</span> " failed because merge switch is off");<a name="line.1167"></a>
+<span class="sourceLineNo">1168</span> }<a name="line.1168"></a>
+<span class="sourceLineNo">1169</span><a name="line.1169"></a>
+<span class="sourceLineNo">1170</span> // Submit the Merge procedure<a name="line.1170"></a>
+<span class="sourceLineNo">1171</span> if (LOG.isDebugEnabled()) {<a name="line.1171"></a>
+<span class="sourceLineNo">1172</span> LOG.debug("Handling merge request from RS=" + merged + ", merged=" + merged);<a name="line.1172"></a>
+<span class="sourceLineNo">1173</span> }<a name="line.1173"></a>
+<span class="sourceLineNo">1174</span> master.getMasterProcedureExecutor().submitProcedure(createMergeProcedure(hriA, hriB));<a name="line.1174"></a>
+<span class="sourceLineNo">1175</span><a name="line.1175"></a>
+<span class="sourceLineNo">1176</span> // If the RS is < 2.0 throw an exception to abort the operation, we are handling the merge<a name="line.1176"></a>
+<span class="sourceLineNo">1177</span> if (master.getServerManager().getVersionNumber(serverName) < 0x0200000) {<a name="line.1177"></a>
+<span class="sourceLineNo">1178</span> throw new UnsupportedOperationException(String.format(<a name="line.1178"></a>
+<span class="sourceLineNo">1179</span> "Merge not handled yet: regionState=%s merged=%s hriA=%s hriB=%s", state, merged, hriA,<a name="line.1179"></a>
+<span class="sourceLineNo">1180</span> hriB));<a name="line.1180"></a>
+<span class="sourceLineNo">1181</span> }<a name="line.1181"></a>
+<span class="sourceLineNo">1182</span> }<a name="line.1182"></a>
+<span class="sourceLineNo">1183</span><a name="line.1183"></a>
+<span class="sourceLineNo">1184</span> // ============================================================================================<a name="line.1184"></a>
+<span class="sourceLineNo">1185</span> // RS Status update (report online regions) helpers<a name="line.1185"></a>
+<span class="sourceLineNo">1186</span> // ============================================================================================<a name="line.1186"></a>
+<span class="sourceLineNo">1187</span> /**<a name="line.1187"></a>
+<span class="sourceLineNo">1188</span> * The master will call this method when the RS send the regionServerReport(). The report will<a name="line.1188"></a>
+<span class="sourceLineNo">1189</span> * contains the "online regions". This method will check the the online regions against the<a name="line.1189"></a>
+<span class="sourceLineNo">1190</span> * in-memory state of the AM, and we will log a warn message if there is a mismatch. This is<a name="line.1190"></a>
+<span class="sourceLineNo">1191</span> * because that there is no fencing between the reportRegionStateTransition method and<a name="line.1191"></a>
+<span class="sourceLineNo">1192</span> * regionServerReport method, so there could be race and introduce inconsistency here, but<a name="line.1192"></a>
+<span class="sourceLineNo">1193</span> * actually there is no problem.<a name="line.1193"></a>
+<span class="sourceLineNo">1194</span> * <p/><a name="line.1194"></a>
+<span class="sourceLineNo">1195</span> * Please see HBASE-21421 and HBASE-21463 for more details.<a name="line.1195"></a>
+<span class="sourceLineNo">1196</span> */<a name="line.1196"></a>
+<span class="sourceLineNo">1197</span> public void reportOnlineRegions(ServerName serverName, Set<byte[]> regionNames) {<a name="line.1197"></a>
+<span class="sourceLineNo">1198</span> if (!isRunning()) {<a name="line.1198"></a>
+<span class="sourceLineNo">1199</span> return;<a name="line.1199"></a>
+<span class="sourceLineNo">1200</span> }<a name="line.1200"></a>
+<span class="sourceLineNo">1201</span> if (LOG.isTraceEnabled()) {<a name="line.1201"></a>
+<span class="sourceLineNo">1202</span> LOG.trace("ReportOnlineRegions {} regionCount={}, metaLoaded={} {}", serverName,<a name="line.1202"></a>
+<span class="sourceLineNo">1203</span> regionNames.size(), isMetaLoaded(),<a name="line.1203"></a>
+<span class="sourceLineNo">1204</span> regionNames.stream().map(Bytes::toStringBinary).collect(Collectors.toList()));<a name="line.1204"></a>
+<span class="sourceLineNo">1205</span> }<a name="line.1205"></a>
+<span class="sourceLineNo">1206</span><a name="line.1206"></a>
+<span class="sourceLineNo">1207</span> ServerStateNode serverNode = regionStates.getOrCreateServer(serverName);<a name="line.1207"></a>
+<span class="sourceLineNo">1208</span> synchronized (serverNode) {<a name="line.1208"></a>
+<span class="sourceLineNo">1209</span> if (!serverNode.isInState(ServerState.ONLINE)) {<a name="line.1209"></a>
+<span class="sourceLineNo">1210</span> LOG.warn("Got a report from a server result in state " + serverNode.getState());<a name="line.1210"></a>
+<span class="sourceLineNo">1211</span> return;<a name="line.1211"></a>
+<span class="sourceLineNo">1212</span> }<a name="line.1212"></a>
+<span class="sourceLineNo">1213</span> }<a name="line.1213"></a>
+<span class="sourceLineNo">1214</span><a name="line.1214"></a>
+<span class="sourceLineNo">1215</span> // Track the regionserver reported online regions in memory.<a name="line.1215"></a>
+<span class="sourceLineNo">1216</span> synchronized (rsReports) {<a name="line.1216"></a>
+<span class="sourceLineNo">1217</span> rsReports.put(serverName, regionNames);<a name="line.1217"></a>
+<span class="sourceLineNo">1218</span> }<a name="line.1218"></a>
+<span class="sourceLineNo">1219</span><a name="line.1219"></a>
+<span class="sourceLineNo">1220</span> if (regionNames.isEmpty()) {<a name="line.1220"></a>
+<span class="sourceLineNo">1221</span> // nothing to do if we don't have regions<a name="line.1221"></a>
+<span class="sourceLineNo">1222</span> LOG.trace("no online region found on {}", serverName);<a name="line.1222"></a>
+<span class="sourceLineNo">1223</span> return;<a name="line.1223"></a>
+<span class="sourceLineNo">1224</span> }<a name="line.1224"></a>
+<span class="sourceLineNo">1225</span> if (!isMetaLoaded()) {<a name="line.1225"></a>
+<span class="sourceLineNo">1226</span> // we are still on startup, skip checking<a name="line.1226"></a>
+<span class="sourceLineNo">1227</span> return;<a name="line.1227"></a>
+<span class="sourceLineNo">1228</span> }<a name="line.1228"></a>
+<span class="sourceLineNo">1229</span> // The Heartbeat tells us of what regions are on the region serve, check the state.<a name="line.1229"></a>
+<span class="sourceLineNo">1230</span> checkOnlineRegionsReport(serverNode, regionNames);<a name="line.1230"></a>
<span class="sourceLineNo">1231</span> }<a name="line.1231"></a>
<span class="sourceLineNo">1232</span><a name="line.1232"></a>
<span class="sourceLineNo">1233</span> /**<a name="line.1233"></a>
-<span class="sourceLineNo">1234</span> * Check that what the RegionServer reports aligns with the Master's image.<a name="line.1234"></a>
-<span class="sourceLineNo">1235</span> * If disagreement, we will tell the RegionServer to expediently close<a name="line.1235"></a>
-<span class="sourceLineNo">1236</span> * a Region we do not think it should have.<a name="line.1236"></a>
-<span class="sourceLineNo">1237</span> */<a name="line.1237"></a>
-<span class="sourceLineNo">1238</span> private void checkOnlineRegionsReport(ServerStateNode serverNode, Set<byte[]> regionNames) {<a name="line.1238"></a>
-<span class="sourceLineNo">1239</span> ServerName serverName = serverNode.getServerName();<a name="line.1239"></a>
-<span class="sourceLineNo">1240</span> for (byte[] regionName : regionNames) {<a name="line.1240"></a>
-<span class="sourceLineNo">1241</span> if (!isRunning()) {<a name="line.1241"></a>
-<span class="sourceLineNo">1242</span> return;<a name="line.1242"></a>
-<span class="sourceLineNo">1243</span> }<a name="line.1243"></a>
-<span class="sourceLineNo">1244</span> RegionStateNode regionNode = regionStates.getRegionStateNodeFromName(regionName);<a name="line.1244"></a>
-<span class="sourceLineNo">1245</span> if (regionNode == null) {<a name="line.1245"></a>
-<span class="sourceLineNo">1246</span> String regionNameAsStr = Bytes.toStringBinary(regionName);<a name="line.1246"></a>
-<span class="sourceLineNo">1247</span> LOG.warn("No RegionStateNode for {} but reported as up on {}; closing...",<a name="line.1247"></a>
-<span class="sourceLineNo">1248</span> regionNameAsStr, serverName);<a name="line.1248"></a>
-<span class="sourceLineNo">1249</span> closeRegionSilently(serverNode.getServerName(), regionName);<a name="line.1249"></a>
-<span class="sourceLineNo">1250</span> continue;<a name="line.1250"></a>
-<span class="sourceLineNo">1251</span> }<a name="line.1251"></a>
-<span class="sourceLineNo">1252</span> final long lag = 1000;<a name="line.1252"></a>
-<span class="sourceLineNo">1253</span> regionNode.lock();<a name="line.1253"></a>
-<span class="sourceLineNo">1254</span> try {<a name="line.1254"></a>
-<span class="sourceLineNo">1255</span> long diff = EnvironmentEdgeManager.currentTime() - regionNode.getLastUpdate();<a name="line.1255"></a>
-<span class="sourceLineNo">1256</span> if (regionNode.isInState(State.OPENING, State.OPEN)) {<a name="line.1256"></a>
-<span class="sourceLineNo">1257</span> // This is possible as a region server has just closed a region but the region server<a name="line.1257"></a>
-<span class="sourceLineNo">1258</span> // report is generated before the closing, but arrive after the closing. Make sure there<a name="line.1258"></a>
-<span class="sourceLineNo">1259</span> // is some elapsed time so less false alarms.<a name="line.1259"></a>
-<span class="sourceLineNo">1260</span> if (!regionNode.getRegionLocation().equals(serverName) && diff > lag) {<a name="line.1260"></a>
-<span class="sourceLineNo">1261</span> LOG.warn("Reporting {} server does not match {} (time since last " +<a name="line.1261"></a>
-<span class="sourceLineNo">1262</span> "update={}ms); closing...",<a name="line.1262"></a>
-<span class="sourceLineNo">1263</span> serverName, regionNode, diff);<a name="line.1263"></a>
-<span class="sourceLineNo">1264</span> closeRegionSilently(serverNode.getServerName(), regionName);<a name="line.1264"></a>
-<span class="sourceLineNo">1265</span> }<a name="line.1265"></a>
-<span class="sourceLineNo">1266</span> } else if (!regionNode.isInState(State.CLOSING, State.SPLITTING)) {<a name="line.1266"></a>
-<span class="sourceLineNo">1267</span> // So, we can get report that a region is CLOSED or SPLIT because a heartbeat<a name="line.1267"></a>
-<span class="sourceLineNo">1268</span> // came in at about same time as a region transition. Make sure there is some<a name="line.1268"></a>
-<span class="sourceLineNo">1269</span> // elapsed time so less false alarms.<a name="line.1269"></a>
-<span class="sourceLineNo">1270</span> if (diff > lag) {<a name="line.1270"></a>
-<span class="sourceLineNo">1271</span> LOG.warn("Reporting {} state does not match {} (time since last update={}ms)",<a name="line.1271"></a>
-<span class="sourceLineNo">1272</span> serverName, regionNode, diff);<a name="line.1272"></a>
-<span class="sourceLineNo">1273</span> }<a name="line.1273"></a>
-<span class="sourceLineNo">1274</span> }<a name="line.1274"></a>
-<span class="sourceLineNo">1275</span> } finally {<a name="line.1275"></a>
-<span class="sourceLineNo">1276</span> regionNode.unlock();<a name="line.1276"></a>
-<span class="sourceLineNo">1277</span> }<a name="line.1277"></a>
-<span class="sourceLineNo">1278</span> }<a name="line.1278"></a>
-<span class="sourceLineNo">1279</span> }<a name="line.1279"></a>
-<span class="sourceLineNo">1280</span><a name="line.1280"></a>
-<span class="sourceLineNo">1281</span> // ============================================================================================<a name="line.1281"></a>
-<span class="sourceLineNo">1282</span> // RIT chore<a name="line.1282"></a>
-<span class="sourceLineNo">1283</span> // ============================================================================================<a name="line.1283"></a>
-<span class="sourceLineNo">1284</span> private static class RegionInTransitionChore extends ProcedureInMemoryChore<MasterProcedureEnv> {<a name="line.1284"></a>
-<span class="sourceLineNo">1285</span> public RegionInTransitionChore(final int timeoutMsec) {<a name="line.1285"></a>
-<span class="sourceLineNo">1286</span> super(timeoutMsec);<a name="line.1286"></a>
-<span class="sourceLineNo">1287</span> }<a name="line.1287"></a>
-<span class="sourceLineNo">1288</span><a name="line.1288"></a>
-<span class="sourceLineNo">1289</span> @Override<a name="line.1289"></a>
-<span class="sourceLineNo">1290</span> protected void periodicExecute(final MasterProcedureEnv env) {<a name="line.1290"></a>
-<span class="sourceLineNo">1291</span> final AssignmentManager am = env.getAssignmentManager();<a name="line.1291"></a>
-<span class="sourceLineNo">1292</span><a name="line.1292"></a>
-<span class="sourceLineNo">1293</span> final RegionInTransitionStat ritStat = am.computeRegionInTransitionStat();<a name="line.1293"></a>
-<span class="sourceLineNo">1294</span> if (ritStat.hasRegionsOverThreshold()) {<a name="line.1294"></a>
-<span class="sourceLineNo">1295</span> for (RegionState hri: ritStat.getRegionOverThreshold()) {<a name="line.1295"></a>
-<span class="sourceLineNo">1296</span> am.handleRegionOverStuckWarningThreshold(hri.getRegion());<a name="line.1296"></a>
-<span class="sourceLineNo">1297</span> }<a name="line.1297"></a>
-<span class="sourceLineNo">1298</span> }<a name="line.1298"></a>
-<span class="sourceLineNo">1299</span><a name="line.1299"></a>
-<span class="sourceLineNo">1300</span> // update metrics<a name="line.1300"></a>
-<span class="sourceLineNo">1301</span> am.updateRegionsInTransitionMetrics(ritStat);<a name="line.1301"></a>
-<span class="sourceLineNo">1302</span> }<a name="line.1302"></a>
-<span class="sourceLineNo">1303</span> }<a name="line.1303"></a>
+<span class="sourceLineNo">1234</span> * Close <code>regionName</code> on <code>sn</code> silently and immediately without<a name="line.1234"></a>
+<span class="sourceLineNo">1235</span> * using a Procedure or going via hbase:meta. For case where a RegionServer's hosting<a name="line.1235"></a>
+<span class="sourceLineNo">1236</span> * of a Region is not aligned w/ the Master's accounting of Region state. This is for<a name="line.1236"></a>
+<span class="sourceLineNo">1237</span> * cleaning up an error in accounting.<a name="line.1237"></a>
+<span class="sourceLineNo">1238</span> */<a name="line.1238"></a>
+<span class="sourceLineNo">1239</span> private void closeRegionSilently(ServerName sn, byte [] regionName) {<a name="line.1239"></a>
+<span class="sourceLineNo">1240</span> try {<a name="line.1240"></a>
+<span class="sourceLineNo">1241</span> RegionInfo ri = CatalogFamilyFormat.parseRegionInfoFromRegionName(regionName);<a name="line.1241"></a>
+<span class="sourceLineNo">1242</span> // Pass -1 for timeout. Means do not wait.<a name="line.1242"></a>
+<span class="sourceLineNo">1243</span> ServerManager.closeRegionSilentlyAndWait(this.master.getAsyncClusterConnection(), sn, ri, -1);<a name="line.1243"></a>
+<span class="sourceLineNo">1244</span> } catch (Exception e) {<a name="line.1244"></a>
+<span class="sourceLineNo">1245</span> LOG.error("Failed trying to close {} on {}", Bytes.toStringBinary(regionName), sn, e);<a name="line.1245"></a>
+<span class="sourceLineNo">1246</span> }<a name="line.1246"></a>
+<span class="sourceLineNo">1247</span> }<a name="line.1247"></a>
+<span class="sourceLineNo">1248</span><a name="line.1248"></a>
+<span class="sourceLineNo">1249</span> /**<a name="line.1249"></a>
+<span class="sourceLineNo">1250</span> * Check that what the RegionServer reports aligns with the Master's image.<a name="line.1250"></a>
+<span class="sourceLineNo">1251</span> * If disagreement, we will tell the RegionServer to expediently close<a name="line.1251"></a>
+<span class="sourceLineNo">1252</span> * a Region we do not think it should have.<a name="line.1252"></a>
+<span class="sourceLineNo">1253</span> */<a name="line.1253"></a>
+<span class="sourceLineNo">1254</span> private void checkOnlineRegionsReport(ServerStateNode serverNode, Set<byte[]> regionNames) {<a name="line.1254"></a>
+<span class="sourceLineNo">1255</span> ServerName serverName = serverNode.getServerName();<a name="line.1255"></a>
+<span class="sourceLineNo">1256</span> for (byte[] regionName : regionNames) {<a name="line.1256"></a>
+<span class="sourceLineNo">1257</span> if (!isRunning()) {<a name="line.1257"></a>
+<span class="sourceLineNo">1258</span> return;<a name="line.1258"></a>
+<span class="sourceLineNo">1259</span> }<a name="line.1259"></a>
+<span class="sourceLineNo">1260</span> RegionStateNode regionNode = regionStates.getRegionStateNodeFromName(regionName);<a name="line.1260"></a>
+<span class="sourceLineNo">1261</span> if (regionNode == null) {<a name="line.1261"></a>
+<span class="sourceLineNo">1262</span> String regionNameAsStr = Bytes.toStringBinary(regionName);<a name="line.1262"></a>
+<span class="sourceLineNo">1263</span> LOG.warn("No RegionStateNode for {} but reported as up on {}; closing...",<a name="line.1263"></a>
+<span class="sourceLineNo">1264</span> regionNameAsStr, serverName);<a name="line.1264"></a>
+<span class="sourceLineNo">1265</span> closeRegionSilently(serverNode.getServerName(), regionName);<a name="line.1265"></a>
+<span class="sourceLineNo">1266</span> continue;<a name="line.1266"></a>
+<span class="sourceLineNo">1267</span> }<a name="line.1267"></a>
+<span class="sourceLineNo">1268</span> final long lag = 1000;<a name="line.1268"></a>
+<span class="sourceLineNo">1269</span> regionNode.lock();<a name="line.1269"></a>
+<span class="sourceLineNo">1270</span> try {<a name="line.1270"></a>
+<span class="sourceLineNo">1271</span> long diff = EnvironmentEdgeManager.currentTime() - regionNode.getLastUpdate();<a name="line.1271"></a>
+<span class="sourceLineNo">1272</span> if (regionNode.isInState(State.OPENING, State.OPEN)) {<a name="line.1272"></a>
+<span class="sourceLineNo">1273</span> // This is possible as a region server has just closed a region but the region server<a name="line.1273"></a>
+<span class="sourceLineNo">1274</span> // report is generated before the closing, but arrive after the closing. Make sure there<a name="line.1274"></a>
+<span class="sourceLineNo">1275</span> // is some elapsed time so less false alarms.<a name="line.1275"></a>
+<span class="sourceLineNo">1276</span> if (!regionNode.getRegionLocation().equals(serverName) && diff > lag) {<a name="line.1276"></a>
+<span class="sourceLineNo">1277</span> LOG.warn("Reporting {} server does not match {} (time since last " +<a name="line.1277"></a>
+<span class="sourceLineNo">1278</span> "update={}ms); closing...",<a name="line.1278"></a>
+<span class="sourceLineNo">1279</span> serverName, regionNode, diff);<a name="line.1279"></a>
+<span class="sourceLineNo">1280</span> closeRegionSilently(serverNode.getServerName(), regionName);<a name="line.1280"></a>
+<span class="sourceLineNo">1281</span> }<a name="line.1281"></a>
+<span class="sourceLineNo">1282</span> } else if (!regionNode.isInState(State.CLOSING, State.SPLITTING)) {<a name="line.1282"></a>
+<span class="sourceLineNo">1283</span> // So, we can get report that a region is CLOSED or SPLIT because a heartbeat<a name="line.1283"></a>
+<span class="sourceLineNo">1284</span> // came in at about same time as a region transition. Make sure there is some<a name="line.1284"></a>
+<span class="sourceLineNo">1285</span> // elapsed time so less false alarms.<a name="line.1285"></a>
+<span class="sourceLineNo">1286</span> if (diff > lag) {<a name="line.1286"></a>
+<span class="sourceLineNo">1287</span> LOG.warn("Reporting {} state does not match {} (time since last update={}ms)",<a name="line.1287"></a>
+<span class="sourceLineNo">1288</span> serverName, regionNode, diff);<a name="line.1288"></a>
+<span class="sourceLineNo">1289</span> }<a name="line.1289"></a>
+<span class="sourceLineNo">1290</span> }<a name="line.1290"></a>
+<span class="sourceLineNo">1291</span> } finally {<a name="line.1291"></a>
+<span class="sourceLineNo">1292</span> regionNode.unlock();<a name="line.1292"></a>
+<span class="sourceLineNo">1293</span> }<a name="line.1293"></a>
+<span class="sourceLineNo">1294</span> }<a name="line.1294"></a>
+<span class="sourceLineNo">1295</span> }<a name="line.1295"></a>
+<span class="sourceLineNo">1296</span><a name="line.1296"></a>
+<span class="sourceLineNo">1297</span> // ============================================================================================<a name="line.1297"></a>
+<span class="sourceLineNo">1298</span> // RIT chore<a name="line.1298"></a>
+<span class="sourceLineNo">1299</span> // ============================================================================================<a name="line.1299"></a>
+<span class="sourceLineNo">1300</span> private static class RegionInTransitionChore extends ProcedureInMemoryChore<MasterProcedureEnv> {<a name="line.1300"></a>
+<span class="sourceLineNo">1301</span> public RegionInTransitionChore(final int timeoutMsec) {<a name="line.1301"></a>
+<span class="sourceLineNo">1302</span> super(timeoutMsec);<a name="line.1302"></a>
+<span class="sourceLineNo">1303</span> }<a name="line.1303"></a>
<span class="sourceLineNo">1304</span><a name="line.1304"></a>
-<span class="sourceLineNo">1305</span> private static class DeadServerMetricRegionChore<a name="line.1305"></a>
-<span class="sourceLineNo">1306</span> extends ProcedureInMemoryChore<MasterProcedureEnv> {<a name="line.1306"></a>
-<span class="sourceLineNo">1307</span> public DeadServerMetricRegionChore(final int timeoutMsec) {<a name="line.1307"></a>
-<span class="sourceLineNo">1308</span> super(timeoutMsec);<a name="line.1308"></a>
-<span class="sourceLineNo">1309</span> }<a name="line.1309"></a>
-<span class="sourceLineNo">1310</span><a name="line.1310"></a>
-<span class="sourceLineNo">1311</span> @Override<a name="line.1311"></a>
-<span class="sourceLineNo">1312</span> protected void periodicExecute(final MasterProcedureEnv env) {<a name="line.1312"></a>
-<span class="sourceLineNo">1313</span> final ServerManager sm = env.getMasterServices().getServerManager();<a name="line.1313"></a>
-<span class="sourceLineNo">1314</span> final AssignmentManager am = env.getAssignmentManager();<a name="line.1314"></a>
-<span class="sourceLineNo">1315</span> // To minimize inconsistencies we are not going to snapshot live servers in advance in case<a name="line.1315"></a>
-<span class="sourceLineNo">1316</span> // new servers are added; OTOH we don't want to add heavy sync for a consistent view since<a name="line.1316"></a>
-<span class="sourceLineNo">1317</span> // this is for metrics. Instead, we're going to check each regions as we go; to avoid making<a name="line.1317"></a>
-<span class="sourceLineNo">1318</span> // too many checks, we maintain a local lists of server, limiting us to false negatives. If<a name="line.1318"></a>
-<span class="sourceLineNo">1319</span> // we miss some recently-dead server, we'll just see it next time.<a name="line.1319"></a>
-<span class="sourceLineNo">1320</span> Set<ServerName> recentlyLiveServers = new HashSet<>();<a name="line.1320"></a>
-<span class="sourceLineNo">1321</span> int deadRegions = 0, unknownRegions = 0;<a name="line.1321"></a>
-<span class="sourceLineNo">1322</span> for (RegionStateNode rsn : am.getRegionStates().getRegionStateNodes()) {<a name="line.1322"></a>
-<span class="sourceLineNo">1323</span> if (rsn.getState() != State.OPEN) {<a name="line.1323"></a>
-<span class="sourceLineNo">1324</span> continue; // Opportunistic check, should quickly skip RITs, offline tables, etc.<a name="line.1324"></a>
-<span class="sourceLineNo">1325</span> }<a name="line.1325"></a>
-<span class="sourceLineNo">1326</span> // Do not need to acquire region state lock as this is only for showing metrics.<a name="line.1326"></a>
-<span class="sourceLineNo">1327</span> ServerName sn = rsn.getRegionLocation();<a name="line.1327"></a>
-<span class="sourceLineNo">1328</span> State state = rsn.getState();<a name="line.1328"></a>
-<span class="sourceLineNo">1329</span> if (state != State.OPEN) {<a name="line.1329"></a>
-<span class="sourceLineNo">1330</span> continue; // Mostly skipping RITs that are already being take care of.<a name="line.1330"></a>
-<span class="sourceLineNo">1331</span> }<a name="line.1331"></a>
-<span class="sourceLineNo">1332</span> if (sn == null) {<a name="line.1332"></a>
-<span class="sourceLineNo">1333</span> ++unknownRegions; // Opened on null?<a name="line.1333"></a>
-<span class="sourceLineNo">1334</span> continue;<a name="line.1334"></a>
-<span class="sourceLineNo">1335</span> }<a name="line.1335"></a>
-<span class="sourceLineNo">1336</span> if (recentlyLiveServers.contains(sn)) {<a name="line.1336"></a>
-<span class="sourceLineNo">1337</span> continue;<a name="line.1337"></a>
-<span class="sourceLineNo">1338</span> }<a name="line.1338"></a>
-<span class="sourceLineNo">1339</span> ServerManager.ServerLiveState sls = sm.isServerKnownAndOnline(sn);<a name="line.1339"></a>
-<span class="sourceLineNo">1340</span> switch (sls) {<a name="line.1340"></a>
-<span class="sourceLineNo">1341</span> case LIVE:<a name="line.1341"></a>
-<span class="sourceLineNo">1342</span> recentlyLiveServers.add(sn);<a name="line.1342"></a>
-<span class="sourceLineNo">1343</span> break;<a name="line.1343"></a>
-<span class="sourceLineNo">1344</span> case DEAD:<a name="line.1344"></a>
-<span class="sourceLineNo">1345</span> ++deadRegions;<a name="line.1345"></a>
-<span class="sourceLineNo">1346</span> break;<a name="line.1346"></a>
-<span class="sourceLineNo">1347</span> case UNKNOWN:<a name="line.1347"></a>
-<span class="sourceLineNo">1348</span> ++unknownRegions;<a name="line.1348"></a>
-<span class="sourceLineNo">1349</span> break;<a name="line.1349"></a>
-<span class="sourceLineNo">1350</span> default: throw new AssertionError("Unexpected " + sls);<a name="line.1350"></a>
+<span class="sourceLineNo">1305</span> @Override<a name="line.1305"></a>
+<span class="sourceLineNo">1306</span> protected void periodicExecute(final MasterProcedureEnv env) {<a name="line.1306"></a>
+<span class="sourceLineNo">1307</span> final AssignmentManager am = env.getAssignmentManager();<a name="line.1307"></a>
+<span class="sourceLineNo">1308</span><a name="line.1308"></a>
+<span class="sourceLineNo">1309</span> final RegionInTransitionStat ritStat = am.computeRegionInTransitionStat();<a name="line.1309"></a>
+<span class="sourceLineNo">1310</span> if (ritStat.hasRegionsOverThreshold()) {<a name="line.1310"></a>
+<span class="sourceLineNo">1311</span> for (RegionState hri: ritStat.getRegionOverThreshold()) {<a name="line.1311"></a>
+<span class="sourceLineNo">1312</span> am.handleRegionOverStuckWarningThreshold(hri.getRegion());<a name="line.1312"></a>
+<span class="sourceLineNo">1313</span> }<a name="line.1313"></a>
+<span class="sourceLineNo">1314</span> }<a name="line.1314"></a>
+<span class="sourceLineNo">1315</span><a name="line.1315"></a>
+<span class="sourceLineNo">1316</span> // update metrics<a name="line.1316"></a>
+<span class="sourceLineNo">1317</span> am.updateRegionsInTransitionMetrics(ritStat);<a name="line.1317"></a>
+<span class="sourceLineNo">1318</span> }<a name="line.1318"></a>
+<span class="sourceLineNo">1319</span> }<a name="line.1319"></a>
+<span class="sourceLineNo">1320</span><a name="line.1320"></a>
+<span class="sourceLineNo">1321</span> private static class DeadServerMetricRegionChore<a name="line.1321"></a>
+<span class="sourceLineNo">1322</span> extends ProcedureInMemoryChore<MasterProcedureEnv> {<a name="line.1322"></a>
+<span class="sourceLineNo">1323</span> public DeadServerMetricRegionChore(final int timeoutMsec) {<a name="line.1323"></a>
+<span class="sourceLineNo">1324</span> super(timeoutMsec);<a name="line.1324"></a>
+<span class="sourceLineNo">1325</span> }<a name="line.1325"></a>
+<span class="sourceLineNo">1326</span><a name="line.1326"></a>
+<span class="sourceLineNo">1327</span> @Override<a name="line.1327"></a>
+<span class="sourceLineNo">1328</span> protected void periodicExecute(final MasterProcedureEnv env) {<a name="line.1328"></a>
+<span class="sourceLineNo">1329</span> final ServerManager sm = env.getMasterServices().getServerManager();<a name="line.1329"></a>
+<span class="sourceLineNo">1330</span> final AssignmentManager am = env.getAssignmentManager();<a name="line.1330"></a>
+<span class="sourceLineNo">1331</span> // To minimize inconsistencies we are not going to snapshot live servers in advance in case<a name="line.1331"></a>
+<span class="sourceLineNo">1332</span> // new servers are added; OTOH we don't want to add heavy sync for a consistent view since<a name="line.1332"></a>
+<span class="sourceLineNo">1333</span> // this is for metrics. Instead, we're going to check each regions as we go; to avoid making<a name="line.1333"></a>
+<span class="sourceLineNo">1334</span> // too many checks, we maintain a local lists of server, limiting us to false negatives. If<a name="line.1334"></a>
+<span class="sourceLineNo">1335</span> // we miss some recently-dead server, we'll just see it next time.<a name="line.1335"></a>
+<span class="sourceLineNo">1336</span> Set<ServerName> recentlyLiveServers = new HashSet<>();<a name="line.1336"></a>
+<span class="sourceLineNo">1337</span> int deadRegions = 0, unknownRegions = 0;<a name="line.1337"></a>
+<span class="sourceLineNo">1338</span> for (RegionStateNode rsn : am.getRegionStates().getRegionStateNodes()) {<a name="line.1338"></a>
+<span class="sourceLineNo">1339</span> if (rsn.getState() != State.OPEN) {<a name="line.1339"></a>
+<span class="sourceLineNo">1340</span> continue; // Opportunistic check, should quickly skip RITs, offline tables, etc.<a name="line.1340"></a>
+<span class="sourceLineNo">1341</span> }<a name="line.1341"></a>
+<span class="sourceLineNo">1342</span> // Do not need to acquire region state lock as this is only for showing metrics.<a name="line.1342"></a>
+<span class="sourceLineNo">1343</span> ServerName sn = rsn.getRegionLocation();<a name="line.1343"></a>
+<span class="sourceLineNo">1344</span> State state = rsn.getState();<a name="line.1344"></a>
+<span class="sourceLineNo">1345</span> if (state != State.OPEN) {<a name="line.1345"></a>
+<span class="sourceLineNo">1346</span> continue; // Mostly skipping RITs that are already being take care of.<a name="line.1346"></a>
+<span class="sourceLineNo">1347</span> }<a name="line.1347"></a>
+<span class="sourceLineNo">1348</span> if (sn == null) {<a name="line.1348"></a>
+<span class="sourceLineNo">1349</span> ++unknownRegions; // Opened on null?<a name="line.1349"></a>
+<span class="sourceLineNo">1350</span> continue;<a name="line.1350"></a>
<span class="sourceLineNo">1351</span> }<a name="line.1351"></a>
-<span class="sourceLineNo">1352</span> }<a name="line.1352"></a>
-<span class="sourceLineNo">1353</span> if (deadRegions > 0 || unknownRegions > 0) {<a name="line.1353"></a>
-<span class="sourceLineNo">1354</span> LOG.info("Found {} OPEN regions on dead servers and {} OPEN regions on unknown servers",<a name="line.1354"></a>
-<span class="sourceLineNo">1355</span> deadRegions, unknownRegions);<a name="line.1355"></a>
-<span class="sourceLineNo">1356</span> }<a name="line.1356"></a>
-<span class="sourceLineNo">1357</span><a name="line.1357"></a>
-<span class="sourceLineNo">1358</span> am.updateDeadServerRegionMetrics(deadRegions, unknownRegions);<a name="line.1358"></a>
-<span class="sourceLineNo">1359</span> }<a name="line.1359"></a>
-<span class="sourceLineNo">1360</span> }<a name="line.1360"></a>
-<span class="sourceLineNo">1361</span><a name="line.1361"></a>
-<span class="sourceLineNo">1362</span> public RegionInTransitionStat computeRegionInTransitionStat() {<a name="line.1362"></a>
-<span class="sourceLineNo">1363</span> final RegionInTransitionStat rit = new RegionInTransitionStat(getConfiguration());<a name="line.1363"></a>
-<span class="sourceLineNo">1364</span> rit.update(this);<a name="line.1364"></a>
-<span class="sourceLineNo">1365</span> return rit;<a name="line.1365"></a>
-<span class="sourceLineNo">1366</span> }<a name="line.1366"></a>
-<span class="sourceLineNo">1367</span><a name="line.1367"></a>
-<span class="sourceLineNo">1368</span> public static class RegionInTransitionStat {<a name="line.1368"></a>
-<span class="sourceLineNo">1369</span> private final int ritThreshold;<a name="line.1369"></a>
-<span class="sourceLineNo">1370</span><a name="line.1370"></a>
-<span class="sourceLineNo">1371</span> private HashMap<String, RegionState> ritsOverThreshold = null;<a name="line.1371"></a>
-<span class="sourceLineNo">1372</span> private long statTimestamp;<a name="line.1372"></a>
-<span class="sourceLineNo">1373</span> private long oldestRITTime = 0;<a name="line.1373"></a>
-<span class="sourceLineNo">1374</span> private int totalRITsTwiceThreshold = 0;<a name="line.1374"></a>
-<span class="sourceLineNo">1375</span> private int totalRITs = 0;<a name="line.1375"></a>
-<span class="sourceLineNo">1376</span><a name="line.1376"></a>
-<span class="sourceLineNo">1377</span> public RegionInTransitionStat(final Configuration conf) {<a name="line.1377"></a>
-<span class="sourceLineNo">1378</span> this.ritThreshold =<a name="line.1378"></a>
-<span class="sourceLineNo">1379</span> conf.getInt(METRICS_RIT_STUCK_WARNING_THRESHOLD, DEFAULT_RIT_STUCK_WARNING_THRESHOLD);<a name="line.1379"></a>
-<span class="sourceLineNo">1380</span> }<a name="line.1380"></a>
-<span class="sourceLineNo">1381</span><a name="line.1381"></a>
-<span class="sourceLineNo">1382</span> public int getRITThreshold() {<a name="line.1382"></a>
-<span class="sourceLineNo">1383</span> return ritThreshold;<a name="line.1383"></a>
-<span class="sourceLineNo">1384</span> }<a name="line.1384"></a>
-<span class="sourceLineNo">1385</span><a name="line.1385"></a>
-<span class="sourceLineNo">1386</span> public long getTimestamp() {<a name="line.1386"></a>
-<span class="sourceLineNo">1387</span> return statTimestamp;<a name="line.1387"></a>
-<span class="sourceLineNo">1388</span> }<a name="line.1388"></a>
-<span class="sourceLineNo">1389</span><a name="line.1389"></a>
-<span class="sourceLineNo">1390</span> public int getTotalRITs() {<a name="line.1390"></a>
-<span class="sourceLineNo">1391</span> return totalRITs;<a name="line.1391"></a>
-<span class="sourceLineNo">1392</span> }<a name="line.1392"></a>
-<span class="sourceLineNo">1393</span><a name="line.1393"></a>
-<span class="sourceLineNo">1394</span> public long getOldestRITTime() {<a name="line.1394"></a>
-<span class="sourceLineNo">1395</span> return oldestRITTime;<a name="line.1395"></a>
+<span class="sourceLineNo">1352</span> if (recentlyLiveServers.contains(sn)) {<a name="line.1352"></a>
+<span class="sourceLineNo">1353</span> continue;<a name="line.1353"></a>
+<span class="sourceLineNo">1354</span> }<a name="line.1354"></a>
+<span class="sourceLineNo">1355</span> ServerManager.ServerLiveState sls = sm.isServerKnownAndOnline(sn);<a name="line.1355"></a>
+<span class="sourceLineNo">1356</span> switch (sls) {<a name="line.1356"></a>
+<span class="sourceLineNo">1357</span> case LIVE:<a name="line.1357"></a>
+<span class="sourceLineNo">1358</span> recentlyLiveServers.add(sn);<a name="line.1358"></a>
+<span class="sourceLineNo">1359</span> break;<a name="line.1359"></a>
+<span class="sourceLineNo">1360</span> case DEAD:<a name="line.1360"></a>
+<span class="sourceLineNo">1361</span> ++deadRegions;<a name="line.1361"></a>
+<span class="sourceLineNo">1362</span> break;<a name="line.1362"></a>
+<span class="sourceLineNo">1363</span> case UNKNOWN:<a name="line.1363"></a>
+<span class="sourceLineNo">1364</span> ++unknownRegions;<a name="line.1364"></a>
+<span class="sourceLineNo">1365</span> break;<a name="line.1365"></a>
+<span class="sourceLineNo">1366</span> default: throw new AssertionError("Unexpected " + sls);<a name="line.1366"></a>
+<span class="sourceLineNo">1367</span> }<a name="line.1367"></a>
+<span class="sourceLineNo">1368</span> }<a name="line.1368"></a>
+<span class="sourceLineNo">1369</span> if (deadRegions > 0 || unknownRegions > 0) {<a name="line.1369"></a>
+<span class="sourceLineNo">1370</span> LOG.info("Found {} OPEN regions on dead servers and {} OPEN regions on unknown servers",<a name="line.1370"></a>
+<span class="sourceLineNo">1371</span> deadRegions, unknownRegions);<a name="line.1371"></a>
+<span class="sourceLineNo">1372</span> }<a name="line.1372"></a>
+<span class="sourceLineNo">1373</span><a name="line.1373"></a>
+<span class="sourceLineNo">1374</span> am.updateDeadServerRegionMetrics(deadRegions, unknownRegions);<a name="line.1374"></a>
+<span class="sourceLineNo">1375</span> }<a name="line.1375"></a>
+<span class="sourceLineNo">1376</span> }<a name="line.1376"></a>
+<span class="sourceLineNo">1377</span><a name="line.1377"></a>
+<span class="sourceLineNo">1378</span> public RegionInTransitionStat computeRegionInTransitionStat() {<a name="line.1378"></a>
+<span class="sourceLineNo">1379</span> final RegionInTransitionStat rit = new RegionInTransitionStat(getConfiguration());<a name="line.1379"></a>
+<span class="sourceLineNo">1380</span> rit.update(this);<a name="line.1380"></a>
+<span class="sourceLineNo">1381</span> return rit;<a name="line.1381"></a>
+<span class="sourceLineNo">1382</span> }<a name="line.1382"></a>
+<span class="sourceLineNo">1383</span><a name="line.1383"></a>
+<span class="sourceLineNo">1384</span> public static class RegionInTransitionStat {<a name="line.1384"></a>
+<span class="sourceLineNo">1385</span> private final int ritThreshold;<a name="line.1385"></a>
+<span class="sourceLineNo">1386</span><a name="line.1386"></a>
+<span class="sourceLineNo">1387</span> private HashMap<String, RegionState> ritsOverThreshold = null;<a name="line.1387"></a>
+<span class="sourceLineNo">1388</span> private long statTimestamp;<a name="line.1388"></a>
+<span class="sourceLineNo">1389</span> private long oldestRITTime = 0;<a name="line.1389"></a>
+<span class="sourceLineNo">1390</span> private int totalRITsTwiceThreshold = 0;<a name="line.1390"></a>
+<span class="sourceLineNo">1391</span> private int totalRITs = 0;<a name="line.1391"></a>
+<span class="sourceLineNo">1392</span><a name="line.1392"></a>
+<span class="sourceLineNo">1393</span> public RegionInTransitionStat(final Configuration conf) {<a name="line.1393"></a>
+<span class="sourceLineNo">1394</span> this.ritThreshold =<a name="line.1394"></a>
+<span class="sourceLineNo">1395</span> conf.getInt(METRICS_RIT_STUCK_WARNING_THRESHOLD, DEFAULT_RIT_STUCK_WARNING_THRESHOLD);<a name="line.1395"></a>
<span class="sourceLineNo">1396</span> }<a name="line.1396"></a>
<span class="sourceLineNo">1397</span><a name="line.1397"></a>
-<span class="sourceLineNo">1398</span> public int getTotalRITsOverThreshold() {<a name="line.1398"></a>
-<span class="sourceLineNo">1399</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1399"></a>
-<span class="sourceLineNo">1400</span> return m != null ? m.size() : 0;<a name="line.1400"></a>
-<span class="sourceLineNo">1401</span> }<a name="line.1401"></a>
-<span class="sourceLineNo">1402</span><a name="line.1402"></a>
-<span class="sourceLineNo">1403</span> public boolean hasRegionsTwiceOverThreshold() {<a name="line.1403"></a>
-<span class="sourceLineNo">1404</span> return totalRITsTwiceThreshold > 0;<a name="line.1404"></a>
-<span class="sourceLineNo">1405</span> }<a name="line.1405"></a>
-<span class="sourceLineNo">1406</span><a name="line.1406"></a>
-<span class="sourceLineNo">1407</span> public boolean hasRegionsOverThreshold() {<a name="line.1407"></a>
-<span class="sourceLineNo">1408</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1408"></a>
-<span class="sourceLineNo">1409</span> return m != null && !m.isEmpty();<a name="line.1409"></a>
-<span class="sourceLineNo">1410</span> }<a name="line.1410"></a>
-<span class="sourceLineNo">1411</span><a name="line.1411"></a>
-<span class="sourceLineNo">1412</span> public Collection<RegionState> getRegionOverThreshold() {<a name="line.1412"></a>
-<span class="sourceLineNo">1413</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1413"></a>
-<span class="sourceLineNo">1414</span> return m != null? m.values(): Collections.emptySet();<a name="line.1414"></a>
-<span class="sourceLineNo">1415</span> }<a name="line.1415"></a>
-<span class="sourceLineNo">1416</span><a name="line.1416"></a>
-<span class="sourceLineNo">1417</span> public boolean isRegionOverThreshold(final RegionInfo regionInfo) {<a name="line.1417"></a>
-<span class="sourceLineNo">1418</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1418"></a>
-<span class="sourceLineNo">1419</span> return m != null && m.containsKey(regionInfo.getEncodedName());<a name="line.1419"></a>
-<span class="sourceLineNo">1420</span> }<a name="line.1420"></a>
-<span class="sourceLineNo">1421</span><a name="line.1421"></a>
-<span class="sourceLineNo">1422</span> public boolean isRegionTwiceOverThreshold(final RegionInfo regionInfo) {<a name="line.1422"></a>
-<span class="sourceLineNo">1423</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1423"></a>
-<span class="sourceLineNo">1424</span> if (m == null) {<a name="line.1424"></a>
-<span class="sourceLineNo">1425</span> return false;<a name="line.1425"></a>
-<span class="sourceLineNo">1426</span> }<a name="line.1426"></a>
-<span class="sourceLineNo">1427</span> final RegionState state = m.get(regionInfo.getEncodedName());<a name="line.1427"></a>
-<span class="sourceLineNo">1428</span> if (state == null) {<a name="line.1428"></a>
-<span class="sourceLineNo">1429</span> return false;<a name="line.1429"></a>
-<span class="sourceLineNo">1430</span> }<a name="line.1430"></a>
-<span class="sourceLineNo">1431</span> return (statTimestamp - state.getStamp()) > (ritThreshold * 2);<a name="line.1431"></a>
-<span class="sourceLineNo">1432</span> }<a name="line.1432"></a>
-<span class="sourceLineNo">1433</span><a name="line.1433"></a>
-<span class="sourceLineNo">1434</span> protected void update(final AssignmentManager am) {<a name="line.1434"></a>
-<span class="sourceLineNo">1435</span> final RegionStates regionStates = am.getRegionStates();<a name="line.1435"></a>
-<span class="sourceLineNo">1436</span> this.statTimestamp = EnvironmentEdgeManager.currentTime();<a name="line.1436"></a>
-<span class="sourceLineNo">1437</span> update(regionStates.getRegionsStateInTransition(), statTimestamp);<a name="line.1437"></a>
-<span class="sourceLineNo">1438</span> update(regionStates.getRegionFailedOpen(), statTimestamp);<a name="line.1438"></a>
-<span class="sourceLineNo">1439</span><a name="line.1439"></a>
-<span class="sourceLineNo">1440</span> if (LOG.isDebugEnabled() && ritsOverThreshold != null && !ritsOverThreshold.isEmpty()) {<a name="line.1440"></a>
-<span class="sourceLineNo">1441</span> LOG.debug("RITs over threshold: {}",<a name="line.1441"></a>
-<span class="sourceLineNo">1442</span> ritsOverThreshold.entrySet().stream()<a name="line.1442"></a>
-<span class="sourceLineNo">1443</span> .map(e -> e.getKey() + ":" + e.getValue().getState().name())<a name="line.1443"></a>
-<span class="sourceLineNo">1444</span> .collect(Collectors.joining("\n")));<a name="line.1444"></a>
-<span class="sourceLineNo">1445</span> }<a name="line.1445"></a>
-<span class="sourceLineNo">1446</span> }<a name="line.1446"></a>
-<span class="sourceLineNo">1447</span><a name="line.1447"></a>
-<span class="sourceLineNo">1448</span> private void update(final Collection<RegionState> regions, final long currentTime) {<a name="line.1448"></a>
-<span class="sourceLineNo">1449</span> for (RegionState state: regions) {<a name="line.1449"></a>
-<span class="sourceLineNo">1450</span> totalRITs++;<a name="line.1450"></a>
-<span class="sourceLineNo">1451</span> final long ritStartedMs = state.getStamp();<a name="line.1451"></a>
-<span class="sourceLineNo">1452</span> if (ritStartedMs == 0) {<a name="line.1452"></a>
-<span class="sourceLineNo">1453</span> // Don't output bogus values to metrics if they accidentally make it here.<a name="line.1453"></a>
-<span class="sourceLineNo">1454</span> LOG.warn("The RIT {} has no start time", state.getRegion());<a name="line.1454"></a>
-<span class="sourceLineNo">1455</span> continue;<a name="line.1455"></a>
-<span class="sourceLineNo">1456</span> }<a name="line.1456"></a>
-<span class="sourceLineNo">1457</span> final long ritTime = currentTime - ritStartedMs;<a name="line.1457"></a>
-<span class="sourceLineNo">1458</span> if (ritTime > ritThreshold) {<a name="line.1458"></a>
-<span class="sourceLineNo">1459</span> if (ritsOverThreshold == null) {<a name="line.1459"></a>
-<span class="sourceLineNo">1460</span> ritsOverThreshold = new HashMap<String, RegionState>();<a name="line.1460"></a>
-<span class="sourceLineNo">1461</span> }<a name="line.1461"></a>
-<span class="sourceLineNo">1462</span> ritsOverThreshold.put(state.getRegion().getEncodedName(), state);<a name="line.1462"></a>
-<span class="sourceLineNo">1463</span> totalRITsTwiceThreshold += (ritTime > (ritThreshold * 2)) ? 1 : 0;<a name="line.1463"></a>
-<span class="sourceLineNo">1464</span> }<a name="line.1464"></a>
-<span class="sourceLineNo">1465</span> if (oldestRITTime < ritTime) {<a name="line.1465"></a>
-<span class="sourceLineNo">1466</span> oldestRITTime = ritTime;<a name="line.1466"></a>
-<span class="sourceLineNo">1467</span> }<a name="line.1467"></a>
-<span class="sourceLineNo">1468</span> }<a name="line.1468"></a>
-<span class="sourceLineNo">1469</span> }<a name="line.1469"></a>
-<span class="sourceLineNo">1470</span> }<a name="line.1470"></a>
-<span class="sourceLineNo">1471</span><a name="line.1471"></a>
-<span class="sourceLineNo">1472</span> private void updateRegionsInTransitionMetrics(final RegionInTransitionStat ritStat) {<a name="line.1472"></a>
-<span class="sourceLineNo">1473</span> metrics.updateRITOldestAge(ritStat.getOldestRITTime());<a name="line.1473"></a>
-<span class="sourceLineNo">1474</span> metrics.updateRITCount(ritStat.getTotalRITs());<a name="line.1474"></a>
-<span class="sourceLineNo">1475</span> metrics.updateRITCountOverThreshold(ritStat.getTotalRITsOverThreshold());<a name="line.1475"></a>
-<span class="sourceLineNo">1476</span> }<a name="line.1476"></a>
-<span class="sourceLineNo">1477</span><a name="line.1477"></a>
-<span class="sourceLineNo">1478</span> private void updateDeadServerRegionMetrics(int deadRegions, int unknownRegions) {<a name="line.1478"></a>
-<span class="sourceLineNo">1479</span> metrics.updateDeadServerOpenRegions(deadRegions);<a name="line.1479"></a>
-<span class="sourceLineNo">1480</span> metrics.updateUnknownServerOpenRegions(unknownRegions);<a name="line.1480"></a>
-<span class="sourceLineNo">1481</span> }<a name="line.1481"></a>
-<span class="sourceLineNo">1482</span><a name="line.1482"></a>
-<span class="sourceLineNo">1483</span> private void handleRegionOverStuckWarningThreshold(final RegionInfo regionInfo) {<a name="line.1483"></a>
-<span class="sourceLineNo">1484</span> final RegionStateNode regionNode = regionStates.getRegionStateNode(regionInfo);<a name="line.1484"></a>
-<span class="sourceLineNo">1485</span> //if (regionNode.isStuck()) {<a name="line.1485"></a>
-<span class="sourceLineNo">1486</span> LOG.warn("STUCK Region-In-Transition {}", regionNode);<a name="line.1486"></a>
-<span class="sourceLineNo">1487</span> }<a name="line.1487"></a>
-<span class="sourceLineNo">1488</span><a name="line.1488"></a>
-<span class="sourceLineNo">1489</span> // ============================================================================================<a name="line.1489"></a>
-<span class="sourceLineNo">1490</span> // TODO: Master load/bootstrap<a name="line.1490"></a>
-<span class="sourceLineNo">1491</span> // ============================================================================================<a name="line.1491"></a>
-<span class="sourceLineNo">1492</span> public void joinCluster() throws IOException {<a name="line.1492"></a>
-<span class="sourceLineNo">1493</span> long startTime = System.nanoTime();<a name="line.1493"></a>
-<span class="sourceLineNo">1494</span> LOG.debug("Joining cluster...");<a name="line.1494"></a>
-<span class="sourceLineNo">1495</span><a name="line.1495"></a>
-<span class="sourceLineNo">1496</span> // Scan hbase:meta to build list of existing regions, servers, and assignment.<a name="line.1496"></a>
-<span class="sourceLineNo">1497</span> // hbase:meta is online now or will be. Inside loadMeta, we keep trying. Can't make progress<a name="line.1497"></a>
-<span class="sourceLineNo">1498</span> // w/o meta.<a name="line.1498"></a>
-<span class="sourceLineNo">1499</span> loadMeta();<a name="line.1499"></a>
-<span class="sourceLineNo">1500</span><a name="line.1500"></a>
-<span class="sourceLineNo">1501</span> while (master.getServerManager().countOfRegionServers() < 1) {<a name="line.1501"></a>
-<span class="sourceLineNo">1502</span> LOG.info("Waiting for RegionServers to join; current count={}",<a name="line.1502"></a>
-<span class="sourceLineNo">1503</span> master.getServerManager().countOfRegionServers());<a name="line.1503"></a>
-<span class="sourceLineNo">1504</span> Threads.sleep(250);<a name="line.1504"></a>
-<span class="sourceLineNo">1505</span> }<a name="line.1505"></a>
-<span class="sourceLineNo">1506</span> LOG.info("Number of RegionServers={}", master.getServerManager().countOfRegionServers());<a name="line.1506"></a>
-<span class="sourceLineNo">1507</span><a name="line.1507"></a>
-<span class="sourceLineNo">1508</span> // Start the chores<a name="line.1508"></a>
-<span class="sourceLineNo">1509</span> master.getMasterProcedureExecutor().addChore(this.ritChore);<a name="line.1509"></a>
-<span class="sourceLineNo">1510</span> master.getMasterProcedureExecutor().addChore(this.deadMetricChore);<a name="line.1510"></a>
+<span class="sourceLineNo">1398</span> public int getRITThreshold() {<a name="line.1398"></a>
+<span class="sourceLineNo">1399</span> return ritThreshold;<a name="line.1399"></a>
+<span class="sourceLineNo">1400</span> }<a name="line.1400"></a>
+<span class="sourceLineNo">1401</span><a name="line.1401"></a>
+<span class="sourceLineNo">1402</span> public long getTimestamp() {<a name="line.1402"></a>
+<span class="sourceLineNo">1403</span> return statTimestamp;<a name="line.1403"></a>
+<span class="sourceLineNo">1404</span> }<a name="line.1404"></a>
+<span class="sourceLineNo">1405</span><a name="line.1405"></a>
+<span class="sourceLineNo">1406</span> public int getTotalRITs() {<a name="line.1406"></a>
+<span class="sourceLineNo">1407</span> return totalRITs;<a name="line.1407"></a>
+<span class="sourceLineNo">1408</span> }<a name="line.1408"></a>
+<span class="sourceLineNo">1409</span><a name="line.1409"></a>
+<span class="sourceLineNo">1410</span> public long getOldestRITTime() {<a name="line.1410"></a>
+<span class="sourceLineNo">1411</span> return oldestRITTime;<a name="line.1411"></a>
+<span class="sourceLineNo">1412</span> }<a name="line.1412"></a>
+<span class="sourceLineNo">1413</span><a name="line.1413"></a>
+<span class="sourceLineNo">1414</span> public int getTotalRITsOverThreshold() {<a name="line.1414"></a>
+<span class="sourceLineNo">1415</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1415"></a>
+<span class="sourceLineNo">1416</span> return m != null ? m.size() : 0;<a name="line.1416"></a>
+<span class="sourceLineNo">1417</span> }<a name="line.1417"></a>
+<span class="sourceLineNo">1418</span><a name="line.1418"></a>
+<span class="sourceLineNo">1419</span> public boolean hasRegionsTwiceOverThreshold() {<a name="line.1419"></a>
+<span class="sourceLineNo">1420</span> return totalRITsTwiceThreshold > 0;<a name="line.1420"></a>
+<span class="sourceLineNo">1421</span> }<a name="line.1421"></a>
+<span class="sourceLineNo">1422</span><a name="line.1422"></a>
+<span class="sourceLineNo">1423</span> public boolean hasRegionsOverThreshold() {<a name="line.1423"></a>
+<span class="sourceLineNo">1424</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1424"></a>
+<span class="sourceLineNo">1425</span> return m != null && !m.isEmpty();<a name="line.1425"></a>
+<span class="sourceLineNo">1426</span> }<a name="line.1426"></a>
+<span class="sourceLineNo">1427</span><a name="line.1427"></a>
+<span class="sourceLineNo">1428</span> public Collection<RegionState> getRegionOverThreshold() {<a name="line.1428"></a>
+<span class="sourceLineNo">1429</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1429"></a>
+<span class="sourceLineNo">1430</span> return m != null? m.values(): Collections.emptySet();<a name="line.1430"></a>
+<span class="sourceLineNo">1431</span> }<a name="line.1431"></a>
+<span class="sourceLineNo">1432</span><a name="line.1432"></a>
+<span class="sourceLineNo">1433</span> public boolean isRegionOverThreshold(final RegionInfo regionInfo) {<a name="line.1433"></a>
+<span class="sourceLineNo">1434</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1434"></a>
+<span class="sourceLineNo">1435</span> return m != null && m.containsKey(regionInfo.getEncodedName());<a name="line.1435"></a>
+<span class="sourceLineNo">1436</span> }<a name="line.1436"></a>
+<span class="sourceLineNo">1437</span><a name="line.1437"></a>
+<span class="sourceLineNo">1438</span> public boolean isRegionTwiceOverThreshold(final RegionInfo regionInfo) {<a name="line.1438"></a>
+<span class="sourceLineNo">1439</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1439"></a>
+<span class="sourceLineNo">1440</span> if (m == null) {<a name="line.1440"></a>
+<span class="sourceLineNo">1441</span> return false;<a name="line.1441"></a>
+<span class="sourceLineNo">1442</span> }<a name="line.1442"></a>
+<span class="sourceLineNo">1443</span> final RegionState state = m.get(regionInfo.getEncodedName());<a name="line.1443"></a>
+<span class="sourceLineNo">1444</span> if (state == null) {<a name="line.1444"></a>
+<span class="sourceLineNo">1445</span> return false;<a name="line.1445"></a>
+<span class="sourceLineNo">1446</span> }<a name="line.1446"></a>
+<span class="sourceLineNo">1447</span> return (statTimestamp - state.getStamp()) > (ritThreshold * 2);<a name="line.1447"></a>
+<span class="sourceLineNo">1448</span> }<a name="line.1448"></a>
+<span class="sourceLineNo">1449</span><a name="line.1449"></a>
+<span class="sourceLineNo">1450</span> protected void update(final AssignmentManager am) {<a name="line.1450"></a>
+<span class="sourceLineNo">1451</span> final RegionStates regionStates = am.getRegionStates();<a name="line.1451"></a>
+<span class="sourceLineNo">1452</span> this.statTimestamp = EnvironmentEdgeManager.currentTime();<a name="line.1452"></a>
+<span class="sourceLineNo">1453</span> update(regionStates.getRegionsStateInTransition(), statTimestamp);<a name="line.1453"></a>
+<span class="sourceLineNo">1454</span> update(regionStates.getRegionFailedOpen(), statTimestamp);<a name="line.1454"></a>
+<span class="sourceLineNo">1455</span><a name="line.1455"></a>
+<span class="sourceLineNo">1456</span> if (LOG.isDebugEnabled() && ritsOverThreshold != null && !ritsOverThreshold.isEmpty()) {<a name="line.1456"></a>
+<span class="sourceLineNo">1457</span> LOG.debug("RITs over threshold: {}",<a name="line.1457"></a>
+<span class="sourceLineNo">1458</span> ritsOverThreshold.entrySet().stream()<a name="line.1458"></a>
+<span class="sourceLineNo">1459</span> .map(e -> e.getKey() + ":" + e.getValue().getState().name())<a name="line.1459"></a>
+<span class="sourceLineNo">1460</span> .collect(Collectors.joining("\n")));<a name="line.1460"></a>
+<span class="sourceLineNo">1461</span> }<a name="line.1461"></a>
+<span class="sourceLineNo">1462</span> }<a name="line.1462"></a>
+<span class="sourceLineNo">1463</span><a name="line.1463"></a>
+<span class="sourceLineNo">1464</span> private void update(final Collection<RegionState> regions, final long currentTime) {<a name="line.1464"></a>
+<span class="sourceLineNo">1465</span> for (RegionState state: regions) {<a name="line.1465"></a>
+<span class="sourceLineNo">1466</span> totalRITs++;<a name="line.1466"></a>
+<span class="sourceLineNo">1467</span> final long ritStartedMs = state.getStamp();<a name="line.1467"></a>
+<span class="sourceLineNo">1468</span> if (ritStartedMs == 0) {<a name="line.1468"></a>
+<span class="sourceLineNo">1469</span> // Don't output bogus values to metrics if they accidentally make it here.<a name="line.1469"></a>
+<span class="sourceLineNo">1470</span> LOG.warn("The RIT {} has no start time", state.getRegion());<a name="line.1470"></a>
+<span class="sourceLineNo">1471</span> continue;<a name="line.1471"></a>
+<span class="sourceLineNo">1472</span> }<a name="line.1472"></a>
+<span class="sourceLineNo">1473</span> final long ritTime = currentTime - ritStartedMs;<a name="line.1473"></a>
+<span class="sourceLineNo">1474</span> if (ritTime > ritThreshold) {<a name="line.1474"></a>
+<span class="sourceLineNo">1475</span> if (ritsOverThreshold == null) {<a name="line.1475"></a>
+<span class="sourceLineNo">1476</span> ritsOverThreshold = new HashMap<String, RegionState>();<a name="line.1476"></a>
+<span class="sourceLineNo">1477</span> }<a name="line.1477"></a>
+<span class="sourceLineNo">1478</span> ritsOverThreshold.put(state.getRegion().getEncodedName(), state);<a name="line.1478"></a>
+<span class="sourceLineNo">1479</span> totalRITsTwiceThreshold += (ritTime > (ritThreshold * 2)) ? 1 : 0;<a name="line.1479"></a>
+<span class="sourceLineNo">1480</span> }<a name="line.1480"></a>
+<span class="sourceLineNo">1481</span> if (oldestRITTime < ritTime) {<a name="line.1481"></a>
+<span class="sourceLineNo">1482</span> oldestRITTime = ritTime;<a name="line.1482"></a>
+<span class="sourceLineNo">1483</span> }<a name="line.1483"></a>
+<span class="sourceLineNo">1484</span> }<a name="line.1484"></a>
+<span class="sourceLineNo">1485</span> }<a name="line.1485"></a>
+<span class="sourceLineNo">1486</span> }<a name="line.1486"></a>
+<span class="sourceLineNo">1487</span><a name="line.1487"></a>
+<span class="sourceLineNo">1488</span> private void updateRegionsInTransitionMetrics(final RegionInTransitionStat ritStat) {<a name="line.1488"></a>
+<span class="sourceLineNo">1489</span> metrics.updateRITOldestAge(ritStat.getOldestRITTime());<a name="line.1489"></a>
+<span class="sourceLineNo">1490</span> metrics.updateRITCount(ritStat.getTotalRITs());<a name="line.1490"></a>
+<span class="sourceLineNo">1491</span> metrics.updateRITCountOverThreshold(ritStat.getTotalRITsOverThreshold());<a name="line.1491"></a>
+<span class="sourceLineNo">1492</span> }<a name="line.1492"></a>
+<span class="sourceLineNo">1493</span><a name="line.1493"></a>
+<span class="sourceLineNo">1494</span> private void updateDeadServerRegionMetrics(int deadRegions, int unknownRegions) {<a name="line.1494"></a>
+<span class="sourceLineNo">1495</span> metrics.updateDeadServerOpenRegions(deadRegions);<a name="line.1495"></a>
+<span class="sourceLineNo">1496</span> metrics.updateUnknownServerOpenRegions(unknownRegions);<a name="line.1496"></a>
+<span class="sourceLineNo">1497</span> }<a name="line.1497"></a>
+<span class="sourceLineNo">1498</span><a name="line.1498"></a>
+<span class="sourceLineNo">1499</span> private void handleRegionOverStuckWarningThreshold(final RegionInfo regionInfo) {<a name="line.1499"></a>
+<span class="sourceLineNo">1500</span> final RegionStateNode regionNode = regionStates.getRegionStateNode(regionInfo);<a name="line.1500"></a>
+<span class="sourceLineNo">1501</span> //if (regionNode.isStuck()) {<a name="line.1501"></a>
+<span class="sourceLineNo">1502</span> LOG.warn("STUCK Region-In-Transition {}", regionNode);<a name="line.1502"></a>
+<span class="sourceLineNo">1503</span> }<a name="line.1503"></a>
+<span class="sourceLineNo">1504</span><a name="line.1504"></a>
+<span class="sourceLineNo">1505</span> // ============================================================================================<a name="line.1505"></a>
+<span class="sourceLineNo">1506</span> // TODO: Master load/bootstrap<a name="line.1506"></a>
+<span class="sourceLineNo">1507</span> // ============================================================================================<a name="line.1507"></a>
+<span class="sourceLineNo">1508</span> public void joinCluster() throws IOException {<a name="line.1508"></a>
+<span class="sourceLineNo">1509</span> long startTime = System.nanoTime();<a name="line.1509"></a>
+<span class="sourceLineNo">1510</span> LOG.debug("Joining cluster...");<a name="line.1510"></a>
<span class="sourceLineNo">1511</span><a name="line.1511"></a>
-<span class="sourceLineNo">1512</span> long costMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);<a name="line.1512"></a>
-<span class="sourceLineNo">1513</span> LOG.info("Joined the cluster in {}", StringUtils.humanTimeDiff(costMs));<a name="line.1513"></a>
-<span class="sourceLineNo">1514</span> }<a name="line.1514"></a>
-<span class="sourceLineNo">1515</span><a name="line.1515"></a>
-<span class="sourceLineNo">1516</span> /**<a name="line.1516"></a>
-<span class="sourceLineNo">1517</span> * Create assign procedure for offline regions.<a name="line.1517"></a>
-<span class="sourceLineNo">1518</span> * Just follow the old processofflineServersWithOnlineRegions method. Since now we do not need to<a name="line.1518"></a>
-<span class="sourceLineNo">1519</span> * deal with dead server any more, we only deal with the regions in OFFLINE state in this method.<a name="line.1519"></a>
-<span class="sourceLineNo">1520</span> * And this is a bit strange, that for new regions, we will add it in CLOSED state instead of<a name="line.1520"></a>
-<span class="sourceLineNo">1521</span> * OFFLINE state, and usually there will be a procedure to track them. The<a name="line.1521"></a>
-<span class="sourceLineNo">1522</span> * processofflineServersWithOnlineRegions is a legacy from long ago, as things are going really<a name="line.1522"></a>
-<span class="sourceLineNo">1523</span> * different now, maybe we do not need this method any more. Need to revisit later.<a name="line.1523"></a>
-<span class="sourceLineNo">1524</span> */<a name="line.1524"></a>
-<span class="sourceLineNo">1525</span> // Public so can be run by the Master as part of the startup. Needs hbase:meta to be online.<a name="line.1525"></a>
-<span class="sourceLineNo">1526</span> // Needs to be done after the table state manager has been started.<a name="line.1526"></a>
-<span class="sourceLineNo">1527</span> public void processOfflineRegions() {<a name="line.1527"></a>
-<span class="sourceLineNo">1528</span> TransitRegionStateProcedure[] procs =<a name="line.1528"></a>
-<span class="sourceLineNo">1529</span> regionStates.getRegionStateNodes().stream().filter(rsn -> rsn.isInState(State.OFFLINE))<a name="line.1529"></a>
-<span class="sourceLineNo">1530</span> .filter(rsn -> isTableEnabled(rsn.getRegionInfo().getTable())).map(rsn -> {<a name="line.1530"></a>
-<span class="sourceLineNo">1531</span> rsn.lock();<a name="line.1531"></a>
-<span class="sourceLineNo">1532</span> try {<a name="line.1532"></a>
-<span class="sourceLineNo">1533</span> if (rsn.getProcedure() != null) {<a name="line.1533"></a>
-<span class="sourceLineNo">1534</span> return null;<a name="line.1534"></a>
-<span class="sourceLineNo">1535</span> } else {<a name="line.1535"></a>
-<span class="sourceLineNo">1536</span> return rsn.setProcedure(TransitRegionStateProcedure.assign(getProcedureEnvironment(),<a name="line.1536"></a>
-<span class="sourceLineNo">1537</span> rsn.getRegionInfo(), null));<a name="line.1537"></a>
-<span class="sourceLineNo">1538</span> }<a name="line.1538"></a>
-<span class="sourceLineNo">1539</span> } finally {<a name="line.1539"></a>
-<span class="sourceLineNo">1540</span> rsn.unlock();<a name="line.1540"></a>
-<span class="sourceLineNo">1541</span> }<a name="line.1541"></a>
-<span class="sourceLineNo">1542</span> }).filter(p -> p != null).toArray(TransitRegionStateProcedure[]::new);<a name="line.1542"></a>
-<span class="sourceLineNo">1543</span> if (procs.length > 0) {<a name="line.1543"></a>
-<span class="sourceLineNo">1544</span> master.getMasterProcedureExecutor().submitProcedures(procs);<a name="line.1544"></a>
-<span class="sourceLineNo">1545</span> }<a name="line.1545"></a>
-<span class="sourceLineNo">1546</span> }<a name="line.1546"></a>
-<span class="sourceLineNo">1547</span><a name="line.1547"></a>
-<span class="sourceLineNo">1548</span> /* AM internal RegionStateStore.RegionStateVisitor implementation. To be used when<a name="line.1548"></a>
-<span class="sourceLineNo">1549</span> * scanning META table for region rows, using RegionStateStore utility methods. RegionStateStore<a name="line.1549"></a>
-<span class="sourceLineNo">1550</span> * methods will convert Result into proper RegionInfo instances, but those would still need to be<a name="line.1550"></a>
-<span class="sourceLineNo">1551</span> * added into AssignmentManager.regionStates in-memory cache.<a name="line.1551"></a>
-<span class="sourceLineNo">1552</span> * RegionMetaLoadingVisitor.visitRegionState method provides the logic for adding RegionInfo<a name="line.1552"></a>
-<span class="sourceLineNo">1553</span> * instances as loaded from latest META scan into AssignmentManager.regionStates.<a name="line.1553"></a>
-<span class="sourceLineNo">1554</span> */<a name="line.1554"></a>
-<span class="sourceLineNo">1555</span> private class RegionMetaLoadingVisitor implements RegionStateStore.RegionStateVisitor {<a name="line.1555"></a>
-<span class="sourceLineNo">1556</span><a name="line.1556"></a>
-<span class="sourceLineNo">1557</span> @Override<a name="line.1557"></a>
-<span class="sourceLineNo">1558</span> public void visitRegionState(Result result, final RegionInfo regionInfo, final State state,<a name="line.1558"></a>
-<span class="sourceLineNo">1559</span> final ServerName regionLocation, final ServerName lastHost, final long openSeqNum) {<a name="line.1559"></a>
-<span class="sourceLineNo">1560</span> if (state == null && regionLocation == null && lastHost == null &&<a name="line.1560"></a>
-<span class="sourceLineNo">1561</span> openSeqNum == SequenceId.NO_SEQUENCE_ID) {<a name="line.1561"></a>
-<span class="sourceLineNo">1562</span> // This is a row with nothing in it.<a name="line.1562"></a>
-<span class="sourceLineNo">1563</span> LOG.warn("Skipping empty row={}", result);<a name="line.1563"></a>
-<span class="sourceLineNo">1564</span> return;<a name="line.1564"></a>
-<span class="sourceLineNo">1565</span> }<a name="line.1565"></a>
-<span class="sourceLineNo">1566</span> State localState = state;<a name="line.1566"></a>
-<span class="sourceLineNo">1567</span> if (localState == null) {<a name="line.1567"></a>
-<span class="sourceLineNo">1568</span> // No region state column data in hbase:meta table! Are I doing a rolling upgrade from<a name="line.1568"></a>
-<span class="sourceLineNo">1569</span> // hbase1 to hbase2? Am I restoring a SNAPSHOT or otherwise adding a region to hbase:meta?<a name="line.1569"></a>
-<span class="sourceLineNo">1570</span> // In any of these cases, state is empty. For now, presume OFFLINE but there are probably<a name="line.1570"></a>
-<span class="sourceLineNo">1571</span> // cases where we need to probe more to be sure this correct; TODO informed by experience.<a name="line.1571"></a>
-<span class="sourceLineNo">1572</span> LOG.info(regionInfo.getEncodedName() + " regionState=null; presuming " + State.OFFLINE);<a name="line.1572"></a>
-<span class="sourceLineNo">1573</span> localState = State.OFFLINE;<a name="line.1573"></a>
-<span class="sourceLineNo">1574</span> }<a name="line.1574"></a>
-<span class="sourceLineNo">1575</span> RegionStateNode regionNode = regionStates.getOrCreateRegionStateNode(regionInfo);<a name="line.1575"></a>
-<span class="sourceLineNo">1576</span> // Do not need to lock on regionNode, as we can make sure that before we finish loading<a name="line.1576"></a>
-<span class="sourceLineNo">1577</span> // meta, all the related procedures can not be executed. The only exception is for meta<a name="line.1577"></a>
-<span class="sourceLineNo">1578</span> // region related operations, but here we do not load the informations for meta region.<a name="line.1578"></a>
-<span class="sourceLineNo">1579</span> regionNode.setState(localState);<a name="line.1579"></a>
-<span class="sourceLineNo">1580</span> regionNode.setLastHost(lastHost);<a name="line.1580"></a>
-<span class="sourceLineNo">1581</span> regionNode.setRegionLocation(regionLocation);<a name="line.1581"></a>
-<span class="sourceLineNo">1582</span> regionNode.setOpenSeqNum(openSeqNum);<a name="line.1582"></a>
-<span class="sourceLineNo">1583</span><a name="line.1583"></a>
-<span class="sourceLineNo">1584</span> // Note: keep consistent with other methods, see region(Opening|Opened|Closing)<a name="line.1584"></a>
-<span class="sourceLineNo">1585</span> // RIT/ServerCrash handling should take care of the transiting regions.<a name="line.1585"></a>
-<span class="sourceLineNo">1586</span> if (localState.matches(State.OPEN, State.OPENING, State.CLOSING, State.SPLITTING,<a name="line.1586"></a>
-<span class="sourceLineNo">1587</span> State.MERGING)) {<a name="line.1587"></a>
-<span class="sourceLineNo">1588</span> assert regionLocation != null : "found null region location for " + regionNode;<a name="line.1588"></a>
-<span class="sourceLineNo">1589</span> regionStates.addRegionToServer(regionNode);<a name="line.1589"></a>
-<span class="sourceLineNo">1590</span> } else if (localState == State.OFFLINE || regionInfo.isOffline()) {<a name="line.1590"></a>
-<span class="sourceLineNo">1591</span> regionStates.addToOfflineRegions(regionNode);<a name="line.1591"></a>
-<span class="sourceLineNo">1592</span> }<a name="line.1592"></a>
-<span class="sourceLineNo">1593</span> if (regionNode.getProcedure() != null) {<a name="line.1593"></a>
-<span class="sourceLineNo">1594</span> regionNode.getProcedure().stateLoaded(AssignmentManager.this, regionNode);<a name="line.1594"></a>
-<span class="sourceLineNo">1595</span> }<a name="line.1595"></a>
-<span class="sourceLineNo">1596</span> }<a name="line.1596"></a>
-<span class="sourceLineNo">1597</span> };<a name="line.1597"></a>
-<span class="sourceLineNo">1598</span><a name="line.1598"></a>
-<span class="sourceLineNo">1599</span> /**<a name="line.1599"></a>
-<span class="sourceLineNo">1600</span> * Query META if the given <code>RegionInfo</code> exists, adding to<a name="line.1600"></a>
-<span class="sourceLineNo">1601</span> * <code>AssignmentManager.regionStateStore</code> cache if the region is found in META.<a name="line.1601"></a>
-<span class="sourceLineNo">1602</span> * @param regionEncodedName encoded name for the region to be loaded from META into<a name="line.1602"></a>
-<span class="sourceLineNo">1603</span> * <code>AssignmentManager.regionStateStore</code> cache<a name="line.1603"></a>
-<span class="sourceLineNo">1604</span> * @return <code>RegionInfo</code> instance for the given region if it is present in META<a name="line.1604"></a>
-<span class="sourceLineNo">1605</span> * and got successfully loaded into <code>AssignmentManager.regionStateStore</code><a name="line.1605"></a>
-<span class="sourceLineNo">1606</span> * cache, <b>null</b> otherwise.<a name="line.1606"></a>
-<span class="sourceLineNo">1607</span> * @throws UnknownRegionException if any errors occur while querying meta.<a name="line.1607"></a>
-<span class="sourceLineNo">1608</span> */<a name="line.1608"></a>
-<span class="sourceLineNo">1609</span> public RegionInfo loadRegionFromMeta(String regionEncodedName) throws UnknownRegionException {<a name="line.1609"></a>
-<span class="sourceLineNo">1610</span> try {<a name="line.1610"></a>
-<span class="sourceLineNo">1611</span> RegionMetaLoadingVisitor visitor = new RegionMetaLoadingVisitor();<a name="line.1611"></a>
-<span class="sourceLineNo">1612</span> regionStateStore.visitMetaForRegion(regionEncodedName, visitor);<a name="line.1612"></a>
-<span class="sourceLineNo">1613</span> return regionStates.getRegionState(regionEncodedName) == null ? null :<a name="line.1613"></a>
-<span class="sourceLineNo">1614</span> regionStates.getRegionState(regionEncodedName).getRegion();<a name="line.1614"></a>
-<span class="sourceLineNo">1615</span> } catch(IOException e) {<a name="line.1615"></a>
-<span class="sourceLineNo">1616</span> LOG.error("Error trying to load region {} from META", regionEncodedName, e);<a name="line.1616"></a>
-<span class="sourceLineNo">1617</span> throw new UnknownRegionException("Error while trying load region from meta");<a name="line.1617"></a>
-<span class="sourceLineNo">1618</span> }<a name="line.1618"></a>
-<span class="sourceLineNo">1619</span> }<a name="line.1619"></a>
-<span class="sourceLineNo">1620</span><a name="line.1620"></a>
-<span class="sourceLineNo">1621</span> private void loadMeta() throws IOException {<a name="line.1621"></a>
-<span class="sourceLineNo">1622</span> // TODO: use a thread pool<a name="line.1622"></a>
-<span class="sourceLineNo">1623</span> regionStateStore.visitMeta(new RegionMetaLoadingVisitor());<a name="line.1623"></a>
-<span class="sourceLineNo">1624</span> }<a name="line.1624"></a>
-<span class="sourceLineNo">1625</span><a name="line.1625"></a>
-<span class="sourceLineNo">1626</span> /**<a name="line.1626"></a>
-<span class="sourceLineNo">1627</span> * Used to check if the meta loading is done.<a name="line.1627"></a>
-<span class="sourceLineNo">1628</span> * <p/><a name="line.1628"></a>
-<span class="sourceLineNo">1629</span> * if not we throw PleaseHoldException since we are rebuilding the RegionStates<a name="line.1629"></a>
-<span class="sourceLineNo">1630</span> * @param hri region to check if it is already rebuild<a name="line.1630"></a>
-<span class="sourceLineNo">1631</span> * @throws PleaseHoldException if meta has not been loaded yet<a name="line.1631"></a>
-<span class="sourceLineNo">1632</span> */<a name="line.1632"></a>
-<span class="sourceLineNo">1633</span> private void checkMetaLoaded(RegionInfo hri) throws PleaseHoldException {<a name="line.1633"></a>
-<span class="sourceLineNo">1634</span> if (!isRunning()) {<a name="line.1634"></a>
-<span class="sourceLineNo">1635</span> throw new PleaseHoldException("AssignmentManager not running");<a name="line.1635"></a>
-<span class="sourceLineNo">1636</span> }<a name="line.1636"></a>
-<span class="sourceLineNo">1637</span> boolean meta = isMetaRegion(hri);<a name="line.1637"></a>
-<span class="sourceLineNo">1638</span> boolean metaLoaded = isMetaLoaded();<a name="line.1638"></a>
-<span class="sourceLineNo">1639</span> if (!meta && !metaLoaded) {<a name="line.1639"></a>
-<span class="sourceLineNo">1640</span> throw new PleaseHoldException(<a name="line.1640"></a>
-<span class="sourceLineNo">1641</span> "Master not fully online; hbase:meta=" + meta + ", metaLoaded=" + metaLoaded);<a name="line.1641"></a>
-<span class="sourceLineNo">1642</span> }<a name="line.1642"></a>
-<span class="sourceLineNo">1643</span> }<a name="line.1643"></a>
-<span class="sourceLineNo">1644</span><a name="line.1644"></a>
-<span class="sourceLineNo">1645</span> // ============================================================================================<a name="line.1645"></a>
-<span class="sourceLineNo">1646</span> // TODO: Metrics<a name="line.1646"></a>
-<span class="sourceLineNo">1647</span> // ============================================================================================<a name="line.1647"></a>
-<span class="sourceLineNo">1648</span> public int getNumRegionsOpened() {<a name="line.1648"></a>
-<span class="sourceLineNo">1649</span> // TODO: Used by TestRegionPlacement.java and assume monotonically increasing value<a name="line.1649"></a>
-<span class="sourceLineNo">1650</span> return 0;<a name="line.1650"></a>
-<span class="sourceLineNo">1651</span> }<a name="line.1651"></a>
-<span class="sourceLineNo">1652</span><a name="line.1652"></a>
-<span class="sourceLineNo">1653</span> /**<a name="line.1653"></a>
-<span class="sourceLineNo">1654</span> * Usually run by the Master in reaction to server crash during normal processing.<a name="line.1654"></a>
-<span class="sourceLineNo">1655</span> * Can also be invoked via external RPC to effect repair; in the latter case,<a name="line.1655"></a>
-<span class="sourceLineNo">1656</span> * the 'force' flag is set so we push through the SCP though context may indicate<a name="line.1656"></a>
-<span class="sourceLineNo">1657</span> * already-running-SCP (An old SCP may have exited abnormally, or damaged cluster<a name="line.1657"></a>
-<span class="sourceLineNo">1658</span> * may still have references in hbase:meta to 'Unknown Servers' -- servers that<a name="line.1658"></a>
-<span class="sourceLineNo">1659</span> * are not online or in dead servers list, etc.)<a name="line.1659"></a>
-<span class="sourceLineNo">1660</span> * @param force Set if the request came in externally over RPC (via hbck2). Force means<a name="line.1660"></a>
-<span class="sourceLineNo">1661</span> * run the SCP even if it seems as though there might be an outstanding<a name="line.1661"></a>
-<span class="sourceLineNo">1662</span> * SCP running.<a name="line.1662"></a>
-<span class="sourceLineNo">1663</span> * @return pid of scheduled SCP or {@link Procedure#NO_PROC_ID} if none scheduled.<a name="line.1663"></a>
-<span class="sourceLineNo">1664</span> */<a name="line.1664"></a>
-<span class="sourceLineNo">1665</span> public long submitServerCrash(ServerName serverName, boolean shouldSplitWal, boolean force) {<a name="line.1665"></a>
-<span class="sourceLineNo">1666</span> // May be an 'Unknown Server' so handle case where serverNode is null.<a name="line.1666"></a>
-<span class="sourceLineNo">1667</span> ServerStateNode serverNode = regionStates.getServerNode(serverName);<a name="line.1667"></a>
-<span class="sourceLineNo">1668</span> // Remove the in-memory rsReports result<a name="line.1668"></a>
-<span class="sourceLineNo">1669</span> synchronized (rsReports) {<a name="line.1669"></a>
-<span class="sourceLineNo">1670</span> rsReports.remove(serverName);<a name="line.1670"></a>
-<span class="sourceLineNo">1671</span> }<a name="line.1671"></a>
-<span class="sourceLineNo">1672</span><a name="line.1672"></a>
-<span class="sourceLineNo">1673</span> // We hold the write lock here for fencing on reportRegionStateTransition. Once we set the<a name="line.1673"></a>
-<span class="sourceLineNo">1674</span> // server state to CRASHED, we will no longer accept the reportRegionStateTransition call from<a name="line.1674"></a>
-<span class="sourceLineNo">1675</span> // this server. This is used to simplify the implementation for TRSP and SCP, where we can make<a name="line.1675"></a>
-<span class="sourceLineNo">1676</span> // sure that, the region list fetched by SCP will not be changed any more.<a name="line.1676"></a>
-<span class="sourceLineNo">1677</span> if (serverNode != null) {<a name="line.1677"></a>
-<span class="sourceLineNo">1678</span> serverNode.writeLock().lock();<a name="line.1678"></a>
-<span class="sourceLineNo">1679</span> }<a name="line.1679"></a>
-<span class="sourceLineNo">1680</span> boolean carryingMeta;<a name="line.1680"></a>
-<span class="sourceLineNo">1681</span> long pid;<a name="line.1681"></a>
-<span class="sourceLineNo">1682</span> try {<a name="line.1682"></a>
-<span class="sourceLineNo">1683</span> ProcedureExecutor<MasterProcedureEnv> procExec = this.master.getMasterProcedureExecutor();<a name="line.1683"></a>
-<span class="sourceLineNo">1684</span> carryingMeta = isCarryingMeta(serverName);<a name="line.1684"></a>
-<span class="sourceLineNo">1685</span> if (!force && serverNode != null && !serverNode.isInState(ServerState.ONLINE)) {<a name="line.1685"></a>
-<span class="sourceLineNo">1686</span> LOG.info("Skip adding ServerCrashProcedure for {} (meta={}) -- running?",<a name="line.1686"></a>
-<span class="sourceLineNo">1687</span> serverNode, carryingMeta);<a name="line.1687"></a>
-<span class="sourceLineNo">1688</span> return Procedure.NO_PROC_ID;<a name="line.1688"></a>
-<span class="sourceLineNo">1689</span> } else {<a name="line.1689"></a>
-<span class="sourceLineNo">1690</span> MasterProcedureEnv mpe = procExec.getEnvironment();<a name="line.1690"></a>
-<span class="sourceLineNo">1691</span> // If serverNode == null, then 'Unknown Server'. Schedule HBCKSCP instead.<a name="line.1691"></a>
-<span class="sourceLineNo">1692</span> // HBCKSCP scours Master in-memory state AND hbase;meta for references to<a name="line.1692"></a>
-<span class="sourceLineNo">1693</span> // serverName just-in-case. An SCP that is scheduled when the server is<a name="line.1693"></a>
-<span class="sourceLineNo">1694</span> // 'Unknown' probably originated externally with HBCK2 fix-it tool.<a name="line.1694"></a>
-<span class="sourceLineNo">1695</span> ServerState oldState = null;<a name="line.1695"></a>
-<span class="sourceLineNo">1696</span> if (serverNode != null) {<a name="line.1696"></a>
-<span class="sourceLineNo">1697</span> oldState = serverNode.getState();<a name="line.1697"></a>
-<span class="sourceLineNo">1698</span> serverNode.setState(ServerState.CRASHED);<a name="line.1698"></a>
-<span class="sourceLineNo">1699</span> }<a name="line.1699"></a>
-<span class="sourceLineNo">1700</span><a name="line.1700"></a>
-<span class="sourceLineNo">1701</span> if (force) {<a name="line.1701"></a>
-<span class="sourceLineNo">1702</span> pid = procExec.submitProcedure(<a name="line.1702"></a>
-<span class="sourceLineNo">1703</span> new HBCKServerCrashProcedure(mpe, serverName, shouldSplitWal, carryingMeta));<a name="line.1703"></a>
-<span class="sourceLineNo">1704</span> } else {<a name="line.1704"></a>
-<span class="sourceLineNo">1705</span> pid = procExec.submitProcedure(<a name="line.1705"></a>
-<span class="sourceLineNo">1706</span> new ServerCrashProcedure(mpe, serverName, shouldSplitWal, carryingMeta));<a name="line.1706"></a>
-<span class="sourceLineNo">1707</span> }<a name="line.1707"></a>
-<span class="sourceLineNo">1708</span> LOG.info("Scheduled ServerCrashProcedure pid={} for {} (carryingMeta={}){}.",<a name="line.1708"></a>
-<span class="sourceLineNo">1709</span> pid, serverName, carryingMeta,<a name="line.1709"></a>
-<span class="sourceLineNo">1710</span> serverNode == null? "": " " + serverNode.toString() + ", oldState=" + oldState);<a name="line.1710"></a>
-<span class="sourceLineNo">1711</span> }<a name="line.1711"></a>
-<span class="sourceLineNo">1712</span> } finally {<a name="line.1712"></a>
-<span class="sourceLineNo">1713</span> if (serverNode != null) {<a name="line.1713"></a>
-<span class="sourceLineNo">1714</span> serverNode.writeLock().unlock();<a name="line.1714"></a>
-<span class="sourceLineNo">1715</span> }<a name="line.1715"></a>
-<span class="sourceLineNo">1716</span> }<a name="line.1716"></a>
-<span class="sourceLineNo">1717</span> return pid;<a name="line.1717"></a>
-<span class="sourceLineNo">1718</span> }<a name="line.1718"></a>
-<span class="sourceLineNo">1719</span><a name="line.1719"></a>
-<span class="sourceLineNo">1720</span> public void offlineRegion(final RegionInfo regionInfo) {<a name="line.1720"></a>
-<span class="sourceLineNo">1721</span> // TODO used by MasterRpcServices<a name="line.1721"></a>
-<span class="sourceLineNo">1722</span> RegionStateNode node = regionStates.getRegionStateNode(regionInfo);<a name="line.1722"></a>
-<span class="sourceLineNo">1723</span> if (node != null) {<a name="line.1723"></a>
-<span class="sourceLineNo">1724</span> node.offline();<a name="line.1724"></a>
-<span class="sourceLineNo">1725</span> }<a name="line.1725"></a>
-<span class="sourceLineNo">1726</span> }<a name="line.1726"></a>
-<span class="sourceLineNo">1727</span><a name="line.1727"></a>
-<span class="sourceLineNo">1728</span> public void onlineRegion(final RegionInfo regionInfo, final ServerName serverName) {<a name="line.1728"></a>
-<span class="sourceLineNo">1729</span> // TODO used by TestSplitTransactionOnCluster.java<a name="line.1729"></a>
-<span class="sourceLineNo">1730</span> }<a name="line.1730"></a>
-<span class="sourceLineNo">1731</span><a name="line.1731"></a>
-<span class="sourceLineNo">1732</span> public Map<ServerName, List<RegionInfo>> getSnapShotOfAssignment(<a name="line.1732"></a>
-<span class="sourceLineNo">1733</span> final Collection<RegionInfo> regions) {<a name="line.1733"></a>
-<span class="sourceLineNo">1734</span> return regionStates.getSnapShotOfAssignment(regions);<a name="line.1734"></a>
-<span class="sourceLineNo">1735</span> }<a name="line.1735"></a>
-<span class="sourceLineNo">1736</span><a name="line.1736"></a>
-<span class="sourceLineNo">1737</span> // ============================================================================================<a name="line.1737"></a>
-<span class="sourceLineNo">1738</span> // TODO: UTILS/HELPERS?<a name="line.1738"></a>
-<span class="sourceLineNo">1739</span> // ============================================================================================<a name="line.1739"></a>
-<span class="sourceLineNo">1740</span> /**<a name="line.1740"></a>
-<span class="sourceLineNo">1741</span> * Used by the client (via master) to identify if all regions have the schema updates<a name="line.1741"></a>
-<span class="sourceLineNo">1742</span> * @return Pair indicating the status of the alter command (pending/total)<a name="line.1742"></a>
-<span class="sourceLineNo">1743</span> */<a name="line.1743"></a>
-<span class="sourceLineNo">1744</span> public Pair<Integer, Integer> getReopenStatus(TableName tableName) {<a name="line.1744"></a>
-<span class="sourceLineNo">1745</span> if (isTableDisabled(tableName)) {<a name="line.1745"></a>
-<span class="sourceLineNo">1746</span> return new Pair<Integer, Integer>(0, 0);<a name="line.1746"></a>
-<span class="sourceLineNo">1747</span> }<a name="line.1747"></a>
-<span class="sourceLineNo">1748</span><a name="line.1748"></a>
-<span class="sourceLineNo">1749</span> final List<RegionState> states = regionStates.getTableRegionStates(tableName);<a name="line.1749"></a>
-<span class="sourceLineNo">1750</span> int ritCount = 0;<a name="line.1750"></a>
-<span class="sourceLineNo">1751</span> for (RegionState regionState: states) {<a name="line.1751"></a>
-<span class="sourceLineNo">1752</span> if (!regionState.isOpened() && !regionState.isSplit()) {<a name="line.1752"></a>
-<span class="sourceLineNo">1753</span> ritCount++;<a name="line.1753"></a>
-<span class="sourceLineNo">1754</span> }<a name="line.1754"></a>
-<span class="sourceLineNo">1755</span> }<a name="line.1755"></a>
-<span class="sourceLineNo">1756</span> return new Pair<Integer, Integer>(ritCount, states.size());<a name="line.1756"></a>
-<span class="sourceLineNo">1757</span> }<a name="line.1757"></a>
-<span class="sourceLineNo">1758</span><a name="line.1758"></a>
-<span class="sourceLineNo">1759</span> // ============================================================================================<a name="line.1759"></a>
-<span class="sourceLineNo">1760</span> // TODO: Region State In Transition<a name="line.1760"></a>
-<span class="sourceLineNo">1761</span> // ============================================================================================<a name="line.1761"></a>
-<span class="sourceLineNo">1762</span> public boolean hasRegionsInTransition() {<a name="line.1762"></a>
-<span class="sourceLineNo">1763</span> return regionStates.hasRegionsInTransition();<a name="line.1763"></a>
-<span class="sourceLineNo">1764</span> }<a name="line.1764"></a>
-<span class="sourceLineNo">1765</span><a name="line.1765"></a>
-<span class="sourceLineNo">1766</span> public List<RegionStateNode> getRegionsInTransition() {<a name="line.1766"></a>
-<span class="sourceLineNo">1767</span> return regionStates.getRegionsInTransition();<a name="line.1767"></a>
-<span class="sourceLineNo">1768</span> }<a name="line.1768"></a>
-<span class="sourceLineNo">1769</span><a name="line.1769"></a>
-<span class="sourceLineNo">1770</span> public List<RegionInfo> getAssignedRegions() {<a name="line.1770"></a>
-<span class="sourceLineNo">1771</span> return regionStates.getAssignedRegions();<a name="line.1771"></a>
-<span class="sourceLineNo">1772</span> }<a name="line.1772"></a>
-<span class="sourceLineNo">1773</span><a name="line.1773"></a>
-<span class="sourceLineNo">1774</span> public RegionInfo getRegionInfo(final byte[] regionName) {<a name="line.1774"></a>
-<span class="sourceLineNo">1775</span> final RegionStateNode regionState = regionStates.getRegionStateNodeFromName(regionName);<a name="line.1775"></a>
-<span class="sourceLineNo">1776</span> return regionState != null ? regionState.getRegionInfo() : null;<a name="line.1776"></a>
-<span class="sourceLineNo">1777</span> }<a name="line.1777"></a>
-<span class="sourceLineNo">1778</span><a name="line.1778"></a>
-<span class="sourceLineNo">1779</span> // ============================================================================================<a name="line.1779"></a>
-<span class="sourceLineNo">1780</span> // Expected states on region state transition.<a name="line.1780"></a>
-<span class="sourceLineNo">1781</span> // Notice that there is expected states for transiting to OPENING state, this is because SCP.<a name="line.1781"></a>
-<span class="sourceLineNo">1782</span> // See the comments in regionOpening method for more details.<a name="line.1782"></a>
-<span class="sourceLineNo">1783</span> // ============================================================================================<a name="line.1783"></a>
-<span class="sourceLineNo">1784</span> private static final State[] STATES_EXPECTED_ON_OPEN = {<a name="line.1784"></a>
-<span class="sourceLineNo">1785</span> State.OPENING, // Normal case<a name="line.1785"></a>
-<span class="sourceLineNo">1786</span> State.OPEN // Retrying<a name="line.1786"></a>
-<span class="sourceLineNo">1787</span> };<a name="line.1787"></a>
-<span class="sourceLineNo">1788</span><a name="line.1788"></a>
-<span class="sourceLineNo">1789</span> private static final State[] STATES_EXPECTED_ON_CLOSING = {<a name="line.1789"></a>
-<span class="sourceLineNo">1790</span> State.OPEN, // Normal case<a name="line.1790"></a>
-<span class="sourceLineNo">1791</span> State.CLOSING, // Retrying<a name="line.1791"></a>
-<span class="sourceLineNo">1792</span> State.SPLITTING, // Offline the split parent<a name="line.1792"></a>
-<span class="sourceLineNo">1793</span> State.MERGING // Offline the merge parents<a name="line.1793"></a>
-<span class="sourceLineNo">1794</span> };<a name="line.1794"></a>
-<span class="sourceLineNo">1795</span><a name="line.1795"></a>
-<span class="sourceLineNo">1796</span> private static final State[] STATES_EXPECTED_ON_CLOSED = {<a name="line.1796"></a>
-<span class="sourceLineNo">1797</span> State.CLOSING, // Normal case<a name="line.1797"></a>
-<span class="sourceLineNo">1798</span> State.CLOSED // Retrying<a name="line.1798"></a>
-<span class="sourceLineNo">1799</span> };<a name="line.1799"></a>
-<span class="sourceLineNo">1800</span><a name="line.1800"></a>
-<span class="sourceLineNo">1801</span> // This is for manually scheduled region assign, can add other states later if we find out other<a name="line.1801"></a>
-<span class="sourceLineNo">1802</span> // usages<a name="line.1802"></a>
-<span class="sourceLineNo">1803</span> private static final State[] STATES_EXPECTED_ON_ASSIGN = { State.CLOSED, State.OFFLINE };<a name="line.1803"></a>
+<span class="sourceLineNo">1512</span> // Scan hbase:meta to build list of existing regions, servers, and assignment.<a name="line.1512"></a>
+<span class="sourceLineNo">1513</span> // hbase:meta is online now or will be. Inside loadMeta, we keep trying. Can't make progress<a name="line.1513"></a>
+<span class="sourceLineNo">1514</span> // w/o meta.<a name="line.1514"></a>
+<span class="sourceLineNo">1515</span> loadMeta();<a name="line.1515"></a>
+<span class="sourceLineNo">1516</span><a name="line.1516"></a>
+<span class="sourceLineNo">1517</span> while (master.getServerManager().countOfRegionServers() < 1) {<a name="line.1517"></a>
+<span class="sourceLineNo">1518</span> LOG.info("Waiting for RegionServers to join; current count={}",<a name="line.1518"></a>
+<span class="sourceLineNo">1519</span> master.getServerManager().countOfRegionServers());<a name="line.1519"></a>
+<span class="sourceLineNo">1520</span> Threads.sleep(250);<a name="line.1520"></a>
+<span class="sourceLineNo">1521</span> }<a name="line.1521"></a>
+<span class="sourceLineNo">1522</span> LOG.info("Number of RegionServers={}", master.getServerManager().countOfRegionServers());<a name="line.1522"></a>
+<span class="sourceLineNo">1523</span><a name="line.1523"></a>
+<span class="sourceLineNo">1524</span> // Start the chores<a name="line.1524"></a>
+<span class="sourceLineNo">1525</span> master.getMasterProcedureExecutor().addChore(this.ritChore);<a name="line.1525"></a>
+<span class="sourceLineNo">1526</span> master.getMasterProcedureExecutor().addChore(this.deadMetricChore);<a name="line.1526"></a>
+<span class="sourceLineNo">1527</span><a name="line.1527"></a>
+<span class="sourceLineNo">1528</span> long costMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);<a name="line.1528"></a>
+<span class="sourceLineNo">1529</span> LOG.info("Joined the cluster in {}", StringUtils.humanTimeDiff(costMs));<a name="line.1529"></a>
+<span class="sourceLineNo">1530</span> }<a name="line.1530"></a>
+<span class="sourceLineNo">1531</span><a name="line.1531"></a>
+<span class="sourceLineNo">1532</span> /**<a name="line.1532"></a>
+<span class="sourceLineNo">1533</span> * Create assign procedure for offline regions.<a name="line.1533"></a>
+<span class="sourceLineNo">1534</span> * Just follow the old processofflineServersWithOnlineRegions method. Since now we do not need to<a name="line.1534"></a>
+<span class="sourceLineNo">1535</span> * deal with dead server any more, we only deal with the regions in OFFLINE state in this method.<a name="line.1535"></a>
+<span class="sourceLineNo">1536</span> * And this is a bit strange, that for new regions, we will add it in CLOSED state instead of<a name="line.1536"></a>
+<span class="sourceLineNo">1537</span> * OFFLINE state, and usually there will be a procedure to track them. The<a name="line.1537"></a>
+<span class="sourceLineNo">1538</span> * processofflineServersWithOnlineRegions is a legacy from long ago, as things are going really<a name="line.1538"></a>
+<span class="sourceLineNo">1539</span> * different now, maybe we do not need this method any more. Need to revisit later.<a name="line.1539"></a>
+<span class="sourceLineNo">1540</span> */<a name="line.1540"></a>
+<span class="sourceLineNo">1541</span> // Public so can be run by the Master as part of the startup. Needs hbase:meta to be online.<a name="line.1541"></a>
+<span class="sourceLineNo">1542</span> // Needs to be done after the table state manager has been started.<a name="line.1542"></a>
+<span class="sourceLineNo">1543</span> public void processOfflineRegions() {<a name="line.1543"></a>
+<span class="sourceLineNo">1544</span> TransitRegionStateProcedure[] procs =<a name="line.1544"></a>
+<span class="sourceLineNo">1545</span> regionStates.getRegionStateNodes().stream().filter(rsn -> rsn.isInState(State.OFFLINE))<a name="line.1545"></a>
+<span class="sourceLineNo">1546</span> .filter(rsn -> isTableEnabled(rsn.getRegionInfo().getTable())).map(rsn -> {<a name="line.1546"></a>
+<span class="sourceLineNo">1547</span> rsn.lock();<a name="line.1547"></a>
+<span class="sourceLineNo">1548</span> try {<a name="line.1548"></a>
+<span class="sourceLineNo">1549</span> if (rsn.getProcedure() != null) {<a name="line.1549"></a>
+<span class="sourceLineNo">1550</span> return null;<a name="line.1550"></a>
+<span class="sourceLineNo">1551</span> } else {<a name="line.1551"></a>
+<span class="sourceLineNo">1552</span> return rsn.setProcedure(TransitRegionStateProcedure.assign(getProcedureEnvironment(),<a name="line.1552"></a>
+<span class="sourceLineNo">1553</span> rsn.getRegionInfo(), null));<a name="line.1553"></a>
+<span class="sourceLineNo">1554</span> }<a name="line.1554"></a>
+<span class="sourceLineNo">1555</span> } finally {<a name="line.1555"></a>
+<span class="sourceLineNo">1556</span> rsn.unlock();<a name="line.1556"></a>
+<span class="sourceLineNo">1557</span> }<a name="line.1557"></a>
+<span class="sourceLineNo">1558</span> }).filter(p -> p != null).toArray(TransitRegionStateProcedure[]::new);<a name="line.1558"></a>
+<span class="sourceLineNo">1559</span> if (procs.length > 0) {<a name="line.1559"></a>
+<span class="sourceLineNo">1560</span> master.getMasterProcedureExecutor().submitProcedures(procs);<a name="line.1560"></a>
+<span class="sourceLineNo">1561</span> }<a name="line.1561"></a>
+<span class="sourceLineNo">1562</span> }<a name="line.1562"></a>
+<span class="sourceLineNo">1563</span><a name="line.1563"></a>
+<span class="sourceLineNo">1564</span> /* AM internal RegionStateStore.RegionStateVisitor implementation. To be used when<a name="line.1564"></a>
+<span class="sourceLineNo">1565</span> * scanning META table for region rows, using RegionStateStore utility methods. RegionStateStore<a name="line.1565"></a>
+<span class="sourceLineNo">1566</span> * methods will convert Result into proper RegionInfo instances, but those would still need to be<a name="line.1566"></a>
+<span class="sourceLineNo">1567</span> * added into AssignmentManager.regionStates in-memory cache.<a name="line.1567"></a>
+<span class="sourceLineNo">1568</span> * RegionMetaLoadingVisitor.visitRegionState method provides the logic for adding RegionInfo<a name="line.1568"></a>
+<span class="sourceLineNo">1569</span> * instances as loaded from latest META scan into AssignmentManager.regionStates.<a name="line.1569"></a>
+<span class="sourceLineNo">1570</span> */<a name="line.1570"></a>
+<span class="sourceLineNo">1571</span> private class RegionMetaLoadingVisitor implements RegionStateStore.RegionStateVisitor {<a name="line.1571"></a>
+<span class="sourceLineNo">1572</span><a name="line.1572"></a>
+<span class="sourceLineNo">1573</span> @Override<a name="line.1573"></a>
+<span class="sourceLineNo">1574</span> public void visitRegionState(Result result, final RegionInfo regionInfo, final State state,<a name="line.1574"></a>
+<span class="sourceLineNo">1575</span> final ServerName regionLocation, final ServerName lastHost, final long openSeqNum) {<a name="line.1575"></a>
+<span class="sourceLineNo">1576</span> if (state == null && regionLocation == null && lastHost == null &&<a name="line.1576"></a>
+<span class="sourceLineNo">1577</span> openSeqNum == SequenceId.NO_SEQUENCE_ID) {<a name="line.1577"></a>
+<span class="sourceLineNo">1578</span> // This is a row with nothing in it.<a name="line.1578"></a>
+<span class="sourceLineNo">1579</span> LOG.warn("Skipping empty row={}", result);<a name="line.1579"></a>
+<span class="sourceLineNo">1580</span> return;<a name="line.1580"></a>
+<span class="sourceLineNo">1581</span> }<a name="line.1581"></a>
+<span class="sourceLineNo">1582</span> State localState = state;<a name="line.1582"></a>
+<span class="sourceLineNo">1583</span> if (localState == null) {<a name="line.1583"></a>
+<span class="sourceLineNo">1584</span> // No region state column data in hbase:meta table! Are I doing a rolling upgrade from<a name="line.1584"></a>
+<span class="sourceLineNo">1585</span> // hbase1 to hbase2? Am I restoring a SNAPSHOT or otherwise adding a region to hbase:meta?<a name="line.1585"></a>
+<span class="sourceLineNo">1586</span> // In any of these cases, state is empty. For now, presume OFFLINE but there are probably<a name="line.1586"></a>
+<span class="sourceLineNo">1587</span> // cases where we need to probe more to be sure this correct; TODO informed by experience.<a name="line.1587"></a>
+<span class="sourceLineNo">1588</span> LOG.info(regionInfo.getEncodedName() + " regionState=null; presuming " + State.OFFLINE);<a name="line.1588"></a>
+<span class="sourceLineNo">1589</span> localState = State.OFFLINE;<a name="line.1589"></a>
+<span class="sourceLineNo">1590</span> }<a name="line.1590"></a>
+<span class="sourceLineNo">1591</span> RegionStateNode regionNode = regionStates.getOrCreateRegionStateNode(regionInfo);<a name="line.1591"></a>
+<span class="sourceLineNo">1592</span> // Do not need to lock on regionNode, as we can make sure that before we finish loading<a name="line.1592"></a>
+<span class="sourceLineNo">1593</span> // meta, all the related procedures can not be executed. The only exception is for meta<a name="line.1593"></a>
+<span class="sourceLineNo">1594</span> // region related operations, but here we do not load the informations for meta region.<a name="line.1594"></a>
+<span class="sourceLineNo">1595</span> regionNode.setState(localState);<a name="line.1595"></a>
+<span class="sourceLineNo">1596</span> regionNode.setLastHost(lastHost);<a name="line.1596"></a>
+<span class="sourceLineNo">1597</span> regionNode.setRegionLocation(regionLocation);<a name="line.1597"></a>
+<span class="sourceLineNo">1598</span> regionNode.setOpenSeqNum(openSeqNum);<a name="line.1598"></a>
+<span class="sourceLineNo">1599</span><a name="line.1599"></a>
+<span class="sourceLineNo">1600</span> // Note: keep consistent with other methods, see region(Opening|Opened|Closing)<a name="line.1600"></a>
+<span class="sourceLineNo">1601</span> // RIT/ServerCrash handling should take care of the transiting regions.<a name="line.1601"></a>
+<span class="sourceLineNo">1602</span> if (localState.matches(State.OPEN, State.OPENING, State.CLOSING, State.SPLITTING,<a name="line.1602"></a>
+<span class="sourceLineNo">1603</span> State.MERGING)) {<a name="line.1603"></a>
+<span class="sourceLineNo">1604</span> assert regionLocation != null : "found null region location for " + regionNode;<a name="line.1604"></a>
+<span class="sourceLineNo">1605</span> regionStates.addRegionToServer(regionNode);<a name="line.1605"></a>
+<span class="sourceLineNo">1606</span> } else if (localState == State.OFFLINE || regionInfo.isOffline()) {<a name="line.1606"></a>
+<span class="sourceLineNo">1607</span> regionStates.addToOfflineRegions(regionNode);<a name="line.1607"></a>
+<span class="sourceLineNo">1608</span> }<a name="line.1608"></a>
+<span class="sourceLineNo">1609</span> if (regionNode.getProcedure() != null) {<a name="line.1609"></a>
+<span class="sourceLineNo">1610</span> regionNode.getProcedure().stateLoaded(AssignmentManager.this, regionNode);<a name="line.1610"></a>
+<span class="sourceLineNo">1611</span> }<a name="line.1611"></a>
+<span class="sourceLineNo">1612</span> }<a name="line.1612"></a>
+<span class="sourceLineNo">1613</span> };<a name="line.1613"></a>
+<span class="sourceLineNo">1614</span><a name="line.1614"></a>
+<span class="sourceLineNo">1615</span> /**<a name="line.1615"></a>
+<span class="sourceLineNo">1616</span> * Query META if the given <code>RegionInfo</code> exists, adding to<a name="line.1616"></a>
+<span class="sourceLineNo">1617</span> * <code>AssignmentManager.regionStateStore</code> cache if the region is found in META.<a name="line.1617"></a>
+<span class="sourceLineNo">1618</span> * @param regionEncodedName encoded name for the region to be loaded from META into<a name="line.1618"></a>
+<span class="sourceLineNo">1619</span> * <code>AssignmentManager.regionStateStore</code> cache<a name="line.1619"></a>
+<span class="sourceLineNo">1620</span> * @return <code>RegionInfo</code> instance for the given region if it is present in META<a name="line.1620"></a>
+<span class="sourceLineNo">1621</span> * and got successfully loaded into <code>AssignmentManager.regionStateStore</code><a name="line.1621"></a>
+<span class="sourceLineNo">1622</span> * cache, <b>null</b> otherwise.<a name="line.1622"></a>
+<span class="sourceLineNo">1623</span> * @throws UnknownRegionException if any errors occur while querying meta.<a name="line.1623"></a>
+<span class="sourceLineNo">1624</span> */<a name="line.1624"></a>
+<span class="sourceLineNo">1625</span> public RegionInfo loadRegionFromMeta(String regionEncodedName) throws UnknownRegionException {<a name="line.1625"></a>
+<span class="sourceLineNo">1626</span> try {<a name="line.1626"></a>
+<span class="sourceLineNo">1627</span> RegionMetaLoadingVisitor visitor = new RegionMetaLoadingVisitor();<a name="line.1627"></a>
+<span class="sourceLineNo">1628</span> regionStateStore.visitMetaForRegion(regionEncodedName, visitor);<a name="line.1628"></a>
+<span class="sourceLineNo">1629</span> return regionStates.getRegionState(regionEncodedName) == null ? null :<a name="line.1629"></a>
+<span class="sourceLineNo">1630</span> regionStates.getRegionState(regionEncodedName).getRegion();<a name="line.1630"></a>
+<span class="sourceLineNo">1631</span> } catch(IOException e) {<a name="line.1631"></a>
+<span class="sourceLineNo">1632</span> LOG.error("Error trying to load region {} from META", regionEncodedName, e);<a name="line.1632"></a>
+<span class="sourceLineNo">1633</span> throw new UnknownRegionException("Error while trying load region from meta");<a name="line.1633"></a>
+<span class="sourceLineNo">1634</span> }<a name="line.1634"></a>
+<span class="sourceLineNo">1635</span> }<a name="line.1635"></a>
+<span class="sourceLineNo">1636</span><a name="line.1636"></a>
+<span class="sourceLineNo">1637</span> private void loadMeta() throws IOException {<a name="line.1637"></a>
+<span class="sourceLineNo">1638</span> // TODO: use a thread pool<a name="line.1638"></a>
+<span class="sourceLineNo">1639</span> regionStateStore.visitMeta(new RegionMetaLoadingVisitor());<a name="line.1639"></a>
+<span class="sourceLineNo">1640</span> }<a name="line.1640"></a>
+<span class="sourceLineNo">1641</span><a name="line.1641"></a>
+<span class="sourceLineNo">1642</span> /**<a name="line.1642"></a>
+<span class="sourceLineNo">1643</span> * Used to check if the meta loading is done.<a name="line.1643"></a>
+<span class="sourceLineNo">1644</span> * <p/><a name="line.1644"></a>
+<span class="sourceLineNo">1645</span> * if not we throw PleaseHoldException since we are rebuilding the RegionStates<a name="line.1645"></a>
+<span class="sourceLineNo">1646</span> * @param hri region to check if it is already rebuild<a name="line.1646"></a>
+<span class="sourceLineNo">1647</span> * @throws PleaseHoldException if meta has not been loaded yet<a name="line.1647"></a>
+<span class="sourceLineNo">1648</span> */<a name="line.1648"></a>
+<span class="sourceLineNo">1649</span> private void checkMetaLoaded(RegionInfo hri) throws PleaseHoldException {<a name="line.1649"></a>
+<span class="sourceLineNo">1650</span> if (!isRunning()) {<a name="line.1650"></a>
+<span class="sourceLineNo">1651</span> throw new PleaseHoldException("AssignmentManager not running");<a name="line.1651"></a>
+<span class="sourceLineNo">1652</span> }<a name="line.1652"></a>
+<span class="sourceLineNo">1653</span> boolean meta = isMetaRegion(hri);<a name="line.1653"></a>
+<span class="sourceLineNo">1654</span> boolean metaLoaded = isMetaLoaded();<a name="line.1654"></a>
+<span class="sourceLineNo">1655</span> if (!meta && !metaLoaded) {<a name="line.1655"></a>
+<span class="sourceLineNo">1656</span> throw new PleaseHoldException(<a name="line.1656"></a>
+<span class="sourceLineNo">1657</span> "Master not fully online; hbase:meta=" + meta + ", metaLoaded=" + metaLoaded);<a name="line.1657"></a>
+<span class="sourceLineNo">1658</span> }<a name="line.1658"></a>
+<span class="sourceLineNo">1659</span> }<a name="line.1659"></a>
+<span class="sourceLineNo">1660</span><a name="line.1660"></a>
+<span class="sourceLineNo">1661</span> // ============================================================================================<a name="line.1661"></a>
+<span class="sourceLineNo">1662</span> // TODO: Metrics<a name="line.1662"></a>
+<span class="sourceLineNo">1663</span> // ============================================================================================<a name="line.1663"></a>
+<span class="sourceLineNo">1664</span> public int getNumRegionsOpened() {<a name="line.1664"></a>
+<span class="sourceLineNo">1665</span> // TODO: Used by TestRegionPlacement.java and assume monotonically increasing value<a name="line.1665"></a>
+<span class="sourceLineNo">1666</span> return 0;<a name="line.1666"></a>
+<span class="sourceLineNo">1667</span> }<a name="line.1667"></a>
+<span class="sourceLineNo">1668</span><a name="line.1668"></a>
+<span class="sourceLineNo">1669</span> /**<a name="line.1669"></a>
+<span class="sourceLineNo">1670</span> * Usually run by the Master in reaction to server crash during normal processing.<a name="line.1670"></a>
+<span class="sourceLineNo">1671</span> * Can also be invoked via external RPC to effect repair; in the latter case,<a name="line.1671"></a>
+<span class="sourceLineNo">1672</span> * the 'force' flag is set so we push through the SCP though context may indicate<a name="line.1672"></a>
+<span class="sourceLineNo">1673</span> * already-running-SCP (An old SCP may have exited abnormally, or damaged cluster<a name="line.1673"></a>
+<span class="sourceLineNo">1674</span> * may still have references in hbase:meta to 'Unknown Servers' -- servers that<a name="line.1674"></a>
+<span class="sourceLineNo">1675</span> * are not online or in dead servers list, etc.)<a name="line.1675"></a>
+<span class="sourceLineNo">1676</span> * @param force Set if the request came in externally over RPC (via hbck2). Force means<a name="line.1676"></a>
+<span class="sourceLineNo">1677</span> * run the SCP even if it seems as though there might be an outstanding<a name="line.1677"></a>
+<span class="sourceLineNo">1678</span> * SCP running.<a name="line.1678"></a>
+<span class="sourceLineNo">1679</span> * @return pid of scheduled SCP or {@link Procedure#NO_PROC_ID} if none scheduled.<a name="line.1679"></a>
+<span class="sourceLineNo">1680</span> */<a name="line.1680"></a>
+<span class="sourceLineNo">1681</span> public long submitServerCrash(ServerName serverName, boolean shouldSplitWal, boolean force) {<a name="line.1681"></a>
+<span class="sourceLineNo">1682</span> // May be an 'Unknown Server' so handle case where serverNode is null.<a name="line.1682"></a>
+<span class="sourceLineNo">1683</span> ServerStateNode serverNode = regionStates.getServerNode(serverName);<a name="line.1683"></a>
+<span class="sourceLineNo">1684</span> // Remove the in-memory rsReports result<a name="line.1684"></a>
+<span class="sourceLineNo">1685</span> synchronized (rsReports) {<a name="line.1685"></a>
+<span class="sourceLineNo">1686</span> rsReports.remove(serverName);<a name="line.1686"></a>
+<span class="sourceLineNo">1687</span> }<a name="line.1687"></a>
+<span class="sourceLineNo">1688</span><a name="line.1688"></a>
+<span class="sourceLineNo">1689</span> // We hold the write lock here for fencing on reportRegionStateTransition. Once we set the<a name="line.1689"></a>
+<span class="sourceLineNo">1690</span> // server state to CRASHED, we will no longer accept the reportRegionStateTransition call from<a name="line.1690"></a>
+<span class="sourceLineNo">1691</span> // this server. This is used to simplify the implementation for TRSP and SCP, where we can make<a name="line.1691"></a>
+<span class="sourceLineNo">1692</span> // sure that, the region list fetched by SCP will not be changed any more.<a name="line.1692"></a>
+<span class="sourceLineNo">1693</span> if (serverNode != null) {<a name="line.1693"></a>
+<span class="sourceLineNo">1694</span> serverNode.writeLock().lock();<a name="line.1694"></a>
+<span class="sourceLineNo">1695</span> }<a name="line.1695"></a>
+<span class="sourceLineNo">1696</span> boolean carryingMeta;<a name="line.1696"></a>
+<span class="sourceLineNo">1697</span> long pid;<a name="line.1697"></a>
+<span class="sourceLineNo">1698</span> try {<a name="line.1698"></a>
+<span class="sourceLineNo">1699</span> ProcedureExecutor<MasterProcedureEnv> procExec = this.master.getMasterProcedureExecutor();<a name="line.1699"></a>
+<span class="sourceLineNo">1700</span> carryingMeta = isCarryingMeta(serverName);<a name="line.1700"></a>
+<span class="sourceLineNo">1701</span> if (!force && serverNode != null && !serverNode.isInState(ServerState.ONLINE)) {<a name="line.1701"></a>
+<span class="sourceLineNo">1702</span> LOG.info("Skip adding ServerCrashProcedure for {} (meta={}) -- running?",<a name="line.1702"></a>
+<span class="sourceLineNo">1703</span> serverNode, carryingMeta);<a name="line.1703"></a>
+<span class="sourceLineNo">1704</span> return Procedure.NO_PROC_ID;<a name="line.1704"></a>
+<span class="sourceLineNo">1705</span> } else {<a name="line.1705"></a>
+<span class="sourceLineNo">1706</span> MasterProcedureEnv mpe = procExec.getEnvironment();<a name="line.1706"></a>
+<span class="sourceLineNo">1707</span> // If serverNode == null, then 'Unknown Server'. Schedule HBCKSCP instead.<a name="line.1707"></a>
+<span class="sourceLineNo">1708</span> // HBCKSCP scours Master in-memory state AND hbase;meta for references to<a name="line.1708"></a>
+<span class="sourceLineNo">1709</span> // serverName just-in-case. An SCP that is scheduled when the server is<a name="line.1709"></a>
+<span class="sourceLineNo">1710</span> // 'Unknown' probably originated externally with HBCK2 fix-it tool.<a name="line.1710"></a>
+<span class="sourceLineNo">1711</span> ServerState oldState = null;<a name="line.1711"></a>
+<span class="sourceLineNo">1712</span> if (serverNode != null) {<a name="line.1712"></a>
+<span class="sourceLineNo">1713</span> oldState = serverNode.getState();<a name="line.1713"></a>
+<span class="sourceLineNo">1714</span> serverNode.setState(ServerState.CRASHED);<a name="line.1714"></a>
+<span class="sourceLineNo">1715</span> }<a name="line.1715"></a>
+<span class="sourceLineNo">1716</span><a name="line.1716"></a>
+<span class="sourceLineNo">1717</span> if (force) {<a name="line.1717"></a>
+<span class="sourceLineNo">1718</span> pid = procExec.submitProcedure(<a name="line.1718"></a>
+<span class="sourceLineNo">1719</span> new HBCKServerCrashProcedure(mpe, serverName, shouldSplitWal, carryingMeta));<a name="line.1719"></a>
+<span class="sourceLineNo">1720</span> } else {<a name="line.1720"></a>
+<span class="sourceLineNo">1721</span> pid = procExec.submitProcedure(<a name="line.1721"></a>
+<span class="sourceLineNo">1722</span> new ServerCrashProcedure(mpe, serverName, shouldSplitWal, carryingMeta));<a name="line.1722"></a>
+<span class="sourceLineNo">1723</span> }<a name="line.1723"></a>
+<span class="sourceLineNo">1724</span> LOG.info("Scheduled ServerCrashProcedure pid={} for {} (carryingMeta={}){}.",<a name="line.1724"></a>
+<span class="sourceLineNo">1725</span> pid, serverName, carryingMeta,<a name="line.1725"></a>
+<span class="sourceLineNo">1726</span> serverNode == null? "": " " + serverNode.toString() + ", oldState=" + oldState);<a name="line.1726"></a>
+<span class="sourceLineNo">1727</span> }<a name="line.1727"></a>
+<span class="sourceLineNo">1728</span> } finally {<a name="line.1728"></a>
+<span class="sourceLineNo">1729</span> if (serverNode != null) {<a name="line.1729"></a>
+<span class="sourceLineNo">1730</span> serverNode.writeLock().unlock();<a name="line.1730"></a>
+<span class="sourceLineNo">1731</span> }<a name="line.1731"></a>
+<span class="sourceLineNo">1732</span> }<a name="line.1732"></a>
+<span class="sourceLineNo">1733</span> return pid;<a name="line.1733"></a>
+<span class="sourceLineNo">1734</span> }<a name="line.1734"></a>
+<span class="sourceLineNo">1735</span><a name="line.1735"></a>
+<span class="sourceLineNo">1736</span> public void offlineRegion(final RegionInfo regionInfo) {<a name="line.1736"></a>
+<span class="sourceLineNo">1737</span> // TODO used by MasterRpcServices<a name="line.1737"></a>
+<span class="sourceLineNo">1738</span> RegionStateNode node = regionStates.getRegionStateNode(regionInfo);<a name="line.1738"></a>
+<span class="sourceLineNo">1739</span> if (node != null) {<a name="line.1739"></a>
+<span class="sourceLineNo">1740</span> node.offline();<a name="line.1740"></a>
+<span class="sourceLineNo">1741</span> }<a name="line.1741"></a>
+<span class="sourceLineNo">1742</span> }<a name="line.1742"></a>
+<span class="sourceLineNo">1743</span><a name="line.1743"></a>
+<span class="sourceLineNo">1744</span> public void onlineRegion(final RegionInfo regionInfo, final ServerName serverName) {<a name="line.1744"></a>
+<span class="sourceLineNo">1745</span> // TODO used by TestSplitTransactionOnCluster.java<a name="line.1745"></a>
+<span class="sourceLineNo">1746</span> }<a name="line.1746"></a>
+<span class="sourceLineNo">1747</span><a name="line.1747"></a>
+<span class="sourceLineNo">1748</span> public Map<ServerName, List<RegionInfo>> getSnapShotOfAssignment(<a name="line.1748"></a>
+<span class="sourceLineNo">1749</span> final Collection<RegionInfo> regions) {<a name="line.1749"></a>
+<span class="sourceLineNo">1750</span> return regionStates.getSnapShotOfAssignment(regions);<a name="line.1750"></a>
+<span class="sourceLineNo">1751</span> }<a name="line.1751"></a>
+<span class="sourceLineNo">1752</span><a name="line.1752"></a>
+<span class="sourceLineNo">1753</span> // ============================================================================================<a name="line.1753"></a>
+<span class="sourceLineNo">1754</span> // TODO: UTILS/HELPERS?<a name="line.1754"></a>
+<span class="sourceLineNo">1755</span> // ============================================================================================<a name="line.1755"></a>
+<span class="sourceLineNo">1756</span> /**<a name="line.1756"></a>
+<span class="sourceLineNo">1757</span> * Used by the client (via master) to identify if all regions have the schema updates<a name="line.1757"></a>
+<span class="sourceLineNo">1758</span> * @return Pair indicating the status of the alter command (pending/total)<a name="line.1758"></a>
+<span class="sourceLineNo">1759</span> */<a name="line.1759"></a>
+<span class="sourceLineNo">1760</span> public Pair<Integer, Integer> getReopenStatus(TableName tableName) {<a name="line.1760"></a>
+<span class="sourceLineNo">1761</span> if (isTableDisabled(tableName)) {<a name="line.1761"></a>
+<span class="sourceLineNo">1762</span> return new Pair<Integer, Integer>(0, 0);<a name="line.1762"></a>
+<span class="sourceLineNo">1763</span> }<a name="line.1763"></a>
+<span class="sourceLineNo">1764</span><a name="line.1764"></a>
+<span class="sourceLineNo">1765</span> final List<RegionState> states = regionStates.getTableRegionStates(tableName);<a name="line.1765"></a>
+<span class="sourceLineNo">1766</span> int ritCount = 0;<a name="line.1766"></a>
+<span class="sourceLineNo">1767</span> for (RegionState regionState: states) {<a name="line.1767"></a>
+<span class="sourceLineNo">1768</span> if (!regionState.isOpened() && !regionState.isSplit()) {<a name="line.1768"></a>
+<span class="sourceLineNo">1769</span> ritCount++;<a name="line.1769"></a>
+<span class="sourceLineNo">1770</span> }<a name="line.1770"></a>
+<span class="sourceLineNo">1771</span> }<a name="line.1771"></a>
+<span class="sourceLineNo">1772</span> return new Pair<Integer, Integer>(ritCount, states.size());<a name="line.1772"></a>
+<span class="sourceLineNo">1773</span> }<a name="line.1773"></a>
+<span class="sourceLineNo">1774</span><a name="line.1774"></a>
+<span class="sourceLineNo">1775</span> // ============================================================================================<a name="line.1775"></a>
+<span class="sourceLineNo">1776</span> // TODO: Region State In Transition<a name="line.1776"></a>
+<span class="sourceLineNo">1777</span> // ============================================================================================<a name="line.1777"></a>
+<span class="sourceLineNo">1778</span> public boolean hasRegionsInTransition() {<a name="line.1778"></a>
+<span class="sourceLineNo">1779</span> return regionStates.hasRegionsInTransition();<a name="line.1779"></a>
+<span class="sourceLineNo">1780</span> }<a name="line.1780"></a>
+<span class="sourceLineNo">1781</span><a name="line.1781"></a>
+<span class="sourceLineNo">1782</span> public List<RegionStateNode> getRegionsInTransition() {<a name="line.1782"></a>
+<span class="sourceLineNo">1783</span> return regionStates.getRegionsInTransition();<a name="line.1783"></a>
+<span class="sourceLineNo">1784</span> }<a name="line.1784"></a>
+<span class="sourceLineNo">1785</span><a name="line.1785"></a>
+<span class="sourceLineNo">1786</span> public List<RegionInfo> getAssignedRegions() {<a name="line.1786"></a>
+<span class="sourceLineNo">1787</span> return regionStates.getAssignedRegions();<a name="line.1787"></a>
+<span class="sourceLineNo">1788</span> }<a name="line.1788"></a>
+<span class="sourceLineNo">1789</span><a name="line.1789"></a>
+<span class="sourceLineNo">1790</span> public RegionInfo getRegionInfo(final byte[] regionName) {<a name="line.1790"></a>
+<span class="sourceLineNo">1791</span> final RegionStateNode regionState = regionStates.getRegionStateNodeFromName(regionName);<a name="line.1791"></a>
+<span class="sourceLineNo">1792</span> return regionState != null ? regionState.getRegionInfo() : null;<a name="line.1792"></a>
+<span class="sourceLineNo">1793</span> }<a name="line.1793"></a>
+<span class="sourceLineNo">1794</span><a name="line.1794"></a>
+<span class="sourceLineNo">1795</span> // ============================================================================================<a name="line.1795"></a>
+<span class="sourceLineNo">1796</span> // Expected states on region state transition.<a name="line.1796"></a>
+<span class="sourceLineNo">1797</span> // Notice that there is expected states for transiting to OPENING state, this is because SCP.<a name="line.1797"></a>
+<span class="sourceLineNo">1798</span> // See the comments in regionOpening method for more details.<a name="line.1798"></a>
+<span class="sourceLineNo">1799</span> // ============================================================================================<a name="line.1799"></a>
+<span class="sourceLineNo">1800</span> private static final State[] STATES_EXPECTED_ON_OPEN = {<a name="line.1800"></a>
+<span class="sourceLineNo">1801</span> State.OPENING, // Normal case<a name="line.1801"></a>
+<span class="sourceLineNo">1802</span> State.OPEN // Retrying<a name="line.1802"></a>
+<span class="sourceLineNo">1803</span> };<a name="line.1803"></a>
<span class="sourceLineNo">1804</span><a name="line.1804"></a>
-<span class="sourceLineNo">1805</span> // We only allow unassign or move a region which is in OPEN state.<a name="line.1805"></a>
-<span class="sourceLineNo">1806</span> private static final State[] STATES_EXPECTED_ON_UNASSIGN_OR_MOVE = { State.OPEN };<a name="line.1806"></a>
-<span class="sourceLineNo">1807</span><a name="line.1807"></a>
-<span class="sourceLineNo">1808</span> // ============================================================================================<a name="line.1808"></a>
-<span class="sourceLineNo">1809</span> // Region Status update<a name="line.1809"></a>
-<span class="sourceLineNo">1810</span> // Should only be called in TransitRegionStateProcedure(and related procedures), as the locking<a name="line.1810"></a>
-<span class="sourceLineNo">1811</span> // and pre-assumptions are very tricky.<a name="line.1811"></a>
-<span class="sourceLineNo">1812</span> // ============================================================================================<a name="line.1812"></a>
-<span class="sourceLineNo">1813</span> private void transitStateAndUpdate(RegionStateNode regionNode, RegionState.State newState,<a name="line.1813"></a>
-<span class="sourceLineNo">1814</span> RegionState.State... expectedStates) throws IOException {<a name="line.1814"></a>
-<span class="sourceLineNo">1815</span> RegionState.State state = regionNode.getState();<a name="line.1815"></a>
-<span class="sourceLineNo">1816</span> regionNode.transitionState(newState, expectedStates);<a name="line.1816"></a>
-<span class="sourceLineNo">1817</span> boolean succ = false;<a name="line.1817"></a>
-<span class="sourceLineNo">1818</span> try {<a name="line.1818"></a>
-<span class="sourceLineNo">1819</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1819"></a>
-<span class="sourceLineNo">1820</span> succ = true;<a name="line.1820"></a>
-<span class="sourceLineNo">1821</span> } finally {<a name="line.1821"></a>
-<span class="sourceLineNo">1822</span> if (!succ) {<a name="line.1822"></a>
-<span class="sourceLineNo">1823</span> // revert<a name="line.1823"></a>
-<span class="sourceLineNo">1824</span> regionNode.setState(state);<a name="line.1824"></a>
-<span class="sourceLineNo">1825</span> }<a name="line.1825"></a>
-<span class="sourceLineNo">1826</span> }<a name="line.1826"></a>
-<span class="sourceLineNo">1827</span> }<a name="line.1827"></a>
-<span class="sourceLineNo">1828</span><a name="line.1828"></a>
-<span class="sourceLineNo">1829</span> // should be called within the synchronized block of RegionStateNode<a name="line.1829"></a>
-<span class="sourceLineNo">1830</span> void regionOpening(RegionStateNode regionNode) throws IOException {<a name="line.1830"></a>
-<span class="sourceLineNo">1831</span> // As in SCP, for performance reason, there is no TRSP attached with this region, we will not<a name="line.1831"></a>
-<span class="sourceLineNo">1832</span> // update the region state, which means that the region could be in any state when we want to<a name="line.1832"></a>
-<span class="sourceLineNo">1833</span> // assign it after a RS crash. So here we do not pass the expectedStates parameter.<a name="line.1833"></a>
-<span class="sourceLineNo">1834</span> transitStateAndUpdate(regionNode, State.OPENING);<a name="line.1834"></a>
-<span class="sourceLineNo">1835</span> regionStates.addRegionToServer(regionNode);<a name="line.1835"></a>
-<span class="sourceLineNo">1836</span> // update the operation count metrics<a name="line.1836"></a>
-<span class="sourceLineNo">1837</span> metrics.incrementOperationCounter();<a name="line.1837"></a>
-<span class="sourceLineNo">1838</span> }<a name="line.1838"></a>
-<span class="sourceLineNo">1839</span><a name="line.1839"></a>
-<span class="sourceLineNo">1840</span> // should be called under the RegionStateNode lock<a name="line.1840"></a>
-<span class="sourceLineNo">1841</span> // The parameter 'giveUp' means whether we will try to open the region again, if it is true, then<a name="line.1841"></a>
-<span class="sourceLineNo">1842</span> // we will persist the FAILED_OPEN state into hbase:meta.<a name="line.1842"></a>
-<span class="sourceLineNo">1843</span> void regionFailedOpen(RegionStateNode regionNode, boolean giveUp) throws IOException {<a name="line.1843"></a>
-<span class="sourceLineNo">1844</span> RegionState.State state = regionNode.getState();<a name="line.1844"></a>
-<span class="sourceLineNo">1845</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1845"></a>
-<span class="sourceLineNo">1846</span> if (giveUp) {<a name="line.1846"></a>
-<span class="sourceLineNo">1847</span> regionNode.setState(State.FAILED_OPEN);<a name="line.1847"></a>
-<span class="sourceLineNo">1848</span> regionNode.setRegionLocation(null);<a name="line.1848"></a>
-<span class="sourceLineNo">1849</span> boolean succ = false;<a name="line.1849"></a>
-<span class="sourceLineNo">1850</span> try {<a name="line.1850"></a>
-<span class="sourceLineNo">1851</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1851"></a>
-<span class="sourceLineNo">1852</span> succ = true;<a name="line.1852"></a>
-<span class="sourceLineNo">1853</span> } finally {<a name="line.1853"></a>
-<span class="sourceLineNo">1854</span> if (!succ) {<a name="line.1854"></a>
-<span class="sourceLineNo">1855</span> // revert<a name="line.1855"></a>
-<span class="sourceLineNo">1856</span> regionNode.setState(state);<a name="line.1856"></a>
-<span class="sourceLineNo">1857</span> regionNode.setRegionLocation(regionLocation);<a name="line.1857"></a>
-<span class="sourceLineNo">1858</span> }<a name="line.1858"></a>
-<span class="sourceLineNo">1859</span> }<a name="line.1859"></a>
-<span class="sourceLineNo">1860</span> }<a name="line.1860"></a>
-<span class="sourceLineNo">1861</span> if (regionLocation != null) {<a name="line.1861"></a>
-<span class="sourceLineNo">1862</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1862"></a>
-<span class="sourceLineNo">1863</span> }<a name="line.1863"></a>
-<span class="sourceLineNo">1864</span> }<a name="line.1864"></a>
-<span class="sourceLineNo">1865</span><a name="line.1865"></a>
-<span class="sourceLineNo">1866</span> // should be called under the RegionStateNode lock<a name="line.1866"></a>
-<span class="sourceLineNo">1867</span> void regionClosing(RegionStateNode regionNode) throws IOException {<a name="line.1867"></a>
-<span class="sourceLineNo">1868</span> transitStateAndUpdate(regionNode, State.CLOSING, STATES_EXPECTED_ON_CLOSING);<a name="line.1868"></a>
-<span class="sourceLineNo">1869</span><a name="line.1869"></a>
-<span class="sourceLineNo">1870</span> RegionInfo hri = regionNode.getRegionInfo();<a name="line.1870"></a>
-<span class="sourceLineNo">1871</span> // Set meta has not initialized early. so people trying to create/edit tables will wait<a name="line.1871"></a>
-<span class="sourceLineNo">1872</span> if (isMetaRegion(hri)) {<a name="line.1872"></a>
-<span class="sourceLineNo">1873</span> setMetaAssigned(hri, false);<a name="line.1873"></a>
-<span class="sourceLineNo">1874</span> }<a name="line.1874"></a>
-<span class="sourceLineNo">1875</span> regionStates.addRegionToServer(regionNode);<a name="line.1875"></a>
-<span class="sourceLineNo">1876</span> // update the operation count metrics<a name="line.1876"></a>
-<span class="sourceLineNo">1877</span> metrics.incrementOperationCounter();<a name="line.1877"></a>
-<span class="sourceLineNo">1878</span> }<a name="line.1878"></a>
-<span class="sourceLineNo">1879</span><a name="line.1879"></a>
-<span class="sourceLineNo">1880</span> // for open and close, they will first be persist to the procedure store in<a name="line.1880"></a>
-<span class="sourceLineNo">1881</span> // RegionRemoteProcedureBase. So here we will first change the in memory state as it is considered<a name="line.1881"></a>
-<span class="sourceLineNo">1882</span> // as succeeded if the persistence to procedure store is succeeded, and then when the<a name="line.1882"></a>
-<span class="sourceLineNo">1883</span> // RegionRemoteProcedureBase is woken up, we will persist the RegionStateNode to hbase:meta.<a name="line.1883"></a>
-<span class="sourceLineNo">1884</span><a name="line.1884"></a>
-<span class="sourceLineNo">1885</span> // should be called under the RegionStateNode lock<a name="line.1885"></a>
-<span class="sourceLineNo">1886</span> void regionOpenedWithoutPersistingToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1886"></a>
-<span class="sourceLineNo">1887</span> regionNode.transitionState(State.OPEN, STATES_EXPECTED_ON_OPEN);<a name="line.1887"></a>
-<span class="sourceLineNo">1888</span> RegionInfo regionInfo = regionNode.getRegionInfo();<a name="line.1888"></a>
-<span class="sourceLineNo">1889</span> regionStates.addRegionToServer(regionNode);<a name="line.1889"></a>
-<span class="sourceLineNo">1890</span> regionStates.removeFromFailedOpen(regionInfo);<a name="line.1890"></a>
-<span class="sourceLineNo">1891</span> }<a name="line.1891"></a>
-<span class="sourceLineNo">1892</span><a name="line.1892"></a>
-<span class="sourceLineNo">1893</span> // should be called under the RegionStateNode lock<a name="line.1893"></a>
-<span class="sourceLineNo">1894</span> void regionClosedWithoutPersistingToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1894"></a>
-<span class="sourceLineNo">1895</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1895"></a>
-<span class="sourceLineNo">1896</span> regionNode.transitionState(State.CLOSED, STATES_EXPECTED_ON_CLOSED);<a name="line.1896"></a>
-<span class="sourceLineNo">1897</span> regionNode.setRegionLocation(null);<a name="line.1897"></a>
-<span class="sourceLineNo">1898</span> if (regionLocation != null) {<a name="line.1898"></a>
-<span class="sourceLineNo">1899</span> regionNode.setLastHost(regionLocation);<a name="line.1899"></a>
-<span class="sourceLineNo">1900</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1900"></a>
-<span class="sourceLineNo">1901</span> }<a name="line.1901"></a>
-<span class="sourceLineNo">1902</span> }<a name="line.1902"></a>
-<span class="sourceLineNo">1903</span><a name="line.1903"></a>
-<span class="sourceLineNo">1904</span> // should be called under the RegionStateNode lock<a name="line.1904"></a>
-<span class="sourceLineNo">1905</span> // for SCP<a name="line.1905"></a>
-<span class="sourceLineNo">1906</span> public void regionClosedAbnormally(RegionStateNode regionNode) throws IOException {<a name="line.1906"></a>
-<span class="sourceLineNo">1907</span> RegionState.State state = regionNode.getState();<a name="line.1907"></a>
-<span class="sourceLineNo">1908</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1908"></a>
-<span class="sourceLineNo">1909</span> regionNode.transitionState(State.ABNORMALLY_CLOSED);<a name="line.1909"></a>
-<span class="sourceLineNo">1910</span> regionNode.setRegionLocation(null);<a name="line.1910"></a>
-<span class="sourceLineNo">1911</span> boolean succ = false;<a name="line.1911"></a>
-<span class="sourceLineNo">1912</span> try {<a name="line.1912"></a>
-<span class="sourceLineNo">1913</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1913"></a>
-<span class="sourceLineNo">1914</span> succ = true;<a name="line.1914"></a>
-<span class="sourceLineNo">1915</span> } finally {<a name="line.1915"></a>
-<span class="sourceLineNo">1916</span> if (!succ) {<a name="line.1916"></a>
-<span class="sourceLineNo">1917</span> // revert<a name="line.1917"></a>
-<span class="sourceLineNo">1918</span> regionNode.setState(state);<a name="line.1918"></a>
-<span class="sourceLineNo">1919</span> regionNode.setRegionLocation(regionLocation);<a name="line.1919"></a>
-<span class="sourceLineNo">1920</span> }<a name="line.1920"></a>
-<span class="sourceLineNo">1921</span> }<a name="line.1921"></a>
-<span class="sourceLineNo">1922</span> if (regionLocation != null) {<a name="line.1922"></a>
-<span class="sourceLineNo">1923</span> regionNode.setLastHost(regionLocation);<a name="line.1923"></a>
-<span class="sourceLineNo">1924</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1924"></a>
-<span class="sourceLineNo">1925</span> }<a name="line.1925"></a>
-<span class="sourceLineNo">1926</span> }<a name="line.1926"></a>
-<span class="sourceLineNo">1927</span><a name="line.1927"></a>
-<span class="sourceLineNo">1928</span> void persistToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1928"></a>
-<span class="sourceLineNo">1929</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1929"></a>
-<span class="sourceLineNo">1930</span> RegionInfo regionInfo = regionNode.getRegionInfo();<a name="line.1930"></a>
-<span class="sourceLineNo">1931</span> if (isMetaRegion(regionInfo) && regionNode.getState() == State.OPEN) {<a name="line.1931"></a>
-<span class="sourceLineNo">1932</span> // Usually we'd set a table ENABLED at this stage but hbase:meta is ALWAYs enabled, it<a name="line.1932"></a>
-<span class="sourceLineNo">1933</span> // can't be disabled -- so skip the RPC (besides... enabled is managed by TableStateManager<a name="line.1933"></a>
-<span class="sourceLineNo">1934</span> // which is backed by hbase:meta... Avoid setting ENABLED to avoid having to update state<a name="line.1934"></a>
-<span class="sourceLineNo">1935</span> // on table that contains state.<a name="line.1935"></a>
-<span class="sourceLineNo">1936</span> setMetaAssigned(regionInfo, true);<a name="line.1936"></a>
+<span class="sourceLineNo">1805</span> private static final State[] STATES_EXPECTED_ON_CLOSING = {<a name="line.1805"></a>
+<span class="sourceLineNo">1806</span> State.OPEN, // Normal case<a name="line.1806"></a>
+<span class="sourceLineNo">1807</span> State.CLOSING, // Retrying<a name="line.1807"></a>
+<span class="sourceLineNo">1808</span> State.SPLITTING, // Offline the split parent<a name="line.1808"></a>
+<span class="sourceLineNo">1809</span> State.MERGING // Offline the merge parents<a name="line.1809"></a>
+<span class="sourceLineNo">1810</span> };<a name="line.1810"></a>
+<span class="sourceLineNo">1811</span><a name="line.1811"></a>
+<span class="sourceLineNo">1812</span> private static final State[] STATES_EXPECTED_ON_CLOSED = {<a name="line.1812"></a>
+<span class="sourceLineNo">1813</span> State.CLOSING, // Normal case<a name="line.1813"></a>
+<span class="sourceLineNo">1814</span> State.CLOSED // Retrying<a name="line.1814"></a>
+<span class="sourceLineNo">1815</span> };<a name="line.1815"></a>
+<span class="sourceLineNo">1816</span><a name="line.1816"></a>
+<span class="sourceLineNo">1817</span> // This is for manually scheduled region assign, can add other states later if we find out other<a name="line.1817"></a>
+<span class="sourceLineNo">1818</span> // usages<a name="line.1818"></a>
+<span class="sourceLineNo">1819</span> private static final State[] STATES_EXPECTED_ON_ASSIGN = { State.CLOSED, State.OFFLINE };<a name="line.1819"></a>
+<span class="sourceLineNo">1820</span><a name="line.1820"></a>
+<span class="sourceLineNo">1821</span> // We only allow unassign or move a region which is in OPEN state.<a name="line.1821"></a>
+<span class="sourceLineNo">1822</span> private static final State[] STATES_EXPECTED_ON_UNASSIGN_OR_MOVE = { State.OPEN };<a name="line.1822"></a>
+<span class="sourceLineNo">1823</span><a name="line.1823"></a>
+<span class="sourceLineNo">1824</span> // ============================================================================================<a name="line.1824"></a>
+<span class="sourceLineNo">1825</span> // Region Status update<a name="line.1825"></a>
+<span class="sourceLineNo">1826</span> // Should only be called in TransitRegionStateProcedure(and related procedures), as the locking<a name="line.1826"></a>
+<span class="sourceLineNo">1827</span> // and pre-assumptions are very tricky.<a name="line.1827"></a>
+<span class="sourceLineNo">1828</span> // ============================================================================================<a name="line.1828"></a>
+<span class="sourceLineNo">1829</span> private void transitStateAndUpdate(RegionStateNode regionNode, RegionState.State newState,<a name="line.1829"></a>
+<span class="sourceLineNo">1830</span> RegionState.State... expectedStates) throws IOException {<a name="line.1830"></a>
+<span class="sourceLineNo">1831</span> RegionState.State state = regionNode.getState();<a name="line.1831"></a>
+<span class="sourceLineNo">1832</span> regionNode.transitionState(newState, expectedStates);<a name="line.1832"></a>
+<span class="sourceLineNo">1833</span> boolean succ = false;<a name="line.1833"></a>
+<span class="sourceLineNo">1834</span> try {<a name="line.1834"></a>
+<span class="sourceLineNo">1835</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1835"></a>
+<span class="sourceLineNo">1836</span> succ = true;<a name="line.1836"></a>
+<span class="sourceLineNo">1837</span> } finally {<a name="line.1837"></a>
+<span class="sourceLineNo">1838</span> if (!succ) {<a name="line.1838"></a>
+<span class="sourceLineNo">1839</span> // revert<a name="line.1839"></a>
+<span class="sourceLineNo">1840</span> regionNode.setState(state);<a name="line.1840"></a>
+<span class="sourceLineNo">1841</span> }<a name="line.1841"></a>
+<span class="sourceLineNo">1842</span> }<a name="line.1842"></a>
+<span class="sourceLineNo">1843</span> }<a name="line.1843"></a>
+<span class="sourceLineNo">1844</span><a name="line.1844"></a>
+<span class="sourceLineNo">1845</span> // should be called within the synchronized block of RegionStateNode<a name="line.1845"></a>
+<span class="sourceLineNo">1846</span> void regionOpening(RegionStateNode regionNode) throws IOException {<a name="line.1846"></a>
+<span class="sourceLineNo">1847</span> // As in SCP, for performance reason, there is no TRSP attached with this region, we will not<a name="line.1847"></a>
+<span class="sourceLineNo">1848</span> // update the region state, which means that the region could be in any state when we want to<a name="line.1848"></a>
+<span class="sourceLineNo">1849</span> // assign it after a RS crash. So here we do not pass the expectedStates parameter.<a name="line.1849"></a>
+<span class="sourceLineNo">1850</span> transitStateAndUpdate(regionNode, State.OPENING);<a name="line.1850"></a>
+<span class="sourceLineNo">1851</span> regionStates.addRegionToServer(regionNode);<a name="line.1851"></a>
+<span class="sourceLineNo">1852</span> // update the operation count metrics<a name="line.1852"></a>
+<span class="sourceLineNo">1853</span> metrics.incrementOperationCounter();<a name="line.1853"></a>
+<span class="sourceLineNo">1854</span> }<a name="line.1854"></a>
+<span class="sourceLineNo">1855</span><a name="line.1855"></a>
+<span class="sourceLineNo">1856</span> // should be called under the RegionStateNode lock<a name="line.1856"></a>
+<span class="sourceLineNo">1857</span> // The parameter 'giveUp' means whether we will try to open the region again, if it is true, then<a name="line.1857"></a>
+<span class="sourceLineNo">1858</span> // we will persist the FAILED_OPEN state into hbase:meta.<a name="line.1858"></a>
+<span class="sourceLineNo">1859</span> void regionFailedOpen(RegionStateNode regionNode, boolean giveUp) throws IOException {<a name="line.1859"></a>
+<span class="sourceLineNo">1860</span> RegionState.State state = regionNode.getState();<a name="line.1860"></a>
+<span class="sourceLineNo">1861</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1861"></a>
+<span class="sourceLineNo">1862</span> if (giveUp) {<a name="line.1862"></a>
+<span class="sourceLineNo">1863</span> regionNode.setState(State.FAILED_OPEN);<a name="line.1863"></a>
+<span class="sourceLineNo">1864</span> regionNode.setRegionLocation(null);<a name="line.1864"></a>
+<span class="sourceLineNo">1865</span> boolean succ = false;<a name="line.1865"></a>
+<span class="sourceLineNo">1866</span> try {<a name="line.1866"></a>
+<span class="sourceLineNo">1867</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1867"></a>
+<span class="sourceLineNo">1868</span> succ = true;<a name="line.1868"></a>
+<span class="sourceLineNo">1869</span> } finally {<a name="line.1869"></a>
+<span class="sourceLineNo">1870</span> if (!succ) {<a name="line.1870"></a>
+<span class="sourceLineNo">1871</span> // revert<a name="line.1871"></a>
+<span class="sourceLineNo">1872</span> regionNode.setState(state);<a name="line.1872"></a>
+<span class="sourceLineNo">1873</span> regionNode.setRegionLocation(regionLocation);<a name="line.1873"></a>
+<span class="sourceLineNo">1874</span> }<a name="line.1874"></a>
+<span class="sourceLineNo">1875</span> }<a name="line.1875"></a>
+<span class="sourceLineNo">1876</span> }<a name="line.1876"></a>
+<span class="sourceLineNo">1877</span> if (regionLocation != null) {<a name="line.1877"></a>
+<span class="sourceLineNo">1878</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1878"></a>
+<span class="sourceLineNo">1879</span> }<a name="line.1879"></a>
+<span class="sourceLineNo">1880</span> }<a name="line.1880"></a>
+<span class="sourceLineNo">1881</span><a name="line.1881"></a>
+<span class="sourceLineNo">1882</span> // should be called under the RegionStateNode lock<a name="line.1882"></a>
+<span class="sourceLineNo">1883</span> void regionClosing(RegionStateNode regionNode) throws IOException {<a name="line.1883"></a>
+<span class="sourceLineNo">1884</span> transitStateAndUpdate(regionNode, State.CLOSING, STATES_EXPECTED_ON_CLOSING);<a name="line.1884"></a>
+<span class="sourceLineNo">1885</span><a name="line.1885"></a>
+<span class="sourceLineNo">1886</span> RegionInfo hri = regionNode.getRegionInfo();<a name="line.1886"></a>
+<span class="sourceLineNo">1887</span> // Set meta has not initialized early. so people trying to create/edit tables will wait<a name="line.1887"></a>
+<span class="sourceLineNo">1888</span> if (isMetaRegion(hri)) {<a name="line.1888"></a>
+<span class="sourceLineNo">1889</span> setMetaAssigned(hri, false);<a name="line.1889"></a>
+<span class="sourceLineNo">1890</span> }<a name="line.1890"></a>
+<span class="sourceLineNo">1891</span> regionStates.addRegionToServer(regionNode);<a name="line.1891"></a>
+<span class="sourceLineNo">1892</span> // update the operation count metrics<a name="line.1892"></a>
+<span class="sourceLineNo">1893</span> metrics.incrementOperationCounter();<a name="line.1893"></a>
+<span class="sourceLineNo">1894</span> }<a name="line.1894"></a>
+<span class="sourceLineNo">1895</span><a name="line.1895"></a>
+<span class="sourceLineNo">1896</span> // for open and close, they will first be persist to the procedure store in<a name="line.1896"></a>
+<span class="sourceLineNo">1897</span> // RegionRemoteProcedureBase. So here we will first change the in memory state as it is considered<a name="line.1897"></a>
+<span class="sourceLineNo">1898</span> // as succeeded if the persistence to procedure store is succeeded, and then when the<a name="line.1898"></a>
+<span class="sourceLineNo">1899</span> // RegionRemoteProcedureBase is woken up, we will persist the RegionStateNode to hbase:meta.<a name="line.1899"></a>
+<span class="sourceLineNo">1900</span><a name="line.1900"></a>
+<span class="sourceLineNo">1901</span> // should be called under the RegionStateNode lock<a name="line.1901"></a>
+<span class="sourceLineNo">1902</span> void regionOpenedWithoutPersistingToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1902"></a>
+<span class="sourceLineNo">1903</span> regionNode.transitionState(State.OPEN, STATES_EXPECTED_ON_OPEN);<a name="line.1903"></a>
+<span class="sourceLineNo">1904</span> RegionInfo regionInfo = regionNode.getRegionInfo();<a name="line.1904"></a>
+<span class="sourceLineNo">1905</span> regionStates.addRegionToServer(regionNode);<a name="line.1905"></a>
+<span class="sourceLineNo">1906</span> regionStates.removeFromFailedOpen(regionInfo);<a name="line.1906"></a>
+<span class="sourceLineNo">1907</span> }<a name="line.1907"></a>
+<span class="sourceLineNo">1908</span><a name="line.1908"></a>
+<span class="sourceLineNo">1909</span> // should be called under the RegionStateNode lock<a name="line.1909"></a>
+<span class="sourceLineNo">1910</span> void regionClosedWithoutPersistingToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1910"></a>
+<span class="sourceLineNo">1911</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1911"></a>
+<span class="sourceLineNo">1912</span> regionNode.transitionState(State.CLOSED, STATES_EXPECTED_ON_CLOSED);<a name="line.1912"></a>
+<span class="sourceLineNo">1913</span> regionNode.setRegionLocation(null);<a name="line.1913"></a>
+<span class="sourceLineNo">1914</span> if (regionLocation != null) {<a name="line.1914"></a>
+<span class="sourceLineNo">1915</span> regionNode.setLastHost(regionLocation);<a name="line.1915"></a>
+<span class="sourceLineNo">1916</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1916"></a>
+<span class="sourceLineNo">1917</span> }<a name="line.1917"></a>
+<span class="sourceLineNo">1918</span> }<a name="line.1918"></a>
+<span class="sourceLineNo">1919</span><a name="line.1919"></a>
+<span class="sourceLineNo">1920</span> // should be called under the RegionStateNode lock<a name="line.1920"></a>
+<span class="sourceLineNo">1921</span> // for SCP<a name="line.1921"></a>
+<span class="sourceLineNo">1922</span> public void regionClosedAbnormally(RegionStateNode regionNode) throws IOException {<a name="line.1922"></a>
+<span class="sourceLineNo">1923</span> RegionState.State state = regionNode.getState();<a name="line.1923"></a>
+<span class="sourceLineNo">1924</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1924"></a>
+<span class="sourceLineNo">1925</span> regionNode.transitionState(State.ABNORMALLY_CLOSED);<a name="line.1925"></a>
+<span class="sourceLineNo">1926</span> regionNode.setRegionLocation(null);<a name="line.1926"></a>
+<span class="sourceLineNo">1927</span> boolean succ = false;<a name="line.1927"></a>
+<span class="sourceLineNo">1928</span> try {<a name="line.1928"></a>
+<span class="sourceLineNo">1929</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1929"></a>
+<span class="sourceLineNo">1930</span> succ = true;<a name="line.1930"></a>
+<span class="sourceLineNo">1931</span> } finally {<a name="line.1931"></a>
+<span class="sourceLineNo">1932</span> if (!succ) {<a name="line.1932"></a>
+<span class="sourceLineNo">1933</span> // revert<a name="line.1933"></a>
+<span class="sourceLineNo">1934</span> regionNode.setState(state);<a name="line.1934"></a>
+<span class="sourceLineNo">1935</span> regionNode.setRegionLocation(regionLocation);<a name="line.1935"></a>
+<span class="sourceLineNo">1936</span> }<a name="line.1936"></a>
<span class="sourceLineNo">1937</span> }<a name="line.1937"></a>
-<span class="sourceLineNo">1938</span> }<a name="line.1938"></a>
-<span class="sourceLineNo">1939</span><a name="line.1939"></a>
-<span class="sourceLineNo">1940</span> // ============================================================================================<a name="line.1940"></a>
-<span class="sourceLineNo">1941</span> // The above methods can only be called in TransitRegionStateProcedure(and related procedures)<a name="line.1941"></a>
-<span class="sourceLineNo">1942</span> // ============================================================================================<a name="line.1942"></a>
+<span class="sourceLineNo">1938</span> if (regionLocation != null) {<a name="line.1938"></a>
+<span class="sourceLineNo">1939</span> regionNode.setLastHost(regionLocation);<a name="line.1939"></a>
+<span class="sourceLineNo">1940</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1940"></a>
+<span class="sourceLineNo">1941</span> }<a name="line.1941"></a>
+<span class="sourceLineNo">1942</span> }<a name="line.1942"></a>
<span class="sourceLineNo">1943</span><a name="line.1943"></a>
-<span class="sourceLineNo">1944</span> public void markRegionAsSplit(final RegionInfo parent, final ServerName serverName,<a name="line.1944"></a>
-<span class="sourceLineNo">1945</span> final RegionInfo daughterA, final RegionInfo daughterB) throws IOException {<a name="line.1945"></a>
-<span class="sourceLineNo">1946</span> // Update hbase:meta. Parent will be marked offline and split up in hbase:meta.<a name="line.1946"></a>
-<span class="sourceLineNo">1947</span> // The parent stays in regionStates until cleared when removed by CatalogJanitor.<a name="line.1947"></a>
-<span class="sourceLineNo">1948</span> // Update its state in regionStates to it shows as offline and split when read<a name="line.1948"></a>
-<span class="sourceLineNo">1949</span> // later figuring what regions are in a table and what are not: see<a name="line.1949"></a>
-<span class="sourceLineNo">1950</span> // regionStates#getRegionsOfTable<a name="line.1950"></a>
-<span class="sourceLineNo">1951</span> final RegionStateNode node = regionStates.getOrCreateRegionStateNode(parent);<a name="line.1951"></a>
-<span class="sourceLineNo">1952</span> node.setState(State.SPLIT);<a name="line.1952"></a>
-<span class="sourceLineNo">1953</span> final RegionStateNode nodeA = regionStates.getOrCreateRegionStateNode(daughterA);<a name="line.1953"></a>
-<span class="sourceLineNo">1954</span> nodeA.setState(State.SPLITTING_NEW);<a name="line.1954"></a>
-<span class="sourceLineNo">1955</span> final RegionStateNode nodeB = regionStates.getOrCreateRegionStateNode(daughterB);<a name="line.1955"></a>
-<span class="sourceLineNo">1956</span> nodeB.setState(State.SPLITTING_NEW);<a name="line.1956"></a>
-<span class="sourceLineNo">1957</span><a name="line.1957"></a>
-<span class="sourceLineNo">1958</span> TableDescriptor td = master.getTableDescriptors().get(parent.getTable());<a name="line.1958"></a>
-<span class="sourceLineNo">1959</span> // TODO: here we just update the parent region info in meta, to set split and offline to true,<a name="line.1959"></a>
-<span class="sourceLineNo">1960</span> // without changing the one in the region node. This is a bit confusing but the region info<a name="line.1960"></a>
-<span class="sourceLineNo">1961</span> // field in RegionStateNode is not expected to be changed in the current design. Need to find a<a name="line.1961"></a>
-<span class="sourceLineNo">1962</span> // possible way to address this problem, or at least adding more comments about the trick to<a name="line.1962"></a>
-<span class="sourceLineNo">1963</span> // deal with this problem, that when you want to filter out split parent, you need to check both<a name="line.1963"></a>
-<span class="sourceLineNo">1964</span> // the RegionState on whether it is split, and also the region info. If one of them matches then<a name="line.1964"></a>
-<span class="sourceLineNo">1965</span> // it is a split parent. And usually only one of them can match, as after restart, the region<a name="line.1965"></a>
-<span class="sourceLineNo">1966</span> // state will be changed from SPLIT to CLOSED.<a name="line.1966"></a>
-<span class="sourceLineNo">1967</span> regionStateStore.splitRegion(parent, daughterA, daughterB, serverName, td);<a name="line.1967"></a>
-<span class="sourceLineNo">1968</span> if (shouldAssignFavoredNodes(parent)) {<a name="line.1968"></a>
-<span class="sourceLineNo">1969</span> List<ServerName> onlineServers = this.master.getServerManager().getOnlineServersList();<a name="line.1969"></a>
-<span class="sourceLineNo">1970</span> getFavoredNodePromoter().generateFavoredNodesForDaughter(onlineServers, parent, daughterA,<a name="line.1970"></a>
-<span class="sourceLineNo">1971</span> daughterB);<a name="line.1971"></a>
-<span class="sourceLineNo">1972</span> }<a name="line.1972"></a>
-<span class="sourceLineNo">1973</span> }<a name="line.1973"></a>
-<span class="sourceLineNo">1974</span><a name="line.1974"></a>
-<span class="sourceLineNo">1975</span> /**<a name="line.1975"></a>
-<span class="sourceLineNo">1976</span> * When called here, the merge has happened. The merged regions have been<a name="line.1976"></a>
-<span class="sourceLineNo">1977</span> * unassigned and the above markRegionClosed has been called on each so they have been<a name="line.1977"></a>
-<span class="sourceLineNo">1978</span> * disassociated from a hosting Server. The merged region will be open after this call. The<a name="line.1978"></a>
-<span class="sourceLineNo">1979</span> * merged regions are removed from hbase:meta below. Later they are deleted from the filesystem<a name="line.1979"></a>
-<span class="sourceLineNo">1980</span> * by the catalog janitor running against hbase:meta. It notices when the merged region no<a name="line.1980"></a>
-<span class="sourceLineNo">1981</span> * longer holds references to the old regions (References are deleted after a compaction<a name="line.1981"></a>
-<span class="sourceLineNo">1982</span> * rewrites what the Reference points at but not until the archiver chore runs, are the<a name="line.1982"></a>
-<span class="sourceLineNo">1983</span> * References removed).<a name="line.1983"></a>
-<span class="sourceLineNo">1984</span> */<a name="line.1984"></a>
-<span class="sourceLineNo">1985</span> public void markRegionAsMerged(final RegionInfo child, final ServerName serverName,<a name="line.1985"></a>
-<span class="sourceLineNo">1986</span> RegionInfo [] mergeParents)<a name="line.1986"></a>
-<span class="sourceLineNo">1987</span> throws IOException {<a name="line.1987"></a>
-<span class="sourceLineNo">1988</span> final RegionStateNode node = regionStates.getOrCreateRegionStateNode(child);<a name="line.1988"></a>
-<span class="sourceLineNo">1989</span> node.setState(State.MERGED);<a name="line.1989"></a>
-<span class="sourceLineNo">1990</span> for (RegionInfo ri: mergeParents) {<a name="line.1990"></a>
-<span class="sourceLineNo">1991</span> regionStates.deleteRegion(ri);<a name="line.1991"></a>
-<span class="sourceLineNo">1992</span> }<a name="line.1992"></a>
-<span class="sourceLineNo">1993</span> TableDescriptor td = master.getTableDescriptors().get(child.getTable());<a name="line.1993"></a>
-<span class="sourceLineNo">1994</span> regionStateStore.mergeRegions(child, mergeParents, serverName, td);<a name="line.1994"></a>
-<span class="sourceLineNo">1995</span> if (shouldAssignFavoredNodes(child)) {<a name="line.1995"></a>
-<span class="sourceLineNo">1996</span> getFavoredNodePromoter().generateFavoredNodesForMergedRegion(child, mergeParents);<a name="line.1996"></a>
-<span class="sourceLineNo">1997</span> }<a name="line.1997"></a>
-<span class="sourceLineNo">1998</span> }<a name="line.1998"></a>
-<span class="sourceLineNo">1999</span><a name="line.1999"></a>
-<span class="sourceLineNo">2000</span> /*<a name="line.2000"></a>
-<span class="sourceLineNo">2001</span> * Favored nodes should be applied only when FavoredNodes balancer is configured and the region<a name="line.2001"></a>
-<span class="sourceLineNo">2002</span> * belongs to a non-system table.<a name="line.2002"></a>
-<span class="sourceLineNo">2003</span> */<a name="line.2003"></a>
-<span class="sourceLineNo">2004</span> private boolean shouldAssignFavoredNodes(RegionInfo region) {<a name="line.2004"></a>
-<span class="sourceLineNo">2005</span> return this.shouldAssignRegionsWithFavoredNodes &&<a name="line.2005"></a>
-<span class="sourceLineNo">2006</span> FavoredNodesManager.isFavoredNodeApplicable(region);<a name="line.2006"></a>
-<span class="sourceLineNo">2007</span> }<a name="line.2007"></a>
-<span class="sourceLineNo">2008</span><a name="line.2008"></a>
-<span class="sourceLineNo">2009</span> // ============================================================================================<a name="line.2009"></a>
-<span class="sourceLineNo">2010</span> // Assign Queue (Assign/Balance)<a name="line.2010"></a>
-<span class="sourceLineNo">2011</span> // ============================================================================================<a name="line.2011"></a>
-<span class="sourceLineNo">2012</span> private final ArrayList<RegionStateNode> pendingAssignQueue = new ArrayList<RegionStateNode>();<a name="line.2012"></a>
-<span class="sourceLineNo">2013</span> private final ReentrantLock assignQueueLock = new ReentrantLock();<a name="line.2013"></a>
-<span class="sourceLineNo">2014</span> private final Condition assignQueueFullCond = assignQueueLock.newCondition();<a name="line.2014"></a>
+<span class="sourceLineNo">1944</span> void persistToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1944"></a>
+<span class="sourceLineNo">1945</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1945"></a>
+<span class="sourceLineNo">1946</span> RegionInfo regionInfo = regionNode.getRegionInfo();<a name="line.1946"></a>
+<span class="sourceLineNo">1947</span> if (isMetaRegion(regionInfo) && regionNode.getState() == State.OPEN) {<a name="line.1947"></a>
+<span class="sourceLineNo">1948</span> // Usually we'd set a table ENABLED at this stage but hbase:meta is ALWAYs enabled, it<a name="line.1948"></a>
+<span class="sourceLineNo">1949</span> // can't be disabled -- so skip the RPC (besides... enabled is managed by TableStateManager<a name="line.1949"></a>
+<span class="sourceLineNo">1950</span> // which is backed by hbase:meta... Avoid setting ENABLED to avoid having to update state<a name="line.1950"></a>
+<span class="sourceLineNo">1951</span> // on table that contains state.<a name="line.1951"></a>
+<span class="sourceLineNo">1952</span> setMetaAssigned(regionInfo, true);<a name="line.1952"></a>
+<span class="sourceLineNo">1953</span> }<a name="line.1953"></a>
+<span class="sourceLineNo">1954</span> }<a name="line.1954"></a>
+<span class="sourceLineNo">1955</span><a name="line.1955"></a>
+<span class="sourceLineNo">1956</span> // ============================================================================================<a name="line.1956"></a>
+<span class="sourceLineNo">1957</span> // The above methods can only be called in TransitRegionStateProcedure(and related procedures)<a name="line.1957"></a>
+<span class="sourceLineNo">1958</span> // ============================================================================================<a name="line.1958"></a>
+<span class="sourceLineNo">1959</span><a name="line.1959"></a>
+<span class="sourceLineNo">1960</span> public void markRegionAsSplit(final RegionInfo parent, final ServerName serverName,<a name="line.1960"></a>
+<span class="sourceLineNo">1961</span> final RegionInfo daughterA, final RegionInfo daughterB) throws IOException {<a name="line.1961"></a>
+<span class="sourceLineNo">1962</span> // Update hbase:meta. Parent will be marked offline and split up in hbase:meta.<a name="line.1962"></a>
+<span class="sourceLineNo">1963</span> // The parent stays in regionStates until cleared when removed by CatalogJanitor.<a name="line.1963"></a>
+<span class="sourceLineNo">1964</span> // Update its state in regionStates to it shows as offline and split when read<a name="line.1964"></a>
+<span class="sourceLineNo">1965</span> // later figuring what regions are in a table and what are not: see<a name="line.1965"></a>
+<span class="sourceLineNo">1966</span> // regionStates#getRegionsOfTable<a name="line.1966"></a>
+<span class="sourceLineNo">1967</span> final RegionStateNode node = regionStates.getOrCreateRegionStateNode(parent);<a name="line.1967"></a>
+<span class="sourceLineNo">1968</span> node.setState(State.SPLIT);<a name="line.1968"></a>
+<span class="sourceLineNo">1969</span> final RegionStateNode nodeA = regionStates.getOrCreateRegionStateNode(daughterA);<a name="line.1969"></a>
+<span class="sourceLineNo">1970</span> nodeA.setState(State.SPLITTING_NEW);<a name="line.1970"></a>
+<span class="sourceLineNo">1971</span> final RegionStateNode nodeB = regionStates.getOrCreateRegionStateNode(daughterB);<a name="line.1971"></a>
+<span class="sourceLineNo">1972</span> nodeB.setState(State.SPLITTING_NEW);<a name="line.1972"></a>
+<span class="sourceLineNo">1973</span><a name="line.1973"></a>
+<span class="sourceLineNo">1974</span> TableDescriptor td = master.getTableDescriptors().get(parent.getTable());<a name="line.1974"></a>
+<span class="sourceLineNo">1975</span> // TODO: here we just update the parent region info in meta, to set split and offline to true,<a name="line.1975"></a>
+<span class="sourceLineNo">1976</span> // without changing the one in the region node. This is a bit confusing but the region info<a name="line.1976"></a>
+<span class="sourceLineNo">1977</span> // field in RegionStateNode is not expected to be changed in the current design. Need to find a<a name="line.1977"></a>
+<span class="sourceLineNo">1978</span> // possible way to address this problem, or at least adding more comments about the trick to<a name="line.1978"></a>
+<span class="sourceLineNo">1979</span> // deal with this problem, that when you want to filter out split parent, you need to check both<a name="line.1979"></a>
+<span class="sourceLineNo">1980</span> // the RegionState on whether it is split, and also the region info. If one of them matches then<a name="line.1980"></a>
+<span class="sourceLineNo">1981</span> // it is a split parent. And usually only one of them can match, as after restart, the region<a name="line.1981"></a>
+<span class="sourceLineNo">1982</span> // state will be changed from SPLIT to CLOSED.<a name="line.1982"></a>
+<span class="sourceLineNo">1983</span> regionStateStore.splitRegion(parent, daughterA, daughterB, serverName, td);<a name="line.1983"></a>
+<span class="sourceLineNo">1984</span> if (shouldAssignFavoredNodes(parent)) {<a name="line.1984"></a>
+<span class="sourceLineNo">1985</span> List<ServerName> onlineServers = this.master.getServerManager().getOnlineServersList();<a name="line.1985"></a>
+<span class="sourceLineNo">1986</span> getFavoredNodePromoter().generateFavoredNodesForDaughter(onlineServers, parent, daughterA,<a name="line.1986"></a>
+<span class="sourceLineNo">1987</span> daughterB);<a name="line.1987"></a>
+<span class="sourceLineNo">1988</span> }<a name="line.1988"></a>
+<span class="sourceLineNo">1989</span> }<a name="line.1989"></a>
+<span class="sourceLineNo">1990</span><a name="line.1990"></a>
+<span class="sourceLineNo">1991</span> /**<a name="line.1991"></a>
+<span class="sourceLineNo">1992</span> * When called here, the merge has happened. The merged regions have been<a name="line.1992"></a>
+<span class="sourceLineNo">1993</span> * unassigned and the above markRegionClosed has been called on each so they have been<a name="line.1993"></a>
+<span class="sourceLineNo">1994</span> * disassociated from a hosting Server. The merged region will be open after this call. The<a name="line.1994"></a>
+<span class="sourceLineNo">1995</span> * merged regions are removed from hbase:meta below. Later they are deleted from the filesystem<a name="line.1995"></a>
+<span class="sourceLineNo">1996</span> * by the catalog janitor running against hbase:meta. It notices when the merged region no<a name="line.1996"></a>
+<span class="sourceLineNo">1997</span> * longer holds references to the old regions (References are deleted after a compaction<a name="line.1997"></a>
+<span class="sourceLineNo">1998</span> * rewrites what the Reference points at but not until the archiver chore runs, are the<a name="line.1998"></a>
+<span class="sourceLineNo">1999</span> * References removed).<a name="line.1999"></a>
+<span class="sourceLineNo">2000</span> */<a name="line.2000"></a>
+<span class="sourceLineNo">2001</span> public void markRegionAsMerged(final RegionInfo child, final ServerName serverName,<a name="line.2001"></a>
+<span class="sourceLineNo">2002</span> RegionInfo [] mergeParents)<a name="line.2002"></a>
+<span class="sourceLineNo">2003</span> throws IOException {<a name="line.2003"></a>
+<span class="sourceLineNo">2004</span> final RegionStateNode node = regionStates.getOrCreateRegionStateNode(child);<a name="line.2004"></a>
+<span class="sourceLineNo">2005</span> node.setState(State.MERGED);<a name="line.2005"></a>
+<span class="sourceLineNo">2006</span> for (RegionInfo ri: mergeParents) {<a name="line.2006"></a>
+<span class="sourceLineNo">2007</span> regionStates.deleteRegion(ri);<a name="line.2007"></a>
+<span class="sourceLineNo">2008</span> }<a name="line.2008"></a>
+<span class="sourceLineNo">2009</span> TableDescriptor td = master.getTableDescriptors().get(child.getTable());<a name="line.2009"></a>
+<span class="sourceLineNo">2010</span> regionStateStore.mergeRegions(child, mergeParents, serverName, td);<a name="line.2010"></a>
+<span class="sourceLineNo">2011</span> if (shouldAssignFavoredNodes(child)) {<a name="line.2011"></a>
+<span class="sourceLineNo">2012</span> getFavoredNodePromoter().generateFavoredNodesForMergedRegion(child, mergeParents);<a name="line.2012"></a>
+<span class="sourceLineNo">2013</span> }<a name="line.2013"></a>
+<span class="sourceLineNo">2014</span> }<a name="line.2014"></a>
<span class="sourceLineNo">2015</span><a name="line.2015"></a>
-<span class="sourceLineNo">2016</span> /**<a name="line.2016"></a>
-<span class="sourceLineNo">2017</span> * Add the assign operation to the assignment queue.<a name="line.2017"></a>
-<span class="sourceLineNo">2018</span> * The pending assignment operation will be processed,<a name="line.2018"></a>
-<span class="sourceLineNo">2019</span> * and each region will be assigned by a server using the balancer.<a name="line.2019"></a>
-<span class="sourceLineNo">2020</span> */<a name="line.2020"></a>
-<span class="sourceLineNo">2021</span> protected void queueAssign(final RegionStateNode regionNode) {<a name="line.2021"></a>
-<span class="sourceLineNo">2022</span> regionNode.getProcedureEvent().suspend();<a name="line.2022"></a>
-<span class="sourceLineNo">2023</span><a name="line.2023"></a>
-<span class="sourceLineNo">2024</span> // TODO: quick-start for meta and the other sys-tables?<a name="line.2024"></a>
-<span class="sourceLineNo">2025</span> assignQueueLock.lock();<a name="line.2025"></a>
-<span class="sourceLineNo">2026</span> try {<a name="line.2026"></a>
-<span class="sourceLineNo">2027</span> pendingAssignQueue.add(regionNode);<a name="line.2027"></a>
-<span class="sourceLineNo">2028</span> if (regionNode.isSystemTable() ||<a name="line.2028"></a>
-<span class="sourceLineNo">2029</span> pendingAssignQueue.size() == 1 ||<a name="line.2029"></a>
-<span class="sourceLineNo">2030</span> pendingAssignQueue.size() >= assignDispatchWaitQueueMaxSize) {<a name="line.2030"></a>
-<span class="sourceLineNo">2031</span> assignQueueFullCond.signal();<a name="line.2031"></a>
-<span class="sourceLineNo">2032</span> }<a name="line.2032"></a>
-<span class="sourceLineNo">2033</span> } finally {<a name="line.2033"></a>
-<span class="sourceLineNo">2034</span> assignQueueLock.unlock();<a name="line.2034"></a>
-<span class="sourceLineNo">2035</span> }<a name="line.2035"></a>
-<span class="sourceLineNo">2036</span> }<a name="line.2036"></a>
-<span class="sourceLineNo">2037</span><a name="line.2037"></a>
-<span class="sourceLineNo">2038</span> private void startAssignmentThread() {<a name="line.2038"></a>
-<span class="sourceLineNo">2039</span> assignThread = new Thread(master.getServerName().toShortString()) {<a name="line.2039"></a>
-<span class="sourceLineNo">2040</span> @Override<a name="line.2040"></a>
-<span class="sourceLineNo">2041</span> public void run() {<a name="line.2041"></a>
-<span class="sourceLineNo">2042</span> while (isRunning()) {<a name="line.2042"></a>
-<span class="sourceLineNo">2043</span> processAssignQueue();<a name="line.2043"></a>
-<span class="sourceLineNo">2044</span> }<a name="line.2044"></a>
-<span class="sourceLineNo">2045</span> pendingAssignQueue.clear();<a name="line.2045"></a>
-<span class="sourceLineNo">2046</span> }<a name="line.2046"></a>
-<span class="sourceLineNo">2047</span> };<a name="line.2047"></a>
-<span class="sourceLineNo">2048</span> assignThread.setDaemon(true);<a name="line.2048"></a>
-<span class="sourceLineNo">2049</span> assignThread.start();<a name="line.2049"></a>
-<span class="sourceLineNo">2050</span> }<a name="line.2050"></a>
-<span class="sourceLineNo">2051</span><a name="line.2051"></a>
-<span class="sourceLineNo">2052</span> private void stopAssignmentThread() {<a name="line.2052"></a>
-<span class="sourceLineNo">2053</span> assignQueueSignal();<a name="line.2053"></a>
-<span class="sourceLineNo">2054</span> try {<a name="line.2054"></a>
-<span class="sourceLineNo">2055</span> while (assignThread.isAlive()) {<a name="line.2055"></a>
-<span class="sourceLineNo">2056</span> assignQueueSignal();<a name="line.2056"></a>
-<span class="sourceLineNo">2057</span> assignThread.join(250);<a name="line.2057"></a>
-<span class="sourceLineNo">2058</span> }<a name="line.2058"></a>
-<span class="sourceLineNo">2059</span> } catch (InterruptedException e) {<a name="line.2059"></a>
-<span class="sourceLineNo">2060</span> LOG.warn("join interrupted", e);<a name="line.2060"></a>
-<span class="sourceLineNo">2061</span> Thread.currentThread().interrupt();<a name="line.2061"></a>
-<span class="sourceLineNo">2062</span> }<a name="line.2062"></a>
-<span class="sourceLineNo">2063</span> }<a name="line.2063"></a>
-<span class="sourceLineNo">2064</span><a name="line.2064"></a>
-<span class="sourceLineNo">2065</span> private void assignQueueSignal() {<a name="line.2065"></a>
-<span class="sourceLineNo">2066</span> assignQueueLock.lock();<a name="line.2066"></a>
-<span class="sourceLineNo">2067</span> try {<a name="line.2067"></a>
-<span class="sourceLineNo">2068</span> assignQueueFullCond.signal();<a name="line.2068"></a>
-<span class="sourceLineNo">2069</span> } finally {<a name="line.2069"></a>
-<span class="sourceLineNo">2070</span> assignQueueLock.unlock();<a name="line.2070"></a>
-<span class="sourceLineNo">2071</span> }<a name="line.2071"></a>
-<span class="sourceLineNo">2072</span> }<a name="line.2072"></a>
-<span class="sourceLineNo">2073</span><a name="line.2073"></a>
-<span class="sourceLineNo">2074</span> @edu.umd.cs.findbugs.annotations.SuppressWarnings("WA_AWAIT_NOT_IN_LOOP")<a name="line.2074"></a>
-<span class="sourceLineNo">2075</span> private HashMap<RegionInfo, RegionStateNode> waitOnAssignQueue() {<a name="line.2075"></a>
-<span class="sourceLineNo">2076</span> HashMap<RegionInfo, RegionStateNode> regions = null;<a name="line.2076"></a>
-<span class="sourceLineNo">2077</span><a name="line.2077"></a>
-<span class="sourceLineNo">2078</span> assignQueueLock.lock();<a name="line.2078"></a>
-<span class="sourceLineNo">2079</span> try {<a name="line.2079"></a>
-<span class="sourceLineNo">2080</span> if (pendingAssignQueue.isEmpty() && isRunning()) {<a name="line.2080"></a>
-<span class="sourceLineNo">2081</span> assignQueueFullCond.await();<a name="line.2081"></a>
-<span class="sourceLineNo">2082</span> }<a name="line.2082"></a>
-<span class="sourceLineNo">2083</span><a name="line.2083"></a>
-<span class="sourceLineNo">2084</span> if (!isRunning()) {<a name="line.2084"></a>
-<span class="sourceLineNo">2085</span> return null;<a name="line.2085"></a>
-<span class="sourceLineNo">2086</span> }<a name="line.2086"></a>
-<span class="sourceLineNo">2087</span> assignQueueFullCond.await(assignDispatchWaitMillis, TimeUnit.MILLISECONDS);<a name="line.2087"></a>
-<span class="sourceLineNo">2088</span> regions = new HashMap<RegionInfo, RegionStateNode>(pendingAssignQueue.size());<a name="line.2088"></a>
-<span class="sourceLineNo">2089</span> for (RegionStateNode regionNode: pendingAssignQueue) {<a name="line.2089"></a>
-<span class="sourceLineNo">2090</span> regions.put(regionNode.getRegionInfo(), regionNode);<a name="line.2090"></a>
-<span class="sourceLineNo">2091</span> }<a name="line.2091"></a>
-<span class="sourceLineNo">2092</span> pendingAssignQueue.clear();<a name="line.2092"></a>
-<span class="sourceLineNo">2093</span> } catch (InterruptedException e) {<a name="line.2093"></a>
-<span class="sourceLineNo">2094</span> LOG.warn("got interrupted ", e);<a name="line.2094"></a>
-<span class="sourceLineNo">2095</span> Thread.currentThread().interrupt();<a name="line.2095"></a>
-<span class="sourceLineNo">2096</span> } finally {<a name="line.2096"></a>
-<span class="sourceLineNo">2097</span> assignQueueLock.unlock();<a name="line.2097"></a>
-<span class="sourceLineNo">2098</span> }<a name="line.2098"></a>
-<span class="sourceLineNo">2099</span> return regions;<a name="line.2099"></a>
-<span class="sourceLineNo">2100</span> }<a name="line.2100"></a>
-<span class="sourceLineNo">2101</span><a name="line.2101"></a>
-<span class="sourceLineNo">2102</span> private void processAssignQueue() {<a name="line.2102"></a>
-<span class="sourceLineNo">2103</span> final HashMap<RegionInfo, RegionStateNode> regions = waitOnAssignQueue();<a name="line.2103"></a>
-<span class="sourceLineNo">2104</span> if (regions == null || regions.size() == 0 || !isRunning()) {<a name="line.2104"></a>
-<span class="sourceLineNo">2105</span> return;<a name="line.2105"></a>
-<span class="sourceLineNo">2106</span> }<a name="line.2106"></a>
-<span class="sourceLineNo">2107</span><a name="line.2107"></a>
-<span class="sourceLineNo">2108</span> if (LOG.isTraceEnabled()) {<a name="line.2108"></a>
-<span class="sourceLineNo">2109</span> LOG.trace("PROCESS ASSIGN QUEUE regionCount=" + regions.size());<a name="line.2109"></a>
-<span class="sourceLineNo">2110</span> }<a name="line.2110"></a>
-<span class="sourceLineNo">2111</span><a name="line.2111"></a>
-<span class="sourceLineNo">2112</span> // TODO: Optimize balancer. pass a RegionPlan?<a name="line.2112"></a>
-<span class="sourceLineNo">2113</span> final HashMap<RegionInfo, ServerName> retainMap = new HashMap<>();<a name="line.2113"></a>
-<span class="sourceLineNo">2114</span> final List<RegionInfo> userHRIs = new ArrayList<>(regions.size());<a name="line.2114"></a>
-<span class="sourceLineNo">2115</span> // Regions for system tables requiring reassignment<a name="line.2115"></a>
-<span class="sourceLineNo">2116</span> final List<RegionInfo> systemHRIs = new ArrayList<>();<a name="line.2116"></a>
-<span class="sourceLineNo">2117</span> for (RegionStateNode regionStateNode: regions.values()) {<a name="line.2117"></a>
-<span class="sourceLineNo">2118</span> boolean sysTable = regionStateNode.isSystemTable();<a name="line.2118"></a>
-<span class="sourceLineNo">2119</span> final List<RegionInfo> hris = sysTable? systemHRIs: userHRIs;<a name="line.2119"></a>
-<span class="sourceLineNo">2120</span> if (regionStateNode.getRegionLocation() != null) {<a name="line.2120"></a>
-<span class="sourceLineNo">2121</span> retainMap.put(regionStateNode.getRegionInfo(), regionStateNode.getRegionLocation());<a name="line.2121"></a>
-<span class="sourceLineNo">2122</span> } else {<a name="line.2122"></a>
-<span class="sourceLineNo">2123</span> hris.add(regionStateNode.getRegionInfo());<a name="line.2123"></a>
-<span class="sourceLineNo">2124</span> }<a name="line.2124"></a>
-<span class="sourceLineNo">2125</span> }<a name="line.2125"></a>
-<span class="sourceLineNo">2126</span><a name="line.2126"></a>
-<span class="sourceLineNo">2127</span> // TODO: connect with the listener to invalidate the cache<a name="line.2127"></a>
-<span class="sourceLineNo">2128</span><a name="line.2128"></a>
-<span class="sourceLineNo">2129</span> // TODO use events<a name="line.2129"></a>
-<span class="sourceLineNo">2130</span> List<ServerName> servers = master.getServerManager().createDestinationServersList();<a name="line.2130"></a>
-<span class="sourceLineNo">2131</span> for (int i = 0; servers.size() < 1; ++i) {<a name="line.2131"></a>
-<span class="sourceLineNo">2132</span> // Report every fourth time around this loop; try not to flood log.<a name="line.2132"></a>
-<span class="sourceLineNo">2133</span> if (i % 4 == 0) {<a name="line.2133"></a>
-<span class="sourceLineNo">2134</span> LOG.warn("No servers available; cannot place " + regions.size() + " unassigned regions.");<a name="line.2134"></a>
-<span class="sourceLineNo">2135</span> }<a name="line.2135"></a>
-<span class="sourceLineNo">2136</span><a name="line.2136"></a>
-<span class="sourceLineNo">2137</span> if (!isRunning()) {<a name="line.2137"></a>
-<span class="sourceLineNo">2138</span> LOG.debug("Stopped! Dropping assign of " + regions.size() + " queued regions.");<a name="line.2138"></a>
-<span class="sourceLineNo">2139</span> return;<a name="line.2139"></a>
+<span class="sourceLineNo">2016</span> /*<a name="line.2016"></a>
+<span class="sourceLineNo">2017</span> * Favored nodes should be applied only when FavoredNodes balancer is configured and the region<a name="line.2017"></a>
+<span class="sourceLineNo">2018</span> * belongs to a non-system table.<a name="line.2018"></a>
+<span class="sourceLineNo">2019</span> */<a name="line.2019"></a>
+<span class="sourceLineNo">2020</span> private boolean shouldAssignFavoredNodes(RegionInfo region) {<a name="line.2020"></a>
+<span class="sourceLineNo">2021</span> return this.shouldAssignRegionsWithFavoredNodes &&<a name="line.2021"></a>
+<span class="sourceLineNo">2022</span> FavoredNodesManager.isFavoredNodeApplicable(region);<a name="line.2022"></a>
+<span class="sourceLineNo">2023</span> }<a name="line.2023"></a>
+<span class="sourceLineNo">2024</span><a name="line.2024"></a>
+<span class="sourceLineNo">2025</span> // ============================================================================================<a name="line.2025"></a>
+<span class="sourceLineNo">2026</span> // Assign Queue (Assign/Balance)<a name="line.2026"></a>
+<span class="sourceLineNo">2027</span> // ============================================================================================<a name="line.2027"></a>
+<span class="sourceLineNo">2028</span> private final ArrayList<RegionStateNode> pendingAssignQueue = new ArrayList<RegionStateNode>();<a name="line.2028"></a>
+<span class="sourceLineNo">2029</span> private final ReentrantLock assignQueueLock = new ReentrantLock();<a name="line.2029"></a>
+<span class="sourceLineNo">2030</span> private final Condition assignQueueFullCond = assignQueueLock.newCondition();<a name="line.2030"></a>
+<span class="sourceLineNo">2031</span><a name="line.2031"></a>
+<span class="sourceLineNo">2032</span> /**<a name="line.2032"></a>
+<span class="sourceLineNo">2033</span> * Add the assign operation to the assignment queue.<a name="line.2033"></a>
+<span class="sourceLineNo">2034</span> * The pending assignment operation will be processed,<a name="line.2034"></a>
+<span class="sourceLineNo">2035</span> * and each region will be assigned by a server using the balancer.<a name="line.2035"></a>
+<span class="sourceLineNo">2036</span> */<a name="line.2036"></a>
+<span class="sourceLineNo">2037</span> protected void queueAssign(final RegionStateNode regionNode) {<a name="line.2037"></a>
+<span class="sourceLineNo">2038</span> regionNode.getProcedureEvent().suspend();<a name="line.2038"></a>
+<span class="sourceLineNo">2039</span><a name="line.2039"></a>
+<span class="sourceLineNo">2040</span> // TODO: quick-start for meta and the other sys-tables?<a name="line.2040"></a>
+<span class="sourceLineNo">2041</span> assignQueueLock.lock();<a name="line.2041"></a>
+<span class="sourceLineNo">2042</span> try {<a name="line.2042"></a>
+<span class="sourceLineNo">2043</span> pendingAssignQueue.add(regionNode);<a name="line.2043"></a>
+<span class="sourceLineNo">2044</span> if (regionNode.isSystemTable() ||<a name="line.2044"></a>
+<span class="sourceLineNo">2045</span> pendingAssignQueue.size() == 1 ||<a name="line.2045"></a>
+<span class="sourceLineNo">2046</span> pendingAssignQueue.size() >= assignDispatchWaitQueueMaxSize) {<a name="line.2046"></a>
+<span class="sourceLineNo">2047</span> assignQueueFullCond.signal();<a name="line.2047"></a>
+<span class="sourceLineNo">2048</span> }<a name="line.2048"></a>
+<span class="sourceLineNo">2049</span> } finally {<a name="line.2049"></a>
+<span class="sourceLineNo">2050</span> assignQueueLock.unlock();<a name="line.2050"></a>
+<span class="sourceLineNo">2051</span> }<a name="line.2051"></a>
+<span class="sourceLineNo">2052</span> }<a name="line.2052"></a>
+<span class="sourceLineNo">2053</span><a name="line.2053"></a>
+<span class="sourceLineNo">2054</span> private void startAssignmentThread() {<a name="line.2054"></a>
+<span class="sourceLineNo">2055</span> assignThread = new Thread(master.getServerName().toShortString()) {<a name="line.2055"></a>
+<span class="sourceLineNo">2056</span> @Override<a name="line.2056"></a>
+<span class="sourceLineNo">2057</span> public void run() {<a name="line.2057"></a>
+<span class="sourceLineNo">2058</span> while (isRunning()) {<a name="line.2058"></a>
+<span class="sourceLineNo">2059</span> processAssignQueue();<a name="line.2059"></a>
+<span class="sourceLineNo">2060</span> }<a name="line.2060"></a>
+<span class="sourceLineNo">2061</span> pendingAssignQueue.clear();<a name="line.2061"></a>
+<span class="sourceLineNo">2062</span> }<a name="line.2062"></a>
+<span class="sourceLineNo">2063</span> };<a name="line.2063"></a>
+<span class="sourceLineNo">2064</span> assignThread.setDaemon(true);<a name="line.2064"></a>
+<span class="sourceLineNo">2065</span> assignThread.start();<a name="line.2065"></a>
+<span class="sourceLineNo">2066</span> }<a name="line.2066"></a>
+<span class="sourceLineNo">2067</span><a name="line.2067"></a>
+<span class="sourceLineNo">2068</span> private void stopAssignmentThread() {<a name="line.2068"></a>
+<span class="sourceLineNo">2069</span> assignQueueSignal();<a name="line.2069"></a>
+<span class="sourceLineNo">2070</span> try {<a name="line.2070"></a>
+<span class="sourceLineNo">2071</span> while (assignThread.isAlive()) {<a name="line.2071"></a>
+<span class="sourceLineNo">2072</span> assignQueueSignal();<a name="line.2072"></a>
+<span class="sourceLineNo">2073</span> assignThread.join(250);<a name="line.2073"></a>
+<span class="sourceLineNo">2074</span> }<a name="line.2074"></a>
+<span class="sourceLineNo">2075</span> } catch (InterruptedException e) {<a name="line.2075"></a>
+<span class="sourceLineNo">2076</span> LOG.warn("join interrupted", e);<a name="line.2076"></a>
+<span class="sourceLineNo">2077</span> Thread.currentThread().interrupt();<a name="line.2077"></a>
+<span class="sourceLineNo">2078</span> }<a name="line.2078"></a>
+<span class="sourceLineNo">2079</span> }<a name="line.2079"></a>
+<span class="sourceLineNo">2080</span><a name="line.2080"></a>
+<span class="sourceLineNo">2081</span> private void assignQueueSignal() {<a name="line.2081"></a>
+<span class="sourceLineNo">2082</span> assignQueueLock.lock();<a name="line.2082"></a>
+<span class="sourceLineNo">2083</span> try {<a name="line.2083"></a>
+<span class="sourceLineNo">2084</span> assignQueueFullCond.signal();<a name="line.2084"></a>
+<span class="sourceLineNo">2085</span> } finally {<a name="line.2085"></a>
+<span class="sourceLineNo">2086</span> assignQueueLock.unlock();<a name="line.2086"></a>
+<span class="sourceLineNo">2087</span> }<a name="line.2087"></a>
+<span class="sourceLineNo">2088</span> }<a name="line.2088"></a>
+<span class="sourceLineNo">2089</span><a name="line.2089"></a>
+<span class="sourceLineNo">2090</span> @edu.umd.cs.findbugs.annotations.SuppressWarnings("WA_AWAIT_NOT_IN_LOOP")<a name="line.2090"></a>
+<span class="sourceLineNo">2091</span> private HashMap<RegionInfo, RegionStateNode> waitOnAssignQueue() {<a name="line.2091"></a>
+<span class="sourceLineNo">2092</span> HashMap<RegionInfo, RegionStateNode> regions = null;<a name="line.2092"></a>
+<span class="sourceLineNo">2093</span><a name="line.2093"></a>
+<span class="sourceLineNo">2094</span> assignQueueLock.lock();<a name="line.2094"></a>
+<span class="sourceLineNo">2095</span> try {<a name="line.2095"></a>
+<span class="sourceLineNo">2096</span> if (pendingAssignQueue.isEmpty() && isRunning()) {<a name="line.2096"></a>
+<span class="sourceLineNo">2097</span> assignQueueFullCond.await();<a name="line.2097"></a>
+<span class="sourceLineNo">2098</span> }<a name="line.2098"></a>
+<span class="sourceLineNo">2099</span><a name="line.2099"></a>
+<span class="sourceLineNo">2100</span> if (!isRunning()) {<a name="line.2100"></a>
+<span class="sourceLineNo">2101</span> return null;<a name="line.2101"></a>
+<span class="sourceLineNo">2102</span> }<a name="line.2102"></a>
+<span class="sourceLineNo">2103</span> assignQueueFullCond.await(assignDispatchWaitMillis, TimeUnit.MILLISECONDS);<a name="line.2103"></a>
+<span class="sourceLineNo">2104</span> regions = new HashMap<RegionInfo, RegionStateNode>(pendingAssignQueue.size());<a name="line.2104"></a>
+<span class="sourceLineNo">2105</span> for (RegionStateNode regionNode: pendingAssignQueue) {<a name="line.2105"></a>
+<span class="sourceLineNo">2106</span> regions.put(regionNode.getRegionInfo(), regionNode);<a name="line.2106"></a>
+<span class="sourceLineNo">2107</span> }<a name="line.2107"></a>
+<span class="sourceLineNo">2108</span> pendingAssignQueue.clear();<a name="line.2108"></a>
+<span class="sourceLineNo">2109</span> } catch (InterruptedException e) {<a name="line.2109"></a>
+<span class="sourceLineNo">2110</span> LOG.warn("got interrupted ", e);<a name="line.2110"></a>
+<span class="sourceLineNo">2111</span> Thread.currentThread().interrupt();<a name="line.2111"></a>
+<span class="sourceLineNo">2112</span> } finally {<a name="line.2112"></a>
+<span class="sourceLineNo">2113</span> assignQueueLock.unlock();<a name="line.2113"></a>
+<span class="sourceLineNo">2114</span> }<a name="line.2114"></a>
+<span class="sourceLineNo">2115</span> return regions;<a name="line.2115"></a>
+<span class="sourceLineNo">2116</span> }<a name="line.2116"></a>
+<span class="sourceLineNo">2117</span><a name="line.2117"></a>
+<span class="sourceLineNo">2118</span> private void processAssignQueue() {<a name="line.2118"></a>
+<span class="sourceLineNo">2119</span> final HashMap<RegionInfo, RegionStateNode> regions = waitOnAssignQueue();<a name="line.2119"></a>
+<span class="sourceLineNo">2120</span> if (regions == null || regions.size() == 0 || !isRunning()) {<a name="line.2120"></a>
+<span class="sourceLineNo">2121</span> return;<a name="line.2121"></a>
+<span class="sourceLineNo">2122</span> }<a name="line.2122"></a>
+<span class="sourceLineNo">2123</span><a name="line.2123"></a>
+<span class="sourceLineNo">2124</span> if (LOG.isTraceEnabled()) {<a name="line.2124"></a>
+<span class="sourceLineNo">2125</span> LOG.trace("PROCESS ASSIGN QUEUE regionCount=" + regions.size());<a name="line.2125"></a>
+<span class="sourceLineNo">2126</span> }<a name="line.2126"></a>
+<span class="sourceLineNo">2127</span><a name="line.2127"></a>
+<span class="sourceLineNo">2128</span> // TODO: Optimize balancer. pass a RegionPlan?<a name="line.2128"></a>
+<span class="sourceLineNo">2129</span> final HashMap<RegionInfo, ServerName> retainMap = new HashMap<>();<a name="line.2129"></a>
+<span class="sourceLineNo">2130</span> final List<RegionInfo> userHRIs = new ArrayList<>(regions.size());<a name="line.2130"></a>
+<span class="sourceLineNo">2131</span> // Regions for system tables requiring reassignment<a name="line.2131"></a>
+<span class="sourceLineNo">2132</span> final List<RegionInfo> systemHRIs = new ArrayList<>();<a name="line.2132"></a>
+<span class="sourceLineNo">2133</span> for (RegionStateNode regionStateNode: regions.values()) {<a name="line.2133"></a>
+<span class="sourceLineNo">2134</span> boolean sysTable = regionStateNode.isSystemTable();<a name="line.2134"></a>
+<span class="sourceLineNo">2135</span> final List<RegionInfo> hris = sysTable? systemHRIs: userHRIs;<a name="line.2135"></a>
+<span class="sourceLineNo">2136</span> if (regionStateNode.getRegionLocation() != null) {<a name="line.2136"></a>
+<span class="sourceLineNo">2137</span> retainMap.put(regionStateNode.getRegionInfo(), regionStateNode.getRegionLocation());<a name="line.2137"></a>
+<span class="sourceLineNo">2138</span> } else {<a name="line.2138"></a>
+<span class="sourceLineNo">2139</span> hris.add(regionStateNode.getRegionInfo());<a name="line.2139"></a>
<span class="sourceLineNo">2140</span> }<a name="line.2140"></a>
-<span class="sourceLineNo">2141</span> Threads.sleep(250);<a name="line.2141"></a>
-<span class="sourceLineNo">2142</span> servers = master.getServerManager().createDestinationServersList();<a name="line.2142"></a>
-<span class="sourceLineNo">2143</span> }<a name="line.2143"></a>
+<span class="sourceLineNo">2141</span> }<a name="line.2141"></a>
+<span class="sourceLineNo">2142</span><a name="line.2142"></a>
+<span class="sourceLineNo">2143</span> // TODO: connect with the listener to invalidate the cache<a name="line.2143"></a>
<span class="sourceLineNo">2144</span><a name="line.2144"></a>
-<span class="sourceLineNo">2145</span> if (!systemHRIs.isEmpty()) {<a name="line.2145"></a>
-<span class="sourceLineNo">2146</span> // System table regions requiring reassignment are present, get region servers<a name="line.2146"></a>
-<span class="sourceLineNo">2147</span> // not available for system table regions<a name="line.2147"></a>
-<span class="sourceLineNo">2148</span> final List<ServerName> excludeServers = getExcludedServersForSystemTable();<a name="line.2148"></a>
-<span class="sourceLineNo">2149</span> List<ServerName> serversForSysTables = servers.stream()<a name="line.2149"></a>
-<span class="sourceLineNo">2150</span> .filter(s -> !excludeServers.contains(s)).collect(Collectors.toList());<a name="line.2150"></a>
-<span class="sourceLineNo">2151</span> if (serversForSysTables.isEmpty()) {<a name="line.2151"></a>
-<span class="sourceLineNo">2152</span> LOG.warn("Filtering old server versions and the excluded produced an empty set; " +<a name="line.2152"></a>
-<span class="sourceLineNo">2153</span> "instead considering all candidate servers!");<a name="line.2153"></a>
-<span class="sourceLineNo">2154</span> }<a name="line.2154"></a>
-<span class="sourceLineNo">2155</span> LOG.debug("Processing assignQueue; systemServersCount=" + serversForSysTables.size() +<a name="line.2155"></a>
-<span class="sourceLineNo">2156</span> ", allServersCount=" + servers.size());<a name="line.2156"></a>
-<span class="sourceLineNo">2157</span> processAssignmentPlans(regions, null, systemHRIs,<a name="line.2157"></a>
-<span class="sourceLineNo">2158</span> serversForSysTables.isEmpty() && !containsBogusAssignments(regions, systemHRIs) ?<a name="line.2158"></a>
-<span class="sourceLineNo">2159</span> servers: serversForSysTables);<a name="line.2159"></a>
-<span class="sourceLineNo">2160</span> }<a name="line.2160"></a>
-<span class="sourceLineNo">2161</span><a name="line.2161"></a>
-<span class="sourceLineNo">2162</span> processAssignmentPlans(regions, retainMap, userHRIs, servers);<a name="line.2162"></a>
-<span class="sourceLineNo">2163</span> }<a name="line.2163"></a>
-<span class="sourceLineNo">2164</span><a name="line.2164"></a>
-<span class="sourceLineNo">2165</span> private boolean containsBogusAssignments(Map<RegionInfo, RegionStateNode> regions,<a name="line.2165"></a>
-<span class="sourceLineNo">2166</span> List<RegionInfo> hirs) {<a name="line.2166"></a>
-<span class="sourceLineNo">2167</span> for (RegionInfo ri : hirs) {<a name="line.2167"></a>
-<span class="sourceLineNo">2168</span> if (regions.get(ri).getRegionLocation() != null &&<a name="line.2168"></a>
-<span class="sourceLineNo">2169</span> regions.get(ri).getRegionLocation().equals(LoadBalancer.BOGUS_SERVER_NAME)){<a name="line.2169"></a>
-<span class="sourceLineNo">2170</span> return true;<a name="line.2170"></a>
-<span class="sourceLineNo">2171</span> }<a name="line.2171"></a>
-<span class="sourceLineNo">2172</span> }<a name="line.2172"></a>
-<span class="sourceLineNo">2173</span> return false;<a name="line.2173"></a>
-<span class="sourceLineNo">2174</span> }<a name="line.2174"></a>
-<span class="sourceLineNo">2175</span><a name="line.2175"></a>
-<span class="sourceLineNo">2176</span> private void processAssignmentPlans(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2176"></a>
-<span class="sourceLineNo">2177</span> final HashMap<RegionInfo, ServerName> retainMap, final List<RegionInfo> hris,<a name="line.2177"></a>
-<span class="sourceLineNo">2178</span> final List<ServerName> servers) {<a name="line.2178"></a>
-<span class="sourceLineNo">2179</span> boolean isTraceEnabled = LOG.isTraceEnabled();<a name="line.2179"></a>
-<span class="sourceLineNo">2180</span> if (isTraceEnabled) {<a name="line.2180"></a>
-<span class="sourceLineNo">2181</span> LOG.trace("Available servers count=" + servers.size() + ": " + servers);<a name="line.2181"></a>
-<span class="sourceLineNo">2182</span> }<a name="line.2182"></a>
-<span class="sourceLineNo">2183</span><a name="line.2183"></a>
-<span class="sourceLineNo">2184</span> final LoadBalancer balancer = getBalancer();<a name="line.2184"></a>
-<span class="sourceLineNo">2185</span> // ask the balancer where to place regions<a name="line.2185"></a>
-<span class="sourceLineNo">2186</span> if (retainMap != null && !retainMap.isEmpty()) {<a name="line.2186"></a>
-<span class="sourceLineNo">2187</span> if (isTraceEnabled) {<a name="line.2187"></a>
-<span class="sourceLineNo">2188</span> LOG.trace("retain assign regions=" + retainMap);<a name="line.2188"></a>
-<span class="sourceLineNo">2189</span> }<a name="line.2189"></a>
-<span class="sourceLineNo">2190</span> try {<a name="line.2190"></a>
-<span class="sourceLineNo">2191</span> acceptPlan(regions, balancer.retainAssignment(retainMap, servers));<a name="line.2191"></a>
-<span class="sourceLineNo">2192</span> } catch (IOException e) {<a name="line.2192"></a>
-<span class="sourceLineNo">2193</span> LOG.warn("unable to retain assignment", e);<a name="line.2193"></a>
-<span class="sourceLineNo">2194</span> addToPendingAssignment(regions, retainMap.keySet());<a name="line.2194"></a>
-<span class="sourceLineNo">2195</span> }<a name="line.2195"></a>
-<span class="sourceLineNo">2196</span> }<a name="line.2196"></a>
-<span class="sourceLineNo">2197</span><a name="line.2197"></a>
-<span class="sourceLineNo">2198</span> // TODO: Do we need to split retain and round-robin?<a name="line.2198"></a>
-<span class="sourceLineNo">2199</span> // the retain seems to fallback to round-robin/random if the region is not in the map.<a name="line.2199"></a>
-<span class="sourceLineNo">2200</span> if (!hris.isEmpty()) {<a name="line.2200"></a>
-<span class="sourceLineNo">2201</span> Collections.sort(hris, RegionInfo.COMPARATOR);<a name="line.2201"></a>
-<span class="sourceLineNo">2202</span> if (isTraceEnabled) {<a name="line.2202"></a>
-<span class="sourceLineNo">2203</span> LOG.trace("round robin regions=" + hris);<a name="line.2203"></a>
-<span class="sourceLineNo">2204</span> }<a name="line.2204"></a>
-<span class="sourceLineNo">2205</span> try {<a name="line.2205"></a>
-<span class="sourceLineNo">2206</span> acceptPlan(regions, balancer.roundRobinAssignment(hris, servers));<a name="line.2206"></a>
-<span class="sourceLineNo">2207</span> } catch (IOException e) {<a name="line.2207"></a>
-<span class="sourceLineNo">2208</span> LOG.warn("unable to round-robin assignment", e);<a name="line.2208"></a>
-<span class="sourceLineNo">2209</span> addToPendingAssignment(regions, hris);<a name="line.2209"></a>
-<span class="sourceLineNo">2210</span> }<a name="line.2210"></a>
-<span class="sourceLineNo">2211</span> }<a name="line.2211"></a>
-<span class="sourceLineNo">2212</span> }<a name="line.2212"></a>
+<span class="sourceLineNo">2145</span> // TODO use events<a name="line.2145"></a>
+<span class="sourceLineNo">2146</span> List<ServerName> servers = master.getServerManager().createDestinationServersList();<a name="line.2146"></a>
+<span class="sourceLineNo">2147</span> for (int i = 0; servers.size() < 1; ++i) {<a name="line.2147"></a>
+<span class="sourceLineNo">2148</span> // Report every fourth time around this loop; try not to flood log.<a name="line.2148"></a>
+<span class="sourceLineNo">2149</span> if (i % 4 == 0) {<a name="line.2149"></a>
+<span class="sourceLineNo">2150</span> LOG.warn("No servers available; cannot place " + regions.size() + " unassigned regions.");<a name="line.2150"></a>
+<span class="sourceLineNo">2151</span> }<a name="line.2151"></a>
+<span class="sourceLineNo">2152</span><a name="line.2152"></a>
+<span class="sourceLineNo">2153</span> if (!isRunning()) {<a name="line.2153"></a>
+<span class="sourceLineNo">2154</span> LOG.debug("Stopped! Dropping assign of " + regions.size() + " queued regions.");<a name="line.2154"></a>
+<span class="sourceLineNo">2155</span> return;<a name="line.2155"></a>
+<span class="sourceLineNo">2156</span> }<a name="line.2156"></a>
+<span class="sourceLineNo">2157</span> Threads.sleep(250);<a name="line.2157"></a>
+<span class="sourceLineNo">2158</span> servers = master.getServerManager().createDestinationServersList();<a name="line.2158"></a>
+<span class="sourceLineNo">2159</span> }<a name="line.2159"></a>
+<span class="sourceLineNo">2160</span><a name="line.2160"></a>
+<span class="sourceLineNo">2161</span> if (!systemHRIs.isEmpty()) {<a name="line.2161"></a>
+<span class="sourceLineNo">2162</span> // System table regions requiring reassignment are present, get region servers<a name="line.2162"></a>
+<span class="sourceLineNo">2163</span> // not available for system table regions<a name="line.2163"></a>
+<span class="sourceLineNo">2164</span> final List<ServerName> excludeServers = getExcludedServersForSystemTable();<a name="line.2164"></a>
+<span class="sourceLineNo">2165</span> List<ServerName> serversForSysTables = servers.stream()<a name="line.2165"></a>
+<span class="sourceLineNo">2166</span> .filter(s -> !excludeServers.contains(s)).collect(Collectors.toList());<a name="line.2166"></a>
+<span class="sourceLineNo">2167</span> if (serversForSysTables.isEmpty()) {<a name="line.2167"></a>
+<span class="sourceLineNo">2168</span> LOG.warn("Filtering old server versions and the excluded produced an empty set; " +<a name="line.2168"></a>
+<span class="sourceLineNo">2169</span> "instead considering all candidate servers!");<a name="line.2169"></a>
+<span class="sourceLineNo">2170</span> }<a name="line.2170"></a>
+<span class="sourceLineNo">2171</span> LOG.debug("Processing assignQueue; systemServersCount=" + serversForSysTables.size() +<a name="line.2171"></a>
+<span class="sourceLineNo">2172</span> ", allServersCount=" + servers.size());<a name="line.2172"></a>
+<span class="sourceLineNo">2173</span> processAssignmentPlans(regions, null, systemHRIs,<a name="line.2173"></a>
+<span class="sourceLineNo">2174</span> serversForSysTables.isEmpty() && !containsBogusAssignments(regions, systemHRIs) ?<a name="line.2174"></a>
+<span class="sourceLineNo">2175</span> servers: serversForSysTables);<a name="line.2175"></a>
+<span class="sourceLineNo">2176</span> }<a name="line.2176"></a>
+<span class="sourceLineNo">2177</span><a name="line.2177"></a>
+<span class="sourceLineNo">2178</span> processAssignmentPlans(regions, retainMap, userHRIs, servers);<a name="line.2178"></a>
+<span class="sourceLineNo">2179</span> }<a name="line.2179"></a>
+<span class="sourceLineNo">2180</span><a name="line.2180"></a>
+<span class="sourceLineNo">2181</span> private boolean containsBogusAssignments(Map<RegionInfo, RegionStateNode> regions,<a name="line.2181"></a>
+<span class="sourceLineNo">2182</span> List<RegionInfo> hirs) {<a name="line.2182"></a>
+<span class="sourceLineNo">2183</span> for (RegionInfo ri : hirs) {<a name="line.2183"></a>
+<span class="sourceLineNo">2184</span> if (regions.get(ri).getRegionLocation() != null &&<a name="line.2184"></a>
+<span class="sourceLineNo">2185</span> regions.get(ri).getRegionLocation().equals(LoadBalancer.BOGUS_SERVER_NAME)){<a name="line.2185"></a>
+<span class="sourceLineNo">2186</span> return true;<a name="line.2186"></a>
+<span class="sourceLineNo">2187</span> }<a name="line.2187"></a>
+<span class="sourceLineNo">2188</span> }<a name="line.2188"></a>
+<span class="sourceLineNo">2189</span> return false;<a name="line.2189"></a>
+<span class="sourceLineNo">2190</span> }<a name="line.2190"></a>
+<span class="sourceLineNo">2191</span><a name="line.2191"></a>
+<span class="sourceLineNo">2192</span> private void processAssignmentPlans(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2192"></a>
+<span class="sourceLineNo">2193</span> final HashMap<RegionInfo, ServerName> retainMap, final List<RegionInfo> hris,<a name="line.2193"></a>
+<span class="sourceLineNo">2194</span> final List<ServerName> servers) {<a name="line.2194"></a>
+<span class="sourceLineNo">2195</span> boolean isTraceEnabled = LOG.isTraceEnabled();<a name="line.2195"></a>
+<span class="sourceLineNo">2196</span> if (isTraceEnabled) {<a name="line.2196"></a>
+<span class="sourceLineNo">2197</span> LOG.trace("Available servers count=" + servers.size() + ": " + servers);<a name="line.2197"></a>
+<span class="sourceLineNo">2198</span> }<a name="line.2198"></a>
+<span class="sourceLineNo">2199</span><a name="line.2199"></a>
+<span class="sourceLineNo">2200</span> final LoadBalancer balancer = getBalancer();<a name="line.2200"></a>
+<span class="sourceLineNo">2201</span> // ask the balancer where to place regions<a name="line.2201"></a>
+<span class="sourceLineNo">2202</span> if (retainMap != null && !retainMap.isEmpty()) {<a name="line.2202"></a>
+<span class="sourceLineNo">2203</span> if (isTraceEnabled) {<a name="line.2203"></a>
+<span class="sourceLineNo">2204</span> LOG.trace("retain assign regions=" + retainMap);<a name="line.2204"></a>
+<span class="sourceLineNo">2205</span> }<a name="line.2205"></a>
+<span class="sourceLineNo">2206</span> try {<a name="line.2206"></a>
+<span class="sourceLineNo">2207</span> acceptPlan(regions, balancer.retainAssignment(retainMap, servers));<a name="line.2207"></a>
+<span class="sourceLineNo">2208</span> } catch (IOException e) {<a name="line.2208"></a>
+<span class="sourceLineNo">2209</span> LOG.warn("unable to retain assignment", e);<a name="line.2209"></a>
+<span class="sourceLineNo">2210</span> addToPendingAssignment(regions, retainMap.keySet());<a name="line.2210"></a>
+<span class="sourceLineNo">2211</span> }<a name="line.2211"></a>
+<span class="sourceLineNo">2212</span> }<a name="line.2212"></a>
<span class="sourceLineNo">2213</span><a name="line.2213"></a>
-<span class="sourceLineNo">2214</span> private void acceptPlan(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2214"></a>
-<span class="sourceLineNo">2215</span> final Map<ServerName, List<RegionInfo>> plan) throws HBaseIOException {<a name="line.2215"></a>
-<span class="sourceLineNo">2216</span> final ProcedureEvent<?>[] events = new ProcedureEvent[regions.size()];<a name="line.2216"></a>
-<span class="sourceLineNo">2217</span> final long st = System.currentTimeMillis();<a name="line.2217"></a>
-<span class="sourceLineNo">2218</span><a name="line.2218"></a>
-<span class="sourceLineNo">2219</span> if (plan.isEmpty()) {<a name="line.2219"></a>
-<span class="sourceLineNo">2220</span> throw new HBaseIOException("unable to compute plans for regions=" + regions.size());<a name="line.2220"></a>
-<span class="sourceLineNo">2221</span> }<a name="line.2221"></a>
-<span class="sourceLineNo">2222</span><a name="line.2222"></a>
-<span class="sourceLineNo">2223</span> int evcount = 0;<a name="line.2223"></a>
-<span class="sourceLineNo">2224</span> for (Map.Entry<ServerName, List<RegionInfo>> entry: plan.entrySet()) {<a name="line.2224"></a>
-<span class="sourceLineNo">2225</span> final ServerName server = entry.getKey();<a name="line.2225"></a>
-<span class="sourceLineNo">2226</span> for (RegionInfo hri: entry.getValue()) {<a name="line.2226"></a>
-<span class="sourceLineNo">2227</span> final RegionStateNode regionNode = regions.get(hri);<a name="line.2227"></a>
-<span class="sourceLineNo">2228</span> regionNode.setRegionLocation(server);<a name="line.2228"></a>
-<span class="sourceLineNo">2229</span> if (server.equals(LoadBalancer.BOGUS_SERVER_NAME) && regionNode.isSystemTable()) {<a name="line.2229"></a>
-<span class="sourceLineNo">2230</span> assignQueueLock.lock();<a name="line.2230"></a>
-<span class="sourceLineNo">2231</span> try {<a name="line.2231"></a>
-<span class="sourceLineNo">2232</span> pendingAssignQueue.add(regionNode);<a name="line.2232"></a>
-<span class="sourceLineNo">2233</span> } finally {<a name="line.2233"></a>
-<span class="sourceLineNo">2234</span> assignQueueLock.unlock();<a name="line.2234"></a>
-<span class="sourceLineNo">2235</span> }<a name="line.2235"></a>
-<span class="sourceLineNo">2236</span> }else {<a name="line.2236"></a>
-<span class="sourceLineNo">2237</span> events[evcount++] = regionNode.getProcedureEvent();<a name="line.2237"></a>
-<span class="sourceLineNo">2238</span> }<a name="line.2238"></a>
-<span class="sourceLineNo">2239</span> }<a name="line.2239"></a>
-<span class="sourceLineNo">2240</span> }<a name="line.2240"></a>
-<span class="sourceLineNo">2241</span> ProcedureEvent.wakeEvents(getProcedureScheduler(), events);<a name="line.2241"></a>
-<span class="sourceLineNo">2242</span><a name="line.2242"></a>
-<span class="sourceLineNo">2243</span> final long et = System.currentTimeMillis();<a name="line.2243"></a>
-<span class="sourceLineNo">2244</span> if (LOG.isTraceEnabled()) {<a name="line.2244"></a>
-<span class="sourceLineNo">2245</span> LOG.trace("ASSIGN ACCEPT " + events.length + " -> " +<a name="line.2245"></a>
-<span class="sourceLineNo">2246</span> StringUtils.humanTimeDiff(et - st));<a name="line.2246"></a>
-<span class="sourceLineNo">2247</span> }<a name="line.2247"></a>
-<span class="sourceLineNo">2248</span> }<a name="line.2248"></a>
-<span class="sourceLineNo">2249</span><a name="line.2249"></a>
-<span class="sourceLineNo">2250</span> private void addToPendingAssignment(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2250"></a>
-<span class="sourceLineNo">2251</span> final Collection<RegionInfo> pendingRegions) {<a name="line.2251"></a>
-<span class="sourceLineNo">2252</span> assignQueueLock.lock();<a name="line.2252"></a>
-<span class="sourceLineNo">2253</span> try {<a name="line.2253"></a>
-<span class="sourceLineNo">2254</span> for (RegionInfo hri: pendingRegions) {<a name="line.2254"></a>
-<span class="sourceLineNo">2255</span> pendingAssignQueue.add(regions.get(hri));<a name="line.2255"></a>
-<span class="sourceLineNo">2256</span> }<a name="line.2256"></a>
-<span class="sourceLineNo">2257</span> } finally {<a name="line.2257"></a>
-<span class="sourceLineNo">2258</span> assignQueueLock.unlock();<a name="line.2258"></a>
-<span class="sourceLineNo">2259</span> }<a name="line.2259"></a>
-<span class="sourceLineNo">2260</span> }<a name="line.2260"></a>
-<span class="sourceLineNo">2261</span><a name="line.2261"></a>
-<span class="sourceLineNo">2262</span> /**<a name="line.2262"></a>
-<span class="sourceLineNo">2263</span> * Get a list of servers that this region cannot be assigned to.<a name="line.2263"></a>
-<span class="sourceLineNo">2264</span> * For system tables, we must assign them to a server with highest version.<a name="line.2264"></a>
-<span class="sourceLineNo">2265</span> */<a name="line.2265"></a>
-<span class="sourceLineNo">2266</span> public List<ServerName> getExcludedServersForSystemTable() {<a name="line.2266"></a>
-<span class="sourceLineNo">2267</span> // TODO: This should be a cached list kept by the ServerManager rather than calculated on each<a name="line.2267"></a>
-<span class="sourceLineNo">2268</span> // move or system region assign. The RegionServerTracker keeps list of online Servers with<a name="line.2268"></a>
-<span class="sourceLineNo">2269</span> // RegionServerInfo that includes Version.<a name="line.2269"></a>
-<span class="sourceLineNo">2270</span> List<Pair<ServerName, String>> serverList = master.getServerManager().getOnlineServersList()<a name="line.2270"></a>
-<span class="sourceLineNo">2271</span> .stream()<a name="line.2271"></a>
-<span class="sourceLineNo">2272</span> .map((s)->new Pair<>(s, master.getRegionServerVersion(s)))<a name="line.2272"></a>
-<span class="sourceLineNo">2273</span> .collect(Collectors.toList());<a name="line.2273"></a>
-<span class="sourceLineNo">2274</span> if (serverList.isEmpty()) {<a name="line.2274"></a>
-<span class="sourceLineNo">2275</span> return Collections.emptyList();<a name="line.2275"></a>
-<span class="sourceLineNo">2276</span> }<a name="line.2276"></a>
-<span class="sourceLineNo">2277</span> String highestVersion = Collections.max(serverList,<a name="line.2277"></a>
-<span class="sourceLineNo">2278</span> (o1, o2) -> VersionInfo.compareVersion(o1.getSecond(), o2.getSecond())).getSecond();<a name="line.2278"></a>
-<span class="sourceLineNo">2279</span> return serverList.stream()<a name="line.2279"></a>
-<span class="sourceLineNo">2280</span> .filter((p)->!p.getSecond().equals(highestVersion))<a name="line.2280"></a>
-<span class="sourceLineNo">2281</span> .map(Pair::getFirst)<a name="line.2281"></a>
-<span class="sourceLineNo">2282</span> .collect(Collectors.toList());<a name="line.2282"></a>
-<span class="sourceLineNo">2283</span> }<a name="line.2283"></a>
-<span class="sourceLineNo">2284</span><a name="line.2284"></a>
-<span class="sourceLineNo">2285</span> MasterServices getMaster() {<a name="line.2285"></a>
-<span class="sourceLineNo">2286</span> return master;<a name="line.2286"></a>
-<span class="sourceLineNo">2287</span> }<a name="line.2287"></a>
-<span class="sourceLineNo">2288</span><a name="line.2288"></a>
-<span class="sourceLineNo">2289</span> /**<a name="line.2289"></a>
-<span class="sourceLineNo">2290</span> * @return a snapshot of rsReports<a name="line.2290"></a>
-<span class="sourceLineNo">2291</span> */<a name="line.2291"></a>
-<span class="sourceLineNo">2292</span> public Map<ServerName, Set<byte[]>> getRSReports() {<a name="line.2292"></a>
-<span class="sourceLineNo">2293</span> Map<ServerName, Set<byte[]>> rsReportsSnapshot = new HashMap<>();<a name="line.2293"></a>
-<span class="sourceLineNo">2294</span> synchronized (rsReports) {<a name="line.2294"></a>
-<span class="sourceLineNo">2295</span> rsReports.entrySet().forEach(e -> rsReportsSnapshot.put(e.getKey(), e.getValue()));<a name="line.2295"></a>
-<span class="sourceLineNo">2296</span> }<a name="line.2296"></a>
-<span class="sourceLineNo">2297</span> return rsReportsSnapshot;<a name="line.2297"></a>
-<span class="sourceLineNo">2298</span> }<a name="line.2298"></a>
-<span class="sourceLineNo">2299</span><a name="line.2299"></a>
-<span class="sourceLineNo">2300</span> /**<a name="line.2300"></a>
-<span class="sourceLineNo">2301</span> * Provide regions state count for given table.<a name="line.2301"></a>
-<span class="sourceLineNo">2302</span> * e.g howmany regions of give table are opened/closed/rit etc<a name="line.2302"></a>
-<span class="sourceLineNo">2303</span> *<a name="line.2303"></a>
-<span class="sourceLineNo">2304</span> * @param tableName TableName<a name="line.2304"></a>
-<span class="sourceLineNo">2305</span> * @return region states count<a name="line.2305"></a>
-<span class="sourceLineNo">2306</span> */<a name="line.2306"></a>
-<span class="sourceLineNo">2307</span> public RegionStatesCount getRegionStatesCount(TableName tableName) {<a name="line.2307"></a>
-<span class="sourceLineNo">2308</span> int openRegionsCount = 0;<a name="line.2308"></a>
-<span class="sourceLineNo">2309</span> int closedRegionCount = 0;<a name="line.2309"></a>
-<span class="sourceLineNo">2310</span> int ritCount = 0;<a name="line.2310"></a>
-<span class="sourceLineNo">2311</span> int splitRegionCount = 0;<a name="line.2311"></a>
-<span class="sourceLineNo">2312</span> int totalRegionCount = 0;<a name="line.2312"></a>
-<span class="sourceLineNo">2313</span> if (!isTableDisabled(tableName)) {<a name="line.2313"></a>
-<span class="sourceLineNo">2314</span> final List<RegionState> states = regionStates.getTableRegionStates(tableName);<a name="line.2314"></a>
-<span class="sourceLineNo">2315</span> for (RegionState regionState : states) {<a name="line.2315"></a>
-<span class="sourceLineNo">2316</span> if (regionState.isOpened()) {<a name="line.2316"></a>
-<span class="sourceLineNo">2317</span> openRegionsCount++;<a name="line.2317"></a>
-<span class="sourceLineNo">2318</span> } else if (regionState.isClosed()) {<a name="line.2318"></a>
-<span class="sourceLineNo">2319</span> closedRegionCount++;<a name="line.2319"></a>
-<span class="sourceLineNo">2320</span> } else if (regionState.isSplit()) {<a name="line.2320"></a>
-<span class="sourceLineNo">2321</span> splitRegionCount++;<a name="line.2321"></a>
-<span class="sourceLineNo">2322</span> }<a name="line.2322"></a>
-<span class="sourceLineNo">2323</span> }<a name="line.2323"></a>
-<span class="sourceLineNo">2324</span> totalRegionCount = states.size();<a name="line.2324"></a>
-<span class="sourceLineNo">2325</span> ritCount = totalRegionCount - openRegionsCount - splitRegionCount;<a name="line.2325"></a>
-<span class="sourceLineNo">2326</span> }<a name="line.2326"></a>
-<span class="sourceLineNo">2327</span> return new RegionStatesCount.RegionStatesCountBuilder()<a name="line.2327"></a>
-<span class="sourceLineNo">2328</span> .setOpenRegions(openRegionsCount)<a name="line.2328"></a>
-<span class="sourceLineNo">2329</span> .setClosedRegions(closedRegionCount)<a name="line.2329"></a>
-<span class="sourceLineNo">2330</span> .setSplitRegions(splitRegionCount)<a name="line.2330"></a>
-<span class="sourceLineNo">2331</span> .setRegionsInTransition(ritCount)<a name="line.2331"></a>
-<span class="sourceLineNo">2332</span> .setTotalRegions(totalRegionCount)<a name="line.2332"></a>
-<span class="sourceLineNo">2333</span> .build();<a name="line.2333"></a>
-<span class="sourceLineNo">2334</span> }<a name="line.2334"></a>
-<span class="sourceLineNo">2335</span><a name="line.2335"></a>
-<span class="sourceLineNo">2336</span>}<a name="line.2336"></a>
+<span class="sourceLineNo">2214</span> // TODO: Do we need to split retain and round-robin?<a name="line.2214"></a>
+<span class="sourceLineNo">2215</span> // the retain seems to fallback to round-robin/random if the region is not in the map.<a name="line.2215"></a>
+<span class="sourceLineNo">2216</span> if (!hris.isEmpty()) {<a name="line.2216"></a>
+<span class="sourceLineNo">2217</span> Collections.sort(hris, RegionInfo.COMPARATOR);<a name="line.2217"></a>
+<span class="sourceLineNo">2218</span> if (isTraceEnabled) {<a name="line.2218"></a>
+<span class="sourceLineNo">2219</span> LOG.trace("round robin regions=" + hris);<a name="line.2219"></a>
+<span class="sourceLineNo">2220</span> }<a name="line.2220"></a>
+<span class="sourceLineNo">2221</span> try {<a name="line.2221"></a>
+<span class="sourceLineNo">2222</span> acceptPlan(regions, balancer.roundRobinAssignment(hris, servers));<a name="line.2222"></a>
+<span class="sourceLineNo">2223</span> } catch (IOException e) {<a name="line.2223"></a>
+<span class="sourceLineNo">2224</span> LOG.warn("unable to round-robin assignment", e);<a name="line.2224"></a>
+<span class="sourceLineNo">2225</span> addToPendingAssignment(regions, hris);<a name="line.2225"></a>
+<span class="sourceLineNo">2226</span> }<a name="line.2226"></a>
+<span class="sourceLineNo">2227</span> }<a name="line.2227"></a>
+<span class="sourceLineNo">2228</span> }<a name="line.2228"></a>
+<span class="sourceLineNo">2229</span><a name="line.2229"></a>
+<span class="sourceLineNo">2230</span> private void acceptPlan(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2230"></a>
+<span class="sourceLineNo">2231</span> final Map<ServerName, List<RegionInfo>> plan) throws HBaseIOException {<a name="line.2231"></a>
+<span class="sourceLineNo">2232</span> final ProcedureEvent<?>[] events = new ProcedureEvent[regions.size()];<a name="line.2232"></a>
+<span class="sourceLineNo">2233</span> final long st = System.currentTimeMillis();<a name="line.2233"></a>
+<span class="sourceLineNo">2234</span><a name="line.2234"></a>
+<span class="sourceLineNo">2235</span> if (plan.isEmpty()) {<a name="line.2235"></a>
+<span class="sourceLineNo">2236</span> throw new HBaseIOException("unable to compute plans for regions=" + regions.size());<a name="line.2236"></a>
+<span class="sourceLineNo">2237</span> }<a name="line.2237"></a>
+<span class="sourceLineNo">2238</span><a name="line.2238"></a>
+<span class="sourceLineNo">2239</span> int evcount = 0;<a name="line.2239"></a>
+<span class="sourceLineNo">2240</span> for (Map.Entry<ServerName, List<RegionInfo>> entry: plan.entrySet()) {<a name="line.2240"></a>
+<span class="sourceLineNo">2241</span> final ServerName server = entry.getKey();<a name="line.2241"></a>
+<span class="sourceLineNo">2242</span> for (RegionInfo hri: entry.getValue()) {<a name="line.2242"></a>
+<span class="sourceLineNo">2243</span> final RegionStateNode regionNode = regions.get(hri);<a name="line.2243"></a>
+<span class="sourceLineNo">2244</span> regionNode.setRegionLocation(server);<a name="line.2244"></a>
+<span class="sourceLineNo">2245</span> if (server.equals(LoadBalancer.BOGUS_SERVER_NAME) && regionNode.isSystemTable()) {<a name="line.2245"></a>
+<span class="sourceLineNo">2246</span> assignQueueLock.lock();<a name="line.2246"></a>
+<span class="sourceLineNo">2247</span> try {<a name="line.2247"></a>
+<span class="sourceLineNo">2248</span> pendingAssignQueue.add(regionNode);<a name="line.2248"></a>
+<span class="sourceLineNo">2249</span> } finally {<a name="line.2249"></a>
+<span class="sourceLineNo">2250</span> assignQueueLock.unlock();<a name="line.2250"></a>
+<span class="sourceLineNo">2251</span> }<a name="line.2251"></a>
+<span class="sourceLineNo">2252</span> }else {<a name="line.2252"></a>
+<span class="sourceLineNo">2253</span> events[evcount++] = regionNode.getProcedureEvent();<a name="line.2253"></a>
+<span class="sourceLineNo">2254</span> }<a name="line.2254"></a>
+<span class="sourceLineNo">2255</span> }<a name="line.2255"></a>
+<span class="sourceLineNo">2256</span> }<a name="line.2256"></a>
+<span class="sourceLineNo">2257</span> ProcedureEvent.wakeEvents(getProcedureScheduler(), events);<a name="line.2257"></a>
+<span class="sourceLineNo">2258</span><a name="line.2258"></a>
+<span class="sourceLineNo">2259</span> final long et = System.currentTimeMillis();<a name="line.2259"></a>
+<span class="sourceLineNo">2260</span> if (LOG.isTraceEnabled()) {<a name="line.2260"></a>
+<span class="sourceLineNo">2261</span> LOG.trace("ASSIGN ACCEPT " + events.length + " -> " +<a name="line.2261"></a>
+<span class="sourceLineNo">2262</span> StringUtils.humanTimeDiff(et - st));<a name="line.2262"></a>
+<span class="sourceLineNo">2263</span> }<a name="line.2263"></a>
+<span class="sourceLineNo">2264</span> }<a name="line.2264"></a>
+<span class="sourceLineNo">2265</span><a name="line.2265"></a>
+<span class="sourceLineNo">2266</span> private void addToPendingAssignment(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2266"></a>
+<span class="sourceLineNo">2267</span> final Collection<RegionInfo> pendingRegions) {<a name="line.2267"></a>
+<span class="sourceLineNo">2268</span> assignQueueLock.lock();<a name="line.2268"></a>
+<span class="sourceLineNo">2269</span> try {<a name="line.2269"></a>
+<span class="sourceLineNo">2270</span> for (RegionInfo hri: pendingRegions) {<a name="line.2270"></a>
+<span class="sourceLineNo">2271</span> pendingAssignQueue.add(regions.get(hri));<a name="line.2271"></a>
+<span class="sourceLineNo">2272</span> }<a name="line.2272"></a>
+<span class="sourceLineNo">2273</span> } finally {<a name="line.2273"></a>
+<span class="sourceLineNo">2274</span> assignQueueLock.unlock();<a name="line.2274"></a>
+<span class="sourceLineNo">2275</span> }<a name="line.2275"></a>
+<span class="sourceLineNo">2276</span> }<a name="line.2276"></a>
+<span class="sourceLineNo">2277</span><a name="line.2277"></a>
+<span class="sourceLineNo">2278</span> /**<a name="line.2278"></a>
+<span class="sourceLineNo">2279</span> * Get a list of servers that this region cannot be assigned to.<a name="line.2279"></a>
+<span class="sourceLineNo">2280</span> * For system tables, we must assign them to a server with highest version.<a name="line.2280"></a>
+<span class="sourceLineNo">2281</span> */<a name="line.2281"></a>
+<span class="sourceLineNo">2282</span> public List<ServerName> getExcludedServersForSystemTable() {<a name="line.2282"></a>
+<span class="sourceLineNo">2283</span> // TODO: This should be a cached list kept by the ServerManager rather than calculated on each<a name="line.2283"></a>
+<span class="sourceLineNo">2284</span> // move or system region assign. The RegionServerTracker keeps list of online Servers with<a name="line.2284"></a>
+<span class="sourceLineNo">2285</span> // RegionServerInfo that includes Version.<a name="line.2285"></a>
+<span class="sourceLineNo">2286</span> List<Pair<ServerName, String>> serverList = master.getServerManager().getOnlineServersList()<a name="line.2286"></a>
+<span class="sourceLineNo">2287</span> .stream()<a name="line.2287"></a>
+<span class="sourceLineNo">2288</span> .map((s)->new Pair<>(s, master.getRegionServerVersion(s)))<a name="line.2288"></a>
+<span class="sourceLineNo">2289</span> .collect(Collectors.toList());<a name="line.2289"></a>
+<span class="sourceLineNo">2290</span> if (serverList.isEmpty()) {<a name="line.2290"></a>
+<span class="sourceLineNo">2291</span> return Collections.emptyList();<a name="line.2291"></a>
+<span class="sourceLineNo">2292</span> }<a name="line.2292"></a>
+<span class="sourceLineNo">2293</span> String highestVersion = Collections.max(serverList,<a name="line.2293"></a>
+<span class="sourceLineNo">2294</span> (o1, o2) -> VersionInfo.compareVersion(o1.getSecond(), o2.getSecond())).getSecond();<a name="line.2294"></a>
+<span class="sourceLineNo">2295</span> return serverList.stream()<a name="line.2295"></a>
+<span class="sourceLineNo">2296</span> .filter((p)->!p.getSecond().equals(highestVersion))<a name="line.2296"></a>
+<span class="sourceLineNo">2297</span> .map(Pair::getFirst)<a name="line.2297"></a>
+<span class="sourceLineNo">2298</span> .collect(Collectors.toList());<a name="line.2298"></a>
+<span class="sourceLineNo">2299</span> }<a name="line.2299"></a>
+<span class="sourceLineNo">2300</span><a name="line.2300"></a>
+<span class="sourceLineNo">2301</span> MasterServices getMaster() {<a name="line.2301"></a>
+<span class="sourceLineNo">2302</span> return master;<a name="line.2302"></a>
+<span class="sourceLineNo">2303</span> }<a name="line.2303"></a>
+<span class="sourceLineNo">2304</span><a name="line.2304"></a>
+<span class="sourceLineNo">2305</span> /**<a name="line.2305"></a>
+<span class="sourceLineNo">2306</span> * @return a snapshot of rsReports<a name="line.2306"></a>
+<span class="sourceLineNo">2307</span> */<a name="line.2307"></a>
+<span class="sourceLineNo">2308</span> public Map<ServerName, Set<byte[]>> getRSReports() {<a name="line.2308"></a>
+<span class="sourceLineNo">2309</span> Map<ServerName, Set<byte[]>> rsReportsSnapshot = new HashMap<>();<a name="line.2309"></a>
+<span class="sourceLineNo">2310</span> synchronized (rsReports) {<a name="line.2310"></a>
+<span class="sourceLineNo">2311</span> rsReports.entrySet().forEach(e -> rsReportsSnapshot.put(e.getKey(), e.getValue()));<a name="line.2311"></a>
+<span class="sourceLineNo">2312</span> }<a name="line.2312"></a>
+<span class="sourceLineNo">2313</span> return rsReportsSnapshot;<a name="line.2313"></a>
+<span class="sourceLineNo">2314</span> }<a name="line.2314"></a>
+<span class="sourceLineNo">2315</span><a name="line.2315"></a>
+<span class="sourceLineNo">2316</span> /**<a name="line.2316"></a>
+<span class="sourceLineNo">2317</span> * Provide regions state count for given table.<a name="line.2317"></a>
+<span class="sourceLineNo">2318</span> * e.g howmany regions of give table are opened/closed/rit etc<a name="line.2318"></a>
+<span class="sourceLineNo">2319</span> *<a name="line.2319"></a>
+<span class="sourceLineNo">2320</span> * @param tableName TableName<a name="line.2320"></a>
+<span class="sourceLineNo">2321</span> * @return region states count<a name="line.2321"></a>
+<span class="sourceLineNo">2322</span> */<a name="line.2322"></a>
+<span class="sourceLineNo">2323</span> public RegionStatesCount getRegionStatesCount(TableName tableName) {<a name="line.2323"></a>
+<span class="sourceLineNo">2324</span> int openRegionsCount = 0;<a name="line.2324"></a>
+<span class="sourceLineNo">2325</span> int closedRegionCount = 0;<a name="line.2325"></a>
+<span class="sourceLineNo">2326</span> int ritCount = 0;<a name="line.2326"></a>
+<span class="sourceLineNo">2327</span> int splitRegionCount = 0;<a name="line.2327"></a>
+<span class="sourceLineNo">2328</span> int totalRegionCount = 0;<a name="line.2328"></a>
+<span class="sourceLineNo">2329</span> if (!isTableDisabled(tableName)) {<a name="line.2329"></a>
+<span class="sourceLineNo">2330</span> final List<RegionState> states = regionStates.getTableRegionStates(tableName);<a name="line.2330"></a>
+<span class="sourceLineNo">2331</span> for (RegionState regionState : states) {<a name="line.2331"></a>
+<span class="sourceLineNo">2332</span> if (regionState.isOpened()) {<a name="line.2332"></a>
+<span class="sourceLineNo">2333</span> openRegionsCount++;<a name="line.2333"></a>
+<span class="sourceLineNo">2334</span> } else if (regionState.isClosed()) {<a name="line.2334"></a>
+<span class="sourceLineNo">2335</span> closedRegionCount++;<a name="line.2335"></a>
+<span class="sourceLineNo">2336</span> } else if (regionState.isSplit()) {<a name="line.2336"></a>
+<span class="sourceLineNo">2337</span> splitRegionCount++;<a name="line.2337"></a>
+<span class="sourceLineNo">2338</span> }<a name="line.2338"></a>
+<span class="sourceLineNo">2339</span> }<a name="line.2339"></a>
+<span class="sourceLineNo">2340</span> totalRegionCount = states.size();<a name="line.2340"></a>
+<span class="sourceLineNo">2341</span> ritCount = totalRegionCount - openRegionsCount - splitRegionCount;<a name="line.2341"></a>
+<span class="sourceLineNo">2342</span> }<a name="line.2342"></a>
+<span class="sourceLineNo">2343</span> return new RegionStatesCount.RegionStatesCountBuilder()<a name="line.2343"></a>
+<span class="sourceLineNo">2344</span> .setOpenRegions(openRegionsCount)<a name="line.2344"></a>
+<span class="sourceLineNo">2345</span> .setClosedRegions(closedRegionCount)<a name="line.2345"></a>
+<span class="sourceLineNo">2346</span> .setSplitRegions(splitRegionCount)<a name="line.2346"></a>
+<span class="sourceLineNo">2347</span> .setRegionsInTransition(ritCount)<a name="line.2347"></a>
+<span class="sourceLineNo">2348</span> .setTotalRegions(totalRegionCount)<a name="line.2348"></a>
+<span class="sourceLineNo">2349</span> .build();<a name="line.2349"></a>
+<span class="sourceLineNo">2350</span> }<a name="line.2350"></a>
+<span class="sourceLineNo">2351</span><a name="line.2351"></a>
+<span class="sourceLineNo">2352</span>}<a name="line.2352"></a>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionChore.html b/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionChore.html
index c00cc30..2c789f6 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionChore.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionChore.html
@@ -1134,1214 +1134,1230 @@
<span class="sourceLineNo">1126</span> LOG.debug("Split request from " + serverName +<a name="line.1126"></a>
<span class="sourceLineNo">1127</span> ", parent=" + parent + " splitKey=" + Bytes.toStringBinary(splitKey));<a name="line.1127"></a>
<span class="sourceLineNo">1128</span> }<a name="line.1128"></a>
-<span class="sourceLineNo">1129</span> master.getMasterProcedureExecutor().submitProcedure(createSplitProcedure(parent, splitKey));<a name="line.1129"></a>
-<span class="sourceLineNo">1130</span><a name="line.1130"></a>
-<span class="sourceLineNo">1131</span> // If the RS is < 2.0 throw an exception to abort the operation, we are handling the split<a name="line.1131"></a>
-<span class="sourceLineNo">1132</span> if (master.getServerManager().getVersionNumber(serverName) < 0x0200000) {<a name="line.1132"></a>
-<span class="sourceLineNo">1133</span> throw new UnsupportedOperationException(String.format("Split handled by the master: " +<a name="line.1133"></a>
-<span class="sourceLineNo">1134</span> "parent=%s hriA=%s hriB=%s", parent.getShortNameToLog(), hriA, hriB));<a name="line.1134"></a>
-<span class="sourceLineNo">1135</span> }<a name="line.1135"></a>
-<span class="sourceLineNo">1136</span> }<a name="line.1136"></a>
-<span class="sourceLineNo">1137</span><a name="line.1137"></a>
-<span class="sourceLineNo">1138</span> private void updateRegionMergeTransition(final ServerName serverName, final TransitionCode state,<a name="line.1138"></a>
-<span class="sourceLineNo">1139</span> final RegionInfo merged, final RegionInfo hriA, final RegionInfo hriB) throws IOException {<a name="line.1139"></a>
-<span class="sourceLineNo">1140</span> checkMetaLoaded(merged);<a name="line.1140"></a>
-<span class="sourceLineNo">1141</span><a name="line.1141"></a>
-<span class="sourceLineNo">1142</span> if (state != TransitionCode.READY_TO_MERGE) {<a name="line.1142"></a>
-<span class="sourceLineNo">1143</span> throw new UnexpectedStateException("Unsupported merge regionState=" + state +<a name="line.1143"></a>
-<span class="sourceLineNo">1144</span> " for regionA=" + hriA + " regionB=" + hriB + " merged=" + merged +<a name="line.1144"></a>
-<span class="sourceLineNo">1145</span> " maybe an old RS (< 2.0) had the operation in progress");<a name="line.1145"></a>
-<span class="sourceLineNo">1146</span> }<a name="line.1146"></a>
-<span class="sourceLineNo">1147</span><a name="line.1147"></a>
-<span class="sourceLineNo">1148</span> if (!master.isSplitOrMergeEnabled(MasterSwitchType.MERGE)) {<a name="line.1148"></a>
-<span class="sourceLineNo">1149</span> LOG.warn("Merge switch is off! skip merge of regionA=" + hriA + " regionB=" + hriB);<a name="line.1149"></a>
-<span class="sourceLineNo">1150</span> throw new DoNotRetryIOException("Merge of regionA=" + hriA + " regionB=" + hriB +<a name="line.1150"></a>
-<span class="sourceLineNo">1151</span> " failed because merge switch is off");<a name="line.1151"></a>
-<span class="sourceLineNo">1152</span> }<a name="line.1152"></a>
+<span class="sourceLineNo">1129</span> // Processing this report happens asynchronously from other activities which can mutate<a name="line.1129"></a>
+<span class="sourceLineNo">1130</span> // the region state. For example, a split procedure may already be running for this parent.<a name="line.1130"></a>
+<span class="sourceLineNo">1131</span> // A split procedure cannot succeed if the parent region is no longer open, so we can<a name="line.1131"></a>
+<span class="sourceLineNo">1132</span> // ignore it in that case.<a name="line.1132"></a>
+<span class="sourceLineNo">1133</span> // Note that submitting more than one split procedure for a given region is<a name="line.1133"></a>
+<span class="sourceLineNo">1134</span> // harmless -- the split is fenced in the procedure handling -- but it would be noisy in<a name="line.1134"></a>
+<span class="sourceLineNo">1135</span> // the logs. Only one procedure can succeed. The other procedure(s) would abort during<a name="line.1135"></a>
+<span class="sourceLineNo">1136</span> // initialization and report failure with WARN level logging.<a name="line.1136"></a>
+<span class="sourceLineNo">1137</span> RegionState parentState = regionStates.getRegionState(parent);<a name="line.1137"></a>
+<span class="sourceLineNo">1138</span> if (parentState != null && parentState.isOpened()) {<a name="line.1138"></a>
+<span class="sourceLineNo">1139</span> master.getMasterProcedureExecutor().submitProcedure(createSplitProcedure(parent,<a name="line.1139"></a>
+<span class="sourceLineNo">1140</span> splitKey));<a name="line.1140"></a>
+<span class="sourceLineNo">1141</span> } else {<a name="line.1141"></a>
+<span class="sourceLineNo">1142</span> LOG.info("Ignoring split request from " + serverName +<a name="line.1142"></a>
+<span class="sourceLineNo">1143</span> ", parent=" + parent + " because parent is unknown or not open");<a name="line.1143"></a>
+<span class="sourceLineNo">1144</span> return;<a name="line.1144"></a>
+<span class="sourceLineNo">1145</span> }<a name="line.1145"></a>
+<span class="sourceLineNo">1146</span><a name="line.1146"></a>
+<span class="sourceLineNo">1147</span> // If the RS is < 2.0 throw an exception to abort the operation, we are handling the split<a name="line.1147"></a>
+<span class="sourceLineNo">1148</span> if (master.getServerManager().getVersionNumber(serverName) < 0x0200000) {<a name="line.1148"></a>
+<span class="sourceLineNo">1149</span> throw new UnsupportedOperationException(String.format("Split handled by the master: " +<a name="line.1149"></a>
+<span class="sourceLineNo">1150</span> "parent=%s hriA=%s hriB=%s", parent.getShortNameToLog(), hriA, hriB));<a name="line.1150"></a>
+<span class="sourceLineNo">1151</span> }<a name="line.1151"></a>
+<span class="sourceLineNo">1152</span> }<a name="line.1152"></a>
<span class="sourceLineNo">1153</span><a name="line.1153"></a>
-<span class="sourceLineNo">1154</span> // Submit the Merge procedure<a name="line.1154"></a>
-<span class="sourceLineNo">1155</span> if (LOG.isDebugEnabled()) {<a name="line.1155"></a>
-<span class="sourceLineNo">1156</span> LOG.debug("Handling merge request from RS=" + merged + ", merged=" + merged);<a name="line.1156"></a>
-<span class="sourceLineNo">1157</span> }<a name="line.1157"></a>
-<span class="sourceLineNo">1158</span> master.getMasterProcedureExecutor().submitProcedure(createMergeProcedure(hriA, hriB));<a name="line.1158"></a>
-<span class="sourceLineNo">1159</span><a name="line.1159"></a>
-<span class="sourceLineNo">1160</span> // If the RS is < 2.0 throw an exception to abort the operation, we are handling the merge<a name="line.1160"></a>
-<span class="sourceLineNo">1161</span> if (master.getServerManager().getVersionNumber(serverName) < 0x0200000) {<a name="line.1161"></a>
-<span class="sourceLineNo">1162</span> throw new UnsupportedOperationException(String.format(<a name="line.1162"></a>
-<span class="sourceLineNo">1163</span> "Merge not handled yet: regionState=%s merged=%s hriA=%s hriB=%s", state, merged, hriA,<a name="line.1163"></a>
-<span class="sourceLineNo">1164</span> hriB));<a name="line.1164"></a>
-<span class="sourceLineNo">1165</span> }<a name="line.1165"></a>
-<span class="sourceLineNo">1166</span> }<a name="line.1166"></a>
-<span class="sourceLineNo">1167</span><a name="line.1167"></a>
-<span class="sourceLineNo">1168</span> // ============================================================================================<a name="line.1168"></a>
-<span class="sourceLineNo">1169</span> // RS Status update (report online regions) helpers<a name="line.1169"></a>
-<span class="sourceLineNo">1170</span> // ============================================================================================<a name="line.1170"></a>
-<span class="sourceLineNo">1171</span> /**<a name="line.1171"></a>
-<span class="sourceLineNo">1172</span> * The master will call this method when the RS send the regionServerReport(). The report will<a name="line.1172"></a>
-<span class="sourceLineNo">1173</span> * contains the "online regions". This method will check the the online regions against the<a name="line.1173"></a>
-<span class="sourceLineNo">1174</span> * in-memory state of the AM, and we will log a warn message if there is a mismatch. This is<a name="line.1174"></a>
-<span class="sourceLineNo">1175</span> * because that there is no fencing between the reportRegionStateTransition method and<a name="line.1175"></a>
-<span class="sourceLineNo">1176</span> * regionServerReport method, so there could be race and introduce inconsistency here, but<a name="line.1176"></a>
-<span class="sourceLineNo">1177</span> * actually there is no problem.<a name="line.1177"></a>
-<span class="sourceLineNo">1178</span> * <p/><a name="line.1178"></a>
-<span class="sourceLineNo">1179</span> * Please see HBASE-21421 and HBASE-21463 for more details.<a name="line.1179"></a>
-<span class="sourceLineNo">1180</span> */<a name="line.1180"></a>
-<span class="sourceLineNo">1181</span> public void reportOnlineRegions(ServerName serverName, Set<byte[]> regionNames) {<a name="line.1181"></a>
-<span class="sourceLineNo">1182</span> if (!isRunning()) {<a name="line.1182"></a>
-<span class="sourceLineNo">1183</span> return;<a name="line.1183"></a>
-<span class="sourceLineNo">1184</span> }<a name="line.1184"></a>
-<span class="sourceLineNo">1185</span> if (LOG.isTraceEnabled()) {<a name="line.1185"></a>
-<span class="sourceLineNo">1186</span> LOG.trace("ReportOnlineRegions {} regionCount={}, metaLoaded={} {}", serverName,<a name="line.1186"></a>
-<span class="sourceLineNo">1187</span> regionNames.size(), isMetaLoaded(),<a name="line.1187"></a>
-<span class="sourceLineNo">1188</span> regionNames.stream().map(Bytes::toStringBinary).collect(Collectors.toList()));<a name="line.1188"></a>
-<span class="sourceLineNo">1189</span> }<a name="line.1189"></a>
-<span class="sourceLineNo">1190</span><a name="line.1190"></a>
-<span class="sourceLineNo">1191</span> ServerStateNode serverNode = regionStates.getOrCreateServer(serverName);<a name="line.1191"></a>
-<span class="sourceLineNo">1192</span> synchronized (serverNode) {<a name="line.1192"></a>
-<span class="sourceLineNo">1193</span> if (!serverNode.isInState(ServerState.ONLINE)) {<a name="line.1193"></a>
-<span class="sourceLineNo">1194</span> LOG.warn("Got a report from a server result in state " + serverNode.getState());<a name="line.1194"></a>
-<span class="sourceLineNo">1195</span> return;<a name="line.1195"></a>
-<span class="sourceLineNo">1196</span> }<a name="line.1196"></a>
-<span class="sourceLineNo">1197</span> }<a name="line.1197"></a>
-<span class="sourceLineNo">1198</span><a name="line.1198"></a>
-<span class="sourceLineNo">1199</span> // Track the regionserver reported online regions in memory.<a name="line.1199"></a>
-<span class="sourceLineNo">1200</span> synchronized (rsReports) {<a name="line.1200"></a>
-<span class="sourceLineNo">1201</span> rsReports.put(serverName, regionNames);<a name="line.1201"></a>
-<span class="sourceLineNo">1202</span> }<a name="line.1202"></a>
-<span class="sourceLineNo">1203</span><a name="line.1203"></a>
-<span class="sourceLineNo">1204</span> if (regionNames.isEmpty()) {<a name="line.1204"></a>
-<span class="sourceLineNo">1205</span> // nothing to do if we don't have regions<a name="line.1205"></a>
-<span class="sourceLineNo">1206</span> LOG.trace("no online region found on {}", serverName);<a name="line.1206"></a>
-<span class="sourceLineNo">1207</span> return;<a name="line.1207"></a>
-<span class="sourceLineNo">1208</span> }<a name="line.1208"></a>
-<span class="sourceLineNo">1209</span> if (!isMetaLoaded()) {<a name="line.1209"></a>
-<span class="sourceLineNo">1210</span> // we are still on startup, skip checking<a name="line.1210"></a>
-<span class="sourceLineNo">1211</span> return;<a name="line.1211"></a>
-<span class="sourceLineNo">1212</span> }<a name="line.1212"></a>
-<span class="sourceLineNo">1213</span> // The Heartbeat tells us of what regions are on the region serve, check the state.<a name="line.1213"></a>
-<span class="sourceLineNo">1214</span> checkOnlineRegionsReport(serverNode, regionNames);<a name="line.1214"></a>
-<span class="sourceLineNo">1215</span> }<a name="line.1215"></a>
-<span class="sourceLineNo">1216</span><a name="line.1216"></a>
-<span class="sourceLineNo">1217</span> /**<a name="line.1217"></a>
-<span class="sourceLineNo">1218</span> * Close <code>regionName</code> on <code>sn</code> silently and immediately without<a name="line.1218"></a>
-<span class="sourceLineNo">1219</span> * using a Procedure or going via hbase:meta. For case where a RegionServer's hosting<a name="line.1219"></a>
-<span class="sourceLineNo">1220</span> * of a Region is not aligned w/ the Master's accounting of Region state. This is for<a name="line.1220"></a>
-<span class="sourceLineNo">1221</span> * cleaning up an error in accounting.<a name="line.1221"></a>
-<span class="sourceLineNo">1222</span> */<a name="line.1222"></a>
-<span class="sourceLineNo">1223</span> private void closeRegionSilently(ServerName sn, byte [] regionName) {<a name="line.1223"></a>
-<span class="sourceLineNo">1224</span> try {<a name="line.1224"></a>
-<span class="sourceLineNo">1225</span> RegionInfo ri = CatalogFamilyFormat.parseRegionInfoFromRegionName(regionName);<a name="line.1225"></a>
-<span class="sourceLineNo">1226</span> // Pass -1 for timeout. Means do not wait.<a name="line.1226"></a>
-<span class="sourceLineNo">1227</span> ServerManager.closeRegionSilentlyAndWait(this.master.getAsyncClusterConnection(), sn, ri, -1);<a name="line.1227"></a>
-<span class="sourceLineNo">1228</span> } catch (Exception e) {<a name="line.1228"></a>
-<span class="sourceLineNo">1229</span> LOG.error("Failed trying to close {} on {}", Bytes.toStringBinary(regionName), sn, e);<a name="line.1229"></a>
-<span class="sourceLineNo">1230</span> }<a name="line.1230"></a>
+<span class="sourceLineNo">1154</span> private void updateRegionMergeTransition(final ServerName serverName, final TransitionCode state,<a name="line.1154"></a>
+<span class="sourceLineNo">1155</span> final RegionInfo merged, final RegionInfo hriA, final RegionInfo hriB) throws IOException {<a name="line.1155"></a>
+<span class="sourceLineNo">1156</span> checkMetaLoaded(merged);<a name="line.1156"></a>
+<span class="sourceLineNo">1157</span><a name="line.1157"></a>
+<span class="sourceLineNo">1158</span> if (state != TransitionCode.READY_TO_MERGE) {<a name="line.1158"></a>
+<span class="sourceLineNo">1159</span> throw new UnexpectedStateException("Unsupported merge regionState=" + state +<a name="line.1159"></a>
+<span class="sourceLineNo">1160</span> " for regionA=" + hriA + " regionB=" + hriB + " merged=" + merged +<a name="line.1160"></a>
+<span class="sourceLineNo">1161</span> " maybe an old RS (< 2.0) had the operation in progress");<a name="line.1161"></a>
+<span class="sourceLineNo">1162</span> }<a name="line.1162"></a>
+<span class="sourceLineNo">1163</span><a name="line.1163"></a>
+<span class="sourceLineNo">1164</span> if (!master.isSplitOrMergeEnabled(MasterSwitchType.MERGE)) {<a name="line.1164"></a>
+<span class="sourceLineNo">1165</span> LOG.warn("Merge switch is off! skip merge of regionA=" + hriA + " regionB=" + hriB);<a name="line.1165"></a>
+<span class="sourceLineNo">1166</span> throw new DoNotRetryIOException("Merge of regionA=" + hriA + " regionB=" + hriB +<a name="line.1166"></a>
+<span class="sourceLineNo">1167</span> " failed because merge switch is off");<a name="line.1167"></a>
+<span class="sourceLineNo">1168</span> }<a name="line.1168"></a>
+<span class="sourceLineNo">1169</span><a name="line.1169"></a>
+<span class="sourceLineNo">1170</span> // Submit the Merge procedure<a name="line.1170"></a>
+<span class="sourceLineNo">1171</span> if (LOG.isDebugEnabled()) {<a name="line.1171"></a>
+<span class="sourceLineNo">1172</span> LOG.debug("Handling merge request from RS=" + merged + ", merged=" + merged);<a name="line.1172"></a>
+<span class="sourceLineNo">1173</span> }<a name="line.1173"></a>
+<span class="sourceLineNo">1174</span> master.getMasterProcedureExecutor().submitProcedure(createMergeProcedure(hriA, hriB));<a name="line.1174"></a>
+<span class="sourceLineNo">1175</span><a name="line.1175"></a>
+<span class="sourceLineNo">1176</span> // If the RS is < 2.0 throw an exception to abort the operation, we are handling the merge<a name="line.1176"></a>
+<span class="sourceLineNo">1177</span> if (master.getServerManager().getVersionNumber(serverName) < 0x0200000) {<a name="line.1177"></a>
+<span class="sourceLineNo">1178</span> throw new UnsupportedOperationException(String.format(<a name="line.1178"></a>
+<span class="sourceLineNo">1179</span> "Merge not handled yet: regionState=%s merged=%s hriA=%s hriB=%s", state, merged, hriA,<a name="line.1179"></a>
+<span class="sourceLineNo">1180</span> hriB));<a name="line.1180"></a>
+<span class="sourceLineNo">1181</span> }<a name="line.1181"></a>
+<span class="sourceLineNo">1182</span> }<a name="line.1182"></a>
+<span class="sourceLineNo">1183</span><a name="line.1183"></a>
+<span class="sourceLineNo">1184</span> // ============================================================================================<a name="line.1184"></a>
+<span class="sourceLineNo">1185</span> // RS Status update (report online regions) helpers<a name="line.1185"></a>
+<span class="sourceLineNo">1186</span> // ============================================================================================<a name="line.1186"></a>
+<span class="sourceLineNo">1187</span> /**<a name="line.1187"></a>
+<span class="sourceLineNo">1188</span> * The master will call this method when the RS send the regionServerReport(). The report will<a name="line.1188"></a>
+<span class="sourceLineNo">1189</span> * contains the "online regions". This method will check the the online regions against the<a name="line.1189"></a>
+<span class="sourceLineNo">1190</span> * in-memory state of the AM, and we will log a warn message if there is a mismatch. This is<a name="line.1190"></a>
+<span class="sourceLineNo">1191</span> * because that there is no fencing between the reportRegionStateTransition method and<a name="line.1191"></a>
+<span class="sourceLineNo">1192</span> * regionServerReport method, so there could be race and introduce inconsistency here, but<a name="line.1192"></a>
+<span class="sourceLineNo">1193</span> * actually there is no problem.<a name="line.1193"></a>
+<span class="sourceLineNo">1194</span> * <p/><a name="line.1194"></a>
+<span class="sourceLineNo">1195</span> * Please see HBASE-21421 and HBASE-21463 for more details.<a name="line.1195"></a>
+<span class="sourceLineNo">1196</span> */<a name="line.1196"></a>
+<span class="sourceLineNo">1197</span> public void reportOnlineRegions(ServerName serverName, Set<byte[]> regionNames) {<a name="line.1197"></a>
+<span class="sourceLineNo">1198</span> if (!isRunning()) {<a name="line.1198"></a>
+<span class="sourceLineNo">1199</span> return;<a name="line.1199"></a>
+<span class="sourceLineNo">1200</span> }<a name="line.1200"></a>
+<span class="sourceLineNo">1201</span> if (LOG.isTraceEnabled()) {<a name="line.1201"></a>
+<span class="sourceLineNo">1202</span> LOG.trace("ReportOnlineRegions {} regionCount={}, metaLoaded={} {}", serverName,<a name="line.1202"></a>
+<span class="sourceLineNo">1203</span> regionNames.size(), isMetaLoaded(),<a name="line.1203"></a>
+<span class="sourceLineNo">1204</span> regionNames.stream().map(Bytes::toStringBinary).collect(Collectors.toList()));<a name="line.1204"></a>
+<span class="sourceLineNo">1205</span> }<a name="line.1205"></a>
+<span class="sourceLineNo">1206</span><a name="line.1206"></a>
+<span class="sourceLineNo">1207</span> ServerStateNode serverNode = regionStates.getOrCreateServer(serverName);<a name="line.1207"></a>
+<span class="sourceLineNo">1208</span> synchronized (serverNode) {<a name="line.1208"></a>
+<span class="sourceLineNo">1209</span> if (!serverNode.isInState(ServerState.ONLINE)) {<a name="line.1209"></a>
+<span class="sourceLineNo">1210</span> LOG.warn("Got a report from a server result in state " + serverNode.getState());<a name="line.1210"></a>
+<span class="sourceLineNo">1211</span> return;<a name="line.1211"></a>
+<span class="sourceLineNo">1212</span> }<a name="line.1212"></a>
+<span class="sourceLineNo">1213</span> }<a name="line.1213"></a>
+<span class="sourceLineNo">1214</span><a name="line.1214"></a>
+<span class="sourceLineNo">1215</span> // Track the regionserver reported online regions in memory.<a name="line.1215"></a>
+<span class="sourceLineNo">1216</span> synchronized (rsReports) {<a name="line.1216"></a>
+<span class="sourceLineNo">1217</span> rsReports.put(serverName, regionNames);<a name="line.1217"></a>
+<span class="sourceLineNo">1218</span> }<a name="line.1218"></a>
+<span class="sourceLineNo">1219</span><a name="line.1219"></a>
+<span class="sourceLineNo">1220</span> if (regionNames.isEmpty()) {<a name="line.1220"></a>
+<span class="sourceLineNo">1221</span> // nothing to do if we don't have regions<a name="line.1221"></a>
+<span class="sourceLineNo">1222</span> LOG.trace("no online region found on {}", serverName);<a name="line.1222"></a>
+<span class="sourceLineNo">1223</span> return;<a name="line.1223"></a>
+<span class="sourceLineNo">1224</span> }<a name="line.1224"></a>
+<span class="sourceLineNo">1225</span> if (!isMetaLoaded()) {<a name="line.1225"></a>
+<span class="sourceLineNo">1226</span> // we are still on startup, skip checking<a name="line.1226"></a>
+<span class="sourceLineNo">1227</span> return;<a name="line.1227"></a>
+<span class="sourceLineNo">1228</span> }<a name="line.1228"></a>
+<span class="sourceLineNo">1229</span> // The Heartbeat tells us of what regions are on the region serve, check the state.<a name="line.1229"></a>
+<span class="sourceLineNo">1230</span> checkOnlineRegionsReport(serverNode, regionNames);<a name="line.1230"></a>
<span class="sourceLineNo">1231</span> }<a name="line.1231"></a>
<span class="sourceLineNo">1232</span><a name="line.1232"></a>
<span class="sourceLineNo">1233</span> /**<a name="line.1233"></a>
-<span class="sourceLineNo">1234</span> * Check that what the RegionServer reports aligns with the Master's image.<a name="line.1234"></a>
-<span class="sourceLineNo">1235</span> * If disagreement, we will tell the RegionServer to expediently close<a name="line.1235"></a>
-<span class="sourceLineNo">1236</span> * a Region we do not think it should have.<a name="line.1236"></a>
-<span class="sourceLineNo">1237</span> */<a name="line.1237"></a>
-<span class="sourceLineNo">1238</span> private void checkOnlineRegionsReport(ServerStateNode serverNode, Set<byte[]> regionNames) {<a name="line.1238"></a>
-<span class="sourceLineNo">1239</span> ServerName serverName = serverNode.getServerName();<a name="line.1239"></a>
-<span class="sourceLineNo">1240</span> for (byte[] regionName : regionNames) {<a name="line.1240"></a>
-<span class="sourceLineNo">1241</span> if (!isRunning()) {<a name="line.1241"></a>
-<span class="sourceLineNo">1242</span> return;<a name="line.1242"></a>
-<span class="sourceLineNo">1243</span> }<a name="line.1243"></a>
-<span class="sourceLineNo">1244</span> RegionStateNode regionNode = regionStates.getRegionStateNodeFromName(regionName);<a name="line.1244"></a>
-<span class="sourceLineNo">1245</span> if (regionNode == null) {<a name="line.1245"></a>
-<span class="sourceLineNo">1246</span> String regionNameAsStr = Bytes.toStringBinary(regionName);<a name="line.1246"></a>
-<span class="sourceLineNo">1247</span> LOG.warn("No RegionStateNode for {} but reported as up on {}; closing...",<a name="line.1247"></a>
-<span class="sourceLineNo">1248</span> regionNameAsStr, serverName);<a name="line.1248"></a>
-<span class="sourceLineNo">1249</span> closeRegionSilently(serverNode.getServerName(), regionName);<a name="line.1249"></a>
-<span class="sourceLineNo">1250</span> continue;<a name="line.1250"></a>
-<span class="sourceLineNo">1251</span> }<a name="line.1251"></a>
-<span class="sourceLineNo">1252</span> final long lag = 1000;<a name="line.1252"></a>
-<span class="sourceLineNo">1253</span> regionNode.lock();<a name="line.1253"></a>
-<span class="sourceLineNo">1254</span> try {<a name="line.1254"></a>
-<span class="sourceLineNo">1255</span> long diff = EnvironmentEdgeManager.currentTime() - regionNode.getLastUpdate();<a name="line.1255"></a>
-<span class="sourceLineNo">1256</span> if (regionNode.isInState(State.OPENING, State.OPEN)) {<a name="line.1256"></a>
-<span class="sourceLineNo">1257</span> // This is possible as a region server has just closed a region but the region server<a name="line.1257"></a>
-<span class="sourceLineNo">1258</span> // report is generated before the closing, but arrive after the closing. Make sure there<a name="line.1258"></a>
-<span class="sourceLineNo">1259</span> // is some elapsed time so less false alarms.<a name="line.1259"></a>
-<span class="sourceLineNo">1260</span> if (!regionNode.getRegionLocation().equals(serverName) && diff > lag) {<a name="line.1260"></a>
-<span class="sourceLineNo">1261</span> LOG.warn("Reporting {} server does not match {} (time since last " +<a name="line.1261"></a>
-<span class="sourceLineNo">1262</span> "update={}ms); closing...",<a name="line.1262"></a>
-<span class="sourceLineNo">1263</span> serverName, regionNode, diff);<a name="line.1263"></a>
-<span class="sourceLineNo">1264</span> closeRegionSilently(serverNode.getServerName(), regionName);<a name="line.1264"></a>
-<span class="sourceLineNo">1265</span> }<a name="line.1265"></a>
-<span class="sourceLineNo">1266</span> } else if (!regionNode.isInState(State.CLOSING, State.SPLITTING)) {<a name="line.1266"></a>
-<span class="sourceLineNo">1267</span> // So, we can get report that a region is CLOSED or SPLIT because a heartbeat<a name="line.1267"></a>
-<span class="sourceLineNo">1268</span> // came in at about same time as a region transition. Make sure there is some<a name="line.1268"></a>
-<span class="sourceLineNo">1269</span> // elapsed time so less false alarms.<a name="line.1269"></a>
-<span class="sourceLineNo">1270</span> if (diff > lag) {<a name="line.1270"></a>
-<span class="sourceLineNo">1271</span> LOG.warn("Reporting {} state does not match {} (time since last update={}ms)",<a name="line.1271"></a>
-<span class="sourceLineNo">1272</span> serverName, regionNode, diff);<a name="line.1272"></a>
-<span class="sourceLineNo">1273</span> }<a name="line.1273"></a>
-<span class="sourceLineNo">1274</span> }<a name="line.1274"></a>
-<span class="sourceLineNo">1275</span> } finally {<a name="line.1275"></a>
-<span class="sourceLineNo">1276</span> regionNode.unlock();<a name="line.1276"></a>
-<span class="sourceLineNo">1277</span> }<a name="line.1277"></a>
-<span class="sourceLineNo">1278</span> }<a name="line.1278"></a>
-<span class="sourceLineNo">1279</span> }<a name="line.1279"></a>
-<span class="sourceLineNo">1280</span><a name="line.1280"></a>
-<span class="sourceLineNo">1281</span> // ============================================================================================<a name="line.1281"></a>
-<span class="sourceLineNo">1282</span> // RIT chore<a name="line.1282"></a>
-<span class="sourceLineNo">1283</span> // ============================================================================================<a name="line.1283"></a>
-<span class="sourceLineNo">1284</span> private static class RegionInTransitionChore extends ProcedureInMemoryChore<MasterProcedureEnv> {<a name="line.1284"></a>
-<span class="sourceLineNo">1285</span> public RegionInTransitionChore(final int timeoutMsec) {<a name="line.1285"></a>
-<span class="sourceLineNo">1286</span> super(timeoutMsec);<a name="line.1286"></a>
-<span class="sourceLineNo">1287</span> }<a name="line.1287"></a>
-<span class="sourceLineNo">1288</span><a name="line.1288"></a>
-<span class="sourceLineNo">1289</span> @Override<a name="line.1289"></a>
-<span class="sourceLineNo">1290</span> protected void periodicExecute(final MasterProcedureEnv env) {<a name="line.1290"></a>
-<span class="sourceLineNo">1291</span> final AssignmentManager am = env.getAssignmentManager();<a name="line.1291"></a>
-<span class="sourceLineNo">1292</span><a name="line.1292"></a>
-<span class="sourceLineNo">1293</span> final RegionInTransitionStat ritStat = am.computeRegionInTransitionStat();<a name="line.1293"></a>
-<span class="sourceLineNo">1294</span> if (ritStat.hasRegionsOverThreshold()) {<a name="line.1294"></a>
-<span class="sourceLineNo">1295</span> for (RegionState hri: ritStat.getRegionOverThreshold()) {<a name="line.1295"></a>
-<span class="sourceLineNo">1296</span> am.handleRegionOverStuckWarningThreshold(hri.getRegion());<a name="line.1296"></a>
-<span class="sourceLineNo">1297</span> }<a name="line.1297"></a>
-<span class="sourceLineNo">1298</span> }<a name="line.1298"></a>
-<span class="sourceLineNo">1299</span><a name="line.1299"></a>
-<span class="sourceLineNo">1300</span> // update metrics<a name="line.1300"></a>
-<span class="sourceLineNo">1301</span> am.updateRegionsInTransitionMetrics(ritStat);<a name="line.1301"></a>
-<span class="sourceLineNo">1302</span> }<a name="line.1302"></a>
-<span class="sourceLineNo">1303</span> }<a name="line.1303"></a>
+<span class="sourceLineNo">1234</span> * Close <code>regionName</code> on <code>sn</code> silently and immediately without<a name="line.1234"></a>
+<span class="sourceLineNo">1235</span> * using a Procedure or going via hbase:meta. For case where a RegionServer's hosting<a name="line.1235"></a>
+<span class="sourceLineNo">1236</span> * of a Region is not aligned w/ the Master's accounting of Region state. This is for<a name="line.1236"></a>
+<span class="sourceLineNo">1237</span> * cleaning up an error in accounting.<a name="line.1237"></a>
+<span class="sourceLineNo">1238</span> */<a name="line.1238"></a>
+<span class="sourceLineNo">1239</span> private void closeRegionSilently(ServerName sn, byte [] regionName) {<a name="line.1239"></a>
+<span class="sourceLineNo">1240</span> try {<a name="line.1240"></a>
+<span class="sourceLineNo">1241</span> RegionInfo ri = CatalogFamilyFormat.parseRegionInfoFromRegionName(regionName);<a name="line.1241"></a>
+<span class="sourceLineNo">1242</span> // Pass -1 for timeout. Means do not wait.<a name="line.1242"></a>
+<span class="sourceLineNo">1243</span> ServerManager.closeRegionSilentlyAndWait(this.master.getAsyncClusterConnection(), sn, ri, -1);<a name="line.1243"></a>
+<span class="sourceLineNo">1244</span> } catch (Exception e) {<a name="line.1244"></a>
+<span class="sourceLineNo">1245</span> LOG.error("Failed trying to close {} on {}", Bytes.toStringBinary(regionName), sn, e);<a name="line.1245"></a>
+<span class="sourceLineNo">1246</span> }<a name="line.1246"></a>
+<span class="sourceLineNo">1247</span> }<a name="line.1247"></a>
+<span class="sourceLineNo">1248</span><a name="line.1248"></a>
+<span class="sourceLineNo">1249</span> /**<a name="line.1249"></a>
+<span class="sourceLineNo">1250</span> * Check that what the RegionServer reports aligns with the Master's image.<a name="line.1250"></a>
+<span class="sourceLineNo">1251</span> * If disagreement, we will tell the RegionServer to expediently close<a name="line.1251"></a>
+<span class="sourceLineNo">1252</span> * a Region we do not think it should have.<a name="line.1252"></a>
+<span class="sourceLineNo">1253</span> */<a name="line.1253"></a>
+<span class="sourceLineNo">1254</span> private void checkOnlineRegionsReport(ServerStateNode serverNode, Set<byte[]> regionNames) {<a name="line.1254"></a>
+<span class="sourceLineNo">1255</span> ServerName serverName = serverNode.getServerName();<a name="line.1255"></a>
+<span class="sourceLineNo">1256</span> for (byte[] regionName : regionNames) {<a name="line.1256"></a>
+<span class="sourceLineNo">1257</span> if (!isRunning()) {<a name="line.1257"></a>
+<span class="sourceLineNo">1258</span> return;<a name="line.1258"></a>
+<span class="sourceLineNo">1259</span> }<a name="line.1259"></a>
+<span class="sourceLineNo">1260</span> RegionStateNode regionNode = regionStates.getRegionStateNodeFromName(regionName);<a name="line.1260"></a>
+<span class="sourceLineNo">1261</span> if (regionNode == null) {<a name="line.1261"></a>
+<span class="sourceLineNo">1262</span> String regionNameAsStr = Bytes.toStringBinary(regionName);<a name="line.1262"></a>
+<span class="sourceLineNo">1263</span> LOG.warn("No RegionStateNode for {} but reported as up on {}; closing...",<a name="line.1263"></a>
+<span class="sourceLineNo">1264</span> regionNameAsStr, serverName);<a name="line.1264"></a>
+<span class="sourceLineNo">1265</span> closeRegionSilently(serverNode.getServerName(), regionName);<a name="line.1265"></a>
+<span class="sourceLineNo">1266</span> continue;<a name="line.1266"></a>
+<span class="sourceLineNo">1267</span> }<a name="line.1267"></a>
+<span class="sourceLineNo">1268</span> final long lag = 1000;<a name="line.1268"></a>
+<span class="sourceLineNo">1269</span> regionNode.lock();<a name="line.1269"></a>
+<span class="sourceLineNo">1270</span> try {<a name="line.1270"></a>
+<span class="sourceLineNo">1271</span> long diff = EnvironmentEdgeManager.currentTime() - regionNode.getLastUpdate();<a name="line.1271"></a>
+<span class="sourceLineNo">1272</span> if (regionNode.isInState(State.OPENING, State.OPEN)) {<a name="line.1272"></a>
+<span class="sourceLineNo">1273</span> // This is possible as a region server has just closed a region but the region server<a name="line.1273"></a>
+<span class="sourceLineNo">1274</span> // report is generated before the closing, but arrive after the closing. Make sure there<a name="line.1274"></a>
+<span class="sourceLineNo">1275</span> // is some elapsed time so less false alarms.<a name="line.1275"></a>
+<span class="sourceLineNo">1276</span> if (!regionNode.getRegionLocation().equals(serverName) && diff > lag) {<a name="line.1276"></a>
+<span class="sourceLineNo">1277</span> LOG.warn("Reporting {} server does not match {} (time since last " +<a name="line.1277"></a>
+<span class="sourceLineNo">1278</span> "update={}ms); closing...",<a name="line.1278"></a>
+<span class="sourceLineNo">1279</span> serverName, regionNode, diff);<a name="line.1279"></a>
+<span class="sourceLineNo">1280</span> closeRegionSilently(serverNode.getServerName(), regionName);<a name="line.1280"></a>
+<span class="sourceLineNo">1281</span> }<a name="line.1281"></a>
+<span class="sourceLineNo">1282</span> } else if (!regionNode.isInState(State.CLOSING, State.SPLITTING)) {<a name="line.1282"></a>
+<span class="sourceLineNo">1283</span> // So, we can get report that a region is CLOSED or SPLIT because a heartbeat<a name="line.1283"></a>
+<span class="sourceLineNo">1284</span> // came in at about same time as a region transition. Make sure there is some<a name="line.1284"></a>
+<span class="sourceLineNo">1285</span> // elapsed time so less false alarms.<a name="line.1285"></a>
+<span class="sourceLineNo">1286</span> if (diff > lag) {<a name="line.1286"></a>
+<span class="sourceLineNo">1287</span> LOG.warn("Reporting {} state does not match {} (time since last update={}ms)",<a name="line.1287"></a>
+<span class="sourceLineNo">1288</span> serverName, regionNode, diff);<a name="line.1288"></a>
+<span class="sourceLineNo">1289</span> }<a name="line.1289"></a>
+<span class="sourceLineNo">1290</span> }<a name="line.1290"></a>
+<span class="sourceLineNo">1291</span> } finally {<a name="line.1291"></a>
+<span class="sourceLineNo">1292</span> regionNode.unlock();<a name="line.1292"></a>
+<span class="sourceLineNo">1293</span> }<a name="line.1293"></a>
+<span class="sourceLineNo">1294</span> }<a name="line.1294"></a>
+<span class="sourceLineNo">1295</span> }<a name="line.1295"></a>
+<span class="sourceLineNo">1296</span><a name="line.1296"></a>
+<span class="sourceLineNo">1297</span> // ============================================================================================<a name="line.1297"></a>
+<span class="sourceLineNo">1298</span> // RIT chore<a name="line.1298"></a>
+<span class="sourceLineNo">1299</span> // ============================================================================================<a name="line.1299"></a>
+<span class="sourceLineNo">1300</span> private static class RegionInTransitionChore extends ProcedureInMemoryChore<MasterProcedureEnv> {<a name="line.1300"></a>
+<span class="sourceLineNo">1301</span> public RegionInTransitionChore(final int timeoutMsec) {<a name="line.1301"></a>
+<span class="sourceLineNo">1302</span> super(timeoutMsec);<a name="line.1302"></a>
+<span class="sourceLineNo">1303</span> }<a name="line.1303"></a>
<span class="sourceLineNo">1304</span><a name="line.1304"></a>
-<span class="sourceLineNo">1305</span> private static class DeadServerMetricRegionChore<a name="line.1305"></a>
-<span class="sourceLineNo">1306</span> extends ProcedureInMemoryChore<MasterProcedureEnv> {<a name="line.1306"></a>
-<span class="sourceLineNo">1307</span> public DeadServerMetricRegionChore(final int timeoutMsec) {<a name="line.1307"></a>
-<span class="sourceLineNo">1308</span> super(timeoutMsec);<a name="line.1308"></a>
-<span class="sourceLineNo">1309</span> }<a name="line.1309"></a>
-<span class="sourceLineNo">1310</span><a name="line.1310"></a>
-<span class="sourceLineNo">1311</span> @Override<a name="line.1311"></a>
-<span class="sourceLineNo">1312</span> protected void periodicExecute(final MasterProcedureEnv env) {<a name="line.1312"></a>
-<span class="sourceLineNo">1313</span> final ServerManager sm = env.getMasterServices().getServerManager();<a name="line.1313"></a>
-<span class="sourceLineNo">1314</span> final AssignmentManager am = env.getAssignmentManager();<a name="line.1314"></a>
-<span class="sourceLineNo">1315</span> // To minimize inconsistencies we are not going to snapshot live servers in advance in case<a name="line.1315"></a>
-<span class="sourceLineNo">1316</span> // new servers are added; OTOH we don't want to add heavy sync for a consistent view since<a name="line.1316"></a>
-<span class="sourceLineNo">1317</span> // this is for metrics. Instead, we're going to check each regions as we go; to avoid making<a name="line.1317"></a>
-<span class="sourceLineNo">1318</span> // too many checks, we maintain a local lists of server, limiting us to false negatives. If<a name="line.1318"></a>
-<span class="sourceLineNo">1319</span> // we miss some recently-dead server, we'll just see it next time.<a name="line.1319"></a>
-<span class="sourceLineNo">1320</span> Set<ServerName> recentlyLiveServers = new HashSet<>();<a name="line.1320"></a>
-<span class="sourceLineNo">1321</span> int deadRegions = 0, unknownRegions = 0;<a name="line.1321"></a>
-<span class="sourceLineNo">1322</span> for (RegionStateNode rsn : am.getRegionStates().getRegionStateNodes()) {<a name="line.1322"></a>
-<span class="sourceLineNo">1323</span> if (rsn.getState() != State.OPEN) {<a name="line.1323"></a>
-<span class="sourceLineNo">1324</span> continue; // Opportunistic check, should quickly skip RITs, offline tables, etc.<a name="line.1324"></a>
-<span class="sourceLineNo">1325</span> }<a name="line.1325"></a>
-<span class="sourceLineNo">1326</span> // Do not need to acquire region state lock as this is only for showing metrics.<a name="line.1326"></a>
-<span class="sourceLineNo">1327</span> ServerName sn = rsn.getRegionLocation();<a name="line.1327"></a>
-<span class="sourceLineNo">1328</span> State state = rsn.getState();<a name="line.1328"></a>
-<span class="sourceLineNo">1329</span> if (state != State.OPEN) {<a name="line.1329"></a>
-<span class="sourceLineNo">1330</span> continue; // Mostly skipping RITs that are already being take care of.<a name="line.1330"></a>
-<span class="sourceLineNo">1331</span> }<a name="line.1331"></a>
-<span class="sourceLineNo">1332</span> if (sn == null) {<a name="line.1332"></a>
-<span class="sourceLineNo">1333</span> ++unknownRegions; // Opened on null?<a name="line.1333"></a>
-<span class="sourceLineNo">1334</span> continue;<a name="line.1334"></a>
-<span class="sourceLineNo">1335</span> }<a name="line.1335"></a>
-<span class="sourceLineNo">1336</span> if (recentlyLiveServers.contains(sn)) {<a name="line.1336"></a>
-<span class="sourceLineNo">1337</span> continue;<a name="line.1337"></a>
-<span class="sourceLineNo">1338</span> }<a name="line.1338"></a>
-<span class="sourceLineNo">1339</span> ServerManager.ServerLiveState sls = sm.isServerKnownAndOnline(sn);<a name="line.1339"></a>
-<span class="sourceLineNo">1340</span> switch (sls) {<a name="line.1340"></a>
-<span class="sourceLineNo">1341</span> case LIVE:<a name="line.1341"></a>
-<span class="sourceLineNo">1342</span> recentlyLiveServers.add(sn);<a name="line.1342"></a>
-<span class="sourceLineNo">1343</span> break;<a name="line.1343"></a>
-<span class="sourceLineNo">1344</span> case DEAD:<a name="line.1344"></a>
-<span class="sourceLineNo">1345</span> ++deadRegions;<a name="line.1345"></a>
-<span class="sourceLineNo">1346</span> break;<a name="line.1346"></a>
-<span class="sourceLineNo">1347</span> case UNKNOWN:<a name="line.1347"></a>
-<span class="sourceLineNo">1348</span> ++unknownRegions;<a name="line.1348"></a>
-<span class="sourceLineNo">1349</span> break;<a name="line.1349"></a>
-<span class="sourceLineNo">1350</span> default: throw new AssertionError("Unexpected " + sls);<a name="line.1350"></a>
+<span class="sourceLineNo">1305</span> @Override<a name="line.1305"></a>
+<span class="sourceLineNo">1306</span> protected void periodicExecute(final MasterProcedureEnv env) {<a name="line.1306"></a>
+<span class="sourceLineNo">1307</span> final AssignmentManager am = env.getAssignmentManager();<a name="line.1307"></a>
+<span class="sourceLineNo">1308</span><a name="line.1308"></a>
+<span class="sourceLineNo">1309</span> final RegionInTransitionStat ritStat = am.computeRegionInTransitionStat();<a name="line.1309"></a>
+<span class="sourceLineNo">1310</span> if (ritStat.hasRegionsOverThreshold()) {<a name="line.1310"></a>
+<span class="sourceLineNo">1311</span> for (RegionState hri: ritStat.getRegionOverThreshold()) {<a name="line.1311"></a>
+<span class="sourceLineNo">1312</span> am.handleRegionOverStuckWarningThreshold(hri.getRegion());<a name="line.1312"></a>
+<span class="sourceLineNo">1313</span> }<a name="line.1313"></a>
+<span class="sourceLineNo">1314</span> }<a name="line.1314"></a>
+<span class="sourceLineNo">1315</span><a name="line.1315"></a>
+<span class="sourceLineNo">1316</span> // update metrics<a name="line.1316"></a>
+<span class="sourceLineNo">1317</span> am.updateRegionsInTransitionMetrics(ritStat);<a name="line.1317"></a>
+<span class="sourceLineNo">1318</span> }<a name="line.1318"></a>
+<span class="sourceLineNo">1319</span> }<a name="line.1319"></a>
+<span class="sourceLineNo">1320</span><a name="line.1320"></a>
+<span class="sourceLineNo">1321</span> private static class DeadServerMetricRegionChore<a name="line.1321"></a>
+<span class="sourceLineNo">1322</span> extends ProcedureInMemoryChore<MasterProcedureEnv> {<a name="line.1322"></a>
+<span class="sourceLineNo">1323</span> public DeadServerMetricRegionChore(final int timeoutMsec) {<a name="line.1323"></a>
+<span class="sourceLineNo">1324</span> super(timeoutMsec);<a name="line.1324"></a>
+<span class="sourceLineNo">1325</span> }<a name="line.1325"></a>
+<span class="sourceLineNo">1326</span><a name="line.1326"></a>
+<span class="sourceLineNo">1327</span> @Override<a name="line.1327"></a>
+<span class="sourceLineNo">1328</span> protected void periodicExecute(final MasterProcedureEnv env) {<a name="line.1328"></a>
+<span class="sourceLineNo">1329</span> final ServerManager sm = env.getMasterServices().getServerManager();<a name="line.1329"></a>
+<span class="sourceLineNo">1330</span> final AssignmentManager am = env.getAssignmentManager();<a name="line.1330"></a>
+<span class="sourceLineNo">1331</span> // To minimize inconsistencies we are not going to snapshot live servers in advance in case<a name="line.1331"></a>
+<span class="sourceLineNo">1332</span> // new servers are added; OTOH we don't want to add heavy sync for a consistent view since<a name="line.1332"></a>
+<span class="sourceLineNo">1333</span> // this is for metrics. Instead, we're going to check each regions as we go; to avoid making<a name="line.1333"></a>
+<span class="sourceLineNo">1334</span> // too many checks, we maintain a local lists of server, limiting us to false negatives. If<a name="line.1334"></a>
+<span class="sourceLineNo">1335</span> // we miss some recently-dead server, we'll just see it next time.<a name="line.1335"></a>
+<span class="sourceLineNo">1336</span> Set<ServerName> recentlyLiveServers = new HashSet<>();<a name="line.1336"></a>
+<span class="sourceLineNo">1337</span> int deadRegions = 0, unknownRegions = 0;<a name="line.1337"></a>
+<span class="sourceLineNo">1338</span> for (RegionStateNode rsn : am.getRegionStates().getRegionStateNodes()) {<a name="line.1338"></a>
+<span class="sourceLineNo">1339</span> if (rsn.getState() != State.OPEN) {<a name="line.1339"></a>
+<span class="sourceLineNo">1340</span> continue; // Opportunistic check, should quickly skip RITs, offline tables, etc.<a name="line.1340"></a>
+<span class="sourceLineNo">1341</span> }<a name="line.1341"></a>
+<span class="sourceLineNo">1342</span> // Do not need to acquire region state lock as this is only for showing metrics.<a name="line.1342"></a>
+<span class="sourceLineNo">1343</span> ServerName sn = rsn.getRegionLocation();<a name="line.1343"></a>
+<span class="sourceLineNo">1344</span> State state = rsn.getState();<a name="line.1344"></a>
+<span class="sourceLineNo">1345</span> if (state != State.OPEN) {<a name="line.1345"></a>
+<span class="sourceLineNo">1346</span> continue; // Mostly skipping RITs that are already being take care of.<a name="line.1346"></a>
+<span class="sourceLineNo">1347</span> }<a name="line.1347"></a>
+<span class="sourceLineNo">1348</span> if (sn == null) {<a name="line.1348"></a>
+<span class="sourceLineNo">1349</span> ++unknownRegions; // Opened on null?<a name="line.1349"></a>
+<span class="sourceLineNo">1350</span> continue;<a name="line.1350"></a>
<span class="sourceLineNo">1351</span> }<a name="line.1351"></a>
-<span class="sourceLineNo">1352</span> }<a name="line.1352"></a>
-<span class="sourceLineNo">1353</span> if (deadRegions > 0 || unknownRegions > 0) {<a name="line.1353"></a>
-<span class="sourceLineNo">1354</span> LOG.info("Found {} OPEN regions on dead servers and {} OPEN regions on unknown servers",<a name="line.1354"></a>
-<span class="sourceLineNo">1355</span> deadRegions, unknownRegions);<a name="line.1355"></a>
-<span class="sourceLineNo">1356</span> }<a name="line.1356"></a>
-<span class="sourceLineNo">1357</span><a name="line.1357"></a>
-<span class="sourceLineNo">1358</span> am.updateDeadServerRegionMetrics(deadRegions, unknownRegions);<a name="line.1358"></a>
-<span class="sourceLineNo">1359</span> }<a name="line.1359"></a>
-<span class="sourceLineNo">1360</span> }<a name="line.1360"></a>
-<span class="sourceLineNo">1361</span><a name="line.1361"></a>
-<span class="sourceLineNo">1362</span> public RegionInTransitionStat computeRegionInTransitionStat() {<a name="line.1362"></a>
-<span class="sourceLineNo">1363</span> final RegionInTransitionStat rit = new RegionInTransitionStat(getConfiguration());<a name="line.1363"></a>
-<span class="sourceLineNo">1364</span> rit.update(this);<a name="line.1364"></a>
-<span class="sourceLineNo">1365</span> return rit;<a name="line.1365"></a>
-<span class="sourceLineNo">1366</span> }<a name="line.1366"></a>
-<span class="sourceLineNo">1367</span><a name="line.1367"></a>
-<span class="sourceLineNo">1368</span> public static class RegionInTransitionStat {<a name="line.1368"></a>
-<span class="sourceLineNo">1369</span> private final int ritThreshold;<a name="line.1369"></a>
-<span class="sourceLineNo">1370</span><a name="line.1370"></a>
-<span class="sourceLineNo">1371</span> private HashMap<String, RegionState> ritsOverThreshold = null;<a name="line.1371"></a>
-<span class="sourceLineNo">1372</span> private long statTimestamp;<a name="line.1372"></a>
-<span class="sourceLineNo">1373</span> private long oldestRITTime = 0;<a name="line.1373"></a>
-<span class="sourceLineNo">1374</span> private int totalRITsTwiceThreshold = 0;<a name="line.1374"></a>
-<span class="sourceLineNo">1375</span> private int totalRITs = 0;<a name="line.1375"></a>
-<span class="sourceLineNo">1376</span><a name="line.1376"></a>
-<span class="sourceLineNo">1377</span> public RegionInTransitionStat(final Configuration conf) {<a name="line.1377"></a>
-<span class="sourceLineNo">1378</span> this.ritThreshold =<a name="line.1378"></a>
-<span class="sourceLineNo">1379</span> conf.getInt(METRICS_RIT_STUCK_WARNING_THRESHOLD, DEFAULT_RIT_STUCK_WARNING_THRESHOLD);<a name="line.1379"></a>
-<span class="sourceLineNo">1380</span> }<a name="line.1380"></a>
-<span class="sourceLineNo">1381</span><a name="line.1381"></a>
-<span class="sourceLineNo">1382</span> public int getRITThreshold() {<a name="line.1382"></a>
-<span class="sourceLineNo">1383</span> return ritThreshold;<a name="line.1383"></a>
-<span class="sourceLineNo">1384</span> }<a name="line.1384"></a>
-<span class="sourceLineNo">1385</span><a name="line.1385"></a>
-<span class="sourceLineNo">1386</span> public long getTimestamp() {<a name="line.1386"></a>
-<span class="sourceLineNo">1387</span> return statTimestamp;<a name="line.1387"></a>
-<span class="sourceLineNo">1388</span> }<a name="line.1388"></a>
-<span class="sourceLineNo">1389</span><a name="line.1389"></a>
-<span class="sourceLineNo">1390</span> public int getTotalRITs() {<a name="line.1390"></a>
-<span class="sourceLineNo">1391</span> return totalRITs;<a name="line.1391"></a>
-<span class="sourceLineNo">1392</span> }<a name="line.1392"></a>
-<span class="sourceLineNo">1393</span><a name="line.1393"></a>
-<span class="sourceLineNo">1394</span> public long getOldestRITTime() {<a name="line.1394"></a>
-<span class="sourceLineNo">1395</span> return oldestRITTime;<a name="line.1395"></a>
+<span class="sourceLineNo">1352</span> if (recentlyLiveServers.contains(sn)) {<a name="line.1352"></a>
+<span class="sourceLineNo">1353</span> continue;<a name="line.1353"></a>
+<span class="sourceLineNo">1354</span> }<a name="line.1354"></a>
+<span class="sourceLineNo">1355</span> ServerManager.ServerLiveState sls = sm.isServerKnownAndOnline(sn);<a name="line.1355"></a>
+<span class="sourceLineNo">1356</span> switch (sls) {<a name="line.1356"></a>
+<span class="sourceLineNo">1357</span> case LIVE:<a name="line.1357"></a>
+<span class="sourceLineNo">1358</span> recentlyLiveServers.add(sn);<a name="line.1358"></a>
+<span class="sourceLineNo">1359</span> break;<a name="line.1359"></a>
+<span class="sourceLineNo">1360</span> case DEAD:<a name="line.1360"></a>
+<span class="sourceLineNo">1361</span> ++deadRegions;<a name="line.1361"></a>
+<span class="sourceLineNo">1362</span> break;<a name="line.1362"></a>
+<span class="sourceLineNo">1363</span> case UNKNOWN:<a name="line.1363"></a>
+<span class="sourceLineNo">1364</span> ++unknownRegions;<a name="line.1364"></a>
+<span class="sourceLineNo">1365</span> break;<a name="line.1365"></a>
+<span class="sourceLineNo">1366</span> default: throw new AssertionError("Unexpected " + sls);<a name="line.1366"></a>
+<span class="sourceLineNo">1367</span> }<a name="line.1367"></a>
+<span class="sourceLineNo">1368</span> }<a name="line.1368"></a>
+<span class="sourceLineNo">1369</span> if (deadRegions > 0 || unknownRegions > 0) {<a name="line.1369"></a>
+<span class="sourceLineNo">1370</span> LOG.info("Found {} OPEN regions on dead servers and {} OPEN regions on unknown servers",<a name="line.1370"></a>
+<span class="sourceLineNo">1371</span> deadRegions, unknownRegions);<a name="line.1371"></a>
+<span class="sourceLineNo">1372</span> }<a name="line.1372"></a>
+<span class="sourceLineNo">1373</span><a name="line.1373"></a>
+<span class="sourceLineNo">1374</span> am.updateDeadServerRegionMetrics(deadRegions, unknownRegions);<a name="line.1374"></a>
+<span class="sourceLineNo">1375</span> }<a name="line.1375"></a>
+<span class="sourceLineNo">1376</span> }<a name="line.1376"></a>
+<span class="sourceLineNo">1377</span><a name="line.1377"></a>
+<span class="sourceLineNo">1378</span> public RegionInTransitionStat computeRegionInTransitionStat() {<a name="line.1378"></a>
+<span class="sourceLineNo">1379</span> final RegionInTransitionStat rit = new RegionInTransitionStat(getConfiguration());<a name="line.1379"></a>
+<span class="sourceLineNo">1380</span> rit.update(this);<a name="line.1380"></a>
+<span class="sourceLineNo">1381</span> return rit;<a name="line.1381"></a>
+<span class="sourceLineNo">1382</span> }<a name="line.1382"></a>
+<span class="sourceLineNo">1383</span><a name="line.1383"></a>
+<span class="sourceLineNo">1384</span> public static class RegionInTransitionStat {<a name="line.1384"></a>
+<span class="sourceLineNo">1385</span> private final int ritThreshold;<a name="line.1385"></a>
+<span class="sourceLineNo">1386</span><a name="line.1386"></a>
+<span class="sourceLineNo">1387</span> private HashMap<String, RegionState> ritsOverThreshold = null;<a name="line.1387"></a>
+<span class="sourceLineNo">1388</span> private long statTimestamp;<a name="line.1388"></a>
+<span class="sourceLineNo">1389</span> private long oldestRITTime = 0;<a name="line.1389"></a>
+<span class="sourceLineNo">1390</span> private int totalRITsTwiceThreshold = 0;<a name="line.1390"></a>
+<span class="sourceLineNo">1391</span> private int totalRITs = 0;<a name="line.1391"></a>
+<span class="sourceLineNo">1392</span><a name="line.1392"></a>
+<span class="sourceLineNo">1393</span> public RegionInTransitionStat(final Configuration conf) {<a name="line.1393"></a>
+<span class="sourceLineNo">1394</span> this.ritThreshold =<a name="line.1394"></a>
+<span class="sourceLineNo">1395</span> conf.getInt(METRICS_RIT_STUCK_WARNING_THRESHOLD, DEFAULT_RIT_STUCK_WARNING_THRESHOLD);<a name="line.1395"></a>
<span class="sourceLineNo">1396</span> }<a name="line.1396"></a>
<span class="sourceLineNo">1397</span><a name="line.1397"></a>
-<span class="sourceLineNo">1398</span> public int getTotalRITsOverThreshold() {<a name="line.1398"></a>
-<span class="sourceLineNo">1399</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1399"></a>
-<span class="sourceLineNo">1400</span> return m != null ? m.size() : 0;<a name="line.1400"></a>
-<span class="sourceLineNo">1401</span> }<a name="line.1401"></a>
-<span class="sourceLineNo">1402</span><a name="line.1402"></a>
-<span class="sourceLineNo">1403</span> public boolean hasRegionsTwiceOverThreshold() {<a name="line.1403"></a>
-<span class="sourceLineNo">1404</span> return totalRITsTwiceThreshold > 0;<a name="line.1404"></a>
-<span class="sourceLineNo">1405</span> }<a name="line.1405"></a>
-<span class="sourceLineNo">1406</span><a name="line.1406"></a>
-<span class="sourceLineNo">1407</span> public boolean hasRegionsOverThreshold() {<a name="line.1407"></a>
-<span class="sourceLineNo">1408</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1408"></a>
-<span class="sourceLineNo">1409</span> return m != null && !m.isEmpty();<a name="line.1409"></a>
-<span class="sourceLineNo">1410</span> }<a name="line.1410"></a>
-<span class="sourceLineNo">1411</span><a name="line.1411"></a>
-<span class="sourceLineNo">1412</span> public Collection<RegionState> getRegionOverThreshold() {<a name="line.1412"></a>
-<span class="sourceLineNo">1413</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1413"></a>
-<span class="sourceLineNo">1414</span> return m != null? m.values(): Collections.emptySet();<a name="line.1414"></a>
-<span class="sourceLineNo">1415</span> }<a name="line.1415"></a>
-<span class="sourceLineNo">1416</span><a name="line.1416"></a>
-<span class="sourceLineNo">1417</span> public boolean isRegionOverThreshold(final RegionInfo regionInfo) {<a name="line.1417"></a>
-<span class="sourceLineNo">1418</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1418"></a>
-<span class="sourceLineNo">1419</span> return m != null && m.containsKey(regionInfo.getEncodedName());<a name="line.1419"></a>
-<span class="sourceLineNo">1420</span> }<a name="line.1420"></a>
-<span class="sourceLineNo">1421</span><a name="line.1421"></a>
-<span class="sourceLineNo">1422</span> public boolean isRegionTwiceOverThreshold(final RegionInfo regionInfo) {<a name="line.1422"></a>
-<span class="sourceLineNo">1423</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1423"></a>
-<span class="sourceLineNo">1424</span> if (m == null) {<a name="line.1424"></a>
-<span class="sourceLineNo">1425</span> return false;<a name="line.1425"></a>
-<span class="sourceLineNo">1426</span> }<a name="line.1426"></a>
-<span class="sourceLineNo">1427</span> final RegionState state = m.get(regionInfo.getEncodedName());<a name="line.1427"></a>
-<span class="sourceLineNo">1428</span> if (state == null) {<a name="line.1428"></a>
-<span class="sourceLineNo">1429</span> return false;<a name="line.1429"></a>
-<span class="sourceLineNo">1430</span> }<a name="line.1430"></a>
-<span class="sourceLineNo">1431</span> return (statTimestamp - state.getStamp()) > (ritThreshold * 2);<a name="line.1431"></a>
-<span class="sourceLineNo">1432</span> }<a name="line.1432"></a>
-<span class="sourceLineNo">1433</span><a name="line.1433"></a>
-<span class="sourceLineNo">1434</span> protected void update(final AssignmentManager am) {<a name="line.1434"></a>
-<span class="sourceLineNo">1435</span> final RegionStates regionStates = am.getRegionStates();<a name="line.1435"></a>
-<span class="sourceLineNo">1436</span> this.statTimestamp = EnvironmentEdgeManager.currentTime();<a name="line.1436"></a>
-<span class="sourceLineNo">1437</span> update(regionStates.getRegionsStateInTransition(), statTimestamp);<a name="line.1437"></a>
-<span class="sourceLineNo">1438</span> update(regionStates.getRegionFailedOpen(), statTimestamp);<a name="line.1438"></a>
-<span class="sourceLineNo">1439</span><a name="line.1439"></a>
-<span class="sourceLineNo">1440</span> if (LOG.isDebugEnabled() && ritsOverThreshold != null && !ritsOverThreshold.isEmpty()) {<a name="line.1440"></a>
-<span class="sourceLineNo">1441</span> LOG.debug("RITs over threshold: {}",<a name="line.1441"></a>
-<span class="sourceLineNo">1442</span> ritsOverThreshold.entrySet().stream()<a name="line.1442"></a>
-<span class="sourceLineNo">1443</span> .map(e -> e.getKey() + ":" + e.getValue().getState().name())<a name="line.1443"></a>
-<span class="sourceLineNo">1444</span> .collect(Collectors.joining("\n")));<a name="line.1444"></a>
-<span class="sourceLineNo">1445</span> }<a name="line.1445"></a>
-<span class="sourceLineNo">1446</span> }<a name="line.1446"></a>
-<span class="sourceLineNo">1447</span><a name="line.1447"></a>
-<span class="sourceLineNo">1448</span> private void update(final Collection<RegionState> regions, final long currentTime) {<a name="line.1448"></a>
-<span class="sourceLineNo">1449</span> for (RegionState state: regions) {<a name="line.1449"></a>
-<span class="sourceLineNo">1450</span> totalRITs++;<a name="line.1450"></a>
-<span class="sourceLineNo">1451</span> final long ritStartedMs = state.getStamp();<a name="line.1451"></a>
-<span class="sourceLineNo">1452</span> if (ritStartedMs == 0) {<a name="line.1452"></a>
-<span class="sourceLineNo">1453</span> // Don't output bogus values to metrics if they accidentally make it here.<a name="line.1453"></a>
-<span class="sourceLineNo">1454</span> LOG.warn("The RIT {} has no start time", state.getRegion());<a name="line.1454"></a>
-<span class="sourceLineNo">1455</span> continue;<a name="line.1455"></a>
-<span class="sourceLineNo">1456</span> }<a name="line.1456"></a>
-<span class="sourceLineNo">1457</span> final long ritTime = currentTime - ritStartedMs;<a name="line.1457"></a>
-<span class="sourceLineNo">1458</span> if (ritTime > ritThreshold) {<a name="line.1458"></a>
-<span class="sourceLineNo">1459</span> if (ritsOverThreshold == null) {<a name="line.1459"></a>
-<span class="sourceLineNo">1460</span> ritsOverThreshold = new HashMap<String, RegionState>();<a name="line.1460"></a>
-<span class="sourceLineNo">1461</span> }<a name="line.1461"></a>
-<span class="sourceLineNo">1462</span> ritsOverThreshold.put(state.getRegion().getEncodedName(), state);<a name="line.1462"></a>
-<span class="sourceLineNo">1463</span> totalRITsTwiceThreshold += (ritTime > (ritThreshold * 2)) ? 1 : 0;<a name="line.1463"></a>
-<span class="sourceLineNo">1464</span> }<a name="line.1464"></a>
-<span class="sourceLineNo">1465</span> if (oldestRITTime < ritTime) {<a name="line.1465"></a>
-<span class="sourceLineNo">1466</span> oldestRITTime = ritTime;<a name="line.1466"></a>
-<span class="sourceLineNo">1467</span> }<a name="line.1467"></a>
-<span class="sourceLineNo">1468</span> }<a name="line.1468"></a>
-<span class="sourceLineNo">1469</span> }<a name="line.1469"></a>
-<span class="sourceLineNo">1470</span> }<a name="line.1470"></a>
-<span class="sourceLineNo">1471</span><a name="line.1471"></a>
-<span class="sourceLineNo">1472</span> private void updateRegionsInTransitionMetrics(final RegionInTransitionStat ritStat) {<a name="line.1472"></a>
-<span class="sourceLineNo">1473</span> metrics.updateRITOldestAge(ritStat.getOldestRITTime());<a name="line.1473"></a>
-<span class="sourceLineNo">1474</span> metrics.updateRITCount(ritStat.getTotalRITs());<a name="line.1474"></a>
-<span class="sourceLineNo">1475</span> metrics.updateRITCountOverThreshold(ritStat.getTotalRITsOverThreshold());<a name="line.1475"></a>
-<span class="sourceLineNo">1476</span> }<a name="line.1476"></a>
-<span class="sourceLineNo">1477</span><a name="line.1477"></a>
-<span class="sourceLineNo">1478</span> private void updateDeadServerRegionMetrics(int deadRegions, int unknownRegions) {<a name="line.1478"></a>
-<span class="sourceLineNo">1479</span> metrics.updateDeadServerOpenRegions(deadRegions);<a name="line.1479"></a>
-<span class="sourceLineNo">1480</span> metrics.updateUnknownServerOpenRegions(unknownRegions);<a name="line.1480"></a>
-<span class="sourceLineNo">1481</span> }<a name="line.1481"></a>
-<span class="sourceLineNo">1482</span><a name="line.1482"></a>
-<span class="sourceLineNo">1483</span> private void handleRegionOverStuckWarningThreshold(final RegionInfo regionInfo) {<a name="line.1483"></a>
-<span class="sourceLineNo">1484</span> final RegionStateNode regionNode = regionStates.getRegionStateNode(regionInfo);<a name="line.1484"></a>
-<span class="sourceLineNo">1485</span> //if (regionNode.isStuck()) {<a name="line.1485"></a>
-<span class="sourceLineNo">1486</span> LOG.warn("STUCK Region-In-Transition {}", regionNode);<a name="line.1486"></a>
-<span class="sourceLineNo">1487</span> }<a name="line.1487"></a>
-<span class="sourceLineNo">1488</span><a name="line.1488"></a>
-<span class="sourceLineNo">1489</span> // ============================================================================================<a name="line.1489"></a>
-<span class="sourceLineNo">1490</span> // TODO: Master load/bootstrap<a name="line.1490"></a>
-<span class="sourceLineNo">1491</span> // ============================================================================================<a name="line.1491"></a>
-<span class="sourceLineNo">1492</span> public void joinCluster() throws IOException {<a name="line.1492"></a>
-<span class="sourceLineNo">1493</span> long startTime = System.nanoTime();<a name="line.1493"></a>
-<span class="sourceLineNo">1494</span> LOG.debug("Joining cluster...");<a name="line.1494"></a>
-<span class="sourceLineNo">1495</span><a name="line.1495"></a>
-<span class="sourceLineNo">1496</span> // Scan hbase:meta to build list of existing regions, servers, and assignment.<a name="line.1496"></a>
-<span class="sourceLineNo">1497</span> // hbase:meta is online now or will be. Inside loadMeta, we keep trying. Can't make progress<a name="line.1497"></a>
-<span class="sourceLineNo">1498</span> // w/o meta.<a name="line.1498"></a>
-<span class="sourceLineNo">1499</span> loadMeta();<a name="line.1499"></a>
-<span class="sourceLineNo">1500</span><a name="line.1500"></a>
-<span class="sourceLineNo">1501</span> while (master.getServerManager().countOfRegionServers() < 1) {<a name="line.1501"></a>
-<span class="sourceLineNo">1502</span> LOG.info("Waiting for RegionServers to join; current count={}",<a name="line.1502"></a>
-<span class="sourceLineNo">1503</span> master.getServerManager().countOfRegionServers());<a name="line.1503"></a>
-<span class="sourceLineNo">1504</span> Threads.sleep(250);<a name="line.1504"></a>
-<span class="sourceLineNo">1505</span> }<a name="line.1505"></a>
-<span class="sourceLineNo">1506</span> LOG.info("Number of RegionServers={}", master.getServerManager().countOfRegionServers());<a name="line.1506"></a>
-<span class="sourceLineNo">1507</span><a name="line.1507"></a>
-<span class="sourceLineNo">1508</span> // Start the chores<a name="line.1508"></a>
-<span class="sourceLineNo">1509</span> master.getMasterProcedureExecutor().addChore(this.ritChore);<a name="line.1509"></a>
-<span class="sourceLineNo">1510</span> master.getMasterProcedureExecutor().addChore(this.deadMetricChore);<a name="line.1510"></a>
+<span class="sourceLineNo">1398</span> public int getRITThreshold() {<a name="line.1398"></a>
+<span class="sourceLineNo">1399</span> return ritThreshold;<a name="line.1399"></a>
+<span class="sourceLineNo">1400</span> }<a name="line.1400"></a>
+<span class="sourceLineNo">1401</span><a name="line.1401"></a>
+<span class="sourceLineNo">1402</span> public long getTimestamp() {<a name="line.1402"></a>
+<span class="sourceLineNo">1403</span> return statTimestamp;<a name="line.1403"></a>
+<span class="sourceLineNo">1404</span> }<a name="line.1404"></a>
+<span class="sourceLineNo">1405</span><a name="line.1405"></a>
+<span class="sourceLineNo">1406</span> public int getTotalRITs() {<a name="line.1406"></a>
+<span class="sourceLineNo">1407</span> return totalRITs;<a name="line.1407"></a>
+<span class="sourceLineNo">1408</span> }<a name="line.1408"></a>
+<span class="sourceLineNo">1409</span><a name="line.1409"></a>
+<span class="sourceLineNo">1410</span> public long getOldestRITTime() {<a name="line.1410"></a>
+<span class="sourceLineNo">1411</span> return oldestRITTime;<a name="line.1411"></a>
+<span class="sourceLineNo">1412</span> }<a name="line.1412"></a>
+<span class="sourceLineNo">1413</span><a name="line.1413"></a>
+<span class="sourceLineNo">1414</span> public int getTotalRITsOverThreshold() {<a name="line.1414"></a>
+<span class="sourceLineNo">1415</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1415"></a>
+<span class="sourceLineNo">1416</span> return m != null ? m.size() : 0;<a name="line.1416"></a>
+<span class="sourceLineNo">1417</span> }<a name="line.1417"></a>
+<span class="sourceLineNo">1418</span><a name="line.1418"></a>
+<span class="sourceLineNo">1419</span> public boolean hasRegionsTwiceOverThreshold() {<a name="line.1419"></a>
+<span class="sourceLineNo">1420</span> return totalRITsTwiceThreshold > 0;<a name="line.1420"></a>
+<span class="sourceLineNo">1421</span> }<a name="line.1421"></a>
+<span class="sourceLineNo">1422</span><a name="line.1422"></a>
+<span class="sourceLineNo">1423</span> public boolean hasRegionsOverThreshold() {<a name="line.1423"></a>
+<span class="sourceLineNo">1424</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1424"></a>
+<span class="sourceLineNo">1425</span> return m != null && !m.isEmpty();<a name="line.1425"></a>
+<span class="sourceLineNo">1426</span> }<a name="line.1426"></a>
+<span class="sourceLineNo">1427</span><a name="line.1427"></a>
+<span class="sourceLineNo">1428</span> public Collection<RegionState> getRegionOverThreshold() {<a name="line.1428"></a>
+<span class="sourceLineNo">1429</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1429"></a>
+<span class="sourceLineNo">1430</span> return m != null? m.values(): Collections.emptySet();<a name="line.1430"></a>
+<span class="sourceLineNo">1431</span> }<a name="line.1431"></a>
+<span class="sourceLineNo">1432</span><a name="line.1432"></a>
+<span class="sourceLineNo">1433</span> public boolean isRegionOverThreshold(final RegionInfo regionInfo) {<a name="line.1433"></a>
+<span class="sourceLineNo">1434</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1434"></a>
+<span class="sourceLineNo">1435</span> return m != null && m.containsKey(regionInfo.getEncodedName());<a name="line.1435"></a>
+<span class="sourceLineNo">1436</span> }<a name="line.1436"></a>
+<span class="sourceLineNo">1437</span><a name="line.1437"></a>
+<span class="sourceLineNo">1438</span> public boolean isRegionTwiceOverThreshold(final RegionInfo regionInfo) {<a name="line.1438"></a>
+<span class="sourceLineNo">1439</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1439"></a>
+<span class="sourceLineNo">1440</span> if (m == null) {<a name="line.1440"></a>
+<span class="sourceLineNo">1441</span> return false;<a name="line.1441"></a>
+<span class="sourceLineNo">1442</span> }<a name="line.1442"></a>
+<span class="sourceLineNo">1443</span> final RegionState state = m.get(regionInfo.getEncodedName());<a name="line.1443"></a>
+<span class="sourceLineNo">1444</span> if (state == null) {<a name="line.1444"></a>
+<span class="sourceLineNo">1445</span> return false;<a name="line.1445"></a>
+<span class="sourceLineNo">1446</span> }<a name="line.1446"></a>
+<span class="sourceLineNo">1447</span> return (statTimestamp - state.getStamp()) > (ritThreshold * 2);<a name="line.1447"></a>
+<span class="sourceLineNo">1448</span> }<a name="line.1448"></a>
+<span class="sourceLineNo">1449</span><a name="line.1449"></a>
+<span class="sourceLineNo">1450</span> protected void update(final AssignmentManager am) {<a name="line.1450"></a>
+<span class="sourceLineNo">1451</span> final RegionStates regionStates = am.getRegionStates();<a name="line.1451"></a>
+<span class="sourceLineNo">1452</span> this.statTimestamp = EnvironmentEdgeManager.currentTime();<a name="line.1452"></a>
+<span class="sourceLineNo">1453</span> update(regionStates.getRegionsStateInTransition(), statTimestamp);<a name="line.1453"></a>
+<span class="sourceLineNo">1454</span> update(regionStates.getRegionFailedOpen(), statTimestamp);<a name="line.1454"></a>
+<span class="sourceLineNo">1455</span><a name="line.1455"></a>
+<span class="sourceLineNo">1456</span> if (LOG.isDebugEnabled() && ritsOverThreshold != null && !ritsOverThreshold.isEmpty()) {<a name="line.1456"></a>
+<span class="sourceLineNo">1457</span> LOG.debug("RITs over threshold: {}",<a name="line.1457"></a>
+<span class="sourceLineNo">1458</span> ritsOverThreshold.entrySet().stream()<a name="line.1458"></a>
+<span class="sourceLineNo">1459</span> .map(e -> e.getKey() + ":" + e.getValue().getState().name())<a name="line.1459"></a>
+<span class="sourceLineNo">1460</span> .collect(Collectors.joining("\n")));<a name="line.1460"></a>
+<span class="sourceLineNo">1461</span> }<a name="line.1461"></a>
+<span class="sourceLineNo">1462</span> }<a name="line.1462"></a>
+<span class="sourceLineNo">1463</span><a name="line.1463"></a>
+<span class="sourceLineNo">1464</span> private void update(final Collection<RegionState> regions, final long currentTime) {<a name="line.1464"></a>
+<span class="sourceLineNo">1465</span> for (RegionState state: regions) {<a name="line.1465"></a>
+<span class="sourceLineNo">1466</span> totalRITs++;<a name="line.1466"></a>
+<span class="sourceLineNo">1467</span> final long ritStartedMs = state.getStamp();<a name="line.1467"></a>
+<span class="sourceLineNo">1468</span> if (ritStartedMs == 0) {<a name="line.1468"></a>
+<span class="sourceLineNo">1469</span> // Don't output bogus values to metrics if they accidentally make it here.<a name="line.1469"></a>
+<span class="sourceLineNo">1470</span> LOG.warn("The RIT {} has no start time", state.getRegion());<a name="line.1470"></a>
+<span class="sourceLineNo">1471</span> continue;<a name="line.1471"></a>
+<span class="sourceLineNo">1472</span> }<a name="line.1472"></a>
+<span class="sourceLineNo">1473</span> final long ritTime = currentTime - ritStartedMs;<a name="line.1473"></a>
+<span class="sourceLineNo">1474</span> if (ritTime > ritThreshold) {<a name="line.1474"></a>
+<span class="sourceLineNo">1475</span> if (ritsOverThreshold == null) {<a name="line.1475"></a>
+<span class="sourceLineNo">1476</span> ritsOverThreshold = new HashMap<String, RegionState>();<a name="line.1476"></a>
+<span class="sourceLineNo">1477</span> }<a name="line.1477"></a>
+<span class="sourceLineNo">1478</span> ritsOverThreshold.put(state.getRegion().getEncodedName(), state);<a name="line.1478"></a>
+<span class="sourceLineNo">1479</span> totalRITsTwiceThreshold += (ritTime > (ritThreshold * 2)) ? 1 : 0;<a name="line.1479"></a>
+<span class="sourceLineNo">1480</span> }<a name="line.1480"></a>
+<span class="sourceLineNo">1481</span> if (oldestRITTime < ritTime) {<a name="line.1481"></a>
+<span class="sourceLineNo">1482</span> oldestRITTime = ritTime;<a name="line.1482"></a>
+<span class="sourceLineNo">1483</span> }<a name="line.1483"></a>
+<span class="sourceLineNo">1484</span> }<a name="line.1484"></a>
+<span class="sourceLineNo">1485</span> }<a name="line.1485"></a>
+<span class="sourceLineNo">1486</span> }<a name="line.1486"></a>
+<span class="sourceLineNo">1487</span><a name="line.1487"></a>
+<span class="sourceLineNo">1488</span> private void updateRegionsInTransitionMetrics(final RegionInTransitionStat ritStat) {<a name="line.1488"></a>
+<span class="sourceLineNo">1489</span> metrics.updateRITOldestAge(ritStat.getOldestRITTime());<a name="line.1489"></a>
+<span class="sourceLineNo">1490</span> metrics.updateRITCount(ritStat.getTotalRITs());<a name="line.1490"></a>
+<span class="sourceLineNo">1491</span> metrics.updateRITCountOverThreshold(ritStat.getTotalRITsOverThreshold());<a name="line.1491"></a>
+<span class="sourceLineNo">1492</span> }<a name="line.1492"></a>
+<span class="sourceLineNo">1493</span><a name="line.1493"></a>
+<span class="sourceLineNo">1494</span> private void updateDeadServerRegionMetrics(int deadRegions, int unknownRegions) {<a name="line.1494"></a>
+<span class="sourceLineNo">1495</span> metrics.updateDeadServerOpenRegions(deadRegions);<a name="line.1495"></a>
+<span class="sourceLineNo">1496</span> metrics.updateUnknownServerOpenRegions(unknownRegions);<a name="line.1496"></a>
+<span class="sourceLineNo">1497</span> }<a name="line.1497"></a>
+<span class="sourceLineNo">1498</span><a name="line.1498"></a>
+<span class="sourceLineNo">1499</span> private void handleRegionOverStuckWarningThreshold(final RegionInfo regionInfo) {<a name="line.1499"></a>
+<span class="sourceLineNo">1500</span> final RegionStateNode regionNode = regionStates.getRegionStateNode(regionInfo);<a name="line.1500"></a>
+<span class="sourceLineNo">1501</span> //if (regionNode.isStuck()) {<a name="line.1501"></a>
+<span class="sourceLineNo">1502</span> LOG.warn("STUCK Region-In-Transition {}", regionNode);<a name="line.1502"></a>
+<span class="sourceLineNo">1503</span> }<a name="line.1503"></a>
+<span class="sourceLineNo">1504</span><a name="line.1504"></a>
+<span class="sourceLineNo">1505</span> // ============================================================================================<a name="line.1505"></a>
+<span class="sourceLineNo">1506</span> // TODO: Master load/bootstrap<a name="line.1506"></a>
+<span class="sourceLineNo">1507</span> // ============================================================================================<a name="line.1507"></a>
+<span class="sourceLineNo">1508</span> public void joinCluster() throws IOException {<a name="line.1508"></a>
+<span class="sourceLineNo">1509</span> long startTime = System.nanoTime();<a name="line.1509"></a>
+<span class="sourceLineNo">1510</span> LOG.debug("Joining cluster...");<a name="line.1510"></a>
<span class="sourceLineNo">1511</span><a name="line.1511"></a>
-<span class="sourceLineNo">1512</span> long costMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);<a name="line.1512"></a>
-<span class="sourceLineNo">1513</span> LOG.info("Joined the cluster in {}", StringUtils.humanTimeDiff(costMs));<a name="line.1513"></a>
-<span class="sourceLineNo">1514</span> }<a name="line.1514"></a>
-<span class="sourceLineNo">1515</span><a name="line.1515"></a>
-<span class="sourceLineNo">1516</span> /**<a name="line.1516"></a>
-<span class="sourceLineNo">1517</span> * Create assign procedure for offline regions.<a name="line.1517"></a>
-<span class="sourceLineNo">1518</span> * Just follow the old processofflineServersWithOnlineRegions method. Since now we do not need to<a name="line.1518"></a>
-<span class="sourceLineNo">1519</span> * deal with dead server any more, we only deal with the regions in OFFLINE state in this method.<a name="line.1519"></a>
-<span class="sourceLineNo">1520</span> * And this is a bit strange, that for new regions, we will add it in CLOSED state instead of<a name="line.1520"></a>
-<span class="sourceLineNo">1521</span> * OFFLINE state, and usually there will be a procedure to track them. The<a name="line.1521"></a>
-<span class="sourceLineNo">1522</span> * processofflineServersWithOnlineRegions is a legacy from long ago, as things are going really<a name="line.1522"></a>
-<span class="sourceLineNo">1523</span> * different now, maybe we do not need this method any more. Need to revisit later.<a name="line.1523"></a>
-<span class="sourceLineNo">1524</span> */<a name="line.1524"></a>
-<span class="sourceLineNo">1525</span> // Public so can be run by the Master as part of the startup. Needs hbase:meta to be online.<a name="line.1525"></a>
-<span class="sourceLineNo">1526</span> // Needs to be done after the table state manager has been started.<a name="line.1526"></a>
-<span class="sourceLineNo">1527</span> public void processOfflineRegions() {<a name="line.1527"></a>
-<span class="sourceLineNo">1528</span> TransitRegionStateProcedure[] procs =<a name="line.1528"></a>
-<span class="sourceLineNo">1529</span> regionStates.getRegionStateNodes().stream().filter(rsn -> rsn.isInState(State.OFFLINE))<a name="line.1529"></a>
-<span class="sourceLineNo">1530</span> .filter(rsn -> isTableEnabled(rsn.getRegionInfo().getTable())).map(rsn -> {<a name="line.1530"></a>
-<span class="sourceLineNo">1531</span> rsn.lock();<a name="line.1531"></a>
-<span class="sourceLineNo">1532</span> try {<a name="line.1532"></a>
-<span class="sourceLineNo">1533</span> if (rsn.getProcedure() != null) {<a name="line.1533"></a>
-<span class="sourceLineNo">1534</span> return null;<a name="line.1534"></a>
-<span class="sourceLineNo">1535</span> } else {<a name="line.1535"></a>
-<span class="sourceLineNo">1536</span> return rsn.setProcedure(TransitRegionStateProcedure.assign(getProcedureEnvironment(),<a name="line.1536"></a>
-<span class="sourceLineNo">1537</span> rsn.getRegionInfo(), null));<a name="line.1537"></a>
-<span class="sourceLineNo">1538</span> }<a name="line.1538"></a>
-<span class="sourceLineNo">1539</span> } finally {<a name="line.1539"></a>
-<span class="sourceLineNo">1540</span> rsn.unlock();<a name="line.1540"></a>
-<span class="sourceLineNo">1541</span> }<a name="line.1541"></a>
-<span class="sourceLineNo">1542</span> }).filter(p -> p != null).toArray(TransitRegionStateProcedure[]::new);<a name="line.1542"></a>
-<span class="sourceLineNo">1543</span> if (procs.length > 0) {<a name="line.1543"></a>
-<span class="sourceLineNo">1544</span> master.getMasterProcedureExecutor().submitProcedures(procs);<a name="line.1544"></a>
-<span class="sourceLineNo">1545</span> }<a name="line.1545"></a>
-<span class="sourceLineNo">1546</span> }<a name="line.1546"></a>
-<span class="sourceLineNo">1547</span><a name="line.1547"></a>
-<span class="sourceLineNo">1548</span> /* AM internal RegionStateStore.RegionStateVisitor implementation. To be used when<a name="line.1548"></a>
-<span class="sourceLineNo">1549</span> * scanning META table for region rows, using RegionStateStore utility methods. RegionStateStore<a name="line.1549"></a>
-<span class="sourceLineNo">1550</span> * methods will convert Result into proper RegionInfo instances, but those would still need to be<a name="line.1550"></a>
-<span class="sourceLineNo">1551</span> * added into AssignmentManager.regionStates in-memory cache.<a name="line.1551"></a>
-<span class="sourceLineNo">1552</span> * RegionMetaLoadingVisitor.visitRegionState method provides the logic for adding RegionInfo<a name="line.1552"></a>
-<span class="sourceLineNo">1553</span> * instances as loaded from latest META scan into AssignmentManager.regionStates.<a name="line.1553"></a>
-<span class="sourceLineNo">1554</span> */<a name="line.1554"></a>
-<span class="sourceLineNo">1555</span> private class RegionMetaLoadingVisitor implements RegionStateStore.RegionStateVisitor {<a name="line.1555"></a>
-<span class="sourceLineNo">1556</span><a name="line.1556"></a>
-<span class="sourceLineNo">1557</span> @Override<a name="line.1557"></a>
-<span class="sourceLineNo">1558</span> public void visitRegionState(Result result, final RegionInfo regionInfo, final State state,<a name="line.1558"></a>
-<span class="sourceLineNo">1559</span> final ServerName regionLocation, final ServerName lastHost, final long openSeqNum) {<a name="line.1559"></a>
-<span class="sourceLineNo">1560</span> if (state == null && regionLocation == null && lastHost == null &&<a name="line.1560"></a>
-<span class="sourceLineNo">1561</span> openSeqNum == SequenceId.NO_SEQUENCE_ID) {<a name="line.1561"></a>
-<span class="sourceLineNo">1562</span> // This is a row with nothing in it.<a name="line.1562"></a>
-<span class="sourceLineNo">1563</span> LOG.warn("Skipping empty row={}", result);<a name="line.1563"></a>
-<span class="sourceLineNo">1564</span> return;<a name="line.1564"></a>
-<span class="sourceLineNo">1565</span> }<a name="line.1565"></a>
-<span class="sourceLineNo">1566</span> State localState = state;<a name="line.1566"></a>
-<span class="sourceLineNo">1567</span> if (localState == null) {<a name="line.1567"></a>
-<span class="sourceLineNo">1568</span> // No region state column data in hbase:meta table! Are I doing a rolling upgrade from<a name="line.1568"></a>
-<span class="sourceLineNo">1569</span> // hbase1 to hbase2? Am I restoring a SNAPSHOT or otherwise adding a region to hbase:meta?<a name="line.1569"></a>
-<span class="sourceLineNo">1570</span> // In any of these cases, state is empty. For now, presume OFFLINE but there are probably<a name="line.1570"></a>
-<span class="sourceLineNo">1571</span> // cases where we need to probe more to be sure this correct; TODO informed by experience.<a name="line.1571"></a>
-<span class="sourceLineNo">1572</span> LOG.info(regionInfo.getEncodedName() + " regionState=null; presuming " + State.OFFLINE);<a name="line.1572"></a>
-<span class="sourceLineNo">1573</span> localState = State.OFFLINE;<a name="line.1573"></a>
-<span class="sourceLineNo">1574</span> }<a name="line.1574"></a>
-<span class="sourceLineNo">1575</span> RegionStateNode regionNode = regionStates.getOrCreateRegionStateNode(regionInfo);<a name="line.1575"></a>
-<span class="sourceLineNo">1576</span> // Do not need to lock on regionNode, as we can make sure that before we finish loading<a name="line.1576"></a>
-<span class="sourceLineNo">1577</span> // meta, all the related procedures can not be executed. The only exception is for meta<a name="line.1577"></a>
-<span class="sourceLineNo">1578</span> // region related operations, but here we do not load the informations for meta region.<a name="line.1578"></a>
-<span class="sourceLineNo">1579</span> regionNode.setState(localState);<a name="line.1579"></a>
-<span class="sourceLineNo">1580</span> regionNode.setLastHost(lastHost);<a name="line.1580"></a>
-<span class="sourceLineNo">1581</span> regionNode.setRegionLocation(regionLocation);<a name="line.1581"></a>
-<span class="sourceLineNo">1582</span> regionNode.setOpenSeqNum(openSeqNum);<a name="line.1582"></a>
-<span class="sourceLineNo">1583</span><a name="line.1583"></a>
-<span class="sourceLineNo">1584</span> // Note: keep consistent with other methods, see region(Opening|Opened|Closing)<a name="line.1584"></a>
-<span class="sourceLineNo">1585</span> // RIT/ServerCrash handling should take care of the transiting regions.<a name="line.1585"></a>
-<span class="sourceLineNo">1586</span> if (localState.matches(State.OPEN, State.OPENING, State.CLOSING, State.SPLITTING,<a name="line.1586"></a>
-<span class="sourceLineNo">1587</span> State.MERGING)) {<a name="line.1587"></a>
-<span class="sourceLineNo">1588</span> assert regionLocation != null : "found null region location for " + regionNode;<a name="line.1588"></a>
-<span class="sourceLineNo">1589</span> regionStates.addRegionToServer(regionNode);<a name="line.1589"></a>
-<span class="sourceLineNo">1590</span> } else if (localState == State.OFFLINE || regionInfo.isOffline()) {<a name="line.1590"></a>
-<span class="sourceLineNo">1591</span> regionStates.addToOfflineRegions(regionNode);<a name="line.1591"></a>
-<span class="sourceLineNo">1592</span> }<a name="line.1592"></a>
-<span class="sourceLineNo">1593</span> if (regionNode.getProcedure() != null) {<a name="line.1593"></a>
-<span class="sourceLineNo">1594</span> regionNode.getProcedure().stateLoaded(AssignmentManager.this, regionNode);<a name="line.1594"></a>
-<span class="sourceLineNo">1595</span> }<a name="line.1595"></a>
-<span class="sourceLineNo">1596</span> }<a name="line.1596"></a>
-<span class="sourceLineNo">1597</span> };<a name="line.1597"></a>
-<span class="sourceLineNo">1598</span><a name="line.1598"></a>
-<span class="sourceLineNo">1599</span> /**<a name="line.1599"></a>
-<span class="sourceLineNo">1600</span> * Query META if the given <code>RegionInfo</code> exists, adding to<a name="line.1600"></a>
-<span class="sourceLineNo">1601</span> * <code>AssignmentManager.regionStateStore</code> cache if the region is found in META.<a name="line.1601"></a>
-<span class="sourceLineNo">1602</span> * @param regionEncodedName encoded name for the region to be loaded from META into<a name="line.1602"></a>
-<span class="sourceLineNo">1603</span> * <code>AssignmentManager.regionStateStore</code> cache<a name="line.1603"></a>
-<span class="sourceLineNo">1604</span> * @return <code>RegionInfo</code> instance for the given region if it is present in META<a name="line.1604"></a>
-<span class="sourceLineNo">1605</span> * and got successfully loaded into <code>AssignmentManager.regionStateStore</code><a name="line.1605"></a>
-<span class="sourceLineNo">1606</span> * cache, <b>null</b> otherwise.<a name="line.1606"></a>
-<span class="sourceLineNo">1607</span> * @throws UnknownRegionException if any errors occur while querying meta.<a name="line.1607"></a>
-<span class="sourceLineNo">1608</span> */<a name="line.1608"></a>
-<span class="sourceLineNo">1609</span> public RegionInfo loadRegionFromMeta(String regionEncodedName) throws UnknownRegionException {<a name="line.1609"></a>
-<span class="sourceLineNo">1610</span> try {<a name="line.1610"></a>
-<span class="sourceLineNo">1611</span> RegionMetaLoadingVisitor visitor = new RegionMetaLoadingVisitor();<a name="line.1611"></a>
-<span class="sourceLineNo">1612</span> regionStateStore.visitMetaForRegion(regionEncodedName, visitor);<a name="line.1612"></a>
-<span class="sourceLineNo">1613</span> return regionStates.getRegionState(regionEncodedName) == null ? null :<a name="line.1613"></a>
-<span class="sourceLineNo">1614</span> regionStates.getRegionState(regionEncodedName).getRegion();<a name="line.1614"></a>
-<span class="sourceLineNo">1615</span> } catch(IOException e) {<a name="line.1615"></a>
-<span class="sourceLineNo">1616</span> LOG.error("Error trying to load region {} from META", regionEncodedName, e);<a name="line.1616"></a>
-<span class="sourceLineNo">1617</span> throw new UnknownRegionException("Error while trying load region from meta");<a name="line.1617"></a>
-<span class="sourceLineNo">1618</span> }<a name="line.1618"></a>
-<span class="sourceLineNo">1619</span> }<a name="line.1619"></a>
-<span class="sourceLineNo">1620</span><a name="line.1620"></a>
-<span class="sourceLineNo">1621</span> private void loadMeta() throws IOException {<a name="line.1621"></a>
-<span class="sourceLineNo">1622</span> // TODO: use a thread pool<a name="line.1622"></a>
-<span class="sourceLineNo">1623</span> regionStateStore.visitMeta(new RegionMetaLoadingVisitor());<a name="line.1623"></a>
-<span class="sourceLineNo">1624</span> }<a name="line.1624"></a>
-<span class="sourceLineNo">1625</span><a name="line.1625"></a>
-<span class="sourceLineNo">1626</span> /**<a name="line.1626"></a>
-<span class="sourceLineNo">1627</span> * Used to check if the meta loading is done.<a name="line.1627"></a>
-<span class="sourceLineNo">1628</span> * <p/><a name="line.1628"></a>
-<span class="sourceLineNo">1629</span> * if not we throw PleaseHoldException since we are rebuilding the RegionStates<a name="line.1629"></a>
-<span class="sourceLineNo">1630</span> * @param hri region to check if it is already rebuild<a name="line.1630"></a>
-<span class="sourceLineNo">1631</span> * @throws PleaseHoldException if meta has not been loaded yet<a name="line.1631"></a>
-<span class="sourceLineNo">1632</span> */<a name="line.1632"></a>
-<span class="sourceLineNo">1633</span> private void checkMetaLoaded(RegionInfo hri) throws PleaseHoldException {<a name="line.1633"></a>
-<span class="sourceLineNo">1634</span> if (!isRunning()) {<a name="line.1634"></a>
-<span class="sourceLineNo">1635</span> throw new PleaseHoldException("AssignmentManager not running");<a name="line.1635"></a>
-<span class="sourceLineNo">1636</span> }<a name="line.1636"></a>
-<span class="sourceLineNo">1637</span> boolean meta = isMetaRegion(hri);<a name="line.1637"></a>
-<span class="sourceLineNo">1638</span> boolean metaLoaded = isMetaLoaded();<a name="line.1638"></a>
-<span class="sourceLineNo">1639</span> if (!meta && !metaLoaded) {<a name="line.1639"></a>
-<span class="sourceLineNo">1640</span> throw new PleaseHoldException(<a name="line.1640"></a>
-<span class="sourceLineNo">1641</span> "Master not fully online; hbase:meta=" + meta + ", metaLoaded=" + metaLoaded);<a name="line.1641"></a>
-<span class="sourceLineNo">1642</span> }<a name="line.1642"></a>
-<span class="sourceLineNo">1643</span> }<a name="line.1643"></a>
-<span class="sourceLineNo">1644</span><a name="line.1644"></a>
-<span class="sourceLineNo">1645</span> // ============================================================================================<a name="line.1645"></a>
-<span class="sourceLineNo">1646</span> // TODO: Metrics<a name="line.1646"></a>
-<span class="sourceLineNo">1647</span> // ============================================================================================<a name="line.1647"></a>
-<span class="sourceLineNo">1648</span> public int getNumRegionsOpened() {<a name="line.1648"></a>
-<span class="sourceLineNo">1649</span> // TODO: Used by TestRegionPlacement.java and assume monotonically increasing value<a name="line.1649"></a>
-<span class="sourceLineNo">1650</span> return 0;<a name="line.1650"></a>
-<span class="sourceLineNo">1651</span> }<a name="line.1651"></a>
-<span class="sourceLineNo">1652</span><a name="line.1652"></a>
-<span class="sourceLineNo">1653</span> /**<a name="line.1653"></a>
-<span class="sourceLineNo">1654</span> * Usually run by the Master in reaction to server crash during normal processing.<a name="line.1654"></a>
-<span class="sourceLineNo">1655</span> * Can also be invoked via external RPC to effect repair; in the latter case,<a name="line.1655"></a>
-<span class="sourceLineNo">1656</span> * the 'force' flag is set so we push through the SCP though context may indicate<a name="line.1656"></a>
-<span class="sourceLineNo">1657</span> * already-running-SCP (An old SCP may have exited abnormally, or damaged cluster<a name="line.1657"></a>
-<span class="sourceLineNo">1658</span> * may still have references in hbase:meta to 'Unknown Servers' -- servers that<a name="line.1658"></a>
-<span class="sourceLineNo">1659</span> * are not online or in dead servers list, etc.)<a name="line.1659"></a>
-<span class="sourceLineNo">1660</span> * @param force Set if the request came in externally over RPC (via hbck2). Force means<a name="line.1660"></a>
-<span class="sourceLineNo">1661</span> * run the SCP even if it seems as though there might be an outstanding<a name="line.1661"></a>
-<span class="sourceLineNo">1662</span> * SCP running.<a name="line.1662"></a>
-<span class="sourceLineNo">1663</span> * @return pid of scheduled SCP or {@link Procedure#NO_PROC_ID} if none scheduled.<a name="line.1663"></a>
-<span class="sourceLineNo">1664</span> */<a name="line.1664"></a>
-<span class="sourceLineNo">1665</span> public long submitServerCrash(ServerName serverName, boolean shouldSplitWal, boolean force) {<a name="line.1665"></a>
-<span class="sourceLineNo">1666</span> // May be an 'Unknown Server' so handle case where serverNode is null.<a name="line.1666"></a>
-<span class="sourceLineNo">1667</span> ServerStateNode serverNode = regionStates.getServerNode(serverName);<a name="line.1667"></a>
-<span class="sourceLineNo">1668</span> // Remove the in-memory rsReports result<a name="line.1668"></a>
-<span class="sourceLineNo">1669</span> synchronized (rsReports) {<a name="line.1669"></a>
-<span class="sourceLineNo">1670</span> rsReports.remove(serverName);<a name="line.1670"></a>
-<span class="sourceLineNo">1671</span> }<a name="line.1671"></a>
-<span class="sourceLineNo">1672</span><a name="line.1672"></a>
-<span class="sourceLineNo">1673</span> // We hold the write lock here for fencing on reportRegionStateTransition. Once we set the<a name="line.1673"></a>
-<span class="sourceLineNo">1674</span> // server state to CRASHED, we will no longer accept the reportRegionStateTransition call from<a name="line.1674"></a>
-<span class="sourceLineNo">1675</span> // this server. This is used to simplify the implementation for TRSP and SCP, where we can make<a name="line.1675"></a>
-<span class="sourceLineNo">1676</span> // sure that, the region list fetched by SCP will not be changed any more.<a name="line.1676"></a>
-<span class="sourceLineNo">1677</span> if (serverNode != null) {<a name="line.1677"></a>
-<span class="sourceLineNo">1678</span> serverNode.writeLock().lock();<a name="line.1678"></a>
-<span class="sourceLineNo">1679</span> }<a name="line.1679"></a>
-<span class="sourceLineNo">1680</span> boolean carryingMeta;<a name="line.1680"></a>
-<span class="sourceLineNo">1681</span> long pid;<a name="line.1681"></a>
-<span class="sourceLineNo">1682</span> try {<a name="line.1682"></a>
-<span class="sourceLineNo">1683</span> ProcedureExecutor<MasterProcedureEnv> procExec = this.master.getMasterProcedureExecutor();<a name="line.1683"></a>
-<span class="sourceLineNo">1684</span> carryingMeta = isCarryingMeta(serverName);<a name="line.1684"></a>
-<span class="sourceLineNo">1685</span> if (!force && serverNode != null && !serverNode.isInState(ServerState.ONLINE)) {<a name="line.1685"></a>
-<span class="sourceLineNo">1686</span> LOG.info("Skip adding ServerCrashProcedure for {} (meta={}) -- running?",<a name="line.1686"></a>
-<span class="sourceLineNo">1687</span> serverNode, carryingMeta);<a name="line.1687"></a>
-<span class="sourceLineNo">1688</span> return Procedure.NO_PROC_ID;<a name="line.1688"></a>
-<span class="sourceLineNo">1689</span> } else {<a name="line.1689"></a>
-<span class="sourceLineNo">1690</span> MasterProcedureEnv mpe = procExec.getEnvironment();<a name="line.1690"></a>
-<span class="sourceLineNo">1691</span> // If serverNode == null, then 'Unknown Server'. Schedule HBCKSCP instead.<a name="line.1691"></a>
-<span class="sourceLineNo">1692</span> // HBCKSCP scours Master in-memory state AND hbase;meta for references to<a name="line.1692"></a>
-<span class="sourceLineNo">1693</span> // serverName just-in-case. An SCP that is scheduled when the server is<a name="line.1693"></a>
-<span class="sourceLineNo">1694</span> // 'Unknown' probably originated externally with HBCK2 fix-it tool.<a name="line.1694"></a>
-<span class="sourceLineNo">1695</span> ServerState oldState = null;<a name="line.1695"></a>
-<span class="sourceLineNo">1696</span> if (serverNode != null) {<a name="line.1696"></a>
-<span class="sourceLineNo">1697</span> oldState = serverNode.getState();<a name="line.1697"></a>
-<span class="sourceLineNo">1698</span> serverNode.setState(ServerState.CRASHED);<a name="line.1698"></a>
-<span class="sourceLineNo">1699</span> }<a name="line.1699"></a>
-<span class="sourceLineNo">1700</span><a name="line.1700"></a>
-<span class="sourceLineNo">1701</span> if (force) {<a name="line.1701"></a>
-<span class="sourceLineNo">1702</span> pid = procExec.submitProcedure(<a name="line.1702"></a>
-<span class="sourceLineNo">1703</span> new HBCKServerCrashProcedure(mpe, serverName, shouldSplitWal, carryingMeta));<a name="line.1703"></a>
-<span class="sourceLineNo">1704</span> } else {<a name="line.1704"></a>
-<span class="sourceLineNo">1705</span> pid = procExec.submitProcedure(<a name="line.1705"></a>
-<span class="sourceLineNo">1706</span> new ServerCrashProcedure(mpe, serverName, shouldSplitWal, carryingMeta));<a name="line.1706"></a>
-<span class="sourceLineNo">1707</span> }<a name="line.1707"></a>
-<span class="sourceLineNo">1708</span> LOG.info("Scheduled ServerCrashProcedure pid={} for {} (carryingMeta={}){}.",<a name="line.1708"></a>
-<span class="sourceLineNo">1709</span> pid, serverName, carryingMeta,<a name="line.1709"></a>
-<span class="sourceLineNo">1710</span> serverNode == null? "": " " + serverNode.toString() + ", oldState=" + oldState);<a name="line.1710"></a>
-<span class="sourceLineNo">1711</span> }<a name="line.1711"></a>
-<span class="sourceLineNo">1712</span> } finally {<a name="line.1712"></a>
-<span class="sourceLineNo">1713</span> if (serverNode != null) {<a name="line.1713"></a>
-<span class="sourceLineNo">1714</span> serverNode.writeLock().unlock();<a name="line.1714"></a>
-<span class="sourceLineNo">1715</span> }<a name="line.1715"></a>
-<span class="sourceLineNo">1716</span> }<a name="line.1716"></a>
-<span class="sourceLineNo">1717</span> return pid;<a name="line.1717"></a>
-<span class="sourceLineNo">1718</span> }<a name="line.1718"></a>
-<span class="sourceLineNo">1719</span><a name="line.1719"></a>
-<span class="sourceLineNo">1720</span> public void offlineRegion(final RegionInfo regionInfo) {<a name="line.1720"></a>
-<span class="sourceLineNo">1721</span> // TODO used by MasterRpcServices<a name="line.1721"></a>
-<span class="sourceLineNo">1722</span> RegionStateNode node = regionStates.getRegionStateNode(regionInfo);<a name="line.1722"></a>
-<span class="sourceLineNo">1723</span> if (node != null) {<a name="line.1723"></a>
-<span class="sourceLineNo">1724</span> node.offline();<a name="line.1724"></a>
-<span class="sourceLineNo">1725</span> }<a name="line.1725"></a>
-<span class="sourceLineNo">1726</span> }<a name="line.1726"></a>
-<span class="sourceLineNo">1727</span><a name="line.1727"></a>
-<span class="sourceLineNo">1728</span> public void onlineRegion(final RegionInfo regionInfo, final ServerName serverName) {<a name="line.1728"></a>
-<span class="sourceLineNo">1729</span> // TODO used by TestSplitTransactionOnCluster.java<a name="line.1729"></a>
-<span class="sourceLineNo">1730</span> }<a name="line.1730"></a>
-<span class="sourceLineNo">1731</span><a name="line.1731"></a>
-<span class="sourceLineNo">1732</span> public Map<ServerName, List<RegionInfo>> getSnapShotOfAssignment(<a name="line.1732"></a>
-<span class="sourceLineNo">1733</span> final Collection<RegionInfo> regions) {<a name="line.1733"></a>
-<span class="sourceLineNo">1734</span> return regionStates.getSnapShotOfAssignment(regions);<a name="line.1734"></a>
-<span class="sourceLineNo">1735</span> }<a name="line.1735"></a>
-<span class="sourceLineNo">1736</span><a name="line.1736"></a>
-<span class="sourceLineNo">1737</span> // ============================================================================================<a name="line.1737"></a>
-<span class="sourceLineNo">1738</span> // TODO: UTILS/HELPERS?<a name="line.1738"></a>
-<span class="sourceLineNo">1739</span> // ============================================================================================<a name="line.1739"></a>
-<span class="sourceLineNo">1740</span> /**<a name="line.1740"></a>
-<span class="sourceLineNo">1741</span> * Used by the client (via master) to identify if all regions have the schema updates<a name="line.1741"></a>
-<span class="sourceLineNo">1742</span> * @return Pair indicating the status of the alter command (pending/total)<a name="line.1742"></a>
-<span class="sourceLineNo">1743</span> */<a name="line.1743"></a>
-<span class="sourceLineNo">1744</span> public Pair<Integer, Integer> getReopenStatus(TableName tableName) {<a name="line.1744"></a>
-<span class="sourceLineNo">1745</span> if (isTableDisabled(tableName)) {<a name="line.1745"></a>
-<span class="sourceLineNo">1746</span> return new Pair<Integer, Integer>(0, 0);<a name="line.1746"></a>
-<span class="sourceLineNo">1747</span> }<a name="line.1747"></a>
-<span class="sourceLineNo">1748</span><a name="line.1748"></a>
-<span class="sourceLineNo">1749</span> final List<RegionState> states = regionStates.getTableRegionStates(tableName);<a name="line.1749"></a>
-<span class="sourceLineNo">1750</span> int ritCount = 0;<a name="line.1750"></a>
-<span class="sourceLineNo">1751</span> for (RegionState regionState: states) {<a name="line.1751"></a>
-<span class="sourceLineNo">1752</span> if (!regionState.isOpened() && !regionState.isSplit()) {<a name="line.1752"></a>
-<span class="sourceLineNo">1753</span> ritCount++;<a name="line.1753"></a>
-<span class="sourceLineNo">1754</span> }<a name="line.1754"></a>
-<span class="sourceLineNo">1755</span> }<a name="line.1755"></a>
-<span class="sourceLineNo">1756</span> return new Pair<Integer, Integer>(ritCount, states.size());<a name="line.1756"></a>
-<span class="sourceLineNo">1757</span> }<a name="line.1757"></a>
-<span class="sourceLineNo">1758</span><a name="line.1758"></a>
-<span class="sourceLineNo">1759</span> // ============================================================================================<a name="line.1759"></a>
-<span class="sourceLineNo">1760</span> // TODO: Region State In Transition<a name="line.1760"></a>
-<span class="sourceLineNo">1761</span> // ============================================================================================<a name="line.1761"></a>
-<span class="sourceLineNo">1762</span> public boolean hasRegionsInTransition() {<a name="line.1762"></a>
-<span class="sourceLineNo">1763</span> return regionStates.hasRegionsInTransition();<a name="line.1763"></a>
-<span class="sourceLineNo">1764</span> }<a name="line.1764"></a>
-<span class="sourceLineNo">1765</span><a name="line.1765"></a>
-<span class="sourceLineNo">1766</span> public List<RegionStateNode> getRegionsInTransition() {<a name="line.1766"></a>
-<span class="sourceLineNo">1767</span> return regionStates.getRegionsInTransition();<a name="line.1767"></a>
-<span class="sourceLineNo">1768</span> }<a name="line.1768"></a>
-<span class="sourceLineNo">1769</span><a name="line.1769"></a>
-<span class="sourceLineNo">1770</span> public List<RegionInfo> getAssignedRegions() {<a name="line.1770"></a>
-<span class="sourceLineNo">1771</span> return regionStates.getAssignedRegions();<a name="line.1771"></a>
-<span class="sourceLineNo">1772</span> }<a name="line.1772"></a>
-<span class="sourceLineNo">1773</span><a name="line.1773"></a>
-<span class="sourceLineNo">1774</span> public RegionInfo getRegionInfo(final byte[] regionName) {<a name="line.1774"></a>
-<span class="sourceLineNo">1775</span> final RegionStateNode regionState = regionStates.getRegionStateNodeFromName(regionName);<a name="line.1775"></a>
-<span class="sourceLineNo">1776</span> return regionState != null ? regionState.getRegionInfo() : null;<a name="line.1776"></a>
-<span class="sourceLineNo">1777</span> }<a name="line.1777"></a>
-<span class="sourceLineNo">1778</span><a name="line.1778"></a>
-<span class="sourceLineNo">1779</span> // ============================================================================================<a name="line.1779"></a>
-<span class="sourceLineNo">1780</span> // Expected states on region state transition.<a name="line.1780"></a>
-<span class="sourceLineNo">1781</span> // Notice that there is expected states for transiting to OPENING state, this is because SCP.<a name="line.1781"></a>
-<span class="sourceLineNo">1782</span> // See the comments in regionOpening method for more details.<a name="line.1782"></a>
-<span class="sourceLineNo">1783</span> // ============================================================================================<a name="line.1783"></a>
-<span class="sourceLineNo">1784</span> private static final State[] STATES_EXPECTED_ON_OPEN = {<a name="line.1784"></a>
-<span class="sourceLineNo">1785</span> State.OPENING, // Normal case<a name="line.1785"></a>
-<span class="sourceLineNo">1786</span> State.OPEN // Retrying<a name="line.1786"></a>
-<span class="sourceLineNo">1787</span> };<a name="line.1787"></a>
-<span class="sourceLineNo">1788</span><a name="line.1788"></a>
-<span class="sourceLineNo">1789</span> private static final State[] STATES_EXPECTED_ON_CLOSING = {<a name="line.1789"></a>
-<span class="sourceLineNo">1790</span> State.OPEN, // Normal case<a name="line.1790"></a>
-<span class="sourceLineNo">1791</span> State.CLOSING, // Retrying<a name="line.1791"></a>
-<span class="sourceLineNo">1792</span> State.SPLITTING, // Offline the split parent<a name="line.1792"></a>
-<span class="sourceLineNo">1793</span> State.MERGING // Offline the merge parents<a name="line.1793"></a>
-<span class="sourceLineNo">1794</span> };<a name="line.1794"></a>
-<span class="sourceLineNo">1795</span><a name="line.1795"></a>
-<span class="sourceLineNo">1796</span> private static final State[] STATES_EXPECTED_ON_CLOSED = {<a name="line.1796"></a>
-<span class="sourceLineNo">1797</span> State.CLOSING, // Normal case<a name="line.1797"></a>
-<span class="sourceLineNo">1798</span> State.CLOSED // Retrying<a name="line.1798"></a>
-<span class="sourceLineNo">1799</span> };<a name="line.1799"></a>
-<span class="sourceLineNo">1800</span><a name="line.1800"></a>
-<span class="sourceLineNo">1801</span> // This is for manually scheduled region assign, can add other states later if we find out other<a name="line.1801"></a>
-<span class="sourceLineNo">1802</span> // usages<a name="line.1802"></a>
-<span class="sourceLineNo">1803</span> private static final State[] STATES_EXPECTED_ON_ASSIGN = { State.CLOSED, State.OFFLINE };<a name="line.1803"></a>
+<span class="sourceLineNo">1512</span> // Scan hbase:meta to build list of existing regions, servers, and assignment.<a name="line.1512"></a>
+<span class="sourceLineNo">1513</span> // hbase:meta is online now or will be. Inside loadMeta, we keep trying. Can't make progress<a name="line.1513"></a>
+<span class="sourceLineNo">1514</span> // w/o meta.<a name="line.1514"></a>
+<span class="sourceLineNo">1515</span> loadMeta();<a name="line.1515"></a>
+<span class="sourceLineNo">1516</span><a name="line.1516"></a>
+<span class="sourceLineNo">1517</span> while (master.getServerManager().countOfRegionServers() < 1) {<a name="line.1517"></a>
+<span class="sourceLineNo">1518</span> LOG.info("Waiting for RegionServers to join; current count={}",<a name="line.1518"></a>
+<span class="sourceLineNo">1519</span> master.getServerManager().countOfRegionServers());<a name="line.1519"></a>
+<span class="sourceLineNo">1520</span> Threads.sleep(250);<a name="line.1520"></a>
+<span class="sourceLineNo">1521</span> }<a name="line.1521"></a>
+<span class="sourceLineNo">1522</span> LOG.info("Number of RegionServers={}", master.getServerManager().countOfRegionServers());<a name="line.1522"></a>
+<span class="sourceLineNo">1523</span><a name="line.1523"></a>
+<span class="sourceLineNo">1524</span> // Start the chores<a name="line.1524"></a>
+<span class="sourceLineNo">1525</span> master.getMasterProcedureExecutor().addChore(this.ritChore);<a name="line.1525"></a>
+<span class="sourceLineNo">1526</span> master.getMasterProcedureExecutor().addChore(this.deadMetricChore);<a name="line.1526"></a>
+<span class="sourceLineNo">1527</span><a name="line.1527"></a>
+<span class="sourceLineNo">1528</span> long costMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);<a name="line.1528"></a>
+<span class="sourceLineNo">1529</span> LOG.info("Joined the cluster in {}", StringUtils.humanTimeDiff(costMs));<a name="line.1529"></a>
+<span class="sourceLineNo">1530</span> }<a name="line.1530"></a>
+<span class="sourceLineNo">1531</span><a name="line.1531"></a>
+<span class="sourceLineNo">1532</span> /**<a name="line.1532"></a>
+<span class="sourceLineNo">1533</span> * Create assign procedure for offline regions.<a name="line.1533"></a>
+<span class="sourceLineNo">1534</span> * Just follow the old processofflineServersWithOnlineRegions method. Since now we do not need to<a name="line.1534"></a>
+<span class="sourceLineNo">1535</span> * deal with dead server any more, we only deal with the regions in OFFLINE state in this method.<a name="line.1535"></a>
+<span class="sourceLineNo">1536</span> * And this is a bit strange, that for new regions, we will add it in CLOSED state instead of<a name="line.1536"></a>
+<span class="sourceLineNo">1537</span> * OFFLINE state, and usually there will be a procedure to track them. The<a name="line.1537"></a>
+<span class="sourceLineNo">1538</span> * processofflineServersWithOnlineRegions is a legacy from long ago, as things are going really<a name="line.1538"></a>
+<span class="sourceLineNo">1539</span> * different now, maybe we do not need this method any more. Need to revisit later.<a name="line.1539"></a>
+<span class="sourceLineNo">1540</span> */<a name="line.1540"></a>
+<span class="sourceLineNo">1541</span> // Public so can be run by the Master as part of the startup. Needs hbase:meta to be online.<a name="line.1541"></a>
+<span class="sourceLineNo">1542</span> // Needs to be done after the table state manager has been started.<a name="line.1542"></a>
+<span class="sourceLineNo">1543</span> public void processOfflineRegions() {<a name="line.1543"></a>
+<span class="sourceLineNo">1544</span> TransitRegionStateProcedure[] procs =<a name="line.1544"></a>
+<span class="sourceLineNo">1545</span> regionStates.getRegionStateNodes().stream().filter(rsn -> rsn.isInState(State.OFFLINE))<a name="line.1545"></a>
+<span class="sourceLineNo">1546</span> .filter(rsn -> isTableEnabled(rsn.getRegionInfo().getTable())).map(rsn -> {<a name="line.1546"></a>
+<span class="sourceLineNo">1547</span> rsn.lock();<a name="line.1547"></a>
+<span class="sourceLineNo">1548</span> try {<a name="line.1548"></a>
+<span class="sourceLineNo">1549</span> if (rsn.getProcedure() != null) {<a name="line.1549"></a>
+<span class="sourceLineNo">1550</span> return null;<a name="line.1550"></a>
+<span class="sourceLineNo">1551</span> } else {<a name="line.1551"></a>
+<span class="sourceLineNo">1552</span> return rsn.setProcedure(TransitRegionStateProcedure.assign(getProcedureEnvironment(),<a name="line.1552"></a>
+<span class="sourceLineNo">1553</span> rsn.getRegionInfo(), null));<a name="line.1553"></a>
+<span class="sourceLineNo">1554</span> }<a name="line.1554"></a>
+<span class="sourceLineNo">1555</span> } finally {<a name="line.1555"></a>
+<span class="sourceLineNo">1556</span> rsn.unlock();<a name="line.1556"></a>
+<span class="sourceLineNo">1557</span> }<a name="line.1557"></a>
+<span class="sourceLineNo">1558</span> }).filter(p -> p != null).toArray(TransitRegionStateProcedure[]::new);<a name="line.1558"></a>
+<span class="sourceLineNo">1559</span> if (procs.length > 0) {<a name="line.1559"></a>
+<span class="sourceLineNo">1560</span> master.getMasterProcedureExecutor().submitProcedures(procs);<a name="line.1560"></a>
+<span class="sourceLineNo">1561</span> }<a name="line.1561"></a>
+<span class="sourceLineNo">1562</span> }<a name="line.1562"></a>
+<span class="sourceLineNo">1563</span><a name="line.1563"></a>
+<span class="sourceLineNo">1564</span> /* AM internal RegionStateStore.RegionStateVisitor implementation. To be used when<a name="line.1564"></a>
+<span class="sourceLineNo">1565</span> * scanning META table for region rows, using RegionStateStore utility methods. RegionStateStore<a name="line.1565"></a>
+<span class="sourceLineNo">1566</span> * methods will convert Result into proper RegionInfo instances, but those would still need to be<a name="line.1566"></a>
+<span class="sourceLineNo">1567</span> * added into AssignmentManager.regionStates in-memory cache.<a name="line.1567"></a>
+<span class="sourceLineNo">1568</span> * RegionMetaLoadingVisitor.visitRegionState method provides the logic for adding RegionInfo<a name="line.1568"></a>
+<span class="sourceLineNo">1569</span> * instances as loaded from latest META scan into AssignmentManager.regionStates.<a name="line.1569"></a>
+<span class="sourceLineNo">1570</span> */<a name="line.1570"></a>
+<span class="sourceLineNo">1571</span> private class RegionMetaLoadingVisitor implements RegionStateStore.RegionStateVisitor {<a name="line.1571"></a>
+<span class="sourceLineNo">1572</span><a name="line.1572"></a>
+<span class="sourceLineNo">1573</span> @Override<a name="line.1573"></a>
+<span class="sourceLineNo">1574</span> public void visitRegionState(Result result, final RegionInfo regionInfo, final State state,<a name="line.1574"></a>
+<span class="sourceLineNo">1575</span> final ServerName regionLocation, final ServerName lastHost, final long openSeqNum) {<a name="line.1575"></a>
+<span class="sourceLineNo">1576</span> if (state == null && regionLocation == null && lastHost == null &&<a name="line.1576"></a>
+<span class="sourceLineNo">1577</span> openSeqNum == SequenceId.NO_SEQUENCE_ID) {<a name="line.1577"></a>
+<span class="sourceLineNo">1578</span> // This is a row with nothing in it.<a name="line.1578"></a>
+<span class="sourceLineNo">1579</span> LOG.warn("Skipping empty row={}", result);<a name="line.1579"></a>
+<span class="sourceLineNo">1580</span> return;<a name="line.1580"></a>
+<span class="sourceLineNo">1581</span> }<a name="line.1581"></a>
+<span class="sourceLineNo">1582</span> State localState = state;<a name="line.1582"></a>
+<span class="sourceLineNo">1583</span> if (localState == null) {<a name="line.1583"></a>
+<span class="sourceLineNo">1584</span> // No region state column data in hbase:meta table! Are I doing a rolling upgrade from<a name="line.1584"></a>
+<span class="sourceLineNo">1585</span> // hbase1 to hbase2? Am I restoring a SNAPSHOT or otherwise adding a region to hbase:meta?<a name="line.1585"></a>
+<span class="sourceLineNo">1586</span> // In any of these cases, state is empty. For now, presume OFFLINE but there are probably<a name="line.1586"></a>
+<span class="sourceLineNo">1587</span> // cases where we need to probe more to be sure this correct; TODO informed by experience.<a name="line.1587"></a>
+<span class="sourceLineNo">1588</span> LOG.info(regionInfo.getEncodedName() + " regionState=null; presuming " + State.OFFLINE);<a name="line.1588"></a>
+<span class="sourceLineNo">1589</span> localState = State.OFFLINE;<a name="line.1589"></a>
+<span class="sourceLineNo">1590</span> }<a name="line.1590"></a>
+<span class="sourceLineNo">1591</span> RegionStateNode regionNode = regionStates.getOrCreateRegionStateNode(regionInfo);<a name="line.1591"></a>
+<span class="sourceLineNo">1592</span> // Do not need to lock on regionNode, as we can make sure that before we finish loading<a name="line.1592"></a>
+<span class="sourceLineNo">1593</span> // meta, all the related procedures can not be executed. The only exception is for meta<a name="line.1593"></a>
+<span class="sourceLineNo">1594</span> // region related operations, but here we do not load the informations for meta region.<a name="line.1594"></a>
+<span class="sourceLineNo">1595</span> regionNode.setState(localState);<a name="line.1595"></a>
+<span class="sourceLineNo">1596</span> regionNode.setLastHost(lastHost);<a name="line.1596"></a>
+<span class="sourceLineNo">1597</span> regionNode.setRegionLocation(regionLocation);<a name="line.1597"></a>
+<span class="sourceLineNo">1598</span> regionNode.setOpenSeqNum(openSeqNum);<a name="line.1598"></a>
+<span class="sourceLineNo">1599</span><a name="line.1599"></a>
+<span class="sourceLineNo">1600</span> // Note: keep consistent with other methods, see region(Opening|Opened|Closing)<a name="line.1600"></a>
+<span class="sourceLineNo">1601</span> // RIT/ServerCrash handling should take care of the transiting regions.<a name="line.1601"></a>
+<span class="sourceLineNo">1602</span> if (localState.matches(State.OPEN, State.OPENING, State.CLOSING, State.SPLITTING,<a name="line.1602"></a>
+<span class="sourceLineNo">1603</span> State.MERGING)) {<a name="line.1603"></a>
+<span class="sourceLineNo">1604</span> assert regionLocation != null : "found null region location for " + regionNode;<a name="line.1604"></a>
+<span class="sourceLineNo">1605</span> regionStates.addRegionToServer(regionNode);<a name="line.1605"></a>
+<span class="sourceLineNo">1606</span> } else if (localState == State.OFFLINE || regionInfo.isOffline()) {<a name="line.1606"></a>
+<span class="sourceLineNo">1607</span> regionStates.addToOfflineRegions(regionNode);<a name="line.1607"></a>
+<span class="sourceLineNo">1608</span> }<a name="line.1608"></a>
+<span class="sourceLineNo">1609</span> if (regionNode.getProcedure() != null) {<a name="line.1609"></a>
+<span class="sourceLineNo">1610</span> regionNode.getProcedure().stateLoaded(AssignmentManager.this, regionNode);<a name="line.1610"></a>
+<span class="sourceLineNo">1611</span> }<a name="line.1611"></a>
+<span class="sourceLineNo">1612</span> }<a name="line.1612"></a>
+<span class="sourceLineNo">1613</span> };<a name="line.1613"></a>
+<span class="sourceLineNo">1614</span><a name="line.1614"></a>
+<span class="sourceLineNo">1615</span> /**<a name="line.1615"></a>
+<span class="sourceLineNo">1616</span> * Query META if the given <code>RegionInfo</code> exists, adding to<a name="line.1616"></a>
+<span class="sourceLineNo">1617</span> * <code>AssignmentManager.regionStateStore</code> cache if the region is found in META.<a name="line.1617"></a>
+<span class="sourceLineNo">1618</span> * @param regionEncodedName encoded name for the region to be loaded from META into<a name="line.1618"></a>
+<span class="sourceLineNo">1619</span> * <code>AssignmentManager.regionStateStore</code> cache<a name="line.1619"></a>
+<span class="sourceLineNo">1620</span> * @return <code>RegionInfo</code> instance for the given region if it is present in META<a name="line.1620"></a>
+<span class="sourceLineNo">1621</span> * and got successfully loaded into <code>AssignmentManager.regionStateStore</code><a name="line.1621"></a>
+<span class="sourceLineNo">1622</span> * cache, <b>null</b> otherwise.<a name="line.1622"></a>
+<span class="sourceLineNo">1623</span> * @throws UnknownRegionException if any errors occur while querying meta.<a name="line.1623"></a>
+<span class="sourceLineNo">1624</span> */<a name="line.1624"></a>
+<span class="sourceLineNo">1625</span> public RegionInfo loadRegionFromMeta(String regionEncodedName) throws UnknownRegionException {<a name="line.1625"></a>
+<span class="sourceLineNo">1626</span> try {<a name="line.1626"></a>
+<span class="sourceLineNo">1627</span> RegionMetaLoadingVisitor visitor = new RegionMetaLoadingVisitor();<a name="line.1627"></a>
+<span class="sourceLineNo">1628</span> regionStateStore.visitMetaForRegion(regionEncodedName, visitor);<a name="line.1628"></a>
+<span class="sourceLineNo">1629</span> return regionStates.getRegionState(regionEncodedName) == null ? null :<a name="line.1629"></a>
+<span class="sourceLineNo">1630</span> regionStates.getRegionState(regionEncodedName).getRegion();<a name="line.1630"></a>
+<span class="sourceLineNo">1631</span> } catch(IOException e) {<a name="line.1631"></a>
+<span class="sourceLineNo">1632</span> LOG.error("Error trying to load region {} from META", regionEncodedName, e);<a name="line.1632"></a>
+<span class="sourceLineNo">1633</span> throw new UnknownRegionException("Error while trying load region from meta");<a name="line.1633"></a>
+<span class="sourceLineNo">1634</span> }<a name="line.1634"></a>
+<span class="sourceLineNo">1635</span> }<a name="line.1635"></a>
+<span class="sourceLineNo">1636</span><a name="line.1636"></a>
+<span class="sourceLineNo">1637</span> private void loadMeta() throws IOException {<a name="line.1637"></a>
+<span class="sourceLineNo">1638</span> // TODO: use a thread pool<a name="line.1638"></a>
+<span class="sourceLineNo">1639</span> regionStateStore.visitMeta(new RegionMetaLoadingVisitor());<a name="line.1639"></a>
+<span class="sourceLineNo">1640</span> }<a name="line.1640"></a>
+<span class="sourceLineNo">1641</span><a name="line.1641"></a>
+<span class="sourceLineNo">1642</span> /**<a name="line.1642"></a>
+<span class="sourceLineNo">1643</span> * Used to check if the meta loading is done.<a name="line.1643"></a>
+<span class="sourceLineNo">1644</span> * <p/><a name="line.1644"></a>
+<span class="sourceLineNo">1645</span> * if not we throw PleaseHoldException since we are rebuilding the RegionStates<a name="line.1645"></a>
+<span class="sourceLineNo">1646</span> * @param hri region to check if it is already rebuild<a name="line.1646"></a>
+<span class="sourceLineNo">1647</span> * @throws PleaseHoldException if meta has not been loaded yet<a name="line.1647"></a>
+<span class="sourceLineNo">1648</span> */<a name="line.1648"></a>
+<span class="sourceLineNo">1649</span> private void checkMetaLoaded(RegionInfo hri) throws PleaseHoldException {<a name="line.1649"></a>
+<span class="sourceLineNo">1650</span> if (!isRunning()) {<a name="line.1650"></a>
+<span class="sourceLineNo">1651</span> throw new PleaseHoldException("AssignmentManager not running");<a name="line.1651"></a>
+<span class="sourceLineNo">1652</span> }<a name="line.1652"></a>
+<span class="sourceLineNo">1653</span> boolean meta = isMetaRegion(hri);<a name="line.1653"></a>
+<span class="sourceLineNo">1654</span> boolean metaLoaded = isMetaLoaded();<a name="line.1654"></a>
+<span class="sourceLineNo">1655</span> if (!meta && !metaLoaded) {<a name="line.1655"></a>
+<span class="sourceLineNo">1656</span> throw new PleaseHoldException(<a name="line.1656"></a>
+<span class="sourceLineNo">1657</span> "Master not fully online; hbase:meta=" + meta + ", metaLoaded=" + metaLoaded);<a name="line.1657"></a>
+<span class="sourceLineNo">1658</span> }<a name="line.1658"></a>
+<span class="sourceLineNo">1659</span> }<a name="line.1659"></a>
+<span class="sourceLineNo">1660</span><a name="line.1660"></a>
+<span class="sourceLineNo">1661</span> // ============================================================================================<a name="line.1661"></a>
+<span class="sourceLineNo">1662</span> // TODO: Metrics<a name="line.1662"></a>
+<span class="sourceLineNo">1663</span> // ============================================================================================<a name="line.1663"></a>
+<span class="sourceLineNo">1664</span> public int getNumRegionsOpened() {<a name="line.1664"></a>
+<span class="sourceLineNo">1665</span> // TODO: Used by TestRegionPlacement.java and assume monotonically increasing value<a name="line.1665"></a>
+<span class="sourceLineNo">1666</span> return 0;<a name="line.1666"></a>
+<span class="sourceLineNo">1667</span> }<a name="line.1667"></a>
+<span class="sourceLineNo">1668</span><a name="line.1668"></a>
+<span class="sourceLineNo">1669</span> /**<a name="line.1669"></a>
+<span class="sourceLineNo">1670</span> * Usually run by the Master in reaction to server crash during normal processing.<a name="line.1670"></a>
+<span class="sourceLineNo">1671</span> * Can also be invoked via external RPC to effect repair; in the latter case,<a name="line.1671"></a>
+<span class="sourceLineNo">1672</span> * the 'force' flag is set so we push through the SCP though context may indicate<a name="line.1672"></a>
+<span class="sourceLineNo">1673</span> * already-running-SCP (An old SCP may have exited abnormally, or damaged cluster<a name="line.1673"></a>
+<span class="sourceLineNo">1674</span> * may still have references in hbase:meta to 'Unknown Servers' -- servers that<a name="line.1674"></a>
+<span class="sourceLineNo">1675</span> * are not online or in dead servers list, etc.)<a name="line.1675"></a>
+<span class="sourceLineNo">1676</span> * @param force Set if the request came in externally over RPC (via hbck2). Force means<a name="line.1676"></a>
+<span class="sourceLineNo">1677</span> * run the SCP even if it seems as though there might be an outstanding<a name="line.1677"></a>
+<span class="sourceLineNo">1678</span> * SCP running.<a name="line.1678"></a>
+<span class="sourceLineNo">1679</span> * @return pid of scheduled SCP or {@link Procedure#NO_PROC_ID} if none scheduled.<a name="line.1679"></a>
+<span class="sourceLineNo">1680</span> */<a name="line.1680"></a>
+<span class="sourceLineNo">1681</span> public long submitServerCrash(ServerName serverName, boolean shouldSplitWal, boolean force) {<a name="line.1681"></a>
+<span class="sourceLineNo">1682</span> // May be an 'Unknown Server' so handle case where serverNode is null.<a name="line.1682"></a>
+<span class="sourceLineNo">1683</span> ServerStateNode serverNode = regionStates.getServerNode(serverName);<a name="line.1683"></a>
+<span class="sourceLineNo">1684</span> // Remove the in-memory rsReports result<a name="line.1684"></a>
+<span class="sourceLineNo">1685</span> synchronized (rsReports) {<a name="line.1685"></a>
+<span class="sourceLineNo">1686</span> rsReports.remove(serverName);<a name="line.1686"></a>
+<span class="sourceLineNo">1687</span> }<a name="line.1687"></a>
+<span class="sourceLineNo">1688</span><a name="line.1688"></a>
+<span class="sourceLineNo">1689</span> // We hold the write lock here for fencing on reportRegionStateTransition. Once we set the<a name="line.1689"></a>
+<span class="sourceLineNo">1690</span> // server state to CRASHED, we will no longer accept the reportRegionStateTransition call from<a name="line.1690"></a>
+<span class="sourceLineNo">1691</span> // this server. This is used to simplify the implementation for TRSP and SCP, where we can make<a name="line.1691"></a>
+<span class="sourceLineNo">1692</span> // sure that, the region list fetched by SCP will not be changed any more.<a name="line.1692"></a>
+<span class="sourceLineNo">1693</span> if (serverNode != null) {<a name="line.1693"></a>
+<span class="sourceLineNo">1694</span> serverNode.writeLock().lock();<a name="line.1694"></a>
+<span class="sourceLineNo">1695</span> }<a name="line.1695"></a>
+<span class="sourceLineNo">1696</span> boolean carryingMeta;<a name="line.1696"></a>
+<span class="sourceLineNo">1697</span> long pid;<a name="line.1697"></a>
+<span class="sourceLineNo">1698</span> try {<a name="line.1698"></a>
+<span class="sourceLineNo">1699</span> ProcedureExecutor<MasterProcedureEnv> procExec = this.master.getMasterProcedureExecutor();<a name="line.1699"></a>
+<span class="sourceLineNo">1700</span> carryingMeta = isCarryingMeta(serverName);<a name="line.1700"></a>
+<span class="sourceLineNo">1701</span> if (!force && serverNode != null && !serverNode.isInState(ServerState.ONLINE)) {<a name="line.1701"></a>
+<span class="sourceLineNo">1702</span> LOG.info("Skip adding ServerCrashProcedure for {} (meta={}) -- running?",<a name="line.1702"></a>
+<span class="sourceLineNo">1703</span> serverNode, carryingMeta);<a name="line.1703"></a>
+<span class="sourceLineNo">1704</span> return Procedure.NO_PROC_ID;<a name="line.1704"></a>
+<span class="sourceLineNo">1705</span> } else {<a name="line.1705"></a>
+<span class="sourceLineNo">1706</span> MasterProcedureEnv mpe = procExec.getEnvironment();<a name="line.1706"></a>
+<span class="sourceLineNo">1707</span> // If serverNode == null, then 'Unknown Server'. Schedule HBCKSCP instead.<a name="line.1707"></a>
+<span class="sourceLineNo">1708</span> // HBCKSCP scours Master in-memory state AND hbase;meta for references to<a name="line.1708"></a>
+<span class="sourceLineNo">1709</span> // serverName just-in-case. An SCP that is scheduled when the server is<a name="line.1709"></a>
+<span class="sourceLineNo">1710</span> // 'Unknown' probably originated externally with HBCK2 fix-it tool.<a name="line.1710"></a>
+<span class="sourceLineNo">1711</span> ServerState oldState = null;<a name="line.1711"></a>
+<span class="sourceLineNo">1712</span> if (serverNode != null) {<a name="line.1712"></a>
+<span class="sourceLineNo">1713</span> oldState = serverNode.getState();<a name="line.1713"></a>
+<span class="sourceLineNo">1714</span> serverNode.setState(ServerState.CRASHED);<a name="line.1714"></a>
+<span class="sourceLineNo">1715</span> }<a name="line.1715"></a>
+<span class="sourceLineNo">1716</span><a name="line.1716"></a>
+<span class="sourceLineNo">1717</span> if (force) {<a name="line.1717"></a>
+<span class="sourceLineNo">1718</span> pid = procExec.submitProcedure(<a name="line.1718"></a>
+<span class="sourceLineNo">1719</span> new HBCKServerCrashProcedure(mpe, serverName, shouldSplitWal, carryingMeta));<a name="line.1719"></a>
+<span class="sourceLineNo">1720</span> } else {<a name="line.1720"></a>
+<span class="sourceLineNo">1721</span> pid = procExec.submitProcedure(<a name="line.1721"></a>
+<span class="sourceLineNo">1722</span> new ServerCrashProcedure(mpe, serverName, shouldSplitWal, carryingMeta));<a name="line.1722"></a>
+<span class="sourceLineNo">1723</span> }<a name="line.1723"></a>
+<span class="sourceLineNo">1724</span> LOG.info("Scheduled ServerCrashProcedure pid={} for {} (carryingMeta={}){}.",<a name="line.1724"></a>
+<span class="sourceLineNo">1725</span> pid, serverName, carryingMeta,<a name="line.1725"></a>
+<span class="sourceLineNo">1726</span> serverNode == null? "": " " + serverNode.toString() + ", oldState=" + oldState);<a name="line.1726"></a>
+<span class="sourceLineNo">1727</span> }<a name="line.1727"></a>
+<span class="sourceLineNo">1728</span> } finally {<a name="line.1728"></a>
+<span class="sourceLineNo">1729</span> if (serverNode != null) {<a name="line.1729"></a>
+<span class="sourceLineNo">1730</span> serverNode.writeLock().unlock();<a name="line.1730"></a>
+<span class="sourceLineNo">1731</span> }<a name="line.1731"></a>
+<span class="sourceLineNo">1732</span> }<a name="line.1732"></a>
+<span class="sourceLineNo">1733</span> return pid;<a name="line.1733"></a>
+<span class="sourceLineNo">1734</span> }<a name="line.1734"></a>
+<span class="sourceLineNo">1735</span><a name="line.1735"></a>
+<span class="sourceLineNo">1736</span> public void offlineRegion(final RegionInfo regionInfo) {<a name="line.1736"></a>
+<span class="sourceLineNo">1737</span> // TODO used by MasterRpcServices<a name="line.1737"></a>
+<span class="sourceLineNo">1738</span> RegionStateNode node = regionStates.getRegionStateNode(regionInfo);<a name="line.1738"></a>
+<span class="sourceLineNo">1739</span> if (node != null) {<a name="line.1739"></a>
+<span class="sourceLineNo">1740</span> node.offline();<a name="line.1740"></a>
+<span class="sourceLineNo">1741</span> }<a name="line.1741"></a>
+<span class="sourceLineNo">1742</span> }<a name="line.1742"></a>
+<span class="sourceLineNo">1743</span><a name="line.1743"></a>
+<span class="sourceLineNo">1744</span> public void onlineRegion(final RegionInfo regionInfo, final ServerName serverName) {<a name="line.1744"></a>
+<span class="sourceLineNo">1745</span> // TODO used by TestSplitTransactionOnCluster.java<a name="line.1745"></a>
+<span class="sourceLineNo">1746</span> }<a name="line.1746"></a>
+<span class="sourceLineNo">1747</span><a name="line.1747"></a>
+<span class="sourceLineNo">1748</span> public Map<ServerName, List<RegionInfo>> getSnapShotOfAssignment(<a name="line.1748"></a>
+<span class="sourceLineNo">1749</span> final Collection<RegionInfo> regions) {<a name="line.1749"></a>
+<span class="sourceLineNo">1750</span> return regionStates.getSnapShotOfAssignment(regions);<a name="line.1750"></a>
+<span class="sourceLineNo">1751</span> }<a name="line.1751"></a>
+<span class="sourceLineNo">1752</span><a name="line.1752"></a>
+<span class="sourceLineNo">1753</span> // ============================================================================================<a name="line.1753"></a>
+<span class="sourceLineNo">1754</span> // TODO: UTILS/HELPERS?<a name="line.1754"></a>
+<span class="sourceLineNo">1755</span> // ============================================================================================<a name="line.1755"></a>
+<span class="sourceLineNo">1756</span> /**<a name="line.1756"></a>
+<span class="sourceLineNo">1757</span> * Used by the client (via master) to identify if all regions have the schema updates<a name="line.1757"></a>
+<span class="sourceLineNo">1758</span> * @return Pair indicating the status of the alter command (pending/total)<a name="line.1758"></a>
+<span class="sourceLineNo">1759</span> */<a name="line.1759"></a>
+<span class="sourceLineNo">1760</span> public Pair<Integer, Integer> getReopenStatus(TableName tableName) {<a name="line.1760"></a>
+<span class="sourceLineNo">1761</span> if (isTableDisabled(tableName)) {<a name="line.1761"></a>
+<span class="sourceLineNo">1762</span> return new Pair<Integer, Integer>(0, 0);<a name="line.1762"></a>
+<span class="sourceLineNo">1763</span> }<a name="line.1763"></a>
+<span class="sourceLineNo">1764</span><a name="line.1764"></a>
+<span class="sourceLineNo">1765</span> final List<RegionState> states = regionStates.getTableRegionStates(tableName);<a name="line.1765"></a>
+<span class="sourceLineNo">1766</span> int ritCount = 0;<a name="line.1766"></a>
+<span class="sourceLineNo">1767</span> for (RegionState regionState: states) {<a name="line.1767"></a>
+<span class="sourceLineNo">1768</span> if (!regionState.isOpened() && !regionState.isSplit()) {<a name="line.1768"></a>
+<span class="sourceLineNo">1769</span> ritCount++;<a name="line.1769"></a>
+<span class="sourceLineNo">1770</span> }<a name="line.1770"></a>
+<span class="sourceLineNo">1771</span> }<a name="line.1771"></a>
+<span class="sourceLineNo">1772</span> return new Pair<Integer, Integer>(ritCount, states.size());<a name="line.1772"></a>
+<span class="sourceLineNo">1773</span> }<a name="line.1773"></a>
+<span class="sourceLineNo">1774</span><a name="line.1774"></a>
+<span class="sourceLineNo">1775</span> // ============================================================================================<a name="line.1775"></a>
+<span class="sourceLineNo">1776</span> // TODO: Region State In Transition<a name="line.1776"></a>
+<span class="sourceLineNo">1777</span> // ============================================================================================<a name="line.1777"></a>
+<span class="sourceLineNo">1778</span> public boolean hasRegionsInTransition() {<a name="line.1778"></a>
+<span class="sourceLineNo">1779</span> return regionStates.hasRegionsInTransition();<a name="line.1779"></a>
+<span class="sourceLineNo">1780</span> }<a name="line.1780"></a>
+<span class="sourceLineNo">1781</span><a name="line.1781"></a>
+<span class="sourceLineNo">1782</span> public List<RegionStateNode> getRegionsInTransition() {<a name="line.1782"></a>
+<span class="sourceLineNo">1783</span> return regionStates.getRegionsInTransition();<a name="line.1783"></a>
+<span class="sourceLineNo">1784</span> }<a name="line.1784"></a>
+<span class="sourceLineNo">1785</span><a name="line.1785"></a>
+<span class="sourceLineNo">1786</span> public List<RegionInfo> getAssignedRegions() {<a name="line.1786"></a>
+<span class="sourceLineNo">1787</span> return regionStates.getAssignedRegions();<a name="line.1787"></a>
+<span class="sourceLineNo">1788</span> }<a name="line.1788"></a>
+<span class="sourceLineNo">1789</span><a name="line.1789"></a>
+<span class="sourceLineNo">1790</span> public RegionInfo getRegionInfo(final byte[] regionName) {<a name="line.1790"></a>
+<span class="sourceLineNo">1791</span> final RegionStateNode regionState = regionStates.getRegionStateNodeFromName(regionName);<a name="line.1791"></a>
+<span class="sourceLineNo">1792</span> return regionState != null ? regionState.getRegionInfo() : null;<a name="line.1792"></a>
+<span class="sourceLineNo">1793</span> }<a name="line.1793"></a>
+<span class="sourceLineNo">1794</span><a name="line.1794"></a>
+<span class="sourceLineNo">1795</span> // ============================================================================================<a name="line.1795"></a>
+<span class="sourceLineNo">1796</span> // Expected states on region state transition.<a name="line.1796"></a>
+<span class="sourceLineNo">1797</span> // Notice that there is expected states for transiting to OPENING state, this is because SCP.<a name="line.1797"></a>
+<span class="sourceLineNo">1798</span> // See the comments in regionOpening method for more details.<a name="line.1798"></a>
+<span class="sourceLineNo">1799</span> // ============================================================================================<a name="line.1799"></a>
+<span class="sourceLineNo">1800</span> private static final State[] STATES_EXPECTED_ON_OPEN = {<a name="line.1800"></a>
+<span class="sourceLineNo">1801</span> State.OPENING, // Normal case<a name="line.1801"></a>
+<span class="sourceLineNo">1802</span> State.OPEN // Retrying<a name="line.1802"></a>
+<span class="sourceLineNo">1803</span> };<a name="line.1803"></a>
<span class="sourceLineNo">1804</span><a name="line.1804"></a>
-<span class="sourceLineNo">1805</span> // We only allow unassign or move a region which is in OPEN state.<a name="line.1805"></a>
-<span class="sourceLineNo">1806</span> private static final State[] STATES_EXPECTED_ON_UNASSIGN_OR_MOVE = { State.OPEN };<a name="line.1806"></a>
-<span class="sourceLineNo">1807</span><a name="line.1807"></a>
-<span class="sourceLineNo">1808</span> // ============================================================================================<a name="line.1808"></a>
-<span class="sourceLineNo">1809</span> // Region Status update<a name="line.1809"></a>
-<span class="sourceLineNo">1810</span> // Should only be called in TransitRegionStateProcedure(and related procedures), as the locking<a name="line.1810"></a>
-<span class="sourceLineNo">1811</span> // and pre-assumptions are very tricky.<a name="line.1811"></a>
-<span class="sourceLineNo">1812</span> // ============================================================================================<a name="line.1812"></a>
-<span class="sourceLineNo">1813</span> private void transitStateAndUpdate(RegionStateNode regionNode, RegionState.State newState,<a name="line.1813"></a>
-<span class="sourceLineNo">1814</span> RegionState.State... expectedStates) throws IOException {<a name="line.1814"></a>
-<span class="sourceLineNo">1815</span> RegionState.State state = regionNode.getState();<a name="line.1815"></a>
-<span class="sourceLineNo">1816</span> regionNode.transitionState(newState, expectedStates);<a name="line.1816"></a>
-<span class="sourceLineNo">1817</span> boolean succ = false;<a name="line.1817"></a>
-<span class="sourceLineNo">1818</span> try {<a name="line.1818"></a>
-<span class="sourceLineNo">1819</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1819"></a>
-<span class="sourceLineNo">1820</span> succ = true;<a name="line.1820"></a>
-<span class="sourceLineNo">1821</span> } finally {<a name="line.1821"></a>
-<span class="sourceLineNo">1822</span> if (!succ) {<a name="line.1822"></a>
-<span class="sourceLineNo">1823</span> // revert<a name="line.1823"></a>
-<span class="sourceLineNo">1824</span> regionNode.setState(state);<a name="line.1824"></a>
-<span class="sourceLineNo">1825</span> }<a name="line.1825"></a>
-<span class="sourceLineNo">1826</span> }<a name="line.1826"></a>
-<span class="sourceLineNo">1827</span> }<a name="line.1827"></a>
-<span class="sourceLineNo">1828</span><a name="line.1828"></a>
-<span class="sourceLineNo">1829</span> // should be called within the synchronized block of RegionStateNode<a name="line.1829"></a>
-<span class="sourceLineNo">1830</span> void regionOpening(RegionStateNode regionNode) throws IOException {<a name="line.1830"></a>
-<span class="sourceLineNo">1831</span> // As in SCP, for performance reason, there is no TRSP attached with this region, we will not<a name="line.1831"></a>
-<span class="sourceLineNo">1832</span> // update the region state, which means that the region could be in any state when we want to<a name="line.1832"></a>
-<span class="sourceLineNo">1833</span> // assign it after a RS crash. So here we do not pass the expectedStates parameter.<a name="line.1833"></a>
-<span class="sourceLineNo">1834</span> transitStateAndUpdate(regionNode, State.OPENING);<a name="line.1834"></a>
-<span class="sourceLineNo">1835</span> regionStates.addRegionToServer(regionNode);<a name="line.1835"></a>
-<span class="sourceLineNo">1836</span> // update the operation count metrics<a name="line.1836"></a>
-<span class="sourceLineNo">1837</span> metrics.incrementOperationCounter();<a name="line.1837"></a>
-<span class="sourceLineNo">1838</span> }<a name="line.1838"></a>
-<span class="sourceLineNo">1839</span><a name="line.1839"></a>
-<span class="sourceLineNo">1840</span> // should be called under the RegionStateNode lock<a name="line.1840"></a>
-<span class="sourceLineNo">1841</span> // The parameter 'giveUp' means whether we will try to open the region again, if it is true, then<a name="line.1841"></a>
-<span class="sourceLineNo">1842</span> // we will persist the FAILED_OPEN state into hbase:meta.<a name="line.1842"></a>
-<span class="sourceLineNo">1843</span> void regionFailedOpen(RegionStateNode regionNode, boolean giveUp) throws IOException {<a name="line.1843"></a>
-<span class="sourceLineNo">1844</span> RegionState.State state = regionNode.getState();<a name="line.1844"></a>
-<span class="sourceLineNo">1845</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1845"></a>
-<span class="sourceLineNo">1846</span> if (giveUp) {<a name="line.1846"></a>
-<span class="sourceLineNo">1847</span> regionNode.setState(State.FAILED_OPEN);<a name="line.1847"></a>
-<span class="sourceLineNo">1848</span> regionNode.setRegionLocation(null);<a name="line.1848"></a>
-<span class="sourceLineNo">1849</span> boolean succ = false;<a name="line.1849"></a>
-<span class="sourceLineNo">1850</span> try {<a name="line.1850"></a>
-<span class="sourceLineNo">1851</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1851"></a>
-<span class="sourceLineNo">1852</span> succ = true;<a name="line.1852"></a>
-<span class="sourceLineNo">1853</span> } finally {<a name="line.1853"></a>
-<span class="sourceLineNo">1854</span> if (!succ) {<a name="line.1854"></a>
-<span class="sourceLineNo">1855</span> // revert<a name="line.1855"></a>
-<span class="sourceLineNo">1856</span> regionNode.setState(state);<a name="line.1856"></a>
-<span class="sourceLineNo">1857</span> regionNode.setRegionLocation(regionLocation);<a name="line.1857"></a>
-<span class="sourceLineNo">1858</span> }<a name="line.1858"></a>
-<span class="sourceLineNo">1859</span> }<a name="line.1859"></a>
-<span class="sourceLineNo">1860</span> }<a name="line.1860"></a>
-<span class="sourceLineNo">1861</span> if (regionLocation != null) {<a name="line.1861"></a>
-<span class="sourceLineNo">1862</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1862"></a>
-<span class="sourceLineNo">1863</span> }<a name="line.1863"></a>
-<span class="sourceLineNo">1864</span> }<a name="line.1864"></a>
-<span class="sourceLineNo">1865</span><a name="line.1865"></a>
-<span class="sourceLineNo">1866</span> // should be called under the RegionStateNode lock<a name="line.1866"></a>
-<span class="sourceLineNo">1867</span> void regionClosing(RegionStateNode regionNode) throws IOException {<a name="line.1867"></a>
-<span class="sourceLineNo">1868</span> transitStateAndUpdate(regionNode, State.CLOSING, STATES_EXPECTED_ON_CLOSING);<a name="line.1868"></a>
-<span class="sourceLineNo">1869</span><a name="line.1869"></a>
-<span class="sourceLineNo">1870</span> RegionInfo hri = regionNode.getRegionInfo();<a name="line.1870"></a>
-<span class="sourceLineNo">1871</span> // Set meta has not initialized early. so people trying to create/edit tables will wait<a name="line.1871"></a>
-<span class="sourceLineNo">1872</span> if (isMetaRegion(hri)) {<a name="line.1872"></a>
-<span class="sourceLineNo">1873</span> setMetaAssigned(hri, false);<a name="line.1873"></a>
-<span class="sourceLineNo">1874</span> }<a name="line.1874"></a>
-<span class="sourceLineNo">1875</span> regionStates.addRegionToServer(regionNode);<a name="line.1875"></a>
-<span class="sourceLineNo">1876</span> // update the operation count metrics<a name="line.1876"></a>
-<span class="sourceLineNo">1877</span> metrics.incrementOperationCounter();<a name="line.1877"></a>
-<span class="sourceLineNo">1878</span> }<a name="line.1878"></a>
-<span class="sourceLineNo">1879</span><a name="line.1879"></a>
-<span class="sourceLineNo">1880</span> // for open and close, they will first be persist to the procedure store in<a name="line.1880"></a>
-<span class="sourceLineNo">1881</span> // RegionRemoteProcedureBase. So here we will first change the in memory state as it is considered<a name="line.1881"></a>
-<span class="sourceLineNo">1882</span> // as succeeded if the persistence to procedure store is succeeded, and then when the<a name="line.1882"></a>
-<span class="sourceLineNo">1883</span> // RegionRemoteProcedureBase is woken up, we will persist the RegionStateNode to hbase:meta.<a name="line.1883"></a>
-<span class="sourceLineNo">1884</span><a name="line.1884"></a>
-<span class="sourceLineNo">1885</span> // should be called under the RegionStateNode lock<a name="line.1885"></a>
-<span class="sourceLineNo">1886</span> void regionOpenedWithoutPersistingToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1886"></a>
-<span class="sourceLineNo">1887</span> regionNode.transitionState(State.OPEN, STATES_EXPECTED_ON_OPEN);<a name="line.1887"></a>
-<span class="sourceLineNo">1888</span> RegionInfo regionInfo = regionNode.getRegionInfo();<a name="line.1888"></a>
-<span class="sourceLineNo">1889</span> regionStates.addRegionToServer(regionNode);<a name="line.1889"></a>
-<span class="sourceLineNo">1890</span> regionStates.removeFromFailedOpen(regionInfo);<a name="line.1890"></a>
-<span class="sourceLineNo">1891</span> }<a name="line.1891"></a>
-<span class="sourceLineNo">1892</span><a name="line.1892"></a>
-<span class="sourceLineNo">1893</span> // should be called under the RegionStateNode lock<a name="line.1893"></a>
-<span class="sourceLineNo">1894</span> void regionClosedWithoutPersistingToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1894"></a>
-<span class="sourceLineNo">1895</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1895"></a>
-<span class="sourceLineNo">1896</span> regionNode.transitionState(State.CLOSED, STATES_EXPECTED_ON_CLOSED);<a name="line.1896"></a>
-<span class="sourceLineNo">1897</span> regionNode.setRegionLocation(null);<a name="line.1897"></a>
-<span class="sourceLineNo">1898</span> if (regionLocation != null) {<a name="line.1898"></a>
-<span class="sourceLineNo">1899</span> regionNode.setLastHost(regionLocation);<a name="line.1899"></a>
-<span class="sourceLineNo">1900</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1900"></a>
-<span class="sourceLineNo">1901</span> }<a name="line.1901"></a>
-<span class="sourceLineNo">1902</span> }<a name="line.1902"></a>
-<span class="sourceLineNo">1903</span><a name="line.1903"></a>
-<span class="sourceLineNo">1904</span> // should be called under the RegionStateNode lock<a name="line.1904"></a>
-<span class="sourceLineNo">1905</span> // for SCP<a name="line.1905"></a>
-<span class="sourceLineNo">1906</span> public void regionClosedAbnormally(RegionStateNode regionNode) throws IOException {<a name="line.1906"></a>
-<span class="sourceLineNo">1907</span> RegionState.State state = regionNode.getState();<a name="line.1907"></a>
-<span class="sourceLineNo">1908</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1908"></a>
-<span class="sourceLineNo">1909</span> regionNode.transitionState(State.ABNORMALLY_CLOSED);<a name="line.1909"></a>
-<span class="sourceLineNo">1910</span> regionNode.setRegionLocation(null);<a name="line.1910"></a>
-<span class="sourceLineNo">1911</span> boolean succ = false;<a name="line.1911"></a>
-<span class="sourceLineNo">1912</span> try {<a name="line.1912"></a>
-<span class="sourceLineNo">1913</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1913"></a>
-<span class="sourceLineNo">1914</span> succ = true;<a name="line.1914"></a>
-<span class="sourceLineNo">1915</span> } finally {<a name="line.1915"></a>
-<span class="sourceLineNo">1916</span> if (!succ) {<a name="line.1916"></a>
-<span class="sourceLineNo">1917</span> // revert<a name="line.1917"></a>
-<span class="sourceLineNo">1918</span> regionNode.setState(state);<a name="line.1918"></a>
-<span class="sourceLineNo">1919</span> regionNode.setRegionLocation(regionLocation);<a name="line.1919"></a>
-<span class="sourceLineNo">1920</span> }<a name="line.1920"></a>
-<span class="sourceLineNo">1921</span> }<a name="line.1921"></a>
-<span class="sourceLineNo">1922</span> if (regionLocation != null) {<a name="line.1922"></a>
-<span class="sourceLineNo">1923</span> regionNode.setLastHost(regionLocation);<a name="line.1923"></a>
-<span class="sourceLineNo">1924</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1924"></a>
-<span class="sourceLineNo">1925</span> }<a name="line.1925"></a>
-<span class="sourceLineNo">1926</span> }<a name="line.1926"></a>
-<span class="sourceLineNo">1927</span><a name="line.1927"></a>
-<span class="sourceLineNo">1928</span> void persistToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1928"></a>
-<span class="sourceLineNo">1929</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1929"></a>
-<span class="sourceLineNo">1930</span> RegionInfo regionInfo = regionNode.getRegionInfo();<a name="line.1930"></a>
-<span class="sourceLineNo">1931</span> if (isMetaRegion(regionInfo) && regionNode.getState() == State.OPEN) {<a name="line.1931"></a>
-<span class="sourceLineNo">1932</span> // Usually we'd set a table ENABLED at this stage but hbase:meta is ALWAYs enabled, it<a name="line.1932"></a>
-<span class="sourceLineNo">1933</span> // can't be disabled -- so skip the RPC (besides... enabled is managed by TableStateManager<a name="line.1933"></a>
-<span class="sourceLineNo">1934</span> // which is backed by hbase:meta... Avoid setting ENABLED to avoid having to update state<a name="line.1934"></a>
-<span class="sourceLineNo">1935</span> // on table that contains state.<a name="line.1935"></a>
-<span class="sourceLineNo">1936</span> setMetaAssigned(regionInfo, true);<a name="line.1936"></a>
+<span class="sourceLineNo">1805</span> private static final State[] STATES_EXPECTED_ON_CLOSING = {<a name="line.1805"></a>
+<span class="sourceLineNo">1806</span> State.OPEN, // Normal case<a name="line.1806"></a>
+<span class="sourceLineNo">1807</span> State.CLOSING, // Retrying<a name="line.1807"></a>
+<span class="sourceLineNo">1808</span> State.SPLITTING, // Offline the split parent<a name="line.1808"></a>
+<span class="sourceLineNo">1809</span> State.MERGING // Offline the merge parents<a name="line.1809"></a>
+<span class="sourceLineNo">1810</span> };<a name="line.1810"></a>
+<span class="sourceLineNo">1811</span><a name="line.1811"></a>
+<span class="sourceLineNo">1812</span> private static final State[] STATES_EXPECTED_ON_CLOSED = {<a name="line.1812"></a>
+<span class="sourceLineNo">1813</span> State.CLOSING, // Normal case<a name="line.1813"></a>
+<span class="sourceLineNo">1814</span> State.CLOSED // Retrying<a name="line.1814"></a>
+<span class="sourceLineNo">1815</span> };<a name="line.1815"></a>
+<span class="sourceLineNo">1816</span><a name="line.1816"></a>
+<span class="sourceLineNo">1817</span> // This is for manually scheduled region assign, can add other states later if we find out other<a name="line.1817"></a>
+<span class="sourceLineNo">1818</span> // usages<a name="line.1818"></a>
+<span class="sourceLineNo">1819</span> private static final State[] STATES_EXPECTED_ON_ASSIGN = { State.CLOSED, State.OFFLINE };<a name="line.1819"></a>
+<span class="sourceLineNo">1820</span><a name="line.1820"></a>
+<span class="sourceLineNo">1821</span> // We only allow unassign or move a region which is in OPEN state.<a name="line.1821"></a>
+<span class="sourceLineNo">1822</span> private static final State[] STATES_EXPECTED_ON_UNASSIGN_OR_MOVE = { State.OPEN };<a name="line.1822"></a>
+<span class="sourceLineNo">1823</span><a name="line.1823"></a>
+<span class="sourceLineNo">1824</span> // ============================================================================================<a name="line.1824"></a>
+<span class="sourceLineNo">1825</span> // Region Status update<a name="line.1825"></a>
+<span class="sourceLineNo">1826</span> // Should only be called in TransitRegionStateProcedure(and related procedures), as the locking<a name="line.1826"></a>
+<span class="sourceLineNo">1827</span> // and pre-assumptions are very tricky.<a name="line.1827"></a>
+<span class="sourceLineNo">1828</span> // ============================================================================================<a name="line.1828"></a>
+<span class="sourceLineNo">1829</span> private void transitStateAndUpdate(RegionStateNode regionNode, RegionState.State newState,<a name="line.1829"></a>
+<span class="sourceLineNo">1830</span> RegionState.State... expectedStates) throws IOException {<a name="line.1830"></a>
+<span class="sourceLineNo">1831</span> RegionState.State state = regionNode.getState();<a name="line.1831"></a>
+<span class="sourceLineNo">1832</span> regionNode.transitionState(newState, expectedStates);<a name="line.1832"></a>
+<span class="sourceLineNo">1833</span> boolean succ = false;<a name="line.1833"></a>
+<span class="sourceLineNo">1834</span> try {<a name="line.1834"></a>
+<span class="sourceLineNo">1835</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1835"></a>
+<span class="sourceLineNo">1836</span> succ = true;<a name="line.1836"></a>
+<span class="sourceLineNo">1837</span> } finally {<a name="line.1837"></a>
+<span class="sourceLineNo">1838</span> if (!succ) {<a name="line.1838"></a>
+<span class="sourceLineNo">1839</span> // revert<a name="line.1839"></a>
+<span class="sourceLineNo">1840</span> regionNode.setState(state);<a name="line.1840"></a>
+<span class="sourceLineNo">1841</span> }<a name="line.1841"></a>
+<span class="sourceLineNo">1842</span> }<a name="line.1842"></a>
+<span class="sourceLineNo">1843</span> }<a name="line.1843"></a>
+<span class="sourceLineNo">1844</span><a name="line.1844"></a>
+<span class="sourceLineNo">1845</span> // should be called within the synchronized block of RegionStateNode<a name="line.1845"></a>
+<span class="sourceLineNo">1846</span> void regionOpening(RegionStateNode regionNode) throws IOException {<a name="line.1846"></a>
+<span class="sourceLineNo">1847</span> // As in SCP, for performance reason, there is no TRSP attached with this region, we will not<a name="line.1847"></a>
+<span class="sourceLineNo">1848</span> // update the region state, which means that the region could be in any state when we want to<a name="line.1848"></a>
+<span class="sourceLineNo">1849</span> // assign it after a RS crash. So here we do not pass the expectedStates parameter.<a name="line.1849"></a>
+<span class="sourceLineNo">1850</span> transitStateAndUpdate(regionNode, State.OPENING);<a name="line.1850"></a>
+<span class="sourceLineNo">1851</span> regionStates.addRegionToServer(regionNode);<a name="line.1851"></a>
+<span class="sourceLineNo">1852</span> // update the operation count metrics<a name="line.1852"></a>
+<span class="sourceLineNo">1853</span> metrics.incrementOperationCounter();<a name="line.1853"></a>
+<span class="sourceLineNo">1854</span> }<a name="line.1854"></a>
+<span class="sourceLineNo">1855</span><a name="line.1855"></a>
+<span class="sourceLineNo">1856</span> // should be called under the RegionStateNode lock<a name="line.1856"></a>
+<span class="sourceLineNo">1857</span> // The parameter 'giveUp' means whether we will try to open the region again, if it is true, then<a name="line.1857"></a>
+<span class="sourceLineNo">1858</span> // we will persist the FAILED_OPEN state into hbase:meta.<a name="line.1858"></a>
+<span class="sourceLineNo">1859</span> void regionFailedOpen(RegionStateNode regionNode, boolean giveUp) throws IOException {<a name="line.1859"></a>
+<span class="sourceLineNo">1860</span> RegionState.State state = regionNode.getState();<a name="line.1860"></a>
+<span class="sourceLineNo">1861</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1861"></a>
+<span class="sourceLineNo">1862</span> if (giveUp) {<a name="line.1862"></a>
+<span class="sourceLineNo">1863</span> regionNode.setState(State.FAILED_OPEN);<a name="line.1863"></a>
+<span class="sourceLineNo">1864</span> regionNode.setRegionLocation(null);<a name="line.1864"></a>
+<span class="sourceLineNo">1865</span> boolean succ = false;<a name="line.1865"></a>
+<span class="sourceLineNo">1866</span> try {<a name="line.1866"></a>
+<span class="sourceLineNo">1867</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1867"></a>
+<span class="sourceLineNo">1868</span> succ = true;<a name="line.1868"></a>
+<span class="sourceLineNo">1869</span> } finally {<a name="line.1869"></a>
+<span class="sourceLineNo">1870</span> if (!succ) {<a name="line.1870"></a>
+<span class="sourceLineNo">1871</span> // revert<a name="line.1871"></a>
+<span class="sourceLineNo">1872</span> regionNode.setState(state);<a name="line.1872"></a>
+<span class="sourceLineNo">1873</span> regionNode.setRegionLocation(regionLocation);<a name="line.1873"></a>
+<span class="sourceLineNo">1874</span> }<a name="line.1874"></a>
+<span class="sourceLineNo">1875</span> }<a name="line.1875"></a>
+<span class="sourceLineNo">1876</span> }<a name="line.1876"></a>
+<span class="sourceLineNo">1877</span> if (regionLocation != null) {<a name="line.1877"></a>
+<span class="sourceLineNo">1878</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1878"></a>
+<span class="sourceLineNo">1879</span> }<a name="line.1879"></a>
+<span class="sourceLineNo">1880</span> }<a name="line.1880"></a>
+<span class="sourceLineNo">1881</span><a name="line.1881"></a>
+<span class="sourceLineNo">1882</span> // should be called under the RegionStateNode lock<a name="line.1882"></a>
+<span class="sourceLineNo">1883</span> void regionClosing(RegionStateNode regionNode) throws IOException {<a name="line.1883"></a>
+<span class="sourceLineNo">1884</span> transitStateAndUpdate(regionNode, State.CLOSING, STATES_EXPECTED_ON_CLOSING);<a name="line.1884"></a>
+<span class="sourceLineNo">1885</span><a name="line.1885"></a>
+<span class="sourceLineNo">1886</span> RegionInfo hri = regionNode.getRegionInfo();<a name="line.1886"></a>
+<span class="sourceLineNo">1887</span> // Set meta has not initialized early. so people trying to create/edit tables will wait<a name="line.1887"></a>
+<span class="sourceLineNo">1888</span> if (isMetaRegion(hri)) {<a name="line.1888"></a>
+<span class="sourceLineNo">1889</span> setMetaAssigned(hri, false);<a name="line.1889"></a>
+<span class="sourceLineNo">1890</span> }<a name="line.1890"></a>
+<span class="sourceLineNo">1891</span> regionStates.addRegionToServer(regionNode);<a name="line.1891"></a>
+<span class="sourceLineNo">1892</span> // update the operation count metrics<a name="line.1892"></a>
+<span class="sourceLineNo">1893</span> metrics.incrementOperationCounter();<a name="line.1893"></a>
+<span class="sourceLineNo">1894</span> }<a name="line.1894"></a>
+<span class="sourceLineNo">1895</span><a name="line.1895"></a>
+<span class="sourceLineNo">1896</span> // for open and close, they will first be persist to the procedure store in<a name="line.1896"></a>
+<span class="sourceLineNo">1897</span> // RegionRemoteProcedureBase. So here we will first change the in memory state as it is considered<a name="line.1897"></a>
+<span class="sourceLineNo">1898</span> // as succeeded if the persistence to procedure store is succeeded, and then when the<a name="line.1898"></a>
+<span class="sourceLineNo">1899</span> // RegionRemoteProcedureBase is woken up, we will persist the RegionStateNode to hbase:meta.<a name="line.1899"></a>
+<span class="sourceLineNo">1900</span><a name="line.1900"></a>
+<span class="sourceLineNo">1901</span> // should be called under the RegionStateNode lock<a name="line.1901"></a>
+<span class="sourceLineNo">1902</span> void regionOpenedWithoutPersistingToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1902"></a>
+<span class="sourceLineNo">1903</span> regionNode.transitionState(State.OPEN, STATES_EXPECTED_ON_OPEN);<a name="line.1903"></a>
+<span class="sourceLineNo">1904</span> RegionInfo regionInfo = regionNode.getRegionInfo();<a name="line.1904"></a>
+<span class="sourceLineNo">1905</span> regionStates.addRegionToServer(regionNode);<a name="line.1905"></a>
+<span class="sourceLineNo">1906</span> regionStates.removeFromFailedOpen(regionInfo);<a name="line.1906"></a>
+<span class="sourceLineNo">1907</span> }<a name="line.1907"></a>
+<span class="sourceLineNo">1908</span><a name="line.1908"></a>
+<span class="sourceLineNo">1909</span> // should be called under the RegionStateNode lock<a name="line.1909"></a>
+<span class="sourceLineNo">1910</span> void regionClosedWithoutPersistingToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1910"></a>
+<span class="sourceLineNo">1911</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1911"></a>
+<span class="sourceLineNo">1912</span> regionNode.transitionState(State.CLOSED, STATES_EXPECTED_ON_CLOSED);<a name="line.1912"></a>
+<span class="sourceLineNo">1913</span> regionNode.setRegionLocation(null);<a name="line.1913"></a>
+<span class="sourceLineNo">1914</span> if (regionLocation != null) {<a name="line.1914"></a>
+<span class="sourceLineNo">1915</span> regionNode.setLastHost(regionLocation);<a name="line.1915"></a>
+<span class="sourceLineNo">1916</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1916"></a>
+<span class="sourceLineNo">1917</span> }<a name="line.1917"></a>
+<span class="sourceLineNo">1918</span> }<a name="line.1918"></a>
+<span class="sourceLineNo">1919</span><a name="line.1919"></a>
+<span class="sourceLineNo">1920</span> // should be called under the RegionStateNode lock<a name="line.1920"></a>
+<span class="sourceLineNo">1921</span> // for SCP<a name="line.1921"></a>
+<span class="sourceLineNo">1922</span> public void regionClosedAbnormally(RegionStateNode regionNode) throws IOException {<a name="line.1922"></a>
+<span class="sourceLineNo">1923</span> RegionState.State state = regionNode.getState();<a name="line.1923"></a>
+<span class="sourceLineNo">1924</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1924"></a>
+<span class="sourceLineNo">1925</span> regionNode.transitionState(State.ABNORMALLY_CLOSED);<a name="line.1925"></a>
+<span class="sourceLineNo">1926</span> regionNode.setRegionLocation(null);<a name="line.1926"></a>
+<span class="sourceLineNo">1927</span> boolean succ = false;<a name="line.1927"></a>
+<span class="sourceLineNo">1928</span> try {<a name="line.1928"></a>
+<span class="sourceLineNo">1929</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1929"></a>
+<span class="sourceLineNo">1930</span> succ = true;<a name="line.1930"></a>
+<span class="sourceLineNo">1931</span> } finally {<a name="line.1931"></a>
+<span class="sourceLineNo">1932</span> if (!succ) {<a name="line.1932"></a>
+<span class="sourceLineNo">1933</span> // revert<a name="line.1933"></a>
+<span class="sourceLineNo">1934</span> regionNode.setState(state);<a name="line.1934"></a>
+<span class="sourceLineNo">1935</span> regionNode.setRegionLocation(regionLocation);<a name="line.1935"></a>
+<span class="sourceLineNo">1936</span> }<a name="line.1936"></a>
<span class="sourceLineNo">1937</span> }<a name="line.1937"></a>
-<span class="sourceLineNo">1938</span> }<a name="line.1938"></a>
-<span class="sourceLineNo">1939</span><a name="line.1939"></a>
-<span class="sourceLineNo">1940</span> // ============================================================================================<a name="line.1940"></a>
-<span class="sourceLineNo">1941</span> // The above methods can only be called in TransitRegionStateProcedure(and related procedures)<a name="line.1941"></a>
-<span class="sourceLineNo">1942</span> // ============================================================================================<a name="line.1942"></a>
+<span class="sourceLineNo">1938</span> if (regionLocation != null) {<a name="line.1938"></a>
+<span class="sourceLineNo">1939</span> regionNode.setLastHost(regionLocation);<a name="line.1939"></a>
+<span class="sourceLineNo">1940</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1940"></a>
+<span class="sourceLineNo">1941</span> }<a name="line.1941"></a>
+<span class="sourceLineNo">1942</span> }<a name="line.1942"></a>
<span class="sourceLineNo">1943</span><a name="line.1943"></a>
-<span class="sourceLineNo">1944</span> public void markRegionAsSplit(final RegionInfo parent, final ServerName serverName,<a name="line.1944"></a>
-<span class="sourceLineNo">1945</span> final RegionInfo daughterA, final RegionInfo daughterB) throws IOException {<a name="line.1945"></a>
-<span class="sourceLineNo">1946</span> // Update hbase:meta. Parent will be marked offline and split up in hbase:meta.<a name="line.1946"></a>
-<span class="sourceLineNo">1947</span> // The parent stays in regionStates until cleared when removed by CatalogJanitor.<a name="line.1947"></a>
-<span class="sourceLineNo">1948</span> // Update its state in regionStates to it shows as offline and split when read<a name="line.1948"></a>
-<span class="sourceLineNo">1949</span> // later figuring what regions are in a table and what are not: see<a name="line.1949"></a>
-<span class="sourceLineNo">1950</span> // regionStates#getRegionsOfTable<a name="line.1950"></a>
-<span class="sourceLineNo">1951</span> final RegionStateNode node = regionStates.getOrCreateRegionStateNode(parent);<a name="line.1951"></a>
-<span class="sourceLineNo">1952</span> node.setState(State.SPLIT);<a name="line.1952"></a>
-<span class="sourceLineNo">1953</span> final RegionStateNode nodeA = regionStates.getOrCreateRegionStateNode(daughterA);<a name="line.1953"></a>
-<span class="sourceLineNo">1954</span> nodeA.setState(State.SPLITTING_NEW);<a name="line.1954"></a>
-<span class="sourceLineNo">1955</span> final RegionStateNode nodeB = regionStates.getOrCreateRegionStateNode(daughterB);<a name="line.1955"></a>
-<span class="sourceLineNo">1956</span> nodeB.setState(State.SPLITTING_NEW);<a name="line.1956"></a>
-<span class="sourceLineNo">1957</span><a name="line.1957"></a>
-<span class="sourceLineNo">1958</span> TableDescriptor td = master.getTableDescriptors().get(parent.getTable());<a name="line.1958"></a>
-<span class="sourceLineNo">1959</span> // TODO: here we just update the parent region info in meta, to set split and offline to true,<a name="line.1959"></a>
-<span class="sourceLineNo">1960</span> // without changing the one in the region node. This is a bit confusing but the region info<a name="line.1960"></a>
-<span class="sourceLineNo">1961</span> // field in RegionStateNode is not expected to be changed in the current design. Need to find a<a name="line.1961"></a>
-<span class="sourceLineNo">1962</span> // possible way to address this problem, or at least adding more comments about the trick to<a name="line.1962"></a>
-<span class="sourceLineNo">1963</span> // deal with this problem, that when you want to filter out split parent, you need to check both<a name="line.1963"></a>
-<span class="sourceLineNo">1964</span> // the RegionState on whether it is split, and also the region info. If one of them matches then<a name="line.1964"></a>
-<span class="sourceLineNo">1965</span> // it is a split parent. And usually only one of them can match, as after restart, the region<a name="line.1965"></a>
-<span class="sourceLineNo">1966</span> // state will be changed from SPLIT to CLOSED.<a name="line.1966"></a>
-<span class="sourceLineNo">1967</span> regionStateStore.splitRegion(parent, daughterA, daughterB, serverName, td);<a name="line.1967"></a>
-<span class="sourceLineNo">1968</span> if (shouldAssignFavoredNodes(parent)) {<a name="line.1968"></a>
-<span class="sourceLineNo">1969</span> List<ServerName> onlineServers = this.master.getServerManager().getOnlineServersList();<a name="line.1969"></a>
-<span class="sourceLineNo">1970</span> getFavoredNodePromoter().generateFavoredNodesForDaughter(onlineServers, parent, daughterA,<a name="line.1970"></a>
-<span class="sourceLineNo">1971</span> daughterB);<a name="line.1971"></a>
-<span class="sourceLineNo">1972</span> }<a name="line.1972"></a>
-<span class="sourceLineNo">1973</span> }<a name="line.1973"></a>
-<span class="sourceLineNo">1974</span><a name="line.1974"></a>
-<span class="sourceLineNo">1975</span> /**<a name="line.1975"></a>
-<span class="sourceLineNo">1976</span> * When called here, the merge has happened. The merged regions have been<a name="line.1976"></a>
-<span class="sourceLineNo">1977</span> * unassigned and the above markRegionClosed has been called on each so they have been<a name="line.1977"></a>
-<span class="sourceLineNo">1978</span> * disassociated from a hosting Server. The merged region will be open after this call. The<a name="line.1978"></a>
-<span class="sourceLineNo">1979</span> * merged regions are removed from hbase:meta below. Later they are deleted from the filesystem<a name="line.1979"></a>
-<span class="sourceLineNo">1980</span> * by the catalog janitor running against hbase:meta. It notices when the merged region no<a name="line.1980"></a>
-<span class="sourceLineNo">1981</span> * longer holds references to the old regions (References are deleted after a compaction<a name="line.1981"></a>
-<span class="sourceLineNo">1982</span> * rewrites what the Reference points at but not until the archiver chore runs, are the<a name="line.1982"></a>
-<span class="sourceLineNo">1983</span> * References removed).<a name="line.1983"></a>
-<span class="sourceLineNo">1984</span> */<a name="line.1984"></a>
-<span class="sourceLineNo">1985</span> public void markRegionAsMerged(final RegionInfo child, final ServerName serverName,<a name="line.1985"></a>
-<span class="sourceLineNo">1986</span> RegionInfo [] mergeParents)<a name="line.1986"></a>
-<span class="sourceLineNo">1987</span> throws IOException {<a name="line.1987"></a>
-<span class="sourceLineNo">1988</span> final RegionStateNode node = regionStates.getOrCreateRegionStateNode(child);<a name="line.1988"></a>
-<span class="sourceLineNo">1989</span> node.setState(State.MERGED);<a name="line.1989"></a>
-<span class="sourceLineNo">1990</span> for (RegionInfo ri: mergeParents) {<a name="line.1990"></a>
-<span class="sourceLineNo">1991</span> regionStates.deleteRegion(ri);<a name="line.1991"></a>
-<span class="sourceLineNo">1992</span> }<a name="line.1992"></a>
-<span class="sourceLineNo">1993</span> TableDescriptor td = master.getTableDescriptors().get(child.getTable());<a name="line.1993"></a>
-<span class="sourceLineNo">1994</span> regionStateStore.mergeRegions(child, mergeParents, serverName, td);<a name="line.1994"></a>
-<span class="sourceLineNo">1995</span> if (shouldAssignFavoredNodes(child)) {<a name="line.1995"></a>
-<span class="sourceLineNo">1996</span> getFavoredNodePromoter().generateFavoredNodesForMergedRegion(child, mergeParents);<a name="line.1996"></a>
-<span class="sourceLineNo">1997</span> }<a name="line.1997"></a>
-<span class="sourceLineNo">1998</span> }<a name="line.1998"></a>
-<span class="sourceLineNo">1999</span><a name="line.1999"></a>
-<span class="sourceLineNo">2000</span> /*<a name="line.2000"></a>
-<span class="sourceLineNo">2001</span> * Favored nodes should be applied only when FavoredNodes balancer is configured and the region<a name="line.2001"></a>
-<span class="sourceLineNo">2002</span> * belongs to a non-system table.<a name="line.2002"></a>
-<span class="sourceLineNo">2003</span> */<a name="line.2003"></a>
-<span class="sourceLineNo">2004</span> private boolean shouldAssignFavoredNodes(RegionInfo region) {<a name="line.2004"></a>
-<span class="sourceLineNo">2005</span> return this.shouldAssignRegionsWithFavoredNodes &&<a name="line.2005"></a>
-<span class="sourceLineNo">2006</span> FavoredNodesManager.isFavoredNodeApplicable(region);<a name="line.2006"></a>
-<span class="sourceLineNo">2007</span> }<a name="line.2007"></a>
-<span class="sourceLineNo">2008</span><a name="line.2008"></a>
-<span class="sourceLineNo">2009</span> // ============================================================================================<a name="line.2009"></a>
-<span class="sourceLineNo">2010</span> // Assign Queue (Assign/Balance)<a name="line.2010"></a>
-<span class="sourceLineNo">2011</span> // ============================================================================================<a name="line.2011"></a>
-<span class="sourceLineNo">2012</span> private final ArrayList<RegionStateNode> pendingAssignQueue = new ArrayList<RegionStateNode>();<a name="line.2012"></a>
-<span class="sourceLineNo">2013</span> private final ReentrantLock assignQueueLock = new ReentrantLock();<a name="line.2013"></a>
-<span class="sourceLineNo">2014</span> private final Condition assignQueueFullCond = assignQueueLock.newCondition();<a name="line.2014"></a>
+<span class="sourceLineNo">1944</span> void persistToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1944"></a>
+<span class="sourceLineNo">1945</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1945"></a>
+<span class="sourceLineNo">1946</span> RegionInfo regionInfo = regionNode.getRegionInfo();<a name="line.1946"></a>
+<span class="sourceLineNo">1947</span> if (isMetaRegion(regionInfo) && regionNode.getState() == State.OPEN) {<a name="line.1947"></a>
+<span class="sourceLineNo">1948</span> // Usually we'd set a table ENABLED at this stage but hbase:meta is ALWAYs enabled, it<a name="line.1948"></a>
+<span class="sourceLineNo">1949</span> // can't be disabled -- so skip the RPC (besides... enabled is managed by TableStateManager<a name="line.1949"></a>
+<span class="sourceLineNo">1950</span> // which is backed by hbase:meta... Avoid setting ENABLED to avoid having to update state<a name="line.1950"></a>
+<span class="sourceLineNo">1951</span> // on table that contains state.<a name="line.1951"></a>
+<span class="sourceLineNo">1952</span> setMetaAssigned(regionInfo, true);<a name="line.1952"></a>
+<span class="sourceLineNo">1953</span> }<a name="line.1953"></a>
+<span class="sourceLineNo">1954</span> }<a name="line.1954"></a>
+<span class="sourceLineNo">1955</span><a name="line.1955"></a>
+<span class="sourceLineNo">1956</span> // ============================================================================================<a name="line.1956"></a>
+<span class="sourceLineNo">1957</span> // The above methods can only be called in TransitRegionStateProcedure(and related procedures)<a name="line.1957"></a>
+<span class="sourceLineNo">1958</span> // ============================================================================================<a name="line.1958"></a>
+<span class="sourceLineNo">1959</span><a name="line.1959"></a>
+<span class="sourceLineNo">1960</span> public void markRegionAsSplit(final RegionInfo parent, final ServerName serverName,<a name="line.1960"></a>
+<span class="sourceLineNo">1961</span> final RegionInfo daughterA, final RegionInfo daughterB) throws IOException {<a name="line.1961"></a>
+<span class="sourceLineNo">1962</span> // Update hbase:meta. Parent will be marked offline and split up in hbase:meta.<a name="line.1962"></a>
+<span class="sourceLineNo">1963</span> // The parent stays in regionStates until cleared when removed by CatalogJanitor.<a name="line.1963"></a>
+<span class="sourceLineNo">1964</span> // Update its state in regionStates to it shows as offline and split when read<a name="line.1964"></a>
+<span class="sourceLineNo">1965</span> // later figuring what regions are in a table and what are not: see<a name="line.1965"></a>
+<span class="sourceLineNo">1966</span> // regionStates#getRegionsOfTable<a name="line.1966"></a>
+<span class="sourceLineNo">1967</span> final RegionStateNode node = regionStates.getOrCreateRegionStateNode(parent);<a name="line.1967"></a>
+<span class="sourceLineNo">1968</span> node.setState(State.SPLIT);<a name="line.1968"></a>
+<span class="sourceLineNo">1969</span> final RegionStateNode nodeA = regionStates.getOrCreateRegionStateNode(daughterA);<a name="line.1969"></a>
+<span class="sourceLineNo">1970</span> nodeA.setState(State.SPLITTING_NEW);<a name="line.1970"></a>
+<span class="sourceLineNo">1971</span> final RegionStateNode nodeB = regionStates.getOrCreateRegionStateNode(daughterB);<a name="line.1971"></a>
+<span class="sourceLineNo">1972</span> nodeB.setState(State.SPLITTING_NEW);<a name="line.1972"></a>
+<span class="sourceLineNo">1973</span><a name="line.1973"></a>
+<span class="sourceLineNo">1974</span> TableDescriptor td = master.getTableDescriptors().get(parent.getTable());<a name="line.1974"></a>
+<span class="sourceLineNo">1975</span> // TODO: here we just update the parent region info in meta, to set split and offline to true,<a name="line.1975"></a>
+<span class="sourceLineNo">1976</span> // without changing the one in the region node. This is a bit confusing but the region info<a name="line.1976"></a>
+<span class="sourceLineNo">1977</span> // field in RegionStateNode is not expected to be changed in the current design. Need to find a<a name="line.1977"></a>
+<span class="sourceLineNo">1978</span> // possible way to address this problem, or at least adding more comments about the trick to<a name="line.1978"></a>
+<span class="sourceLineNo">1979</span> // deal with this problem, that when you want to filter out split parent, you need to check both<a name="line.1979"></a>
+<span class="sourceLineNo">1980</span> // the RegionState on whether it is split, and also the region info. If one of them matches then<a name="line.1980"></a>
+<span class="sourceLineNo">1981</span> // it is a split parent. And usually only one of them can match, as after restart, the region<a name="line.1981"></a>
+<span class="sourceLineNo">1982</span> // state will be changed from SPLIT to CLOSED.<a name="line.1982"></a>
+<span class="sourceLineNo">1983</span> regionStateStore.splitRegion(parent, daughterA, daughterB, serverName, td);<a name="line.1983"></a>
+<span class="sourceLineNo">1984</span> if (shouldAssignFavoredNodes(parent)) {<a name="line.1984"></a>
+<span class="sourceLineNo">1985</span> List<ServerName> onlineServers = this.master.getServerManager().getOnlineServersList();<a name="line.1985"></a>
+<span class="sourceLineNo">1986</span> getFavoredNodePromoter().generateFavoredNodesForDaughter(onlineServers, parent, daughterA,<a name="line.1986"></a>
+<span class="sourceLineNo">1987</span> daughterB);<a name="line.1987"></a>
+<span class="sourceLineNo">1988</span> }<a name="line.1988"></a>
+<span class="sourceLineNo">1989</span> }<a name="line.1989"></a>
+<span class="sourceLineNo">1990</span><a name="line.1990"></a>
+<span class="sourceLineNo">1991</span> /**<a name="line.1991"></a>
+<span class="sourceLineNo">1992</span> * When called here, the merge has happened. The merged regions have been<a name="line.1992"></a>
+<span class="sourceLineNo">1993</span> * unassigned and the above markRegionClosed has been called on each so they have been<a name="line.1993"></a>
+<span class="sourceLineNo">1994</span> * disassociated from a hosting Server. The merged region will be open after this call. The<a name="line.1994"></a>
+<span class="sourceLineNo">1995</span> * merged regions are removed from hbase:meta below. Later they are deleted from the filesystem<a name="line.1995"></a>
+<span class="sourceLineNo">1996</span> * by the catalog janitor running against hbase:meta. It notices when the merged region no<a name="line.1996"></a>
+<span class="sourceLineNo">1997</span> * longer holds references to the old regions (References are deleted after a compaction<a name="line.1997"></a>
+<span class="sourceLineNo">1998</span> * rewrites what the Reference points at but not until the archiver chore runs, are the<a name="line.1998"></a>
+<span class="sourceLineNo">1999</span> * References removed).<a name="line.1999"></a>
+<span class="sourceLineNo">2000</span> */<a name="line.2000"></a>
+<span class="sourceLineNo">2001</span> public void markRegionAsMerged(final RegionInfo child, final ServerName serverName,<a name="line.2001"></a>
+<span class="sourceLineNo">2002</span> RegionInfo [] mergeParents)<a name="line.2002"></a>
+<span class="sourceLineNo">2003</span> throws IOException {<a name="line.2003"></a>
+<span class="sourceLineNo">2004</span> final RegionStateNode node = regionStates.getOrCreateRegionStateNode(child);<a name="line.2004"></a>
+<span class="sourceLineNo">2005</span> node.setState(State.MERGED);<a name="line.2005"></a>
+<span class="sourceLineNo">2006</span> for (RegionInfo ri: mergeParents) {<a name="line.2006"></a>
+<span class="sourceLineNo">2007</span> regionStates.deleteRegion(ri);<a name="line.2007"></a>
+<span class="sourceLineNo">2008</span> }<a name="line.2008"></a>
+<span class="sourceLineNo">2009</span> TableDescriptor td = master.getTableDescriptors().get(child.getTable());<a name="line.2009"></a>
+<span class="sourceLineNo">2010</span> regionStateStore.mergeRegions(child, mergeParents, serverName, td);<a name="line.2010"></a>
+<span class="sourceLineNo">2011</span> if (shouldAssignFavoredNodes(child)) {<a name="line.2011"></a>
+<span class="sourceLineNo">2012</span> getFavoredNodePromoter().generateFavoredNodesForMergedRegion(child, mergeParents);<a name="line.2012"></a>
+<span class="sourceLineNo">2013</span> }<a name="line.2013"></a>
+<span class="sourceLineNo">2014</span> }<a name="line.2014"></a>
<span class="sourceLineNo">2015</span><a name="line.2015"></a>
-<span class="sourceLineNo">2016</span> /**<a name="line.2016"></a>
-<span class="sourceLineNo">2017</span> * Add the assign operation to the assignment queue.<a name="line.2017"></a>
-<span class="sourceLineNo">2018</span> * The pending assignment operation will be processed,<a name="line.2018"></a>
-<span class="sourceLineNo">2019</span> * and each region will be assigned by a server using the balancer.<a name="line.2019"></a>
-<span class="sourceLineNo">2020</span> */<a name="line.2020"></a>
-<span class="sourceLineNo">2021</span> protected void queueAssign(final RegionStateNode regionNode) {<a name="line.2021"></a>
-<span class="sourceLineNo">2022</span> regionNode.getProcedureEvent().suspend();<a name="line.2022"></a>
-<span class="sourceLineNo">2023</span><a name="line.2023"></a>
-<span class="sourceLineNo">2024</span> // TODO: quick-start for meta and the other sys-tables?<a name="line.2024"></a>
-<span class="sourceLineNo">2025</span> assignQueueLock.lock();<a name="line.2025"></a>
-<span class="sourceLineNo">2026</span> try {<a name="line.2026"></a>
-<span class="sourceLineNo">2027</span> pendingAssignQueue.add(regionNode);<a name="line.2027"></a>
-<span class="sourceLineNo">2028</span> if (regionNode.isSystemTable() ||<a name="line.2028"></a>
-<span class="sourceLineNo">2029</span> pendingAssignQueue.size() == 1 ||<a name="line.2029"></a>
-<span class="sourceLineNo">2030</span> pendingAssignQueue.size() >= assignDispatchWaitQueueMaxSize) {<a name="line.2030"></a>
-<span class="sourceLineNo">2031</span> assignQueueFullCond.signal();<a name="line.2031"></a>
-<span class="sourceLineNo">2032</span> }<a name="line.2032"></a>
-<span class="sourceLineNo">2033</span> } finally {<a name="line.2033"></a>
-<span class="sourceLineNo">2034</span> assignQueueLock.unlock();<a name="line.2034"></a>
-<span class="sourceLineNo">2035</span> }<a name="line.2035"></a>
-<span class="sourceLineNo">2036</span> }<a name="line.2036"></a>
-<span class="sourceLineNo">2037</span><a name="line.2037"></a>
-<span class="sourceLineNo">2038</span> private void startAssignmentThread() {<a name="line.2038"></a>
-<span class="sourceLineNo">2039</span> assignThread = new Thread(master.getServerName().toShortString()) {<a name="line.2039"></a>
-<span class="sourceLineNo">2040</span> @Override<a name="line.2040"></a>
-<span class="sourceLineNo">2041</span> public void run() {<a name="line.2041"></a>
-<span class="sourceLineNo">2042</span> while (isRunning()) {<a name="line.2042"></a>
-<span class="sourceLineNo">2043</span> processAssignQueue();<a name="line.2043"></a>
-<span class="sourceLineNo">2044</span> }<a name="line.2044"></a>
-<span class="sourceLineNo">2045</span> pendingAssignQueue.clear();<a name="line.2045"></a>
-<span class="sourceLineNo">2046</span> }<a name="line.2046"></a>
-<span class="sourceLineNo">2047</span> };<a name="line.2047"></a>
-<span class="sourceLineNo">2048</span> assignThread.setDaemon(true);<a name="line.2048"></a>
-<span class="sourceLineNo">2049</span> assignThread.start();<a name="line.2049"></a>
-<span class="sourceLineNo">2050</span> }<a name="line.2050"></a>
-<span class="sourceLineNo">2051</span><a name="line.2051"></a>
-<span class="sourceLineNo">2052</span> private void stopAssignmentThread() {<a name="line.2052"></a>
-<span class="sourceLineNo">2053</span> assignQueueSignal();<a name="line.2053"></a>
-<span class="sourceLineNo">2054</span> try {<a name="line.2054"></a>
-<span class="sourceLineNo">2055</span> while (assignThread.isAlive()) {<a name="line.2055"></a>
-<span class="sourceLineNo">2056</span> assignQueueSignal();<a name="line.2056"></a>
-<span class="sourceLineNo">2057</span> assignThread.join(250);<a name="line.2057"></a>
-<span class="sourceLineNo">2058</span> }<a name="line.2058"></a>
-<span class="sourceLineNo">2059</span> } catch (InterruptedException e) {<a name="line.2059"></a>
-<span class="sourceLineNo">2060</span> LOG.warn("join interrupted", e);<a name="line.2060"></a>
-<span class="sourceLineNo">2061</span> Thread.currentThread().interrupt();<a name="line.2061"></a>
-<span class="sourceLineNo">2062</span> }<a name="line.2062"></a>
-<span class="sourceLineNo">2063</span> }<a name="line.2063"></a>
-<span class="sourceLineNo">2064</span><a name="line.2064"></a>
-<span class="sourceLineNo">2065</span> private void assignQueueSignal() {<a name="line.2065"></a>
-<span class="sourceLineNo">2066</span> assignQueueLock.lock();<a name="line.2066"></a>
-<span class="sourceLineNo">2067</span> try {<a name="line.2067"></a>
-<span class="sourceLineNo">2068</span> assignQueueFullCond.signal();<a name="line.2068"></a>
-<span class="sourceLineNo">2069</span> } finally {<a name="line.2069"></a>
-<span class="sourceLineNo">2070</span> assignQueueLock.unlock();<a name="line.2070"></a>
-<span class="sourceLineNo">2071</span> }<a name="line.2071"></a>
-<span class="sourceLineNo">2072</span> }<a name="line.2072"></a>
-<span class="sourceLineNo">2073</span><a name="line.2073"></a>
-<span class="sourceLineNo">2074</span> @edu.umd.cs.findbugs.annotations.SuppressWarnings("WA_AWAIT_NOT_IN_LOOP")<a name="line.2074"></a>
-<span class="sourceLineNo">2075</span> private HashMap<RegionInfo, RegionStateNode> waitOnAssignQueue() {<a name="line.2075"></a>
-<span class="sourceLineNo">2076</span> HashMap<RegionInfo, RegionStateNode> regions = null;<a name="line.2076"></a>
-<span class="sourceLineNo">2077</span><a name="line.2077"></a>
-<span class="sourceLineNo">2078</span> assignQueueLock.lock();<a name="line.2078"></a>
-<span class="sourceLineNo">2079</span> try {<a name="line.2079"></a>
-<span class="sourceLineNo">2080</span> if (pendingAssignQueue.isEmpty() && isRunning()) {<a name="line.2080"></a>
-<span class="sourceLineNo">2081</span> assignQueueFullCond.await();<a name="line.2081"></a>
-<span class="sourceLineNo">2082</span> }<a name="line.2082"></a>
-<span class="sourceLineNo">2083</span><a name="line.2083"></a>
-<span class="sourceLineNo">2084</span> if (!isRunning()) {<a name="line.2084"></a>
-<span class="sourceLineNo">2085</span> return null;<a name="line.2085"></a>
-<span class="sourceLineNo">2086</span> }<a name="line.2086"></a>
-<span class="sourceLineNo">2087</span> assignQueueFullCond.await(assignDispatchWaitMillis, TimeUnit.MILLISECONDS);<a name="line.2087"></a>
-<span class="sourceLineNo">2088</span> regions = new HashMap<RegionInfo, RegionStateNode>(pendingAssignQueue.size());<a name="line.2088"></a>
-<span class="sourceLineNo">2089</span> for (RegionStateNode regionNode: pendingAssignQueue) {<a name="line.2089"></a>
-<span class="sourceLineNo">2090</span> regions.put(regionNode.getRegionInfo(), regionNode);<a name="line.2090"></a>
-<span class="sourceLineNo">2091</span> }<a name="line.2091"></a>
-<span class="sourceLineNo">2092</span> pendingAssignQueue.clear();<a name="line.2092"></a>
-<span class="sourceLineNo">2093</span> } catch (InterruptedException e) {<a name="line.2093"></a>
-<span class="sourceLineNo">2094</span> LOG.warn("got interrupted ", e);<a name="line.2094"></a>
-<span class="sourceLineNo">2095</span> Thread.currentThread().interrupt();<a name="line.2095"></a>
-<span class="sourceLineNo">2096</span> } finally {<a name="line.2096"></a>
-<span class="sourceLineNo">2097</span> assignQueueLock.unlock();<a name="line.2097"></a>
-<span class="sourceLineNo">2098</span> }<a name="line.2098"></a>
-<span class="sourceLineNo">2099</span> return regions;<a name="line.2099"></a>
-<span class="sourceLineNo">2100</span> }<a name="line.2100"></a>
-<span class="sourceLineNo">2101</span><a name="line.2101"></a>
-<span class="sourceLineNo">2102</span> private void processAssignQueue() {<a name="line.2102"></a>
-<span class="sourceLineNo">2103</span> final HashMap<RegionInfo, RegionStateNode> regions = waitOnAssignQueue();<a name="line.2103"></a>
-<span class="sourceLineNo">2104</span> if (regions == null || regions.size() == 0 || !isRunning()) {<a name="line.2104"></a>
-<span class="sourceLineNo">2105</span> return;<a name="line.2105"></a>
-<span class="sourceLineNo">2106</span> }<a name="line.2106"></a>
-<span class="sourceLineNo">2107</span><a name="line.2107"></a>
-<span class="sourceLineNo">2108</span> if (LOG.isTraceEnabled()) {<a name="line.2108"></a>
-<span class="sourceLineNo">2109</span> LOG.trace("PROCESS ASSIGN QUEUE regionCount=" + regions.size());<a name="line.2109"></a>
-<span class="sourceLineNo">2110</span> }<a name="line.2110"></a>
-<span class="sourceLineNo">2111</span><a name="line.2111"></a>
-<span class="sourceLineNo">2112</span> // TODO: Optimize balancer. pass a RegionPlan?<a name="line.2112"></a>
-<span class="sourceLineNo">2113</span> final HashMap<RegionInfo, ServerName> retainMap = new HashMap<>();<a name="line.2113"></a>
-<span class="sourceLineNo">2114</span> final List<RegionInfo> userHRIs = new ArrayList<>(regions.size());<a name="line.2114"></a>
-<span class="sourceLineNo">2115</span> // Regions for system tables requiring reassignment<a name="line.2115"></a>
-<span class="sourceLineNo">2116</span> final List<RegionInfo> systemHRIs = new ArrayList<>();<a name="line.2116"></a>
-<span class="sourceLineNo">2117</span> for (RegionStateNode regionStateNode: regions.values()) {<a name="line.2117"></a>
-<span class="sourceLineNo">2118</span> boolean sysTable = regionStateNode.isSystemTable();<a name="line.2118"></a>
-<span class="sourceLineNo">2119</span> final List<RegionInfo> hris = sysTable? systemHRIs: userHRIs;<a name="line.2119"></a>
-<span class="sourceLineNo">2120</span> if (regionStateNode.getRegionLocation() != null) {<a name="line.2120"></a>
-<span class="sourceLineNo">2121</span> retainMap.put(regionStateNode.getRegionInfo(), regionStateNode.getRegionLocation());<a name="line.2121"></a>
-<span class="sourceLineNo">2122</span> } else {<a name="line.2122"></a>
-<span class="sourceLineNo">2123</span> hris.add(regionStateNode.getRegionInfo());<a name="line.2123"></a>
-<span class="sourceLineNo">2124</span> }<a name="line.2124"></a>
-<span class="sourceLineNo">2125</span> }<a name="line.2125"></a>
-<span class="sourceLineNo">2126</span><a name="line.2126"></a>
-<span class="sourceLineNo">2127</span> // TODO: connect with the listener to invalidate the cache<a name="line.2127"></a>
-<span class="sourceLineNo">2128</span><a name="line.2128"></a>
-<span class="sourceLineNo">2129</span> // TODO use events<a name="line.2129"></a>
-<span class="sourceLineNo">2130</span> List<ServerName> servers = master.getServerManager().createDestinationServersList();<a name="line.2130"></a>
-<span class="sourceLineNo">2131</span> for (int i = 0; servers.size() < 1; ++i) {<a name="line.2131"></a>
-<span class="sourceLineNo">2132</span> // Report every fourth time around this loop; try not to flood log.<a name="line.2132"></a>
-<span class="sourceLineNo">2133</span> if (i % 4 == 0) {<a name="line.2133"></a>
-<span class="sourceLineNo">2134</span> LOG.warn("No servers available; cannot place " + regions.size() + " unassigned regions.");<a name="line.2134"></a>
-<span class="sourceLineNo">2135</span> }<a name="line.2135"></a>
-<span class="sourceLineNo">2136</span><a name="line.2136"></a>
-<span class="sourceLineNo">2137</span> if (!isRunning()) {<a name="line.2137"></a>
-<span class="sourceLineNo">2138</span> LOG.debug("Stopped! Dropping assign of " + regions.size() + " queued regions.");<a name="line.2138"></a>
-<span class="sourceLineNo">2139</span> return;<a name="line.2139"></a>
+<span class="sourceLineNo">2016</span> /*<a name="line.2016"></a>
+<span class="sourceLineNo">2017</span> * Favored nodes should be applied only when FavoredNodes balancer is configured and the region<a name="line.2017"></a>
+<span class="sourceLineNo">2018</span> * belongs to a non-system table.<a name="line.2018"></a>
+<span class="sourceLineNo">2019</span> */<a name="line.2019"></a>
+<span class="sourceLineNo">2020</span> private boolean shouldAssignFavoredNodes(RegionInfo region) {<a name="line.2020"></a>
+<span class="sourceLineNo">2021</span> return this.shouldAssignRegionsWithFavoredNodes &&<a name="line.2021"></a>
+<span class="sourceLineNo">2022</span> FavoredNodesManager.isFavoredNodeApplicable(region);<a name="line.2022"></a>
+<span class="sourceLineNo">2023</span> }<a name="line.2023"></a>
+<span class="sourceLineNo">2024</span><a name="line.2024"></a>
+<span class="sourceLineNo">2025</span> // ============================================================================================<a name="line.2025"></a>
+<span class="sourceLineNo">2026</span> // Assign Queue (Assign/Balance)<a name="line.2026"></a>
+<span class="sourceLineNo">2027</span> // ============================================================================================<a name="line.2027"></a>
+<span class="sourceLineNo">2028</span> private final ArrayList<RegionStateNode> pendingAssignQueue = new ArrayList<RegionStateNode>();<a name="line.2028"></a>
+<span class="sourceLineNo">2029</span> private final ReentrantLock assignQueueLock = new ReentrantLock();<a name="line.2029"></a>
+<span class="sourceLineNo">2030</span> private final Condition assignQueueFullCond = assignQueueLock.newCondition();<a name="line.2030"></a>
+<span class="sourceLineNo">2031</span><a name="line.2031"></a>
+<span class="sourceLineNo">2032</span> /**<a name="line.2032"></a>
+<span class="sourceLineNo">2033</span> * Add the assign operation to the assignment queue.<a name="line.2033"></a>
+<span class="sourceLineNo">2034</span> * The pending assignment operation will be processed,<a name="line.2034"></a>
+<span class="sourceLineNo">2035</span> * and each region will be assigned by a server using the balancer.<a name="line.2035"></a>
+<span class="sourceLineNo">2036</span> */<a name="line.2036"></a>
+<span class="sourceLineNo">2037</span> protected void queueAssign(final RegionStateNode regionNode) {<a name="line.2037"></a>
+<span class="sourceLineNo">2038</span> regionNode.getProcedureEvent().suspend();<a name="line.2038"></a>
+<span class="sourceLineNo">2039</span><a name="line.2039"></a>
+<span class="sourceLineNo">2040</span> // TODO: quick-start for meta and the other sys-tables?<a name="line.2040"></a>
+<span class="sourceLineNo">2041</span> assignQueueLock.lock();<a name="line.2041"></a>
+<span class="sourceLineNo">2042</span> try {<a name="line.2042"></a>
+<span class="sourceLineNo">2043</span> pendingAssignQueue.add(regionNode);<a name="line.2043"></a>
+<span class="sourceLineNo">2044</span> if (regionNode.isSystemTable() ||<a name="line.2044"></a>
+<span class="sourceLineNo">2045</span> pendingAssignQueue.size() == 1 ||<a name="line.2045"></a>
+<span class="sourceLineNo">2046</span> pendingAssignQueue.size() >= assignDispatchWaitQueueMaxSize) {<a name="line.2046"></a>
+<span class="sourceLineNo">2047</span> assignQueueFullCond.signal();<a name="line.2047"></a>
+<span class="sourceLineNo">2048</span> }<a name="line.2048"></a>
+<span class="sourceLineNo">2049</span> } finally {<a name="line.2049"></a>
+<span class="sourceLineNo">2050</span> assignQueueLock.unlock();<a name="line.2050"></a>
+<span class="sourceLineNo">2051</span> }<a name="line.2051"></a>
+<span class="sourceLineNo">2052</span> }<a name="line.2052"></a>
+<span class="sourceLineNo">2053</span><a name="line.2053"></a>
+<span class="sourceLineNo">2054</span> private void startAssignmentThread() {<a name="line.2054"></a>
+<span class="sourceLineNo">2055</span> assignThread = new Thread(master.getServerName().toShortString()) {<a name="line.2055"></a>
+<span class="sourceLineNo">2056</span> @Override<a name="line.2056"></a>
+<span class="sourceLineNo">2057</span> public void run() {<a name="line.2057"></a>
+<span class="sourceLineNo">2058</span> while (isRunning()) {<a name="line.2058"></a>
+<span class="sourceLineNo">2059</span> processAssignQueue();<a name="line.2059"></a>
+<span class="sourceLineNo">2060</span> }<a name="line.2060"></a>
+<span class="sourceLineNo">2061</span> pendingAssignQueue.clear();<a name="line.2061"></a>
+<span class="sourceLineNo">2062</span> }<a name="line.2062"></a>
+<span class="sourceLineNo">2063</span> };<a name="line.2063"></a>
+<span class="sourceLineNo">2064</span> assignThread.setDaemon(true);<a name="line.2064"></a>
+<span class="sourceLineNo">2065</span> assignThread.start();<a name="line.2065"></a>
+<span class="sourceLineNo">2066</span> }<a name="line.2066"></a>
+<span class="sourceLineNo">2067</span><a name="line.2067"></a>
+<span class="sourceLineNo">2068</span> private void stopAssignmentThread() {<a name="line.2068"></a>
+<span class="sourceLineNo">2069</span> assignQueueSignal();<a name="line.2069"></a>
+<span class="sourceLineNo">2070</span> try {<a name="line.2070"></a>
+<span class="sourceLineNo">2071</span> while (assignThread.isAlive()) {<a name="line.2071"></a>
+<span class="sourceLineNo">2072</span> assignQueueSignal();<a name="line.2072"></a>
+<span class="sourceLineNo">2073</span> assignThread.join(250);<a name="line.2073"></a>
+<span class="sourceLineNo">2074</span> }<a name="line.2074"></a>
+<span class="sourceLineNo">2075</span> } catch (InterruptedException e) {<a name="line.2075"></a>
+<span class="sourceLineNo">2076</span> LOG.warn("join interrupted", e);<a name="line.2076"></a>
+<span class="sourceLineNo">2077</span> Thread.currentThread().interrupt();<a name="line.2077"></a>
+<span class="sourceLineNo">2078</span> }<a name="line.2078"></a>
+<span class="sourceLineNo">2079</span> }<a name="line.2079"></a>
+<span class="sourceLineNo">2080</span><a name="line.2080"></a>
+<span class="sourceLineNo">2081</span> private void assignQueueSignal() {<a name="line.2081"></a>
+<span class="sourceLineNo">2082</span> assignQueueLock.lock();<a name="line.2082"></a>
+<span class="sourceLineNo">2083</span> try {<a name="line.2083"></a>
+<span class="sourceLineNo">2084</span> assignQueueFullCond.signal();<a name="line.2084"></a>
+<span class="sourceLineNo">2085</span> } finally {<a name="line.2085"></a>
+<span class="sourceLineNo">2086</span> assignQueueLock.unlock();<a name="line.2086"></a>
+<span class="sourceLineNo">2087</span> }<a name="line.2087"></a>
+<span class="sourceLineNo">2088</span> }<a name="line.2088"></a>
+<span class="sourceLineNo">2089</span><a name="line.2089"></a>
+<span class="sourceLineNo">2090</span> @edu.umd.cs.findbugs.annotations.SuppressWarnings("WA_AWAIT_NOT_IN_LOOP")<a name="line.2090"></a>
+<span class="sourceLineNo">2091</span> private HashMap<RegionInfo, RegionStateNode> waitOnAssignQueue() {<a name="line.2091"></a>
+<span class="sourceLineNo">2092</span> HashMap<RegionInfo, RegionStateNode> regions = null;<a name="line.2092"></a>
+<span class="sourceLineNo">2093</span><a name="line.2093"></a>
+<span class="sourceLineNo">2094</span> assignQueueLock.lock();<a name="line.2094"></a>
+<span class="sourceLineNo">2095</span> try {<a name="line.2095"></a>
+<span class="sourceLineNo">2096</span> if (pendingAssignQueue.isEmpty() && isRunning()) {<a name="line.2096"></a>
+<span class="sourceLineNo">2097</span> assignQueueFullCond.await();<a name="line.2097"></a>
+<span class="sourceLineNo">2098</span> }<a name="line.2098"></a>
+<span class="sourceLineNo">2099</span><a name="line.2099"></a>
+<span class="sourceLineNo">2100</span> if (!isRunning()) {<a name="line.2100"></a>
+<span class="sourceLineNo">2101</span> return null;<a name="line.2101"></a>
+<span class="sourceLineNo">2102</span> }<a name="line.2102"></a>
+<span class="sourceLineNo">2103</span> assignQueueFullCond.await(assignDispatchWaitMillis, TimeUnit.MILLISECONDS);<a name="line.2103"></a>
+<span class="sourceLineNo">2104</span> regions = new HashMap<RegionInfo, RegionStateNode>(pendingAssignQueue.size());<a name="line.2104"></a>
+<span class="sourceLineNo">2105</span> for (RegionStateNode regionNode: pendingAssignQueue) {<a name="line.2105"></a>
+<span class="sourceLineNo">2106</span> regions.put(regionNode.getRegionInfo(), regionNode);<a name="line.2106"></a>
+<span class="sourceLineNo">2107</span> }<a name="line.2107"></a>
+<span class="sourceLineNo">2108</span> pendingAssignQueue.clear();<a name="line.2108"></a>
+<span class="sourceLineNo">2109</span> } catch (InterruptedException e) {<a name="line.2109"></a>
+<span class="sourceLineNo">2110</span> LOG.warn("got interrupted ", e);<a name="line.2110"></a>
+<span class="sourceLineNo">2111</span> Thread.currentThread().interrupt();<a name="line.2111"></a>
+<span class="sourceLineNo">2112</span> } finally {<a name="line.2112"></a>
+<span class="sourceLineNo">2113</span> assignQueueLock.unlock();<a name="line.2113"></a>
+<span class="sourceLineNo">2114</span> }<a name="line.2114"></a>
+<span class="sourceLineNo">2115</span> return regions;<a name="line.2115"></a>
+<span class="sourceLineNo">2116</span> }<a name="line.2116"></a>
+<span class="sourceLineNo">2117</span><a name="line.2117"></a>
+<span class="sourceLineNo">2118</span> private void processAssignQueue() {<a name="line.2118"></a>
+<span class="sourceLineNo">2119</span> final HashMap<RegionInfo, RegionStateNode> regions = waitOnAssignQueue();<a name="line.2119"></a>
+<span class="sourceLineNo">2120</span> if (regions == null || regions.size() == 0 || !isRunning()) {<a name="line.2120"></a>
+<span class="sourceLineNo">2121</span> return;<a name="line.2121"></a>
+<span class="sourceLineNo">2122</span> }<a name="line.2122"></a>
+<span class="sourceLineNo">2123</span><a name="line.2123"></a>
+<span class="sourceLineNo">2124</span> if (LOG.isTraceEnabled()) {<a name="line.2124"></a>
+<span class="sourceLineNo">2125</span> LOG.trace("PROCESS ASSIGN QUEUE regionCount=" + regions.size());<a name="line.2125"></a>
+<span class="sourceLineNo">2126</span> }<a name="line.2126"></a>
+<span class="sourceLineNo">2127</span><a name="line.2127"></a>
+<span class="sourceLineNo">2128</span> // TODO: Optimize balancer. pass a RegionPlan?<a name="line.2128"></a>
+<span class="sourceLineNo">2129</span> final HashMap<RegionInfo, ServerName> retainMap = new HashMap<>();<a name="line.2129"></a>
+<span class="sourceLineNo">2130</span> final List<RegionInfo> userHRIs = new ArrayList<>(regions.size());<a name="line.2130"></a>
+<span class="sourceLineNo">2131</span> // Regions for system tables requiring reassignment<a name="line.2131"></a>
+<span class="sourceLineNo">2132</span> final List<RegionInfo> systemHRIs = new ArrayList<>();<a name="line.2132"></a>
+<span class="sourceLineNo">2133</span> for (RegionStateNode regionStateNode: regions.values()) {<a name="line.2133"></a>
+<span class="sourceLineNo">2134</span> boolean sysTable = regionStateNode.isSystemTable();<a name="line.2134"></a>
+<span class="sourceLineNo">2135</span> final List<RegionInfo> hris = sysTable? systemHRIs: userHRIs;<a name="line.2135"></a>
+<span class="sourceLineNo">2136</span> if (regionStateNode.getRegionLocation() != null) {<a name="line.2136"></a>
+<span class="sourceLineNo">2137</span> retainMap.put(regionStateNode.getRegionInfo(), regionStateNode.getRegionLocation());<a name="line.2137"></a>
+<span class="sourceLineNo">2138</span> } else {<a name="line.2138"></a>
+<span class="sourceLineNo">2139</span> hris.add(regionStateNode.getRegionInfo());<a name="line.2139"></a>
<span class="sourceLineNo">2140</span> }<a name="line.2140"></a>
-<span class="sourceLineNo">2141</span> Threads.sleep(250);<a name="line.2141"></a>
-<span class="sourceLineNo">2142</span> servers = master.getServerManager().createDestinationServersList();<a name="line.2142"></a>
-<span class="sourceLineNo">2143</span> }<a name="line.2143"></a>
+<span class="sourceLineNo">2141</span> }<a name="line.2141"></a>
+<span class="sourceLineNo">2142</span><a name="line.2142"></a>
+<span class="sourceLineNo">2143</span> // TODO: connect with the listener to invalidate the cache<a name="line.2143"></a>
<span class="sourceLineNo">2144</span><a name="line.2144"></a>
-<span class="sourceLineNo">2145</span> if (!systemHRIs.isEmpty()) {<a name="line.2145"></a>
-<span class="sourceLineNo">2146</span> // System table regions requiring reassignment are present, get region servers<a name="line.2146"></a>
-<span class="sourceLineNo">2147</span> // not available for system table regions<a name="line.2147"></a>
-<span class="sourceLineNo">2148</span> final List<ServerName> excludeServers = getExcludedServersForSystemTable();<a name="line.2148"></a>
-<span class="sourceLineNo">2149</span> List<ServerName> serversForSysTables = servers.stream()<a name="line.2149"></a>
-<span class="sourceLineNo">2150</span> .filter(s -> !excludeServers.contains(s)).collect(Collectors.toList());<a name="line.2150"></a>
-<span class="sourceLineNo">2151</span> if (serversForSysTables.isEmpty()) {<a name="line.2151"></a>
-<span class="sourceLineNo">2152</span> LOG.warn("Filtering old server versions and the excluded produced an empty set; " +<a name="line.2152"></a>
-<span class="sourceLineNo">2153</span> "instead considering all candidate servers!");<a name="line.2153"></a>
-<span class="sourceLineNo">2154</span> }<a name="line.2154"></a>
-<span class="sourceLineNo">2155</span> LOG.debug("Processing assignQueue; systemServersCount=" + serversForSysTables.size() +<a name="line.2155"></a>
-<span class="sourceLineNo">2156</span> ", allServersCount=" + servers.size());<a name="line.2156"></a>
-<span class="sourceLineNo">2157</span> processAssignmentPlans(regions, null, systemHRIs,<a name="line.2157"></a>
-<span class="sourceLineNo">2158</span> serversForSysTables.isEmpty() && !containsBogusAssignments(regions, systemHRIs) ?<a name="line.2158"></a>
-<span class="sourceLineNo">2159</span> servers: serversForSysTables);<a name="line.2159"></a>
-<span class="sourceLineNo">2160</span> }<a name="line.2160"></a>
-<span class="sourceLineNo">2161</span><a name="line.2161"></a>
-<span class="sourceLineNo">2162</span> processAssignmentPlans(regions, retainMap, userHRIs, servers);<a name="line.2162"></a>
-<span class="sourceLineNo">2163</span> }<a name="line.2163"></a>
-<span class="sourceLineNo">2164</span><a name="line.2164"></a>
-<span class="sourceLineNo">2165</span> private boolean containsBogusAssignments(Map<RegionInfo, RegionStateNode> regions,<a name="line.2165"></a>
-<span class="sourceLineNo">2166</span> List<RegionInfo> hirs) {<a name="line.2166"></a>
-<span class="sourceLineNo">2167</span> for (RegionInfo ri : hirs) {<a name="line.2167"></a>
-<span class="sourceLineNo">2168</span> if (regions.get(ri).getRegionLocation() != null &&<a name="line.2168"></a>
-<span class="sourceLineNo">2169</span> regions.get(ri).getRegionLocation().equals(LoadBalancer.BOGUS_SERVER_NAME)){<a name="line.2169"></a>
-<span class="sourceLineNo">2170</span> return true;<a name="line.2170"></a>
-<span class="sourceLineNo">2171</span> }<a name="line.2171"></a>
-<span class="sourceLineNo">2172</span> }<a name="line.2172"></a>
-<span class="sourceLineNo">2173</span> return false;<a name="line.2173"></a>
-<span class="sourceLineNo">2174</span> }<a name="line.2174"></a>
-<span class="sourceLineNo">2175</span><a name="line.2175"></a>
-<span class="sourceLineNo">2176</span> private void processAssignmentPlans(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2176"></a>
-<span class="sourceLineNo">2177</span> final HashMap<RegionInfo, ServerName> retainMap, final List<RegionInfo> hris,<a name="line.2177"></a>
-<span class="sourceLineNo">2178</span> final List<ServerName> servers) {<a name="line.2178"></a>
-<span class="sourceLineNo">2179</span> boolean isTraceEnabled = LOG.isTraceEnabled();<a name="line.2179"></a>
-<span class="sourceLineNo">2180</span> if (isTraceEnabled) {<a name="line.2180"></a>
-<span class="sourceLineNo">2181</span> LOG.trace("Available servers count=" + servers.size() + ": " + servers);<a name="line.2181"></a>
-<span class="sourceLineNo">2182</span> }<a name="line.2182"></a>
-<span class="sourceLineNo">2183</span><a name="line.2183"></a>
-<span class="sourceLineNo">2184</span> final LoadBalancer balancer = getBalancer();<a name="line.2184"></a>
-<span class="sourceLineNo">2185</span> // ask the balancer where to place regions<a name="line.2185"></a>
-<span class="sourceLineNo">2186</span> if (retainMap != null && !retainMap.isEmpty()) {<a name="line.2186"></a>
-<span class="sourceLineNo">2187</span> if (isTraceEnabled) {<a name="line.2187"></a>
-<span class="sourceLineNo">2188</span> LOG.trace("retain assign regions=" + retainMap);<a name="line.2188"></a>
-<span class="sourceLineNo">2189</span> }<a name="line.2189"></a>
-<span class="sourceLineNo">2190</span> try {<a name="line.2190"></a>
-<span class="sourceLineNo">2191</span> acceptPlan(regions, balancer.retainAssignment(retainMap, servers));<a name="line.2191"></a>
-<span class="sourceLineNo">2192</span> } catch (IOException e) {<a name="line.2192"></a>
-<span class="sourceLineNo">2193</span> LOG.warn("unable to retain assignment", e);<a name="line.2193"></a>
-<span class="sourceLineNo">2194</span> addToPendingAssignment(regions, retainMap.keySet());<a name="line.2194"></a>
-<span class="sourceLineNo">2195</span> }<a name="line.2195"></a>
-<span class="sourceLineNo">2196</span> }<a name="line.2196"></a>
-<span class="sourceLineNo">2197</span><a name="line.2197"></a>
-<span class="sourceLineNo">2198</span> // TODO: Do we need to split retain and round-robin?<a name="line.2198"></a>
-<span class="sourceLineNo">2199</span> // the retain seems to fallback to round-robin/random if the region is not in the map.<a name="line.2199"></a>
-<span class="sourceLineNo">2200</span> if (!hris.isEmpty()) {<a name="line.2200"></a>
-<span class="sourceLineNo">2201</span> Collections.sort(hris, RegionInfo.COMPARATOR);<a name="line.2201"></a>
-<span class="sourceLineNo">2202</span> if (isTraceEnabled) {<a name="line.2202"></a>
-<span class="sourceLineNo">2203</span> LOG.trace("round robin regions=" + hris);<a name="line.2203"></a>
-<span class="sourceLineNo">2204</span> }<a name="line.2204"></a>
-<span class="sourceLineNo">2205</span> try {<a name="line.2205"></a>
-<span class="sourceLineNo">2206</span> acceptPlan(regions, balancer.roundRobinAssignment(hris, servers));<a name="line.2206"></a>
-<span class="sourceLineNo">2207</span> } catch (IOException e) {<a name="line.2207"></a>
-<span class="sourceLineNo">2208</span> LOG.warn("unable to round-robin assignment", e);<a name="line.2208"></a>
-<span class="sourceLineNo">2209</span> addToPendingAssignment(regions, hris);<a name="line.2209"></a>
-<span class="sourceLineNo">2210</span> }<a name="line.2210"></a>
-<span class="sourceLineNo">2211</span> }<a name="line.2211"></a>
-<span class="sourceLineNo">2212</span> }<a name="line.2212"></a>
+<span class="sourceLineNo">2145</span> // TODO use events<a name="line.2145"></a>
+<span class="sourceLineNo">2146</span> List<ServerName> servers = master.getServerManager().createDestinationServersList();<a name="line.2146"></a>
+<span class="sourceLineNo">2147</span> for (int i = 0; servers.size() < 1; ++i) {<a name="line.2147"></a>
+<span class="sourceLineNo">2148</span> // Report every fourth time around this loop; try not to flood log.<a name="line.2148"></a>
+<span class="sourceLineNo">2149</span> if (i % 4 == 0) {<a name="line.2149"></a>
+<span class="sourceLineNo">2150</span> LOG.warn("No servers available; cannot place " + regions.size() + " unassigned regions.");<a name="line.2150"></a>
+<span class="sourceLineNo">2151</span> }<a name="line.2151"></a>
+<span class="sourceLineNo">2152</span><a name="line.2152"></a>
+<span class="sourceLineNo">2153</span> if (!isRunning()) {<a name="line.2153"></a>
+<span class="sourceLineNo">2154</span> LOG.debug("Stopped! Dropping assign of " + regions.size() + " queued regions.");<a name="line.2154"></a>
+<span class="sourceLineNo">2155</span> return;<a name="line.2155"></a>
+<span class="sourceLineNo">2156</span> }<a name="line.2156"></a>
+<span class="sourceLineNo">2157</span> Threads.sleep(250);<a name="line.2157"></a>
+<span class="sourceLineNo">2158</span> servers = master.getServerManager().createDestinationServersList();<a name="line.2158"></a>
+<span class="sourceLineNo">2159</span> }<a name="line.2159"></a>
+<span class="sourceLineNo">2160</span><a name="line.2160"></a>
+<span class="sourceLineNo">2161</span> if (!systemHRIs.isEmpty()) {<a name="line.2161"></a>
+<span class="sourceLineNo">2162</span> // System table regions requiring reassignment are present, get region servers<a name="line.2162"></a>
+<span class="sourceLineNo">2163</span> // not available for system table regions<a name="line.2163"></a>
+<span class="sourceLineNo">2164</span> final List<ServerName> excludeServers = getExcludedServersForSystemTable();<a name="line.2164"></a>
+<span class="sourceLineNo">2165</span> List<ServerName> serversForSysTables = servers.stream()<a name="line.2165"></a>
+<span class="sourceLineNo">2166</span> .filter(s -> !excludeServers.contains(s)).collect(Collectors.toList());<a name="line.2166"></a>
+<span class="sourceLineNo">2167</span> if (serversForSysTables.isEmpty()) {<a name="line.2167"></a>
+<span class="sourceLineNo">2168</span> LOG.warn("Filtering old server versions and the excluded produced an empty set; " +<a name="line.2168"></a>
+<span class="sourceLineNo">2169</span> "instead considering all candidate servers!");<a name="line.2169"></a>
+<span class="sourceLineNo">2170</span> }<a name="line.2170"></a>
+<span class="sourceLineNo">2171</span> LOG.debug("Processing assignQueue; systemServersCount=" + serversForSysTables.size() +<a name="line.2171"></a>
+<span class="sourceLineNo">2172</span> ", allServersCount=" + servers.size());<a name="line.2172"></a>
+<span class="sourceLineNo">2173</span> processAssignmentPlans(regions, null, systemHRIs,<a name="line.2173"></a>
+<span class="sourceLineNo">2174</span> serversForSysTables.isEmpty() && !containsBogusAssignments(regions, systemHRIs) ?<a name="line.2174"></a>
+<span class="sourceLineNo">2175</span> servers: serversForSysTables);<a name="line.2175"></a>
+<span class="sourceLineNo">2176</span> }<a name="line.2176"></a>
+<span class="sourceLineNo">2177</span><a name="line.2177"></a>
+<span class="sourceLineNo">2178</span> processAssignmentPlans(regions, retainMap, userHRIs, servers);<a name="line.2178"></a>
+<span class="sourceLineNo">2179</span> }<a name="line.2179"></a>
+<span class="sourceLineNo">2180</span><a name="line.2180"></a>
+<span class="sourceLineNo">2181</span> private boolean containsBogusAssignments(Map<RegionInfo, RegionStateNode> regions,<a name="line.2181"></a>
+<span class="sourceLineNo">2182</span> List<RegionInfo> hirs) {<a name="line.2182"></a>
+<span class="sourceLineNo">2183</span> for (RegionInfo ri : hirs) {<a name="line.2183"></a>
+<span class="sourceLineNo">2184</span> if (regions.get(ri).getRegionLocation() != null &&<a name="line.2184"></a>
+<span class="sourceLineNo">2185</span> regions.get(ri).getRegionLocation().equals(LoadBalancer.BOGUS_SERVER_NAME)){<a name="line.2185"></a>
+<span class="sourceLineNo">2186</span> return true;<a name="line.2186"></a>
+<span class="sourceLineNo">2187</span> }<a name="line.2187"></a>
+<span class="sourceLineNo">2188</span> }<a name="line.2188"></a>
+<span class="sourceLineNo">2189</span> return false;<a name="line.2189"></a>
+<span class="sourceLineNo">2190</span> }<a name="line.2190"></a>
+<span class="sourceLineNo">2191</span><a name="line.2191"></a>
+<span class="sourceLineNo">2192</span> private void processAssignmentPlans(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2192"></a>
+<span class="sourceLineNo">2193</span> final HashMap<RegionInfo, ServerName> retainMap, final List<RegionInfo> hris,<a name="line.2193"></a>
+<span class="sourceLineNo">2194</span> final List<ServerName> servers) {<a name="line.2194"></a>
+<span class="sourceLineNo">2195</span> boolean isTraceEnabled = LOG.isTraceEnabled();<a name="line.2195"></a>
+<span class="sourceLineNo">2196</span> if (isTraceEnabled) {<a name="line.2196"></a>
+<span class="sourceLineNo">2197</span> LOG.trace("Available servers count=" + servers.size() + ": " + servers);<a name="line.2197"></a>
+<span class="sourceLineNo">2198</span> }<a name="line.2198"></a>
+<span class="sourceLineNo">2199</span><a name="line.2199"></a>
+<span class="sourceLineNo">2200</span> final LoadBalancer balancer = getBalancer();<a name="line.2200"></a>
+<span class="sourceLineNo">2201</span> // ask the balancer where to place regions<a name="line.2201"></a>
+<span class="sourceLineNo">2202</span> if (retainMap != null && !retainMap.isEmpty()) {<a name="line.2202"></a>
+<span class="sourceLineNo">2203</span> if (isTraceEnabled) {<a name="line.2203"></a>
+<span class="sourceLineNo">2204</span> LOG.trace("retain assign regions=" + retainMap);<a name="line.2204"></a>
+<span class="sourceLineNo">2205</span> }<a name="line.2205"></a>
+<span class="sourceLineNo">2206</span> try {<a name="line.2206"></a>
+<span class="sourceLineNo">2207</span> acceptPlan(regions, balancer.retainAssignment(retainMap, servers));<a name="line.2207"></a>
+<span class="sourceLineNo">2208</span> } catch (IOException e) {<a name="line.2208"></a>
+<span class="sourceLineNo">2209</span> LOG.warn("unable to retain assignment", e);<a name="line.2209"></a>
+<span class="sourceLineNo">2210</span> addToPendingAssignment(regions, retainMap.keySet());<a name="line.2210"></a>
+<span class="sourceLineNo">2211</span> }<a name="line.2211"></a>
+<span class="sourceLineNo">2212</span> }<a name="line.2212"></a>
<span class="sourceLineNo">2213</span><a name="line.2213"></a>
-<span class="sourceLineNo">2214</span> private void acceptPlan(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2214"></a>
-<span class="sourceLineNo">2215</span> final Map<ServerName, List<RegionInfo>> plan) throws HBaseIOException {<a name="line.2215"></a>
-<span class="sourceLineNo">2216</span> final ProcedureEvent<?>[] events = new ProcedureEvent[regions.size()];<a name="line.2216"></a>
-<span class="sourceLineNo">2217</span> final long st = System.currentTimeMillis();<a name="line.2217"></a>
-<span class="sourceLineNo">2218</span><a name="line.2218"></a>
-<span class="sourceLineNo">2219</span> if (plan.isEmpty()) {<a name="line.2219"></a>
-<span class="sourceLineNo">2220</span> throw new HBaseIOException("unable to compute plans for regions=" + regions.size());<a name="line.2220"></a>
-<span class="sourceLineNo">2221</span> }<a name="line.2221"></a>
-<span class="sourceLineNo">2222</span><a name="line.2222"></a>
-<span class="sourceLineNo">2223</span> int evcount = 0;<a name="line.2223"></a>
-<span class="sourceLineNo">2224</span> for (Map.Entry<ServerName, List<RegionInfo>> entry: plan.entrySet()) {<a name="line.2224"></a>
-<span class="sourceLineNo">2225</span> final ServerName server = entry.getKey();<a name="line.2225"></a>
-<span class="sourceLineNo">2226</span> for (RegionInfo hri: entry.getValue()) {<a name="line.2226"></a>
-<span class="sourceLineNo">2227</span> final RegionStateNode regionNode = regions.get(hri);<a name="line.2227"></a>
-<span class="sourceLineNo">2228</span> regionNode.setRegionLocation(server);<a name="line.2228"></a>
-<span class="sourceLineNo">2229</span> if (server.equals(LoadBalancer.BOGUS_SERVER_NAME) && regionNode.isSystemTable()) {<a name="line.2229"></a>
-<span class="sourceLineNo">2230</span> assignQueueLock.lock();<a name="line.2230"></a>
-<span class="sourceLineNo">2231</span> try {<a name="line.2231"></a>
-<span class="sourceLineNo">2232</span> pendingAssignQueue.add(regionNode);<a name="line.2232"></a>
-<span class="sourceLineNo">2233</span> } finally {<a name="line.2233"></a>
-<span class="sourceLineNo">2234</span> assignQueueLock.unlock();<a name="line.2234"></a>
-<span class="sourceLineNo">2235</span> }<a name="line.2235"></a>
-<span class="sourceLineNo">2236</span> }else {<a name="line.2236"></a>
-<span class="sourceLineNo">2237</span> events[evcount++] = regionNode.getProcedureEvent();<a name="line.2237"></a>
-<span class="sourceLineNo">2238</span> }<a name="line.2238"></a>
-<span class="sourceLineNo">2239</span> }<a name="line.2239"></a>
-<span class="sourceLineNo">2240</span> }<a name="line.2240"></a>
-<span class="sourceLineNo">2241</span> ProcedureEvent.wakeEvents(getProcedureScheduler(), events);<a name="line.2241"></a>
-<span class="sourceLineNo">2242</span><a name="line.2242"></a>
-<span class="sourceLineNo">2243</span> final long et = System.currentTimeMillis();<a name="line.2243"></a>
-<span class="sourceLineNo">2244</span> if (LOG.isTraceEnabled()) {<a name="line.2244"></a>
-<span class="sourceLineNo">2245</span> LOG.trace("ASSIGN ACCEPT " + events.length + " -> " +<a name="line.2245"></a>
-<span class="sourceLineNo">2246</span> StringUtils.humanTimeDiff(et - st));<a name="line.2246"></a>
-<span class="sourceLineNo">2247</span> }<a name="line.2247"></a>
-<span class="sourceLineNo">2248</span> }<a name="line.2248"></a>
-<span class="sourceLineNo">2249</span><a name="line.2249"></a>
-<span class="sourceLineNo">2250</span> private void addToPendingAssignment(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2250"></a>
-<span class="sourceLineNo">2251</span> final Collection<RegionInfo> pendingRegions) {<a name="line.2251"></a>
-<span class="sourceLineNo">2252</span> assignQueueLock.lock();<a name="line.2252"></a>
-<span class="sourceLineNo">2253</span> try {<a name="line.2253"></a>
-<span class="sourceLineNo">2254</span> for (RegionInfo hri: pendingRegions) {<a name="line.2254"></a>
-<span class="sourceLineNo">2255</span> pendingAssignQueue.add(regions.get(hri));<a name="line.2255"></a>
-<span class="sourceLineNo">2256</span> }<a name="line.2256"></a>
-<span class="sourceLineNo">2257</span> } finally {<a name="line.2257"></a>
-<span class="sourceLineNo">2258</span> assignQueueLock.unlock();<a name="line.2258"></a>
-<span class="sourceLineNo">2259</span> }<a name="line.2259"></a>
-<span class="sourceLineNo">2260</span> }<a name="line.2260"></a>
-<span class="sourceLineNo">2261</span><a name="line.2261"></a>
-<span class="sourceLineNo">2262</span> /**<a name="line.2262"></a>
-<span class="sourceLineNo">2263</span> * Get a list of servers that this region cannot be assigned to.<a name="line.2263"></a>
-<span class="sourceLineNo">2264</span> * For system tables, we must assign them to a server with highest version.<a name="line.2264"></a>
-<span class="sourceLineNo">2265</span> */<a name="line.2265"></a>
-<span class="sourceLineNo">2266</span> public List<ServerName> getExcludedServersForSystemTable() {<a name="line.2266"></a>
-<span class="sourceLineNo">2267</span> // TODO: This should be a cached list kept by the ServerManager rather than calculated on each<a name="line.2267"></a>
-<span class="sourceLineNo">2268</span> // move or system region assign. The RegionServerTracker keeps list of online Servers with<a name="line.2268"></a>
-<span class="sourceLineNo">2269</span> // RegionServerInfo that includes Version.<a name="line.2269"></a>
-<span class="sourceLineNo">2270</span> List<Pair<ServerName, String>> serverList = master.getServerManager().getOnlineServersList()<a name="line.2270"></a>
-<span class="sourceLineNo">2271</span> .stream()<a name="line.2271"></a>
-<span class="sourceLineNo">2272</span> .map((s)->new Pair<>(s, master.getRegionServerVersion(s)))<a name="line.2272"></a>
-<span class="sourceLineNo">2273</span> .collect(Collectors.toList());<a name="line.2273"></a>
-<span class="sourceLineNo">2274</span> if (serverList.isEmpty()) {<a name="line.2274"></a>
-<span class="sourceLineNo">2275</span> return Collections.emptyList();<a name="line.2275"></a>
-<span class="sourceLineNo">2276</span> }<a name="line.2276"></a>
-<span class="sourceLineNo">2277</span> String highestVersion = Collections.max(serverList,<a name="line.2277"></a>
-<span class="sourceLineNo">2278</span> (o1, o2) -> VersionInfo.compareVersion(o1.getSecond(), o2.getSecond())).getSecond();<a name="line.2278"></a>
-<span class="sourceLineNo">2279</span> return serverList.stream()<a name="line.2279"></a>
-<span class="sourceLineNo">2280</span> .filter((p)->!p.getSecond().equals(highestVersion))<a name="line.2280"></a>
-<span class="sourceLineNo">2281</span> .map(Pair::getFirst)<a name="line.2281"></a>
-<span class="sourceLineNo">2282</span> .collect(Collectors.toList());<a name="line.2282"></a>
-<span class="sourceLineNo">2283</span> }<a name="line.2283"></a>
-<span class="sourceLineNo">2284</span><a name="line.2284"></a>
-<span class="sourceLineNo">2285</span> MasterServices getMaster() {<a name="line.2285"></a>
-<span class="sourceLineNo">2286</span> return master;<a name="line.2286"></a>
-<span class="sourceLineNo">2287</span> }<a name="line.2287"></a>
-<span class="sourceLineNo">2288</span><a name="line.2288"></a>
-<span class="sourceLineNo">2289</span> /**<a name="line.2289"></a>
-<span class="sourceLineNo">2290</span> * @return a snapshot of rsReports<a name="line.2290"></a>
-<span class="sourceLineNo">2291</span> */<a name="line.2291"></a>
-<span class="sourceLineNo">2292</span> public Map<ServerName, Set<byte[]>> getRSReports() {<a name="line.2292"></a>
-<span class="sourceLineNo">2293</span> Map<ServerName, Set<byte[]>> rsReportsSnapshot = new HashMap<>();<a name="line.2293"></a>
-<span class="sourceLineNo">2294</span> synchronized (rsReports) {<a name="line.2294"></a>
-<span class="sourceLineNo">2295</span> rsReports.entrySet().forEach(e -> rsReportsSnapshot.put(e.getKey(), e.getValue()));<a name="line.2295"></a>
-<span class="sourceLineNo">2296</span> }<a name="line.2296"></a>
-<span class="sourceLineNo">2297</span> return rsReportsSnapshot;<a name="line.2297"></a>
-<span class="sourceLineNo">2298</span> }<a name="line.2298"></a>
-<span class="sourceLineNo">2299</span><a name="line.2299"></a>
-<span class="sourceLineNo">2300</span> /**<a name="line.2300"></a>
-<span class="sourceLineNo">2301</span> * Provide regions state count for given table.<a name="line.2301"></a>
-<span class="sourceLineNo">2302</span> * e.g howmany regions of give table are opened/closed/rit etc<a name="line.2302"></a>
-<span class="sourceLineNo">2303</span> *<a name="line.2303"></a>
-<span class="sourceLineNo">2304</span> * @param tableName TableName<a name="line.2304"></a>
-<span class="sourceLineNo">2305</span> * @return region states count<a name="line.2305"></a>
-<span class="sourceLineNo">2306</span> */<a name="line.2306"></a>
-<span class="sourceLineNo">2307</span> public RegionStatesCount getRegionStatesCount(TableName tableName) {<a name="line.2307"></a>
-<span class="sourceLineNo">2308</span> int openRegionsCount = 0;<a name="line.2308"></a>
-<span class="sourceLineNo">2309</span> int closedRegionCount = 0;<a name="line.2309"></a>
-<span class="sourceLineNo">2310</span> int ritCount = 0;<a name="line.2310"></a>
-<span class="sourceLineNo">2311</span> int splitRegionCount = 0;<a name="line.2311"></a>
-<span class="sourceLineNo">2312</span> int totalRegionCount = 0;<a name="line.2312"></a>
-<span class="sourceLineNo">2313</span> if (!isTableDisabled(tableName)) {<a name="line.2313"></a>
-<span class="sourceLineNo">2314</span> final List<RegionState> states = regionStates.getTableRegionStates(tableName);<a name="line.2314"></a>
-<span class="sourceLineNo">2315</span> for (RegionState regionState : states) {<a name="line.2315"></a>
-<span class="sourceLineNo">2316</span> if (regionState.isOpened()) {<a name="line.2316"></a>
-<span class="sourceLineNo">2317</span> openRegionsCount++;<a name="line.2317"></a>
-<span class="sourceLineNo">2318</span> } else if (regionState.isClosed()) {<a name="line.2318"></a>
-<span class="sourceLineNo">2319</span> closedRegionCount++;<a name="line.2319"></a>
-<span class="sourceLineNo">2320</span> } else if (regionState.isSplit()) {<a name="line.2320"></a>
-<span class="sourceLineNo">2321</span> splitRegionCount++;<a name="line.2321"></a>
-<span class="sourceLineNo">2322</span> }<a name="line.2322"></a>
-<span class="sourceLineNo">2323</span> }<a name="line.2323"></a>
-<span class="sourceLineNo">2324</span> totalRegionCount = states.size();<a name="line.2324"></a>
-<span class="sourceLineNo">2325</span> ritCount = totalRegionCount - openRegionsCount - splitRegionCount;<a name="line.2325"></a>
-<span class="sourceLineNo">2326</span> }<a name="line.2326"></a>
-<span class="sourceLineNo">2327</span> return new RegionStatesCount.RegionStatesCountBuilder()<a name="line.2327"></a>
-<span class="sourceLineNo">2328</span> .setOpenRegions(openRegionsCount)<a name="line.2328"></a>
-<span class="sourceLineNo">2329</span> .setClosedRegions(closedRegionCount)<a name="line.2329"></a>
-<span class="sourceLineNo">2330</span> .setSplitRegions(splitRegionCount)<a name="line.2330"></a>
-<span class="sourceLineNo">2331</span> .setRegionsInTransition(ritCount)<a name="line.2331"></a>
-<span class="sourceLineNo">2332</span> .setTotalRegions(totalRegionCount)<a name="line.2332"></a>
-<span class="sourceLineNo">2333</span> .build();<a name="line.2333"></a>
-<span class="sourceLineNo">2334</span> }<a name="line.2334"></a>
-<span class="sourceLineNo">2335</span><a name="line.2335"></a>
-<span class="sourceLineNo">2336</span>}<a name="line.2336"></a>
+<span class="sourceLineNo">2214</span> // TODO: Do we need to split retain and round-robin?<a name="line.2214"></a>
+<span class="sourceLineNo">2215</span> // the retain seems to fallback to round-robin/random if the region is not in the map.<a name="line.2215"></a>
+<span class="sourceLineNo">2216</span> if (!hris.isEmpty()) {<a name="line.2216"></a>
+<span class="sourceLineNo">2217</span> Collections.sort(hris, RegionInfo.COMPARATOR);<a name="line.2217"></a>
+<span class="sourceLineNo">2218</span> if (isTraceEnabled) {<a name="line.2218"></a>
+<span class="sourceLineNo">2219</span> LOG.trace("round robin regions=" + hris);<a name="line.2219"></a>
+<span class="sourceLineNo">2220</span> }<a name="line.2220"></a>
+<span class="sourceLineNo">2221</span> try {<a name="line.2221"></a>
+<span class="sourceLineNo">2222</span> acceptPlan(regions, balancer.roundRobinAssignment(hris, servers));<a name="line.2222"></a>
+<span class="sourceLineNo">2223</span> } catch (IOException e) {<a name="line.2223"></a>
+<span class="sourceLineNo">2224</span> LOG.warn("unable to round-robin assignment", e);<a name="line.2224"></a>
+<span class="sourceLineNo">2225</span> addToPendingAssignment(regions, hris);<a name="line.2225"></a>
+<span class="sourceLineNo">2226</span> }<a name="line.2226"></a>
+<span class="sourceLineNo">2227</span> }<a name="line.2227"></a>
+<span class="sourceLineNo">2228</span> }<a name="line.2228"></a>
+<span class="sourceLineNo">2229</span><a name="line.2229"></a>
+<span class="sourceLineNo">2230</span> private void acceptPlan(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2230"></a>
+<span class="sourceLineNo">2231</span> final Map<ServerName, List<RegionInfo>> plan) throws HBaseIOException {<a name="line.2231"></a>
+<span class="sourceLineNo">2232</span> final ProcedureEvent<?>[] events = new ProcedureEvent[regions.size()];<a name="line.2232"></a>
+<span class="sourceLineNo">2233</span> final long st = System.currentTimeMillis();<a name="line.2233"></a>
+<span class="sourceLineNo">2234</span><a name="line.2234"></a>
+<span class="sourceLineNo">2235</span> if (plan.isEmpty()) {<a name="line.2235"></a>
+<span class="sourceLineNo">2236</span> throw new HBaseIOException("unable to compute plans for regions=" + regions.size());<a name="line.2236"></a>
+<span class="sourceLineNo">2237</span> }<a name="line.2237"></a>
+<span class="sourceLineNo">2238</span><a name="line.2238"></a>
+<span class="sourceLineNo">2239</span> int evcount = 0;<a name="line.2239"></a>
+<span class="sourceLineNo">2240</span> for (Map.Entry<ServerName, List<RegionInfo>> entry: plan.entrySet()) {<a name="line.2240"></a>
+<span class="sourceLineNo">2241</span> final ServerName server = entry.getKey();<a name="line.2241"></a>
+<span class="sourceLineNo">2242</span> for (RegionInfo hri: entry.getValue()) {<a name="line.2242"></a>
+<span class="sourceLineNo">2243</span> final RegionStateNode regionNode = regions.get(hri);<a name="line.2243"></a>
+<span class="sourceLineNo">2244</span> regionNode.setRegionLocation(server);<a name="line.2244"></a>
+<span class="sourceLineNo">2245</span> if (server.equals(LoadBalancer.BOGUS_SERVER_NAME) && regionNode.isSystemTable()) {<a name="line.2245"></a>
+<span class="sourceLineNo">2246</span> assignQueueLock.lock();<a name="line.2246"></a>
+<span class="sourceLineNo">2247</span> try {<a name="line.2247"></a>
+<span class="sourceLineNo">2248</span> pendingAssignQueue.add(regionNode);<a name="line.2248"></a>
+<span class="sourceLineNo">2249</span> } finally {<a name="line.2249"></a>
+<span class="sourceLineNo">2250</span> assignQueueLock.unlock();<a name="line.2250"></a>
+<span class="sourceLineNo">2251</span> }<a name="line.2251"></a>
+<span class="sourceLineNo">2252</span> }else {<a name="line.2252"></a>
+<span class="sourceLineNo">2253</span> events[evcount++] = regionNode.getProcedureEvent();<a name="line.2253"></a>
+<span class="sourceLineNo">2254</span> }<a name="line.2254"></a>
+<span class="sourceLineNo">2255</span> }<a name="line.2255"></a>
+<span class="sourceLineNo">2256</span> }<a name="line.2256"></a>
+<span class="sourceLineNo">2257</span> ProcedureEvent.wakeEvents(getProcedureScheduler(), events);<a name="line.2257"></a>
+<span class="sourceLineNo">2258</span><a name="line.2258"></a>
+<span class="sourceLineNo">2259</span> final long et = System.currentTimeMillis();<a name="line.2259"></a>
+<span class="sourceLineNo">2260</span> if (LOG.isTraceEnabled()) {<a name="line.2260"></a>
+<span class="sourceLineNo">2261</span> LOG.trace("ASSIGN ACCEPT " + events.length + " -> " +<a name="line.2261"></a>
+<span class="sourceLineNo">2262</span> StringUtils.humanTimeDiff(et - st));<a name="line.2262"></a>
+<span class="sourceLineNo">2263</span> }<a name="line.2263"></a>
+<span class="sourceLineNo">2264</span> }<a name="line.2264"></a>
+<span class="sourceLineNo">2265</span><a name="line.2265"></a>
+<span class="sourceLineNo">2266</span> private void addToPendingAssignment(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2266"></a>
+<span class="sourceLineNo">2267</span> final Collection<RegionInfo> pendingRegions) {<a name="line.2267"></a>
+<span class="sourceLineNo">2268</span> assignQueueLock.lock();<a name="line.2268"></a>
+<span class="sourceLineNo">2269</span> try {<a name="line.2269"></a>
+<span class="sourceLineNo">2270</span> for (RegionInfo hri: pendingRegions) {<a name="line.2270"></a>
+<span class="sourceLineNo">2271</span> pendingAssignQueue.add(regions.get(hri));<a name="line.2271"></a>
+<span class="sourceLineNo">2272</span> }<a name="line.2272"></a>
+<span class="sourceLineNo">2273</span> } finally {<a name="line.2273"></a>
+<span class="sourceLineNo">2274</span> assignQueueLock.unlock();<a name="line.2274"></a>
+<span class="sourceLineNo">2275</span> }<a name="line.2275"></a>
+<span class="sourceLineNo">2276</span> }<a name="line.2276"></a>
+<span class="sourceLineNo">2277</span><a name="line.2277"></a>
+<span class="sourceLineNo">2278</span> /**<a name="line.2278"></a>
+<span class="sourceLineNo">2279</span> * Get a list of servers that this region cannot be assigned to.<a name="line.2279"></a>
+<span class="sourceLineNo">2280</span> * For system tables, we must assign them to a server with highest version.<a name="line.2280"></a>
+<span class="sourceLineNo">2281</span> */<a name="line.2281"></a>
+<span class="sourceLineNo">2282</span> public List<ServerName> getExcludedServersForSystemTable() {<a name="line.2282"></a>
+<span class="sourceLineNo">2283</span> // TODO: This should be a cached list kept by the ServerManager rather than calculated on each<a name="line.2283"></a>
+<span class="sourceLineNo">2284</span> // move or system region assign. The RegionServerTracker keeps list of online Servers with<a name="line.2284"></a>
+<span class="sourceLineNo">2285</span> // RegionServerInfo that includes Version.<a name="line.2285"></a>
+<span class="sourceLineNo">2286</span> List<Pair<ServerName, String>> serverList = master.getServerManager().getOnlineServersList()<a name="line.2286"></a>
+<span class="sourceLineNo">2287</span> .stream()<a name="line.2287"></a>
+<span class="sourceLineNo">2288</span> .map((s)->new Pair<>(s, master.getRegionServerVersion(s)))<a name="line.2288"></a>
+<span class="sourceLineNo">2289</span> .collect(Collectors.toList());<a name="line.2289"></a>
+<span class="sourceLineNo">2290</span> if (serverList.isEmpty()) {<a name="line.2290"></a>
+<span class="sourceLineNo">2291</span> return Collections.emptyList();<a name="line.2291"></a>
+<span class="sourceLineNo">2292</span> }<a name="line.2292"></a>
+<span class="sourceLineNo">2293</span> String highestVersion = Collections.max(serverList,<a name="line.2293"></a>
+<span class="sourceLineNo">2294</span> (o1, o2) -> VersionInfo.compareVersion(o1.getSecond(), o2.getSecond())).getSecond();<a name="line.2294"></a>
+<span class="sourceLineNo">2295</span> return serverList.stream()<a name="line.2295"></a>
+<span class="sourceLineNo">2296</span> .filter((p)->!p.getSecond().equals(highestVersion))<a name="line.2296"></a>
+<span class="sourceLineNo">2297</span> .map(Pair::getFirst)<a name="line.2297"></a>
+<span class="sourceLineNo">2298</span> .collect(Collectors.toList());<a name="line.2298"></a>
+<span class="sourceLineNo">2299</span> }<a name="line.2299"></a>
+<span class="sourceLineNo">2300</span><a name="line.2300"></a>
+<span class="sourceLineNo">2301</span> MasterServices getMaster() {<a name="line.2301"></a>
+<span class="sourceLineNo">2302</span> return master;<a name="line.2302"></a>
+<span class="sourceLineNo">2303</span> }<a name="line.2303"></a>
+<span class="sourceLineNo">2304</span><a name="line.2304"></a>
+<span class="sourceLineNo">2305</span> /**<a name="line.2305"></a>
+<span class="sourceLineNo">2306</span> * @return a snapshot of rsReports<a name="line.2306"></a>
+<span class="sourceLineNo">2307</span> */<a name="line.2307"></a>
+<span class="sourceLineNo">2308</span> public Map<ServerName, Set<byte[]>> getRSReports() {<a name="line.2308"></a>
+<span class="sourceLineNo">2309</span> Map<ServerName, Set<byte[]>> rsReportsSnapshot = new HashMap<>();<a name="line.2309"></a>
+<span class="sourceLineNo">2310</span> synchronized (rsReports) {<a name="line.2310"></a>
+<span class="sourceLineNo">2311</span> rsReports.entrySet().forEach(e -> rsReportsSnapshot.put(e.getKey(), e.getValue()));<a name="line.2311"></a>
+<span class="sourceLineNo">2312</span> }<a name="line.2312"></a>
+<span class="sourceLineNo">2313</span> return rsReportsSnapshot;<a name="line.2313"></a>
+<span class="sourceLineNo">2314</span> }<a name="line.2314"></a>
+<span class="sourceLineNo">2315</span><a name="line.2315"></a>
+<span class="sourceLineNo">2316</span> /**<a name="line.2316"></a>
+<span class="sourceLineNo">2317</span> * Provide regions state count for given table.<a name="line.2317"></a>
+<span class="sourceLineNo">2318</span> * e.g howmany regions of give table are opened/closed/rit etc<a name="line.2318"></a>
+<span class="sourceLineNo">2319</span> *<a name="line.2319"></a>
+<span class="sourceLineNo">2320</span> * @param tableName TableName<a name="line.2320"></a>
+<span class="sourceLineNo">2321</span> * @return region states count<a name="line.2321"></a>
+<span class="sourceLineNo">2322</span> */<a name="line.2322"></a>
+<span class="sourceLineNo">2323</span> public RegionStatesCount getRegionStatesCount(TableName tableName) {<a name="line.2323"></a>
+<span class="sourceLineNo">2324</span> int openRegionsCount = 0;<a name="line.2324"></a>
+<span class="sourceLineNo">2325</span> int closedRegionCount = 0;<a name="line.2325"></a>
+<span class="sourceLineNo">2326</span> int ritCount = 0;<a name="line.2326"></a>
+<span class="sourceLineNo">2327</span> int splitRegionCount = 0;<a name="line.2327"></a>
+<span class="sourceLineNo">2328</span> int totalRegionCount = 0;<a name="line.2328"></a>
+<span class="sourceLineNo">2329</span> if (!isTableDisabled(tableName)) {<a name="line.2329"></a>
+<span class="sourceLineNo">2330</span> final List<RegionState> states = regionStates.getTableRegionStates(tableName);<a name="line.2330"></a>
+<span class="sourceLineNo">2331</span> for (RegionState regionState : states) {<a name="line.2331"></a>
+<span class="sourceLineNo">2332</span> if (regionState.isOpened()) {<a name="line.2332"></a>
+<span class="sourceLineNo">2333</span> openRegionsCount++;<a name="line.2333"></a>
+<span class="sourceLineNo">2334</span> } else if (regionState.isClosed()) {<a name="line.2334"></a>
+<span class="sourceLineNo">2335</span> closedRegionCount++;<a name="line.2335"></a>
+<span class="sourceLineNo">2336</span> } else if (regionState.isSplit()) {<a name="line.2336"></a>
+<span class="sourceLineNo">2337</span> splitRegionCount++;<a name="line.2337"></a>
+<span class="sourceLineNo">2338</span> }<a name="line.2338"></a>
+<span class="sourceLineNo">2339</span> }<a name="line.2339"></a>
+<span class="sourceLineNo">2340</span> totalRegionCount = states.size();<a name="line.2340"></a>
+<span class="sourceLineNo">2341</span> ritCount = totalRegionCount - openRegionsCount - splitRegionCount;<a name="line.2341"></a>
+<span class="sourceLineNo">2342</span> }<a name="line.2342"></a>
+<span class="sourceLineNo">2343</span> return new RegionStatesCount.RegionStatesCountBuilder()<a name="line.2343"></a>
+<span class="sourceLineNo">2344</span> .setOpenRegions(openRegionsCount)<a name="line.2344"></a>
+<span class="sourceLineNo">2345</span> .setClosedRegions(closedRegionCount)<a name="line.2345"></a>
+<span class="sourceLineNo">2346</span> .setSplitRegions(splitRegionCount)<a name="line.2346"></a>
+<span class="sourceLineNo">2347</span> .setRegionsInTransition(ritCount)<a name="line.2347"></a>
+<span class="sourceLineNo">2348</span> .setTotalRegions(totalRegionCount)<a name="line.2348"></a>
+<span class="sourceLineNo">2349</span> .build();<a name="line.2349"></a>
+<span class="sourceLineNo">2350</span> }<a name="line.2350"></a>
+<span class="sourceLineNo">2351</span><a name="line.2351"></a>
+<span class="sourceLineNo">2352</span>}<a name="line.2352"></a>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html b/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html
index c00cc30..2c789f6 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionInTransitionStat.html
@@ -1134,1214 +1134,1230 @@
<span class="sourceLineNo">1126</span> LOG.debug("Split request from " + serverName +<a name="line.1126"></a>
<span class="sourceLineNo">1127</span> ", parent=" + parent + " splitKey=" + Bytes.toStringBinary(splitKey));<a name="line.1127"></a>
<span class="sourceLineNo">1128</span> }<a name="line.1128"></a>
-<span class="sourceLineNo">1129</span> master.getMasterProcedureExecutor().submitProcedure(createSplitProcedure(parent, splitKey));<a name="line.1129"></a>
-<span class="sourceLineNo">1130</span><a name="line.1130"></a>
-<span class="sourceLineNo">1131</span> // If the RS is < 2.0 throw an exception to abort the operation, we are handling the split<a name="line.1131"></a>
-<span class="sourceLineNo">1132</span> if (master.getServerManager().getVersionNumber(serverName) < 0x0200000) {<a name="line.1132"></a>
-<span class="sourceLineNo">1133</span> throw new UnsupportedOperationException(String.format("Split handled by the master: " +<a name="line.1133"></a>
-<span class="sourceLineNo">1134</span> "parent=%s hriA=%s hriB=%s", parent.getShortNameToLog(), hriA, hriB));<a name="line.1134"></a>
-<span class="sourceLineNo">1135</span> }<a name="line.1135"></a>
-<span class="sourceLineNo">1136</span> }<a name="line.1136"></a>
-<span class="sourceLineNo">1137</span><a name="line.1137"></a>
-<span class="sourceLineNo">1138</span> private void updateRegionMergeTransition(final ServerName serverName, final TransitionCode state,<a name="line.1138"></a>
-<span class="sourceLineNo">1139</span> final RegionInfo merged, final RegionInfo hriA, final RegionInfo hriB) throws IOException {<a name="line.1139"></a>
-<span class="sourceLineNo">1140</span> checkMetaLoaded(merged);<a name="line.1140"></a>
-<span class="sourceLineNo">1141</span><a name="line.1141"></a>
-<span class="sourceLineNo">1142</span> if (state != TransitionCode.READY_TO_MERGE) {<a name="line.1142"></a>
-<span class="sourceLineNo">1143</span> throw new UnexpectedStateException("Unsupported merge regionState=" + state +<a name="line.1143"></a>
-<span class="sourceLineNo">1144</span> " for regionA=" + hriA + " regionB=" + hriB + " merged=" + merged +<a name="line.1144"></a>
-<span class="sourceLineNo">1145</span> " maybe an old RS (< 2.0) had the operation in progress");<a name="line.1145"></a>
-<span class="sourceLineNo">1146</span> }<a name="line.1146"></a>
-<span class="sourceLineNo">1147</span><a name="line.1147"></a>
-<span class="sourceLineNo">1148</span> if (!master.isSplitOrMergeEnabled(MasterSwitchType.MERGE)) {<a name="line.1148"></a>
-<span class="sourceLineNo">1149</span> LOG.warn("Merge switch is off! skip merge of regionA=" + hriA + " regionB=" + hriB);<a name="line.1149"></a>
-<span class="sourceLineNo">1150</span> throw new DoNotRetryIOException("Merge of regionA=" + hriA + " regionB=" + hriB +<a name="line.1150"></a>
-<span class="sourceLineNo">1151</span> " failed because merge switch is off");<a name="line.1151"></a>
-<span class="sourceLineNo">1152</span> }<a name="line.1152"></a>
+<span class="sourceLineNo">1129</span> // Processing this report happens asynchronously from other activities which can mutate<a name="line.1129"></a>
+<span class="sourceLineNo">1130</span> // the region state. For example, a split procedure may already be running for this parent.<a name="line.1130"></a>
+<span class="sourceLineNo">1131</span> // A split procedure cannot succeed if the parent region is no longer open, so we can<a name="line.1131"></a>
+<span class="sourceLineNo">1132</span> // ignore it in that case.<a name="line.1132"></a>
+<span class="sourceLineNo">1133</span> // Note that submitting more than one split procedure for a given region is<a name="line.1133"></a>
+<span class="sourceLineNo">1134</span> // harmless -- the split is fenced in the procedure handling -- but it would be noisy in<a name="line.1134"></a>
+<span class="sourceLineNo">1135</span> // the logs. Only one procedure can succeed. The other procedure(s) would abort during<a name="line.1135"></a>
+<span class="sourceLineNo">1136</span> // initialization and report failure with WARN level logging.<a name="line.1136"></a>
+<span class="sourceLineNo">1137</span> RegionState parentState = regionStates.getRegionState(parent);<a name="line.1137"></a>
+<span class="sourceLineNo">1138</span> if (parentState != null && parentState.isOpened()) {<a name="line.1138"></a>
+<span class="sourceLineNo">1139</span> master.getMasterProcedureExecutor().submitProcedure(createSplitProcedure(parent,<a name="line.1139"></a>
+<span class="sourceLineNo">1140</span> splitKey));<a name="line.1140"></a>
+<span class="sourceLineNo">1141</span> } else {<a name="line.1141"></a>
+<span class="sourceLineNo">1142</span> LOG.info("Ignoring split request from " + serverName +<a name="line.1142"></a>
+<span class="sourceLineNo">1143</span> ", parent=" + parent + " because parent is unknown or not open");<a name="line.1143"></a>
+<span class="sourceLineNo">1144</span> return;<a name="line.1144"></a>
+<span class="sourceLineNo">1145</span> }<a name="line.1145"></a>
+<span class="sourceLineNo">1146</span><a name="line.1146"></a>
+<span class="sourceLineNo">1147</span> // If the RS is < 2.0 throw an exception to abort the operation, we are handling the split<a name="line.1147"></a>
+<span class="sourceLineNo">1148</span> if (master.getServerManager().getVersionNumber(serverName) < 0x0200000) {<a name="line.1148"></a>
+<span class="sourceLineNo">1149</span> throw new UnsupportedOperationException(String.format("Split handled by the master: " +<a name="line.1149"></a>
+<span class="sourceLineNo">1150</span> "parent=%s hriA=%s hriB=%s", parent.getShortNameToLog(), hriA, hriB));<a name="line.1150"></a>
+<span class="sourceLineNo">1151</span> }<a name="line.1151"></a>
+<span class="sourceLineNo">1152</span> }<a name="line.1152"></a>
<span class="sourceLineNo">1153</span><a name="line.1153"></a>
-<span class="sourceLineNo">1154</span> // Submit the Merge procedure<a name="line.1154"></a>
-<span class="sourceLineNo">1155</span> if (LOG.isDebugEnabled()) {<a name="line.1155"></a>
-<span class="sourceLineNo">1156</span> LOG.debug("Handling merge request from RS=" + merged + ", merged=" + merged);<a name="line.1156"></a>
-<span class="sourceLineNo">1157</span> }<a name="line.1157"></a>
-<span class="sourceLineNo">1158</span> master.getMasterProcedureExecutor().submitProcedure(createMergeProcedure(hriA, hriB));<a name="line.1158"></a>
-<span class="sourceLineNo">1159</span><a name="line.1159"></a>
-<span class="sourceLineNo">1160</span> // If the RS is < 2.0 throw an exception to abort the operation, we are handling the merge<a name="line.1160"></a>
-<span class="sourceLineNo">1161</span> if (master.getServerManager().getVersionNumber(serverName) < 0x0200000) {<a name="line.1161"></a>
-<span class="sourceLineNo">1162</span> throw new UnsupportedOperationException(String.format(<a name="line.1162"></a>
-<span class="sourceLineNo">1163</span> "Merge not handled yet: regionState=%s merged=%s hriA=%s hriB=%s", state, merged, hriA,<a name="line.1163"></a>
-<span class="sourceLineNo">1164</span> hriB));<a name="line.1164"></a>
-<span class="sourceLineNo">1165</span> }<a name="line.1165"></a>
-<span class="sourceLineNo">1166</span> }<a name="line.1166"></a>
-<span class="sourceLineNo">1167</span><a name="line.1167"></a>
-<span class="sourceLineNo">1168</span> // ============================================================================================<a name="line.1168"></a>
-<span class="sourceLineNo">1169</span> // RS Status update (report online regions) helpers<a name="line.1169"></a>
-<span class="sourceLineNo">1170</span> // ============================================================================================<a name="line.1170"></a>
-<span class="sourceLineNo">1171</span> /**<a name="line.1171"></a>
-<span class="sourceLineNo">1172</span> * The master will call this method when the RS send the regionServerReport(). The report will<a name="line.1172"></a>
-<span class="sourceLineNo">1173</span> * contains the "online regions". This method will check the the online regions against the<a name="line.1173"></a>
-<span class="sourceLineNo">1174</span> * in-memory state of the AM, and we will log a warn message if there is a mismatch. This is<a name="line.1174"></a>
-<span class="sourceLineNo">1175</span> * because that there is no fencing between the reportRegionStateTransition method and<a name="line.1175"></a>
-<span class="sourceLineNo">1176</span> * regionServerReport method, so there could be race and introduce inconsistency here, but<a name="line.1176"></a>
-<span class="sourceLineNo">1177</span> * actually there is no problem.<a name="line.1177"></a>
-<span class="sourceLineNo">1178</span> * <p/><a name="line.1178"></a>
-<span class="sourceLineNo">1179</span> * Please see HBASE-21421 and HBASE-21463 for more details.<a name="line.1179"></a>
-<span class="sourceLineNo">1180</span> */<a name="line.1180"></a>
-<span class="sourceLineNo">1181</span> public void reportOnlineRegions(ServerName serverName, Set<byte[]> regionNames) {<a name="line.1181"></a>
-<span class="sourceLineNo">1182</span> if (!isRunning()) {<a name="line.1182"></a>
-<span class="sourceLineNo">1183</span> return;<a name="line.1183"></a>
-<span class="sourceLineNo">1184</span> }<a name="line.1184"></a>
-<span class="sourceLineNo">1185</span> if (LOG.isTraceEnabled()) {<a name="line.1185"></a>
-<span class="sourceLineNo">1186</span> LOG.trace("ReportOnlineRegions {} regionCount={}, metaLoaded={} {}", serverName,<a name="line.1186"></a>
-<span class="sourceLineNo">1187</span> regionNames.size(), isMetaLoaded(),<a name="line.1187"></a>
-<span class="sourceLineNo">1188</span> regionNames.stream().map(Bytes::toStringBinary).collect(Collectors.toList()));<a name="line.1188"></a>
-<span class="sourceLineNo">1189</span> }<a name="line.1189"></a>
-<span class="sourceLineNo">1190</span><a name="line.1190"></a>
-<span class="sourceLineNo">1191</span> ServerStateNode serverNode = regionStates.getOrCreateServer(serverName);<a name="line.1191"></a>
-<span class="sourceLineNo">1192</span> synchronized (serverNode) {<a name="line.1192"></a>
-<span class="sourceLineNo">1193</span> if (!serverNode.isInState(ServerState.ONLINE)) {<a name="line.1193"></a>
-<span class="sourceLineNo">1194</span> LOG.warn("Got a report from a server result in state " + serverNode.getState());<a name="line.1194"></a>
-<span class="sourceLineNo">1195</span> return;<a name="line.1195"></a>
-<span class="sourceLineNo">1196</span> }<a name="line.1196"></a>
-<span class="sourceLineNo">1197</span> }<a name="line.1197"></a>
-<span class="sourceLineNo">1198</span><a name="line.1198"></a>
-<span class="sourceLineNo">1199</span> // Track the regionserver reported online regions in memory.<a name="line.1199"></a>
-<span class="sourceLineNo">1200</span> synchronized (rsReports) {<a name="line.1200"></a>
-<span class="sourceLineNo">1201</span> rsReports.put(serverName, regionNames);<a name="line.1201"></a>
-<span class="sourceLineNo">1202</span> }<a name="line.1202"></a>
-<span class="sourceLineNo">1203</span><a name="line.1203"></a>
-<span class="sourceLineNo">1204</span> if (regionNames.isEmpty()) {<a name="line.1204"></a>
-<span class="sourceLineNo">1205</span> // nothing to do if we don't have regions<a name="line.1205"></a>
-<span class="sourceLineNo">1206</span> LOG.trace("no online region found on {}", serverName);<a name="line.1206"></a>
-<span class="sourceLineNo">1207</span> return;<a name="line.1207"></a>
-<span class="sourceLineNo">1208</span> }<a name="line.1208"></a>
-<span class="sourceLineNo">1209</span> if (!isMetaLoaded()) {<a name="line.1209"></a>
-<span class="sourceLineNo">1210</span> // we are still on startup, skip checking<a name="line.1210"></a>
-<span class="sourceLineNo">1211</span> return;<a name="line.1211"></a>
-<span class="sourceLineNo">1212</span> }<a name="line.1212"></a>
-<span class="sourceLineNo">1213</span> // The Heartbeat tells us of what regions are on the region serve, check the state.<a name="line.1213"></a>
-<span class="sourceLineNo">1214</span> checkOnlineRegionsReport(serverNode, regionNames);<a name="line.1214"></a>
-<span class="sourceLineNo">1215</span> }<a name="line.1215"></a>
-<span class="sourceLineNo">1216</span><a name="line.1216"></a>
-<span class="sourceLineNo">1217</span> /**<a name="line.1217"></a>
-<span class="sourceLineNo">1218</span> * Close <code>regionName</code> on <code>sn</code> silently and immediately without<a name="line.1218"></a>
-<span class="sourceLineNo">1219</span> * using a Procedure or going via hbase:meta. For case where a RegionServer's hosting<a name="line.1219"></a>
-<span class="sourceLineNo">1220</span> * of a Region is not aligned w/ the Master's accounting of Region state. This is for<a name="line.1220"></a>
-<span class="sourceLineNo">1221</span> * cleaning up an error in accounting.<a name="line.1221"></a>
-<span class="sourceLineNo">1222</span> */<a name="line.1222"></a>
-<span class="sourceLineNo">1223</span> private void closeRegionSilently(ServerName sn, byte [] regionName) {<a name="line.1223"></a>
-<span class="sourceLineNo">1224</span> try {<a name="line.1224"></a>
-<span class="sourceLineNo">1225</span> RegionInfo ri = CatalogFamilyFormat.parseRegionInfoFromRegionName(regionName);<a name="line.1225"></a>
-<span class="sourceLineNo">1226</span> // Pass -1 for timeout. Means do not wait.<a name="line.1226"></a>
-<span class="sourceLineNo">1227</span> ServerManager.closeRegionSilentlyAndWait(this.master.getAsyncClusterConnection(), sn, ri, -1);<a name="line.1227"></a>
-<span class="sourceLineNo">1228</span> } catch (Exception e) {<a name="line.1228"></a>
-<span class="sourceLineNo">1229</span> LOG.error("Failed trying to close {} on {}", Bytes.toStringBinary(regionName), sn, e);<a name="line.1229"></a>
-<span class="sourceLineNo">1230</span> }<a name="line.1230"></a>
+<span class="sourceLineNo">1154</span> private void updateRegionMergeTransition(final ServerName serverName, final TransitionCode state,<a name="line.1154"></a>
+<span class="sourceLineNo">1155</span> final RegionInfo merged, final RegionInfo hriA, final RegionInfo hriB) throws IOException {<a name="line.1155"></a>
+<span class="sourceLineNo">1156</span> checkMetaLoaded(merged);<a name="line.1156"></a>
+<span class="sourceLineNo">1157</span><a name="line.1157"></a>
+<span class="sourceLineNo">1158</span> if (state != TransitionCode.READY_TO_MERGE) {<a name="line.1158"></a>
+<span class="sourceLineNo">1159</span> throw new UnexpectedStateException("Unsupported merge regionState=" + state +<a name="line.1159"></a>
+<span class="sourceLineNo">1160</span> " for regionA=" + hriA + " regionB=" + hriB + " merged=" + merged +<a name="line.1160"></a>
+<span class="sourceLineNo">1161</span> " maybe an old RS (< 2.0) had the operation in progress");<a name="line.1161"></a>
+<span class="sourceLineNo">1162</span> }<a name="line.1162"></a>
+<span class="sourceLineNo">1163</span><a name="line.1163"></a>
+<span class="sourceLineNo">1164</span> if (!master.isSplitOrMergeEnabled(MasterSwitchType.MERGE)) {<a name="line.1164"></a>
+<span class="sourceLineNo">1165</span> LOG.warn("Merge switch is off! skip merge of regionA=" + hriA + " regionB=" + hriB);<a name="line.1165"></a>
+<span class="sourceLineNo">1166</span> throw new DoNotRetryIOException("Merge of regionA=" + hriA + " regionB=" + hriB +<a name="line.1166"></a>
+<span class="sourceLineNo">1167</span> " failed because merge switch is off");<a name="line.1167"></a>
+<span class="sourceLineNo">1168</span> }<a name="line.1168"></a>
+<span class="sourceLineNo">1169</span><a name="line.1169"></a>
+<span class="sourceLineNo">1170</span> // Submit the Merge procedure<a name="line.1170"></a>
+<span class="sourceLineNo">1171</span> if (LOG.isDebugEnabled()) {<a name="line.1171"></a>
+<span class="sourceLineNo">1172</span> LOG.debug("Handling merge request from RS=" + merged + ", merged=" + merged);<a name="line.1172"></a>
+<span class="sourceLineNo">1173</span> }<a name="line.1173"></a>
+<span class="sourceLineNo">1174</span> master.getMasterProcedureExecutor().submitProcedure(createMergeProcedure(hriA, hriB));<a name="line.1174"></a>
+<span class="sourceLineNo">1175</span><a name="line.1175"></a>
+<span class="sourceLineNo">1176</span> // If the RS is < 2.0 throw an exception to abort the operation, we are handling the merge<a name="line.1176"></a>
+<span class="sourceLineNo">1177</span> if (master.getServerManager().getVersionNumber(serverName) < 0x0200000) {<a name="line.1177"></a>
+<span class="sourceLineNo">1178</span> throw new UnsupportedOperationException(String.format(<a name="line.1178"></a>
+<span class="sourceLineNo">1179</span> "Merge not handled yet: regionState=%s merged=%s hriA=%s hriB=%s", state, merged, hriA,<a name="line.1179"></a>
+<span class="sourceLineNo">1180</span> hriB));<a name="line.1180"></a>
+<span class="sourceLineNo">1181</span> }<a name="line.1181"></a>
+<span class="sourceLineNo">1182</span> }<a name="line.1182"></a>
+<span class="sourceLineNo">1183</span><a name="line.1183"></a>
+<span class="sourceLineNo">1184</span> // ============================================================================================<a name="line.1184"></a>
+<span class="sourceLineNo">1185</span> // RS Status update (report online regions) helpers<a name="line.1185"></a>
+<span class="sourceLineNo">1186</span> // ============================================================================================<a name="line.1186"></a>
+<span class="sourceLineNo">1187</span> /**<a name="line.1187"></a>
+<span class="sourceLineNo">1188</span> * The master will call this method when the RS send the regionServerReport(). The report will<a name="line.1188"></a>
+<span class="sourceLineNo">1189</span> * contains the "online regions". This method will check the the online regions against the<a name="line.1189"></a>
+<span class="sourceLineNo">1190</span> * in-memory state of the AM, and we will log a warn message if there is a mismatch. This is<a name="line.1190"></a>
+<span class="sourceLineNo">1191</span> * because that there is no fencing between the reportRegionStateTransition method and<a name="line.1191"></a>
+<span class="sourceLineNo">1192</span> * regionServerReport method, so there could be race and introduce inconsistency here, but<a name="line.1192"></a>
+<span class="sourceLineNo">1193</span> * actually there is no problem.<a name="line.1193"></a>
+<span class="sourceLineNo">1194</span> * <p/><a name="line.1194"></a>
+<span class="sourceLineNo">1195</span> * Please see HBASE-21421 and HBASE-21463 for more details.<a name="line.1195"></a>
+<span class="sourceLineNo">1196</span> */<a name="line.1196"></a>
+<span class="sourceLineNo">1197</span> public void reportOnlineRegions(ServerName serverName, Set<byte[]> regionNames) {<a name="line.1197"></a>
+<span class="sourceLineNo">1198</span> if (!isRunning()) {<a name="line.1198"></a>
+<span class="sourceLineNo">1199</span> return;<a name="line.1199"></a>
+<span class="sourceLineNo">1200</span> }<a name="line.1200"></a>
+<span class="sourceLineNo">1201</span> if (LOG.isTraceEnabled()) {<a name="line.1201"></a>
+<span class="sourceLineNo">1202</span> LOG.trace("ReportOnlineRegions {} regionCount={}, metaLoaded={} {}", serverName,<a name="line.1202"></a>
+<span class="sourceLineNo">1203</span> regionNames.size(), isMetaLoaded(),<a name="line.1203"></a>
+<span class="sourceLineNo">1204</span> regionNames.stream().map(Bytes::toStringBinary).collect(Collectors.toList()));<a name="line.1204"></a>
+<span class="sourceLineNo">1205</span> }<a name="line.1205"></a>
+<span class="sourceLineNo">1206</span><a name="line.1206"></a>
+<span class="sourceLineNo">1207</span> ServerStateNode serverNode = regionStates.getOrCreateServer(serverName);<a name="line.1207"></a>
+<span class="sourceLineNo">1208</span> synchronized (serverNode) {<a name="line.1208"></a>
+<span class="sourceLineNo">1209</span> if (!serverNode.isInState(ServerState.ONLINE)) {<a name="line.1209"></a>
+<span class="sourceLineNo">1210</span> LOG.warn("Got a report from a server result in state " + serverNode.getState());<a name="line.1210"></a>
+<span class="sourceLineNo">1211</span> return;<a name="line.1211"></a>
+<span class="sourceLineNo">1212</span> }<a name="line.1212"></a>
+<span class="sourceLineNo">1213</span> }<a name="line.1213"></a>
+<span class="sourceLineNo">1214</span><a name="line.1214"></a>
+<span class="sourceLineNo">1215</span> // Track the regionserver reported online regions in memory.<a name="line.1215"></a>
+<span class="sourceLineNo">1216</span> synchronized (rsReports) {<a name="line.1216"></a>
+<span class="sourceLineNo">1217</span> rsReports.put(serverName, regionNames);<a name="line.1217"></a>
+<span class="sourceLineNo">1218</span> }<a name="line.1218"></a>
+<span class="sourceLineNo">1219</span><a name="line.1219"></a>
+<span class="sourceLineNo">1220</span> if (regionNames.isEmpty()) {<a name="line.1220"></a>
+<span class="sourceLineNo">1221</span> // nothing to do if we don't have regions<a name="line.1221"></a>
+<span class="sourceLineNo">1222</span> LOG.trace("no online region found on {}", serverName);<a name="line.1222"></a>
+<span class="sourceLineNo">1223</span> return;<a name="line.1223"></a>
+<span class="sourceLineNo">1224</span> }<a name="line.1224"></a>
+<span class="sourceLineNo">1225</span> if (!isMetaLoaded()) {<a name="line.1225"></a>
+<span class="sourceLineNo">1226</span> // we are still on startup, skip checking<a name="line.1226"></a>
+<span class="sourceLineNo">1227</span> return;<a name="line.1227"></a>
+<span class="sourceLineNo">1228</span> }<a name="line.1228"></a>
+<span class="sourceLineNo">1229</span> // The Heartbeat tells us of what regions are on the region serve, check the state.<a name="line.1229"></a>
+<span class="sourceLineNo">1230</span> checkOnlineRegionsReport(serverNode, regionNames);<a name="line.1230"></a>
<span class="sourceLineNo">1231</span> }<a name="line.1231"></a>
<span class="sourceLineNo">1232</span><a name="line.1232"></a>
<span class="sourceLineNo">1233</span> /**<a name="line.1233"></a>
-<span class="sourceLineNo">1234</span> * Check that what the RegionServer reports aligns with the Master's image.<a name="line.1234"></a>
-<span class="sourceLineNo">1235</span> * If disagreement, we will tell the RegionServer to expediently close<a name="line.1235"></a>
-<span class="sourceLineNo">1236</span> * a Region we do not think it should have.<a name="line.1236"></a>
-<span class="sourceLineNo">1237</span> */<a name="line.1237"></a>
-<span class="sourceLineNo">1238</span> private void checkOnlineRegionsReport(ServerStateNode serverNode, Set<byte[]> regionNames) {<a name="line.1238"></a>
-<span class="sourceLineNo">1239</span> ServerName serverName = serverNode.getServerName();<a name="line.1239"></a>
-<span class="sourceLineNo">1240</span> for (byte[] regionName : regionNames) {<a name="line.1240"></a>
-<span class="sourceLineNo">1241</span> if (!isRunning()) {<a name="line.1241"></a>
-<span class="sourceLineNo">1242</span> return;<a name="line.1242"></a>
-<span class="sourceLineNo">1243</span> }<a name="line.1243"></a>
-<span class="sourceLineNo">1244</span> RegionStateNode regionNode = regionStates.getRegionStateNodeFromName(regionName);<a name="line.1244"></a>
-<span class="sourceLineNo">1245</span> if (regionNode == null) {<a name="line.1245"></a>
-<span class="sourceLineNo">1246</span> String regionNameAsStr = Bytes.toStringBinary(regionName);<a name="line.1246"></a>
-<span class="sourceLineNo">1247</span> LOG.warn("No RegionStateNode for {} but reported as up on {}; closing...",<a name="line.1247"></a>
-<span class="sourceLineNo">1248</span> regionNameAsStr, serverName);<a name="line.1248"></a>
-<span class="sourceLineNo">1249</span> closeRegionSilently(serverNode.getServerName(), regionName);<a name="line.1249"></a>
-<span class="sourceLineNo">1250</span> continue;<a name="line.1250"></a>
-<span class="sourceLineNo">1251</span> }<a name="line.1251"></a>
-<span class="sourceLineNo">1252</span> final long lag = 1000;<a name="line.1252"></a>
-<span class="sourceLineNo">1253</span> regionNode.lock();<a name="line.1253"></a>
-<span class="sourceLineNo">1254</span> try {<a name="line.1254"></a>
-<span class="sourceLineNo">1255</span> long diff = EnvironmentEdgeManager.currentTime() - regionNode.getLastUpdate();<a name="line.1255"></a>
-<span class="sourceLineNo">1256</span> if (regionNode.isInState(State.OPENING, State.OPEN)) {<a name="line.1256"></a>
-<span class="sourceLineNo">1257</span> // This is possible as a region server has just closed a region but the region server<a name="line.1257"></a>
-<span class="sourceLineNo">1258</span> // report is generated before the closing, but arrive after the closing. Make sure there<a name="line.1258"></a>
-<span class="sourceLineNo">1259</span> // is some elapsed time so less false alarms.<a name="line.1259"></a>
-<span class="sourceLineNo">1260</span> if (!regionNode.getRegionLocation().equals(serverName) && diff > lag) {<a name="line.1260"></a>
-<span class="sourceLineNo">1261</span> LOG.warn("Reporting {} server does not match {} (time since last " +<a name="line.1261"></a>
-<span class="sourceLineNo">1262</span> "update={}ms); closing...",<a name="line.1262"></a>
-<span class="sourceLineNo">1263</span> serverName, regionNode, diff);<a name="line.1263"></a>
-<span class="sourceLineNo">1264</span> closeRegionSilently(serverNode.getServerName(), regionName);<a name="line.1264"></a>
-<span class="sourceLineNo">1265</span> }<a name="line.1265"></a>
-<span class="sourceLineNo">1266</span> } else if (!regionNode.isInState(State.CLOSING, State.SPLITTING)) {<a name="line.1266"></a>
-<span class="sourceLineNo">1267</span> // So, we can get report that a region is CLOSED or SPLIT because a heartbeat<a name="line.1267"></a>
-<span class="sourceLineNo">1268</span> // came in at about same time as a region transition. Make sure there is some<a name="line.1268"></a>
-<span class="sourceLineNo">1269</span> // elapsed time so less false alarms.<a name="line.1269"></a>
-<span class="sourceLineNo">1270</span> if (diff > lag) {<a name="line.1270"></a>
-<span class="sourceLineNo">1271</span> LOG.warn("Reporting {} state does not match {} (time since last update={}ms)",<a name="line.1271"></a>
-<span class="sourceLineNo">1272</span> serverName, regionNode, diff);<a name="line.1272"></a>
-<span class="sourceLineNo">1273</span> }<a name="line.1273"></a>
-<span class="sourceLineNo">1274</span> }<a name="line.1274"></a>
-<span class="sourceLineNo">1275</span> } finally {<a name="line.1275"></a>
-<span class="sourceLineNo">1276</span> regionNode.unlock();<a name="line.1276"></a>
-<span class="sourceLineNo">1277</span> }<a name="line.1277"></a>
-<span class="sourceLineNo">1278</span> }<a name="line.1278"></a>
-<span class="sourceLineNo">1279</span> }<a name="line.1279"></a>
-<span class="sourceLineNo">1280</span><a name="line.1280"></a>
-<span class="sourceLineNo">1281</span> // ============================================================================================<a name="line.1281"></a>
-<span class="sourceLineNo">1282</span> // RIT chore<a name="line.1282"></a>
-<span class="sourceLineNo">1283</span> // ============================================================================================<a name="line.1283"></a>
-<span class="sourceLineNo">1284</span> private static class RegionInTransitionChore extends ProcedureInMemoryChore<MasterProcedureEnv> {<a name="line.1284"></a>
-<span class="sourceLineNo">1285</span> public RegionInTransitionChore(final int timeoutMsec) {<a name="line.1285"></a>
-<span class="sourceLineNo">1286</span> super(timeoutMsec);<a name="line.1286"></a>
-<span class="sourceLineNo">1287</span> }<a name="line.1287"></a>
-<span class="sourceLineNo">1288</span><a name="line.1288"></a>
-<span class="sourceLineNo">1289</span> @Override<a name="line.1289"></a>
-<span class="sourceLineNo">1290</span> protected void periodicExecute(final MasterProcedureEnv env) {<a name="line.1290"></a>
-<span class="sourceLineNo">1291</span> final AssignmentManager am = env.getAssignmentManager();<a name="line.1291"></a>
-<span class="sourceLineNo">1292</span><a name="line.1292"></a>
-<span class="sourceLineNo">1293</span> final RegionInTransitionStat ritStat = am.computeRegionInTransitionStat();<a name="line.1293"></a>
-<span class="sourceLineNo">1294</span> if (ritStat.hasRegionsOverThreshold()) {<a name="line.1294"></a>
-<span class="sourceLineNo">1295</span> for (RegionState hri: ritStat.getRegionOverThreshold()) {<a name="line.1295"></a>
-<span class="sourceLineNo">1296</span> am.handleRegionOverStuckWarningThreshold(hri.getRegion());<a name="line.1296"></a>
-<span class="sourceLineNo">1297</span> }<a name="line.1297"></a>
-<span class="sourceLineNo">1298</span> }<a name="line.1298"></a>
-<span class="sourceLineNo">1299</span><a name="line.1299"></a>
-<span class="sourceLineNo">1300</span> // update metrics<a name="line.1300"></a>
-<span class="sourceLineNo">1301</span> am.updateRegionsInTransitionMetrics(ritStat);<a name="line.1301"></a>
-<span class="sourceLineNo">1302</span> }<a name="line.1302"></a>
-<span class="sourceLineNo">1303</span> }<a name="line.1303"></a>
+<span class="sourceLineNo">1234</span> * Close <code>regionName</code> on <code>sn</code> silently and immediately without<a name="line.1234"></a>
+<span class="sourceLineNo">1235</span> * using a Procedure or going via hbase:meta. For case where a RegionServer's hosting<a name="line.1235"></a>
+<span class="sourceLineNo">1236</span> * of a Region is not aligned w/ the Master's accounting of Region state. This is for<a name="line.1236"></a>
+<span class="sourceLineNo">1237</span> * cleaning up an error in accounting.<a name="line.1237"></a>
+<span class="sourceLineNo">1238</span> */<a name="line.1238"></a>
+<span class="sourceLineNo">1239</span> private void closeRegionSilently(ServerName sn, byte [] regionName) {<a name="line.1239"></a>
+<span class="sourceLineNo">1240</span> try {<a name="line.1240"></a>
+<span class="sourceLineNo">1241</span> RegionInfo ri = CatalogFamilyFormat.parseRegionInfoFromRegionName(regionName);<a name="line.1241"></a>
+<span class="sourceLineNo">1242</span> // Pass -1 for timeout. Means do not wait.<a name="line.1242"></a>
+<span class="sourceLineNo">1243</span> ServerManager.closeRegionSilentlyAndWait(this.master.getAsyncClusterConnection(), sn, ri, -1);<a name="line.1243"></a>
+<span class="sourceLineNo">1244</span> } catch (Exception e) {<a name="line.1244"></a>
+<span class="sourceLineNo">1245</span> LOG.error("Failed trying to close {} on {}", Bytes.toStringBinary(regionName), sn, e);<a name="line.1245"></a>
+<span class="sourceLineNo">1246</span> }<a name="line.1246"></a>
+<span class="sourceLineNo">1247</span> }<a name="line.1247"></a>
+<span class="sourceLineNo">1248</span><a name="line.1248"></a>
+<span class="sourceLineNo">1249</span> /**<a name="line.1249"></a>
+<span class="sourceLineNo">1250</span> * Check that what the RegionServer reports aligns with the Master's image.<a name="line.1250"></a>
+<span class="sourceLineNo">1251</span> * If disagreement, we will tell the RegionServer to expediently close<a name="line.1251"></a>
+<span class="sourceLineNo">1252</span> * a Region we do not think it should have.<a name="line.1252"></a>
+<span class="sourceLineNo">1253</span> */<a name="line.1253"></a>
+<span class="sourceLineNo">1254</span> private void checkOnlineRegionsReport(ServerStateNode serverNode, Set<byte[]> regionNames) {<a name="line.1254"></a>
+<span class="sourceLineNo">1255</span> ServerName serverName = serverNode.getServerName();<a name="line.1255"></a>
+<span class="sourceLineNo">1256</span> for (byte[] regionName : regionNames) {<a name="line.1256"></a>
+<span class="sourceLineNo">1257</span> if (!isRunning()) {<a name="line.1257"></a>
+<span class="sourceLineNo">1258</span> return;<a name="line.1258"></a>
+<span class="sourceLineNo">1259</span> }<a name="line.1259"></a>
+<span class="sourceLineNo">1260</span> RegionStateNode regionNode = regionStates.getRegionStateNodeFromName(regionName);<a name="line.1260"></a>
+<span class="sourceLineNo">1261</span> if (regionNode == null) {<a name="line.1261"></a>
+<span class="sourceLineNo">1262</span> String regionNameAsStr = Bytes.toStringBinary(regionName);<a name="line.1262"></a>
+<span class="sourceLineNo">1263</span> LOG.warn("No RegionStateNode for {} but reported as up on {}; closing...",<a name="line.1263"></a>
+<span class="sourceLineNo">1264</span> regionNameAsStr, serverName);<a name="line.1264"></a>
+<span class="sourceLineNo">1265</span> closeRegionSilently(serverNode.getServerName(), regionName);<a name="line.1265"></a>
+<span class="sourceLineNo">1266</span> continue;<a name="line.1266"></a>
+<span class="sourceLineNo">1267</span> }<a name="line.1267"></a>
+<span class="sourceLineNo">1268</span> final long lag = 1000;<a name="line.1268"></a>
+<span class="sourceLineNo">1269</span> regionNode.lock();<a name="line.1269"></a>
+<span class="sourceLineNo">1270</span> try {<a name="line.1270"></a>
+<span class="sourceLineNo">1271</span> long diff = EnvironmentEdgeManager.currentTime() - regionNode.getLastUpdate();<a name="line.1271"></a>
+<span class="sourceLineNo">1272</span> if (regionNode.isInState(State.OPENING, State.OPEN)) {<a name="line.1272"></a>
+<span class="sourceLineNo">1273</span> // This is possible as a region server has just closed a region but the region server<a name="line.1273"></a>
+<span class="sourceLineNo">1274</span> // report is generated before the closing, but arrive after the closing. Make sure there<a name="line.1274"></a>
+<span class="sourceLineNo">1275</span> // is some elapsed time so less false alarms.<a name="line.1275"></a>
+<span class="sourceLineNo">1276</span> if (!regionNode.getRegionLocation().equals(serverName) && diff > lag) {<a name="line.1276"></a>
+<span class="sourceLineNo">1277</span> LOG.warn("Reporting {} server does not match {} (time since last " +<a name="line.1277"></a>
+<span class="sourceLineNo">1278</span> "update={}ms); closing...",<a name="line.1278"></a>
+<span class="sourceLineNo">1279</span> serverName, regionNode, diff);<a name="line.1279"></a>
+<span class="sourceLineNo">1280</span> closeRegionSilently(serverNode.getServerName(), regionName);<a name="line.1280"></a>
+<span class="sourceLineNo">1281</span> }<a name="line.1281"></a>
+<span class="sourceLineNo">1282</span> } else if (!regionNode.isInState(State.CLOSING, State.SPLITTING)) {<a name="line.1282"></a>
+<span class="sourceLineNo">1283</span> // So, we can get report that a region is CLOSED or SPLIT because a heartbeat<a name="line.1283"></a>
+<span class="sourceLineNo">1284</span> // came in at about same time as a region transition. Make sure there is some<a name="line.1284"></a>
+<span class="sourceLineNo">1285</span> // elapsed time so less false alarms.<a name="line.1285"></a>
+<span class="sourceLineNo">1286</span> if (diff > lag) {<a name="line.1286"></a>
+<span class="sourceLineNo">1287</span> LOG.warn("Reporting {} state does not match {} (time since last update={}ms)",<a name="line.1287"></a>
+<span class="sourceLineNo">1288</span> serverName, regionNode, diff);<a name="line.1288"></a>
+<span class="sourceLineNo">1289</span> }<a name="line.1289"></a>
+<span class="sourceLineNo">1290</span> }<a name="line.1290"></a>
+<span class="sourceLineNo">1291</span> } finally {<a name="line.1291"></a>
+<span class="sourceLineNo">1292</span> regionNode.unlock();<a name="line.1292"></a>
+<span class="sourceLineNo">1293</span> }<a name="line.1293"></a>
+<span class="sourceLineNo">1294</span> }<a name="line.1294"></a>
+<span class="sourceLineNo">1295</span> }<a name="line.1295"></a>
+<span class="sourceLineNo">1296</span><a name="line.1296"></a>
+<span class="sourceLineNo">1297</span> // ============================================================================================<a name="line.1297"></a>
+<span class="sourceLineNo">1298</span> // RIT chore<a name="line.1298"></a>
+<span class="sourceLineNo">1299</span> // ============================================================================================<a name="line.1299"></a>
+<span class="sourceLineNo">1300</span> private static class RegionInTransitionChore extends ProcedureInMemoryChore<MasterProcedureEnv> {<a name="line.1300"></a>
+<span class="sourceLineNo">1301</span> public RegionInTransitionChore(final int timeoutMsec) {<a name="line.1301"></a>
+<span class="sourceLineNo">1302</span> super(timeoutMsec);<a name="line.1302"></a>
+<span class="sourceLineNo">1303</span> }<a name="line.1303"></a>
<span class="sourceLineNo">1304</span><a name="line.1304"></a>
-<span class="sourceLineNo">1305</span> private static class DeadServerMetricRegionChore<a name="line.1305"></a>
-<span class="sourceLineNo">1306</span> extends ProcedureInMemoryChore<MasterProcedureEnv> {<a name="line.1306"></a>
-<span class="sourceLineNo">1307</span> public DeadServerMetricRegionChore(final int timeoutMsec) {<a name="line.1307"></a>
-<span class="sourceLineNo">1308</span> super(timeoutMsec);<a name="line.1308"></a>
-<span class="sourceLineNo">1309</span> }<a name="line.1309"></a>
-<span class="sourceLineNo">1310</span><a name="line.1310"></a>
-<span class="sourceLineNo">1311</span> @Override<a name="line.1311"></a>
-<span class="sourceLineNo">1312</span> protected void periodicExecute(final MasterProcedureEnv env) {<a name="line.1312"></a>
-<span class="sourceLineNo">1313</span> final ServerManager sm = env.getMasterServices().getServerManager();<a name="line.1313"></a>
-<span class="sourceLineNo">1314</span> final AssignmentManager am = env.getAssignmentManager();<a name="line.1314"></a>
-<span class="sourceLineNo">1315</span> // To minimize inconsistencies we are not going to snapshot live servers in advance in case<a name="line.1315"></a>
-<span class="sourceLineNo">1316</span> // new servers are added; OTOH we don't want to add heavy sync for a consistent view since<a name="line.1316"></a>
-<span class="sourceLineNo">1317</span> // this is for metrics. Instead, we're going to check each regions as we go; to avoid making<a name="line.1317"></a>
-<span class="sourceLineNo">1318</span> // too many checks, we maintain a local lists of server, limiting us to false negatives. If<a name="line.1318"></a>
-<span class="sourceLineNo">1319</span> // we miss some recently-dead server, we'll just see it next time.<a name="line.1319"></a>
-<span class="sourceLineNo">1320</span> Set<ServerName> recentlyLiveServers = new HashSet<>();<a name="line.1320"></a>
-<span class="sourceLineNo">1321</span> int deadRegions = 0, unknownRegions = 0;<a name="line.1321"></a>
-<span class="sourceLineNo">1322</span> for (RegionStateNode rsn : am.getRegionStates().getRegionStateNodes()) {<a name="line.1322"></a>
-<span class="sourceLineNo">1323</span> if (rsn.getState() != State.OPEN) {<a name="line.1323"></a>
-<span class="sourceLineNo">1324</span> continue; // Opportunistic check, should quickly skip RITs, offline tables, etc.<a name="line.1324"></a>
-<span class="sourceLineNo">1325</span> }<a name="line.1325"></a>
-<span class="sourceLineNo">1326</span> // Do not need to acquire region state lock as this is only for showing metrics.<a name="line.1326"></a>
-<span class="sourceLineNo">1327</span> ServerName sn = rsn.getRegionLocation();<a name="line.1327"></a>
-<span class="sourceLineNo">1328</span> State state = rsn.getState();<a name="line.1328"></a>
-<span class="sourceLineNo">1329</span> if (state != State.OPEN) {<a name="line.1329"></a>
-<span class="sourceLineNo">1330</span> continue; // Mostly skipping RITs that are already being take care of.<a name="line.1330"></a>
-<span class="sourceLineNo">1331</span> }<a name="line.1331"></a>
-<span class="sourceLineNo">1332</span> if (sn == null) {<a name="line.1332"></a>
-<span class="sourceLineNo">1333</span> ++unknownRegions; // Opened on null?<a name="line.1333"></a>
-<span class="sourceLineNo">1334</span> continue;<a name="line.1334"></a>
-<span class="sourceLineNo">1335</span> }<a name="line.1335"></a>
-<span class="sourceLineNo">1336</span> if (recentlyLiveServers.contains(sn)) {<a name="line.1336"></a>
-<span class="sourceLineNo">1337</span> continue;<a name="line.1337"></a>
-<span class="sourceLineNo">1338</span> }<a name="line.1338"></a>
-<span class="sourceLineNo">1339</span> ServerManager.ServerLiveState sls = sm.isServerKnownAndOnline(sn);<a name="line.1339"></a>
-<span class="sourceLineNo">1340</span> switch (sls) {<a name="line.1340"></a>
-<span class="sourceLineNo">1341</span> case LIVE:<a name="line.1341"></a>
-<span class="sourceLineNo">1342</span> recentlyLiveServers.add(sn);<a name="line.1342"></a>
-<span class="sourceLineNo">1343</span> break;<a name="line.1343"></a>
-<span class="sourceLineNo">1344</span> case DEAD:<a name="line.1344"></a>
-<span class="sourceLineNo">1345</span> ++deadRegions;<a name="line.1345"></a>
-<span class="sourceLineNo">1346</span> break;<a name="line.1346"></a>
-<span class="sourceLineNo">1347</span> case UNKNOWN:<a name="line.1347"></a>
-<span class="sourceLineNo">1348</span> ++unknownRegions;<a name="line.1348"></a>
-<span class="sourceLineNo">1349</span> break;<a name="line.1349"></a>
-<span class="sourceLineNo">1350</span> default: throw new AssertionError("Unexpected " + sls);<a name="line.1350"></a>
+<span class="sourceLineNo">1305</span> @Override<a name="line.1305"></a>
+<span class="sourceLineNo">1306</span> protected void periodicExecute(final MasterProcedureEnv env) {<a name="line.1306"></a>
+<span class="sourceLineNo">1307</span> final AssignmentManager am = env.getAssignmentManager();<a name="line.1307"></a>
+<span class="sourceLineNo">1308</span><a name="line.1308"></a>
+<span class="sourceLineNo">1309</span> final RegionInTransitionStat ritStat = am.computeRegionInTransitionStat();<a name="line.1309"></a>
+<span class="sourceLineNo">1310</span> if (ritStat.hasRegionsOverThreshold()) {<a name="line.1310"></a>
+<span class="sourceLineNo">1311</span> for (RegionState hri: ritStat.getRegionOverThreshold()) {<a name="line.1311"></a>
+<span class="sourceLineNo">1312</span> am.handleRegionOverStuckWarningThreshold(hri.getRegion());<a name="line.1312"></a>
+<span class="sourceLineNo">1313</span> }<a name="line.1313"></a>
+<span class="sourceLineNo">1314</span> }<a name="line.1314"></a>
+<span class="sourceLineNo">1315</span><a name="line.1315"></a>
+<span class="sourceLineNo">1316</span> // update metrics<a name="line.1316"></a>
+<span class="sourceLineNo">1317</span> am.updateRegionsInTransitionMetrics(ritStat);<a name="line.1317"></a>
+<span class="sourceLineNo">1318</span> }<a name="line.1318"></a>
+<span class="sourceLineNo">1319</span> }<a name="line.1319"></a>
+<span class="sourceLineNo">1320</span><a name="line.1320"></a>
+<span class="sourceLineNo">1321</span> private static class DeadServerMetricRegionChore<a name="line.1321"></a>
+<span class="sourceLineNo">1322</span> extends ProcedureInMemoryChore<MasterProcedureEnv> {<a name="line.1322"></a>
+<span class="sourceLineNo">1323</span> public DeadServerMetricRegionChore(final int timeoutMsec) {<a name="line.1323"></a>
+<span class="sourceLineNo">1324</span> super(timeoutMsec);<a name="line.1324"></a>
+<span class="sourceLineNo">1325</span> }<a name="line.1325"></a>
+<span class="sourceLineNo">1326</span><a name="line.1326"></a>
+<span class="sourceLineNo">1327</span> @Override<a name="line.1327"></a>
+<span class="sourceLineNo">1328</span> protected void periodicExecute(final MasterProcedureEnv env) {<a name="line.1328"></a>
+<span class="sourceLineNo">1329</span> final ServerManager sm = env.getMasterServices().getServerManager();<a name="line.1329"></a>
+<span class="sourceLineNo">1330</span> final AssignmentManager am = env.getAssignmentManager();<a name="line.1330"></a>
+<span class="sourceLineNo">1331</span> // To minimize inconsistencies we are not going to snapshot live servers in advance in case<a name="line.1331"></a>
+<span class="sourceLineNo">1332</span> // new servers are added; OTOH we don't want to add heavy sync for a consistent view since<a name="line.1332"></a>
+<span class="sourceLineNo">1333</span> // this is for metrics. Instead, we're going to check each regions as we go; to avoid making<a name="line.1333"></a>
+<span class="sourceLineNo">1334</span> // too many checks, we maintain a local lists of server, limiting us to false negatives. If<a name="line.1334"></a>
+<span class="sourceLineNo">1335</span> // we miss some recently-dead server, we'll just see it next time.<a name="line.1335"></a>
+<span class="sourceLineNo">1336</span> Set<ServerName> recentlyLiveServers = new HashSet<>();<a name="line.1336"></a>
+<span class="sourceLineNo">1337</span> int deadRegions = 0, unknownRegions = 0;<a name="line.1337"></a>
+<span class="sourceLineNo">1338</span> for (RegionStateNode rsn : am.getRegionStates().getRegionStateNodes()) {<a name="line.1338"></a>
+<span class="sourceLineNo">1339</span> if (rsn.getState() != State.OPEN) {<a name="line.1339"></a>
+<span class="sourceLineNo">1340</span> continue; // Opportunistic check, should quickly skip RITs, offline tables, etc.<a name="line.1340"></a>
+<span class="sourceLineNo">1341</span> }<a name="line.1341"></a>
+<span class="sourceLineNo">1342</span> // Do not need to acquire region state lock as this is only for showing metrics.<a name="line.1342"></a>
+<span class="sourceLineNo">1343</span> ServerName sn = rsn.getRegionLocation();<a name="line.1343"></a>
+<span class="sourceLineNo">1344</span> State state = rsn.getState();<a name="line.1344"></a>
+<span class="sourceLineNo">1345</span> if (state != State.OPEN) {<a name="line.1345"></a>
+<span class="sourceLineNo">1346</span> continue; // Mostly skipping RITs that are already being take care of.<a name="line.1346"></a>
+<span class="sourceLineNo">1347</span> }<a name="line.1347"></a>
+<span class="sourceLineNo">1348</span> if (sn == null) {<a name="line.1348"></a>
+<span class="sourceLineNo">1349</span> ++unknownRegions; // Opened on null?<a name="line.1349"></a>
+<span class="sourceLineNo">1350</span> continue;<a name="line.1350"></a>
<span class="sourceLineNo">1351</span> }<a name="line.1351"></a>
-<span class="sourceLineNo">1352</span> }<a name="line.1352"></a>
-<span class="sourceLineNo">1353</span> if (deadRegions > 0 || unknownRegions > 0) {<a name="line.1353"></a>
-<span class="sourceLineNo">1354</span> LOG.info("Found {} OPEN regions on dead servers and {} OPEN regions on unknown servers",<a name="line.1354"></a>
-<span class="sourceLineNo">1355</span> deadRegions, unknownRegions);<a name="line.1355"></a>
-<span class="sourceLineNo">1356</span> }<a name="line.1356"></a>
-<span class="sourceLineNo">1357</span><a name="line.1357"></a>
-<span class="sourceLineNo">1358</span> am.updateDeadServerRegionMetrics(deadRegions, unknownRegions);<a name="line.1358"></a>
-<span class="sourceLineNo">1359</span> }<a name="line.1359"></a>
-<span class="sourceLineNo">1360</span> }<a name="line.1360"></a>
-<span class="sourceLineNo">1361</span><a name="line.1361"></a>
-<span class="sourceLineNo">1362</span> public RegionInTransitionStat computeRegionInTransitionStat() {<a name="line.1362"></a>
-<span class="sourceLineNo">1363</span> final RegionInTransitionStat rit = new RegionInTransitionStat(getConfiguration());<a name="line.1363"></a>
-<span class="sourceLineNo">1364</span> rit.update(this);<a name="line.1364"></a>
-<span class="sourceLineNo">1365</span> return rit;<a name="line.1365"></a>
-<span class="sourceLineNo">1366</span> }<a name="line.1366"></a>
-<span class="sourceLineNo">1367</span><a name="line.1367"></a>
-<span class="sourceLineNo">1368</span> public static class RegionInTransitionStat {<a name="line.1368"></a>
-<span class="sourceLineNo">1369</span> private final int ritThreshold;<a name="line.1369"></a>
-<span class="sourceLineNo">1370</span><a name="line.1370"></a>
-<span class="sourceLineNo">1371</span> private HashMap<String, RegionState> ritsOverThreshold = null;<a name="line.1371"></a>
-<span class="sourceLineNo">1372</span> private long statTimestamp;<a name="line.1372"></a>
-<span class="sourceLineNo">1373</span> private long oldestRITTime = 0;<a name="line.1373"></a>
-<span class="sourceLineNo">1374</span> private int totalRITsTwiceThreshold = 0;<a name="line.1374"></a>
-<span class="sourceLineNo">1375</span> private int totalRITs = 0;<a name="line.1375"></a>
-<span class="sourceLineNo">1376</span><a name="line.1376"></a>
-<span class="sourceLineNo">1377</span> public RegionInTransitionStat(final Configuration conf) {<a name="line.1377"></a>
-<span class="sourceLineNo">1378</span> this.ritThreshold =<a name="line.1378"></a>
-<span class="sourceLineNo">1379</span> conf.getInt(METRICS_RIT_STUCK_WARNING_THRESHOLD, DEFAULT_RIT_STUCK_WARNING_THRESHOLD);<a name="line.1379"></a>
-<span class="sourceLineNo">1380</span> }<a name="line.1380"></a>
-<span class="sourceLineNo">1381</span><a name="line.1381"></a>
-<span class="sourceLineNo">1382</span> public int getRITThreshold() {<a name="line.1382"></a>
-<span class="sourceLineNo">1383</span> return ritThreshold;<a name="line.1383"></a>
-<span class="sourceLineNo">1384</span> }<a name="line.1384"></a>
-<span class="sourceLineNo">1385</span><a name="line.1385"></a>
-<span class="sourceLineNo">1386</span> public long getTimestamp() {<a name="line.1386"></a>
-<span class="sourceLineNo">1387</span> return statTimestamp;<a name="line.1387"></a>
-<span class="sourceLineNo">1388</span> }<a name="line.1388"></a>
-<span class="sourceLineNo">1389</span><a name="line.1389"></a>
-<span class="sourceLineNo">1390</span> public int getTotalRITs() {<a name="line.1390"></a>
-<span class="sourceLineNo">1391</span> return totalRITs;<a name="line.1391"></a>
-<span class="sourceLineNo">1392</span> }<a name="line.1392"></a>
-<span class="sourceLineNo">1393</span><a name="line.1393"></a>
-<span class="sourceLineNo">1394</span> public long getOldestRITTime() {<a name="line.1394"></a>
-<span class="sourceLineNo">1395</span> return oldestRITTime;<a name="line.1395"></a>
+<span class="sourceLineNo">1352</span> if (recentlyLiveServers.contains(sn)) {<a name="line.1352"></a>
+<span class="sourceLineNo">1353</span> continue;<a name="line.1353"></a>
+<span class="sourceLineNo">1354</span> }<a name="line.1354"></a>
+<span class="sourceLineNo">1355</span> ServerManager.ServerLiveState sls = sm.isServerKnownAndOnline(sn);<a name="line.1355"></a>
+<span class="sourceLineNo">1356</span> switch (sls) {<a name="line.1356"></a>
+<span class="sourceLineNo">1357</span> case LIVE:<a name="line.1357"></a>
+<span class="sourceLineNo">1358</span> recentlyLiveServers.add(sn);<a name="line.1358"></a>
+<span class="sourceLineNo">1359</span> break;<a name="line.1359"></a>
+<span class="sourceLineNo">1360</span> case DEAD:<a name="line.1360"></a>
+<span class="sourceLineNo">1361</span> ++deadRegions;<a name="line.1361"></a>
+<span class="sourceLineNo">1362</span> break;<a name="line.1362"></a>
+<span class="sourceLineNo">1363</span> case UNKNOWN:<a name="line.1363"></a>
+<span class="sourceLineNo">1364</span> ++unknownRegions;<a name="line.1364"></a>
+<span class="sourceLineNo">1365</span> break;<a name="line.1365"></a>
+<span class="sourceLineNo">1366</span> default: throw new AssertionError("Unexpected " + sls);<a name="line.1366"></a>
+<span class="sourceLineNo">1367</span> }<a name="line.1367"></a>
+<span class="sourceLineNo">1368</span> }<a name="line.1368"></a>
+<span class="sourceLineNo">1369</span> if (deadRegions > 0 || unknownRegions > 0) {<a name="line.1369"></a>
+<span class="sourceLineNo">1370</span> LOG.info("Found {} OPEN regions on dead servers and {} OPEN regions on unknown servers",<a name="line.1370"></a>
+<span class="sourceLineNo">1371</span> deadRegions, unknownRegions);<a name="line.1371"></a>
+<span class="sourceLineNo">1372</span> }<a name="line.1372"></a>
+<span class="sourceLineNo">1373</span><a name="line.1373"></a>
+<span class="sourceLineNo">1374</span> am.updateDeadServerRegionMetrics(deadRegions, unknownRegions);<a name="line.1374"></a>
+<span class="sourceLineNo">1375</span> }<a name="line.1375"></a>
+<span class="sourceLineNo">1376</span> }<a name="line.1376"></a>
+<span class="sourceLineNo">1377</span><a name="line.1377"></a>
+<span class="sourceLineNo">1378</span> public RegionInTransitionStat computeRegionInTransitionStat() {<a name="line.1378"></a>
+<span class="sourceLineNo">1379</span> final RegionInTransitionStat rit = new RegionInTransitionStat(getConfiguration());<a name="line.1379"></a>
+<span class="sourceLineNo">1380</span> rit.update(this);<a name="line.1380"></a>
+<span class="sourceLineNo">1381</span> return rit;<a name="line.1381"></a>
+<span class="sourceLineNo">1382</span> }<a name="line.1382"></a>
+<span class="sourceLineNo">1383</span><a name="line.1383"></a>
+<span class="sourceLineNo">1384</span> public static class RegionInTransitionStat {<a name="line.1384"></a>
+<span class="sourceLineNo">1385</span> private final int ritThreshold;<a name="line.1385"></a>
+<span class="sourceLineNo">1386</span><a name="line.1386"></a>
+<span class="sourceLineNo">1387</span> private HashMap<String, RegionState> ritsOverThreshold = null;<a name="line.1387"></a>
+<span class="sourceLineNo">1388</span> private long statTimestamp;<a name="line.1388"></a>
+<span class="sourceLineNo">1389</span> private long oldestRITTime = 0;<a name="line.1389"></a>
+<span class="sourceLineNo">1390</span> private int totalRITsTwiceThreshold = 0;<a name="line.1390"></a>
+<span class="sourceLineNo">1391</span> private int totalRITs = 0;<a name="line.1391"></a>
+<span class="sourceLineNo">1392</span><a name="line.1392"></a>
+<span class="sourceLineNo">1393</span> public RegionInTransitionStat(final Configuration conf) {<a name="line.1393"></a>
+<span class="sourceLineNo">1394</span> this.ritThreshold =<a name="line.1394"></a>
+<span class="sourceLineNo">1395</span> conf.getInt(METRICS_RIT_STUCK_WARNING_THRESHOLD, DEFAULT_RIT_STUCK_WARNING_THRESHOLD);<a name="line.1395"></a>
<span class="sourceLineNo">1396</span> }<a name="line.1396"></a>
<span class="sourceLineNo">1397</span><a name="line.1397"></a>
-<span class="sourceLineNo">1398</span> public int getTotalRITsOverThreshold() {<a name="line.1398"></a>
-<span class="sourceLineNo">1399</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1399"></a>
-<span class="sourceLineNo">1400</span> return m != null ? m.size() : 0;<a name="line.1400"></a>
-<span class="sourceLineNo">1401</span> }<a name="line.1401"></a>
-<span class="sourceLineNo">1402</span><a name="line.1402"></a>
-<span class="sourceLineNo">1403</span> public boolean hasRegionsTwiceOverThreshold() {<a name="line.1403"></a>
-<span class="sourceLineNo">1404</span> return totalRITsTwiceThreshold > 0;<a name="line.1404"></a>
-<span class="sourceLineNo">1405</span> }<a name="line.1405"></a>
-<span class="sourceLineNo">1406</span><a name="line.1406"></a>
-<span class="sourceLineNo">1407</span> public boolean hasRegionsOverThreshold() {<a name="line.1407"></a>
-<span class="sourceLineNo">1408</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1408"></a>
-<span class="sourceLineNo">1409</span> return m != null && !m.isEmpty();<a name="line.1409"></a>
-<span class="sourceLineNo">1410</span> }<a name="line.1410"></a>
-<span class="sourceLineNo">1411</span><a name="line.1411"></a>
-<span class="sourceLineNo">1412</span> public Collection<RegionState> getRegionOverThreshold() {<a name="line.1412"></a>
-<span class="sourceLineNo">1413</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1413"></a>
-<span class="sourceLineNo">1414</span> return m != null? m.values(): Collections.emptySet();<a name="line.1414"></a>
-<span class="sourceLineNo">1415</span> }<a name="line.1415"></a>
-<span class="sourceLineNo">1416</span><a name="line.1416"></a>
-<span class="sourceLineNo">1417</span> public boolean isRegionOverThreshold(final RegionInfo regionInfo) {<a name="line.1417"></a>
-<span class="sourceLineNo">1418</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1418"></a>
-<span class="sourceLineNo">1419</span> return m != null && m.containsKey(regionInfo.getEncodedName());<a name="line.1419"></a>
-<span class="sourceLineNo">1420</span> }<a name="line.1420"></a>
-<span class="sourceLineNo">1421</span><a name="line.1421"></a>
-<span class="sourceLineNo">1422</span> public boolean isRegionTwiceOverThreshold(final RegionInfo regionInfo) {<a name="line.1422"></a>
-<span class="sourceLineNo">1423</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1423"></a>
-<span class="sourceLineNo">1424</span> if (m == null) {<a name="line.1424"></a>
-<span class="sourceLineNo">1425</span> return false;<a name="line.1425"></a>
-<span class="sourceLineNo">1426</span> }<a name="line.1426"></a>
-<span class="sourceLineNo">1427</span> final RegionState state = m.get(regionInfo.getEncodedName());<a name="line.1427"></a>
-<span class="sourceLineNo">1428</span> if (state == null) {<a name="line.1428"></a>
-<span class="sourceLineNo">1429</span> return false;<a name="line.1429"></a>
-<span class="sourceLineNo">1430</span> }<a name="line.1430"></a>
-<span class="sourceLineNo">1431</span> return (statTimestamp - state.getStamp()) > (ritThreshold * 2);<a name="line.1431"></a>
-<span class="sourceLineNo">1432</span> }<a name="line.1432"></a>
-<span class="sourceLineNo">1433</span><a name="line.1433"></a>
-<span class="sourceLineNo">1434</span> protected void update(final AssignmentManager am) {<a name="line.1434"></a>
-<span class="sourceLineNo">1435</span> final RegionStates regionStates = am.getRegionStates();<a name="line.1435"></a>
-<span class="sourceLineNo">1436</span> this.statTimestamp = EnvironmentEdgeManager.currentTime();<a name="line.1436"></a>
-<span class="sourceLineNo">1437</span> update(regionStates.getRegionsStateInTransition(), statTimestamp);<a name="line.1437"></a>
-<span class="sourceLineNo">1438</span> update(regionStates.getRegionFailedOpen(), statTimestamp);<a name="line.1438"></a>
-<span class="sourceLineNo">1439</span><a name="line.1439"></a>
-<span class="sourceLineNo">1440</span> if (LOG.isDebugEnabled() && ritsOverThreshold != null && !ritsOverThreshold.isEmpty()) {<a name="line.1440"></a>
-<span class="sourceLineNo">1441</span> LOG.debug("RITs over threshold: {}",<a name="line.1441"></a>
-<span class="sourceLineNo">1442</span> ritsOverThreshold.entrySet().stream()<a name="line.1442"></a>
-<span class="sourceLineNo">1443</span> .map(e -> e.getKey() + ":" + e.getValue().getState().name())<a name="line.1443"></a>
-<span class="sourceLineNo">1444</span> .collect(Collectors.joining("\n")));<a name="line.1444"></a>
-<span class="sourceLineNo">1445</span> }<a name="line.1445"></a>
-<span class="sourceLineNo">1446</span> }<a name="line.1446"></a>
-<span class="sourceLineNo">1447</span><a name="line.1447"></a>
-<span class="sourceLineNo">1448</span> private void update(final Collection<RegionState> regions, final long currentTime) {<a name="line.1448"></a>
-<span class="sourceLineNo">1449</span> for (RegionState state: regions) {<a name="line.1449"></a>
-<span class="sourceLineNo">1450</span> totalRITs++;<a name="line.1450"></a>
-<span class="sourceLineNo">1451</span> final long ritStartedMs = state.getStamp();<a name="line.1451"></a>
-<span class="sourceLineNo">1452</span> if (ritStartedMs == 0) {<a name="line.1452"></a>
-<span class="sourceLineNo">1453</span> // Don't output bogus values to metrics if they accidentally make it here.<a name="line.1453"></a>
-<span class="sourceLineNo">1454</span> LOG.warn("The RIT {} has no start time", state.getRegion());<a name="line.1454"></a>
-<span class="sourceLineNo">1455</span> continue;<a name="line.1455"></a>
-<span class="sourceLineNo">1456</span> }<a name="line.1456"></a>
-<span class="sourceLineNo">1457</span> final long ritTime = currentTime - ritStartedMs;<a name="line.1457"></a>
-<span class="sourceLineNo">1458</span> if (ritTime > ritThreshold) {<a name="line.1458"></a>
-<span class="sourceLineNo">1459</span> if (ritsOverThreshold == null) {<a name="line.1459"></a>
-<span class="sourceLineNo">1460</span> ritsOverThreshold = new HashMap<String, RegionState>();<a name="line.1460"></a>
-<span class="sourceLineNo">1461</span> }<a name="line.1461"></a>
-<span class="sourceLineNo">1462</span> ritsOverThreshold.put(state.getRegion().getEncodedName(), state);<a name="line.1462"></a>
-<span class="sourceLineNo">1463</span> totalRITsTwiceThreshold += (ritTime > (ritThreshold * 2)) ? 1 : 0;<a name="line.1463"></a>
-<span class="sourceLineNo">1464</span> }<a name="line.1464"></a>
-<span class="sourceLineNo">1465</span> if (oldestRITTime < ritTime) {<a name="line.1465"></a>
-<span class="sourceLineNo">1466</span> oldestRITTime = ritTime;<a name="line.1466"></a>
-<span class="sourceLineNo">1467</span> }<a name="line.1467"></a>
-<span class="sourceLineNo">1468</span> }<a name="line.1468"></a>
-<span class="sourceLineNo">1469</span> }<a name="line.1469"></a>
-<span class="sourceLineNo">1470</span> }<a name="line.1470"></a>
-<span class="sourceLineNo">1471</span><a name="line.1471"></a>
-<span class="sourceLineNo">1472</span> private void updateRegionsInTransitionMetrics(final RegionInTransitionStat ritStat) {<a name="line.1472"></a>
-<span class="sourceLineNo">1473</span> metrics.updateRITOldestAge(ritStat.getOldestRITTime());<a name="line.1473"></a>
-<span class="sourceLineNo">1474</span> metrics.updateRITCount(ritStat.getTotalRITs());<a name="line.1474"></a>
-<span class="sourceLineNo">1475</span> metrics.updateRITCountOverThreshold(ritStat.getTotalRITsOverThreshold());<a name="line.1475"></a>
-<span class="sourceLineNo">1476</span> }<a name="line.1476"></a>
-<span class="sourceLineNo">1477</span><a name="line.1477"></a>
-<span class="sourceLineNo">1478</span> private void updateDeadServerRegionMetrics(int deadRegions, int unknownRegions) {<a name="line.1478"></a>
-<span class="sourceLineNo">1479</span> metrics.updateDeadServerOpenRegions(deadRegions);<a name="line.1479"></a>
-<span class="sourceLineNo">1480</span> metrics.updateUnknownServerOpenRegions(unknownRegions);<a name="line.1480"></a>
-<span class="sourceLineNo">1481</span> }<a name="line.1481"></a>
-<span class="sourceLineNo">1482</span><a name="line.1482"></a>
-<span class="sourceLineNo">1483</span> private void handleRegionOverStuckWarningThreshold(final RegionInfo regionInfo) {<a name="line.1483"></a>
-<span class="sourceLineNo">1484</span> final RegionStateNode regionNode = regionStates.getRegionStateNode(regionInfo);<a name="line.1484"></a>
-<span class="sourceLineNo">1485</span> //if (regionNode.isStuck()) {<a name="line.1485"></a>
-<span class="sourceLineNo">1486</span> LOG.warn("STUCK Region-In-Transition {}", regionNode);<a name="line.1486"></a>
-<span class="sourceLineNo">1487</span> }<a name="line.1487"></a>
-<span class="sourceLineNo">1488</span><a name="line.1488"></a>
-<span class="sourceLineNo">1489</span> // ============================================================================================<a name="line.1489"></a>
-<span class="sourceLineNo">1490</span> // TODO: Master load/bootstrap<a name="line.1490"></a>
-<span class="sourceLineNo">1491</span> // ============================================================================================<a name="line.1491"></a>
-<span class="sourceLineNo">1492</span> public void joinCluster() throws IOException {<a name="line.1492"></a>
-<span class="sourceLineNo">1493</span> long startTime = System.nanoTime();<a name="line.1493"></a>
-<span class="sourceLineNo">1494</span> LOG.debug("Joining cluster...");<a name="line.1494"></a>
-<span class="sourceLineNo">1495</span><a name="line.1495"></a>
-<span class="sourceLineNo">1496</span> // Scan hbase:meta to build list of existing regions, servers, and assignment.<a name="line.1496"></a>
-<span class="sourceLineNo">1497</span> // hbase:meta is online now or will be. Inside loadMeta, we keep trying. Can't make progress<a name="line.1497"></a>
-<span class="sourceLineNo">1498</span> // w/o meta.<a name="line.1498"></a>
-<span class="sourceLineNo">1499</span> loadMeta();<a name="line.1499"></a>
-<span class="sourceLineNo">1500</span><a name="line.1500"></a>
-<span class="sourceLineNo">1501</span> while (master.getServerManager().countOfRegionServers() < 1) {<a name="line.1501"></a>
-<span class="sourceLineNo">1502</span> LOG.info("Waiting for RegionServers to join; current count={}",<a name="line.1502"></a>
-<span class="sourceLineNo">1503</span> master.getServerManager().countOfRegionServers());<a name="line.1503"></a>
-<span class="sourceLineNo">1504</span> Threads.sleep(250);<a name="line.1504"></a>
-<span class="sourceLineNo">1505</span> }<a name="line.1505"></a>
-<span class="sourceLineNo">1506</span> LOG.info("Number of RegionServers={}", master.getServerManager().countOfRegionServers());<a name="line.1506"></a>
-<span class="sourceLineNo">1507</span><a name="line.1507"></a>
-<span class="sourceLineNo">1508</span> // Start the chores<a name="line.1508"></a>
-<span class="sourceLineNo">1509</span> master.getMasterProcedureExecutor().addChore(this.ritChore);<a name="line.1509"></a>
-<span class="sourceLineNo">1510</span> master.getMasterProcedureExecutor().addChore(this.deadMetricChore);<a name="line.1510"></a>
+<span class="sourceLineNo">1398</span> public int getRITThreshold() {<a name="line.1398"></a>
+<span class="sourceLineNo">1399</span> return ritThreshold;<a name="line.1399"></a>
+<span class="sourceLineNo">1400</span> }<a name="line.1400"></a>
+<span class="sourceLineNo">1401</span><a name="line.1401"></a>
+<span class="sourceLineNo">1402</span> public long getTimestamp() {<a name="line.1402"></a>
+<span class="sourceLineNo">1403</span> return statTimestamp;<a name="line.1403"></a>
+<span class="sourceLineNo">1404</span> }<a name="line.1404"></a>
+<span class="sourceLineNo">1405</span><a name="line.1405"></a>
+<span class="sourceLineNo">1406</span> public int getTotalRITs() {<a name="line.1406"></a>
+<span class="sourceLineNo">1407</span> return totalRITs;<a name="line.1407"></a>
+<span class="sourceLineNo">1408</span> }<a name="line.1408"></a>
+<span class="sourceLineNo">1409</span><a name="line.1409"></a>
+<span class="sourceLineNo">1410</span> public long getOldestRITTime() {<a name="line.1410"></a>
+<span class="sourceLineNo">1411</span> return oldestRITTime;<a name="line.1411"></a>
+<span class="sourceLineNo">1412</span> }<a name="line.1412"></a>
+<span class="sourceLineNo">1413</span><a name="line.1413"></a>
+<span class="sourceLineNo">1414</span> public int getTotalRITsOverThreshold() {<a name="line.1414"></a>
+<span class="sourceLineNo">1415</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1415"></a>
+<span class="sourceLineNo">1416</span> return m != null ? m.size() : 0;<a name="line.1416"></a>
+<span class="sourceLineNo">1417</span> }<a name="line.1417"></a>
+<span class="sourceLineNo">1418</span><a name="line.1418"></a>
+<span class="sourceLineNo">1419</span> public boolean hasRegionsTwiceOverThreshold() {<a name="line.1419"></a>
+<span class="sourceLineNo">1420</span> return totalRITsTwiceThreshold > 0;<a name="line.1420"></a>
+<span class="sourceLineNo">1421</span> }<a name="line.1421"></a>
+<span class="sourceLineNo">1422</span><a name="line.1422"></a>
+<span class="sourceLineNo">1423</span> public boolean hasRegionsOverThreshold() {<a name="line.1423"></a>
+<span class="sourceLineNo">1424</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1424"></a>
+<span class="sourceLineNo">1425</span> return m != null && !m.isEmpty();<a name="line.1425"></a>
+<span class="sourceLineNo">1426</span> }<a name="line.1426"></a>
+<span class="sourceLineNo">1427</span><a name="line.1427"></a>
+<span class="sourceLineNo">1428</span> public Collection<RegionState> getRegionOverThreshold() {<a name="line.1428"></a>
+<span class="sourceLineNo">1429</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1429"></a>
+<span class="sourceLineNo">1430</span> return m != null? m.values(): Collections.emptySet();<a name="line.1430"></a>
+<span class="sourceLineNo">1431</span> }<a name="line.1431"></a>
+<span class="sourceLineNo">1432</span><a name="line.1432"></a>
+<span class="sourceLineNo">1433</span> public boolean isRegionOverThreshold(final RegionInfo regionInfo) {<a name="line.1433"></a>
+<span class="sourceLineNo">1434</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1434"></a>
+<span class="sourceLineNo">1435</span> return m != null && m.containsKey(regionInfo.getEncodedName());<a name="line.1435"></a>
+<span class="sourceLineNo">1436</span> }<a name="line.1436"></a>
+<span class="sourceLineNo">1437</span><a name="line.1437"></a>
+<span class="sourceLineNo">1438</span> public boolean isRegionTwiceOverThreshold(final RegionInfo regionInfo) {<a name="line.1438"></a>
+<span class="sourceLineNo">1439</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1439"></a>
+<span class="sourceLineNo">1440</span> if (m == null) {<a name="line.1440"></a>
+<span class="sourceLineNo">1441</span> return false;<a name="line.1441"></a>
+<span class="sourceLineNo">1442</span> }<a name="line.1442"></a>
+<span class="sourceLineNo">1443</span> final RegionState state = m.get(regionInfo.getEncodedName());<a name="line.1443"></a>
+<span class="sourceLineNo">1444</span> if (state == null) {<a name="line.1444"></a>
+<span class="sourceLineNo">1445</span> return false;<a name="line.1445"></a>
+<span class="sourceLineNo">1446</span> }<a name="line.1446"></a>
+<span class="sourceLineNo">1447</span> return (statTimestamp - state.getStamp()) > (ritThreshold * 2);<a name="line.1447"></a>
+<span class="sourceLineNo">1448</span> }<a name="line.1448"></a>
+<span class="sourceLineNo">1449</span><a name="line.1449"></a>
+<span class="sourceLineNo">1450</span> protected void update(final AssignmentManager am) {<a name="line.1450"></a>
+<span class="sourceLineNo">1451</span> final RegionStates regionStates = am.getRegionStates();<a name="line.1451"></a>
+<span class="sourceLineNo">1452</span> this.statTimestamp = EnvironmentEdgeManager.currentTime();<a name="line.1452"></a>
+<span class="sourceLineNo">1453</span> update(regionStates.getRegionsStateInTransition(), statTimestamp);<a name="line.1453"></a>
+<span class="sourceLineNo">1454</span> update(regionStates.getRegionFailedOpen(), statTimestamp);<a name="line.1454"></a>
+<span class="sourceLineNo">1455</span><a name="line.1455"></a>
+<span class="sourceLineNo">1456</span> if (LOG.isDebugEnabled() && ritsOverThreshold != null && !ritsOverThreshold.isEmpty()) {<a name="line.1456"></a>
+<span class="sourceLineNo">1457</span> LOG.debug("RITs over threshold: {}",<a name="line.1457"></a>
+<span class="sourceLineNo">1458</span> ritsOverThreshold.entrySet().stream()<a name="line.1458"></a>
+<span class="sourceLineNo">1459</span> .map(e -> e.getKey() + ":" + e.getValue().getState().name())<a name="line.1459"></a>
+<span class="sourceLineNo">1460</span> .collect(Collectors.joining("\n")));<a name="line.1460"></a>
+<span class="sourceLineNo">1461</span> }<a name="line.1461"></a>
+<span class="sourceLineNo">1462</span> }<a name="line.1462"></a>
+<span class="sourceLineNo">1463</span><a name="line.1463"></a>
+<span class="sourceLineNo">1464</span> private void update(final Collection<RegionState> regions, final long currentTime) {<a name="line.1464"></a>
+<span class="sourceLineNo">1465</span> for (RegionState state: regions) {<a name="line.1465"></a>
+<span class="sourceLineNo">1466</span> totalRITs++;<a name="line.1466"></a>
+<span class="sourceLineNo">1467</span> final long ritStartedMs = state.getStamp();<a name="line.1467"></a>
+<span class="sourceLineNo">1468</span> if (ritStartedMs == 0) {<a name="line.1468"></a>
+<span class="sourceLineNo">1469</span> // Don't output bogus values to metrics if they accidentally make it here.<a name="line.1469"></a>
+<span class="sourceLineNo">1470</span> LOG.warn("The RIT {} has no start time", state.getRegion());<a name="line.1470"></a>
+<span class="sourceLineNo">1471</span> continue;<a name="line.1471"></a>
+<span class="sourceLineNo">1472</span> }<a name="line.1472"></a>
+<span class="sourceLineNo">1473</span> final long ritTime = currentTime - ritStartedMs;<a name="line.1473"></a>
+<span class="sourceLineNo">1474</span> if (ritTime > ritThreshold) {<a name="line.1474"></a>
+<span class="sourceLineNo">1475</span> if (ritsOverThreshold == null) {<a name="line.1475"></a>
+<span class="sourceLineNo">1476</span> ritsOverThreshold = new HashMap<String, RegionState>();<a name="line.1476"></a>
+<span class="sourceLineNo">1477</span> }<a name="line.1477"></a>
+<span class="sourceLineNo">1478</span> ritsOverThreshold.put(state.getRegion().getEncodedName(), state);<a name="line.1478"></a>
+<span class="sourceLineNo">1479</span> totalRITsTwiceThreshold += (ritTime > (ritThreshold * 2)) ? 1 : 0;<a name="line.1479"></a>
+<span class="sourceLineNo">1480</span> }<a name="line.1480"></a>
+<span class="sourceLineNo">1481</span> if (oldestRITTime < ritTime) {<a name="line.1481"></a>
+<span class="sourceLineNo">1482</span> oldestRITTime = ritTime;<a name="line.1482"></a>
+<span class="sourceLineNo">1483</span> }<a name="line.1483"></a>
+<span class="sourceLineNo">1484</span> }<a name="line.1484"></a>
+<span class="sourceLineNo">1485</span> }<a name="line.1485"></a>
+<span class="sourceLineNo">1486</span> }<a name="line.1486"></a>
+<span class="sourceLineNo">1487</span><a name="line.1487"></a>
+<span class="sourceLineNo">1488</span> private void updateRegionsInTransitionMetrics(final RegionInTransitionStat ritStat) {<a name="line.1488"></a>
+<span class="sourceLineNo">1489</span> metrics.updateRITOldestAge(ritStat.getOldestRITTime());<a name="line.1489"></a>
+<span class="sourceLineNo">1490</span> metrics.updateRITCount(ritStat.getTotalRITs());<a name="line.1490"></a>
+<span class="sourceLineNo">1491</span> metrics.updateRITCountOverThreshold(ritStat.getTotalRITsOverThreshold());<a name="line.1491"></a>
+<span class="sourceLineNo">1492</span> }<a name="line.1492"></a>
+<span class="sourceLineNo">1493</span><a name="line.1493"></a>
+<span class="sourceLineNo">1494</span> private void updateDeadServerRegionMetrics(int deadRegions, int unknownRegions) {<a name="line.1494"></a>
+<span class="sourceLineNo">1495</span> metrics.updateDeadServerOpenRegions(deadRegions);<a name="line.1495"></a>
+<span class="sourceLineNo">1496</span> metrics.updateUnknownServerOpenRegions(unknownRegions);<a name="line.1496"></a>
+<span class="sourceLineNo">1497</span> }<a name="line.1497"></a>
+<span class="sourceLineNo">1498</span><a name="line.1498"></a>
+<span class="sourceLineNo">1499</span> private void handleRegionOverStuckWarningThreshold(final RegionInfo regionInfo) {<a name="line.1499"></a>
+<span class="sourceLineNo">1500</span> final RegionStateNode regionNode = regionStates.getRegionStateNode(regionInfo);<a name="line.1500"></a>
+<span class="sourceLineNo">1501</span> //if (regionNode.isStuck()) {<a name="line.1501"></a>
+<span class="sourceLineNo">1502</span> LOG.warn("STUCK Region-In-Transition {}", regionNode);<a name="line.1502"></a>
+<span class="sourceLineNo">1503</span> }<a name="line.1503"></a>
+<span class="sourceLineNo">1504</span><a name="line.1504"></a>
+<span class="sourceLineNo">1505</span> // ============================================================================================<a name="line.1505"></a>
+<span class="sourceLineNo">1506</span> // TODO: Master load/bootstrap<a name="line.1506"></a>
+<span class="sourceLineNo">1507</span> // ============================================================================================<a name="line.1507"></a>
+<span class="sourceLineNo">1508</span> public void joinCluster() throws IOException {<a name="line.1508"></a>
+<span class="sourceLineNo">1509</span> long startTime = System.nanoTime();<a name="line.1509"></a>
+<span class="sourceLineNo">1510</span> LOG.debug("Joining cluster...");<a name="line.1510"></a>
<span class="sourceLineNo">1511</span><a name="line.1511"></a>
-<span class="sourceLineNo">1512</span> long costMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);<a name="line.1512"></a>
-<span class="sourceLineNo">1513</span> LOG.info("Joined the cluster in {}", StringUtils.humanTimeDiff(costMs));<a name="line.1513"></a>
-<span class="sourceLineNo">1514</span> }<a name="line.1514"></a>
-<span class="sourceLineNo">1515</span><a name="line.1515"></a>
-<span class="sourceLineNo">1516</span> /**<a name="line.1516"></a>
-<span class="sourceLineNo">1517</span> * Create assign procedure for offline regions.<a name="line.1517"></a>
-<span class="sourceLineNo">1518</span> * Just follow the old processofflineServersWithOnlineRegions method. Since now we do not need to<a name="line.1518"></a>
-<span class="sourceLineNo">1519</span> * deal with dead server any more, we only deal with the regions in OFFLINE state in this method.<a name="line.1519"></a>
-<span class="sourceLineNo">1520</span> * And this is a bit strange, that for new regions, we will add it in CLOSED state instead of<a name="line.1520"></a>
-<span class="sourceLineNo">1521</span> * OFFLINE state, and usually there will be a procedure to track them. The<a name="line.1521"></a>
-<span class="sourceLineNo">1522</span> * processofflineServersWithOnlineRegions is a legacy from long ago, as things are going really<a name="line.1522"></a>
-<span class="sourceLineNo">1523</span> * different now, maybe we do not need this method any more. Need to revisit later.<a name="line.1523"></a>
-<span class="sourceLineNo">1524</span> */<a name="line.1524"></a>
-<span class="sourceLineNo">1525</span> // Public so can be run by the Master as part of the startup. Needs hbase:meta to be online.<a name="line.1525"></a>
-<span class="sourceLineNo">1526</span> // Needs to be done after the table state manager has been started.<a name="line.1526"></a>
-<span class="sourceLineNo">1527</span> public void processOfflineRegions() {<a name="line.1527"></a>
-<span class="sourceLineNo">1528</span> TransitRegionStateProcedure[] procs =<a name="line.1528"></a>
-<span class="sourceLineNo">1529</span> regionStates.getRegionStateNodes().stream().filter(rsn -> rsn.isInState(State.OFFLINE))<a name="line.1529"></a>
-<span class="sourceLineNo">1530</span> .filter(rsn -> isTableEnabled(rsn.getRegionInfo().getTable())).map(rsn -> {<a name="line.1530"></a>
-<span class="sourceLineNo">1531</span> rsn.lock();<a name="line.1531"></a>
-<span class="sourceLineNo">1532</span> try {<a name="line.1532"></a>
-<span class="sourceLineNo">1533</span> if (rsn.getProcedure() != null) {<a name="line.1533"></a>
-<span class="sourceLineNo">1534</span> return null;<a name="line.1534"></a>
-<span class="sourceLineNo">1535</span> } else {<a name="line.1535"></a>
-<span class="sourceLineNo">1536</span> return rsn.setProcedure(TransitRegionStateProcedure.assign(getProcedureEnvironment(),<a name="line.1536"></a>
-<span class="sourceLineNo">1537</span> rsn.getRegionInfo(), null));<a name="line.1537"></a>
-<span class="sourceLineNo">1538</span> }<a name="line.1538"></a>
-<span class="sourceLineNo">1539</span> } finally {<a name="line.1539"></a>
-<span class="sourceLineNo">1540</span> rsn.unlock();<a name="line.1540"></a>
-<span class="sourceLineNo">1541</span> }<a name="line.1541"></a>
-<span class="sourceLineNo">1542</span> }).filter(p -> p != null).toArray(TransitRegionStateProcedure[]::new);<a name="line.1542"></a>
-<span class="sourceLineNo">1543</span> if (procs.length > 0) {<a name="line.1543"></a>
-<span class="sourceLineNo">1544</span> master.getMasterProcedureExecutor().submitProcedures(procs);<a name="line.1544"></a>
-<span class="sourceLineNo">1545</span> }<a name="line.1545"></a>
-<span class="sourceLineNo">1546</span> }<a name="line.1546"></a>
-<span class="sourceLineNo">1547</span><a name="line.1547"></a>
-<span class="sourceLineNo">1548</span> /* AM internal RegionStateStore.RegionStateVisitor implementation. To be used when<a name="line.1548"></a>
-<span class="sourceLineNo">1549</span> * scanning META table for region rows, using RegionStateStore utility methods. RegionStateStore<a name="line.1549"></a>
-<span class="sourceLineNo">1550</span> * methods will convert Result into proper RegionInfo instances, but those would still need to be<a name="line.1550"></a>
-<span class="sourceLineNo">1551</span> * added into AssignmentManager.regionStates in-memory cache.<a name="line.1551"></a>
-<span class="sourceLineNo">1552</span> * RegionMetaLoadingVisitor.visitRegionState method provides the logic for adding RegionInfo<a name="line.1552"></a>
-<span class="sourceLineNo">1553</span> * instances as loaded from latest META scan into AssignmentManager.regionStates.<a name="line.1553"></a>
-<span class="sourceLineNo">1554</span> */<a name="line.1554"></a>
-<span class="sourceLineNo">1555</span> private class RegionMetaLoadingVisitor implements RegionStateStore.RegionStateVisitor {<a name="line.1555"></a>
-<span class="sourceLineNo">1556</span><a name="line.1556"></a>
-<span class="sourceLineNo">1557</span> @Override<a name="line.1557"></a>
-<span class="sourceLineNo">1558</span> public void visitRegionState(Result result, final RegionInfo regionInfo, final State state,<a name="line.1558"></a>
-<span class="sourceLineNo">1559</span> final ServerName regionLocation, final ServerName lastHost, final long openSeqNum) {<a name="line.1559"></a>
-<span class="sourceLineNo">1560</span> if (state == null && regionLocation == null && lastHost == null &&<a name="line.1560"></a>
-<span class="sourceLineNo">1561</span> openSeqNum == SequenceId.NO_SEQUENCE_ID) {<a name="line.1561"></a>
-<span class="sourceLineNo">1562</span> // This is a row with nothing in it.<a name="line.1562"></a>
-<span class="sourceLineNo">1563</span> LOG.warn("Skipping empty row={}", result);<a name="line.1563"></a>
-<span class="sourceLineNo">1564</span> return;<a name="line.1564"></a>
-<span class="sourceLineNo">1565</span> }<a name="line.1565"></a>
-<span class="sourceLineNo">1566</span> State localState = state;<a name="line.1566"></a>
-<span class="sourceLineNo">1567</span> if (localState == null) {<a name="line.1567"></a>
-<span class="sourceLineNo">1568</span> // No region state column data in hbase:meta table! Are I doing a rolling upgrade from<a name="line.1568"></a>
-<span class="sourceLineNo">1569</span> // hbase1 to hbase2? Am I restoring a SNAPSHOT or otherwise adding a region to hbase:meta?<a name="line.1569"></a>
-<span class="sourceLineNo">1570</span> // In any of these cases, state is empty. For now, presume OFFLINE but there are probably<a name="line.1570"></a>
-<span class="sourceLineNo">1571</span> // cases where we need to probe more to be sure this correct; TODO informed by experience.<a name="line.1571"></a>
-<span class="sourceLineNo">1572</span> LOG.info(regionInfo.getEncodedName() + " regionState=null; presuming " + State.OFFLINE);<a name="line.1572"></a>
-<span class="sourceLineNo">1573</span> localState = State.OFFLINE;<a name="line.1573"></a>
-<span class="sourceLineNo">1574</span> }<a name="line.1574"></a>
-<span class="sourceLineNo">1575</span> RegionStateNode regionNode = regionStates.getOrCreateRegionStateNode(regionInfo);<a name="line.1575"></a>
-<span class="sourceLineNo">1576</span> // Do not need to lock on regionNode, as we can make sure that before we finish loading<a name="line.1576"></a>
-<span class="sourceLineNo">1577</span> // meta, all the related procedures can not be executed. The only exception is for meta<a name="line.1577"></a>
-<span class="sourceLineNo">1578</span> // region related operations, but here we do not load the informations for meta region.<a name="line.1578"></a>
-<span class="sourceLineNo">1579</span> regionNode.setState(localState);<a name="line.1579"></a>
-<span class="sourceLineNo">1580</span> regionNode.setLastHost(lastHost);<a name="line.1580"></a>
-<span class="sourceLineNo">1581</span> regionNode.setRegionLocation(regionLocation);<a name="line.1581"></a>
-<span class="sourceLineNo">1582</span> regionNode.setOpenSeqNum(openSeqNum);<a name="line.1582"></a>
-<span class="sourceLineNo">1583</span><a name="line.1583"></a>
-<span class="sourceLineNo">1584</span> // Note: keep consistent with other methods, see region(Opening|Opened|Closing)<a name="line.1584"></a>
-<span class="sourceLineNo">1585</span> // RIT/ServerCrash handling should take care of the transiting regions.<a name="line.1585"></a>
-<span class="sourceLineNo">1586</span> if (localState.matches(State.OPEN, State.OPENING, State.CLOSING, State.SPLITTING,<a name="line.1586"></a>
-<span class="sourceLineNo">1587</span> State.MERGING)) {<a name="line.1587"></a>
-<span class="sourceLineNo">1588</span> assert regionLocation != null : "found null region location for " + regionNode;<a name="line.1588"></a>
-<span class="sourceLineNo">1589</span> regionStates.addRegionToServer(regionNode);<a name="line.1589"></a>
-<span class="sourceLineNo">1590</span> } else if (localState == State.OFFLINE || regionInfo.isOffline()) {<a name="line.1590"></a>
-<span class="sourceLineNo">1591</span> regionStates.addToOfflineRegions(regionNode);<a name="line.1591"></a>
-<span class="sourceLineNo">1592</span> }<a name="line.1592"></a>
-<span class="sourceLineNo">1593</span> if (regionNode.getProcedure() != null) {<a name="line.1593"></a>
-<span class="sourceLineNo">1594</span> regionNode.getProcedure().stateLoaded(AssignmentManager.this, regionNode);<a name="line.1594"></a>
-<span class="sourceLineNo">1595</span> }<a name="line.1595"></a>
-<span class="sourceLineNo">1596</span> }<a name="line.1596"></a>
-<span class="sourceLineNo">1597</span> };<a name="line.1597"></a>
-<span class="sourceLineNo">1598</span><a name="line.1598"></a>
-<span class="sourceLineNo">1599</span> /**<a name="line.1599"></a>
-<span class="sourceLineNo">1600</span> * Query META if the given <code>RegionInfo</code> exists, adding to<a name="line.1600"></a>
-<span class="sourceLineNo">1601</span> * <code>AssignmentManager.regionStateStore</code> cache if the region is found in META.<a name="line.1601"></a>
-<span class="sourceLineNo">1602</span> * @param regionEncodedName encoded name for the region to be loaded from META into<a name="line.1602"></a>
-<span class="sourceLineNo">1603</span> * <code>AssignmentManager.regionStateStore</code> cache<a name="line.1603"></a>
-<span class="sourceLineNo">1604</span> * @return <code>RegionInfo</code> instance for the given region if it is present in META<a name="line.1604"></a>
-<span class="sourceLineNo">1605</span> * and got successfully loaded into <code>AssignmentManager.regionStateStore</code><a name="line.1605"></a>
-<span class="sourceLineNo">1606</span> * cache, <b>null</b> otherwise.<a name="line.1606"></a>
-<span class="sourceLineNo">1607</span> * @throws UnknownRegionException if any errors occur while querying meta.<a name="line.1607"></a>
-<span class="sourceLineNo">1608</span> */<a name="line.1608"></a>
-<span class="sourceLineNo">1609</span> public RegionInfo loadRegionFromMeta(String regionEncodedName) throws UnknownRegionException {<a name="line.1609"></a>
-<span class="sourceLineNo">1610</span> try {<a name="line.1610"></a>
-<span class="sourceLineNo">1611</span> RegionMetaLoadingVisitor visitor = new RegionMetaLoadingVisitor();<a name="line.1611"></a>
-<span class="sourceLineNo">1612</span> regionStateStore.visitMetaForRegion(regionEncodedName, visitor);<a name="line.1612"></a>
-<span class="sourceLineNo">1613</span> return regionStates.getRegionState(regionEncodedName) == null ? null :<a name="line.1613"></a>
-<span class="sourceLineNo">1614</span> regionStates.getRegionState(regionEncodedName).getRegion();<a name="line.1614"></a>
-<span class="sourceLineNo">1615</span> } catch(IOException e) {<a name="line.1615"></a>
-<span class="sourceLineNo">1616</span> LOG.error("Error trying to load region {} from META", regionEncodedName, e);<a name="line.1616"></a>
-<span class="sourceLineNo">1617</span> throw new UnknownRegionException("Error while trying load region from meta");<a name="line.1617"></a>
-<span class="sourceLineNo">1618</span> }<a name="line.1618"></a>
-<span class="sourceLineNo">1619</span> }<a name="line.1619"></a>
-<span class="sourceLineNo">1620</span><a name="line.1620"></a>
-<span class="sourceLineNo">1621</span> private void loadMeta() throws IOException {<a name="line.1621"></a>
-<span class="sourceLineNo">1622</span> // TODO: use a thread pool<a name="line.1622"></a>
-<span class="sourceLineNo">1623</span> regionStateStore.visitMeta(new RegionMetaLoadingVisitor());<a name="line.1623"></a>
-<span class="sourceLineNo">1624</span> }<a name="line.1624"></a>
-<span class="sourceLineNo">1625</span><a name="line.1625"></a>
-<span class="sourceLineNo">1626</span> /**<a name="line.1626"></a>
-<span class="sourceLineNo">1627</span> * Used to check if the meta loading is done.<a name="line.1627"></a>
-<span class="sourceLineNo">1628</span> * <p/><a name="line.1628"></a>
-<span class="sourceLineNo">1629</span> * if not we throw PleaseHoldException since we are rebuilding the RegionStates<a name="line.1629"></a>
-<span class="sourceLineNo">1630</span> * @param hri region to check if it is already rebuild<a name="line.1630"></a>
-<span class="sourceLineNo">1631</span> * @throws PleaseHoldException if meta has not been loaded yet<a name="line.1631"></a>
-<span class="sourceLineNo">1632</span> */<a name="line.1632"></a>
-<span class="sourceLineNo">1633</span> private void checkMetaLoaded(RegionInfo hri) throws PleaseHoldException {<a name="line.1633"></a>
-<span class="sourceLineNo">1634</span> if (!isRunning()) {<a name="line.1634"></a>
-<span class="sourceLineNo">1635</span> throw new PleaseHoldException("AssignmentManager not running");<a name="line.1635"></a>
-<span class="sourceLineNo">1636</span> }<a name="line.1636"></a>
-<span class="sourceLineNo">1637</span> boolean meta = isMetaRegion(hri);<a name="line.1637"></a>
-<span class="sourceLineNo">1638</span> boolean metaLoaded = isMetaLoaded();<a name="line.1638"></a>
-<span class="sourceLineNo">1639</span> if (!meta && !metaLoaded) {<a name="line.1639"></a>
-<span class="sourceLineNo">1640</span> throw new PleaseHoldException(<a name="line.1640"></a>
-<span class="sourceLineNo">1641</span> "Master not fully online; hbase:meta=" + meta + ", metaLoaded=" + metaLoaded);<a name="line.1641"></a>
-<span class="sourceLineNo">1642</span> }<a name="line.1642"></a>
-<span class="sourceLineNo">1643</span> }<a name="line.1643"></a>
-<span class="sourceLineNo">1644</span><a name="line.1644"></a>
-<span class="sourceLineNo">1645</span> // ============================================================================================<a name="line.1645"></a>
-<span class="sourceLineNo">1646</span> // TODO: Metrics<a name="line.1646"></a>
-<span class="sourceLineNo">1647</span> // ============================================================================================<a name="line.1647"></a>
-<span class="sourceLineNo">1648</span> public int getNumRegionsOpened() {<a name="line.1648"></a>
-<span class="sourceLineNo">1649</span> // TODO: Used by TestRegionPlacement.java and assume monotonically increasing value<a name="line.1649"></a>
-<span class="sourceLineNo">1650</span> return 0;<a name="line.1650"></a>
-<span class="sourceLineNo">1651</span> }<a name="line.1651"></a>
-<span class="sourceLineNo">1652</span><a name="line.1652"></a>
-<span class="sourceLineNo">1653</span> /**<a name="line.1653"></a>
-<span class="sourceLineNo">1654</span> * Usually run by the Master in reaction to server crash during normal processing.<a name="line.1654"></a>
-<span class="sourceLineNo">1655</span> * Can also be invoked via external RPC to effect repair; in the latter case,<a name="line.1655"></a>
-<span class="sourceLineNo">1656</span> * the 'force' flag is set so we push through the SCP though context may indicate<a name="line.1656"></a>
-<span class="sourceLineNo">1657</span> * already-running-SCP (An old SCP may have exited abnormally, or damaged cluster<a name="line.1657"></a>
-<span class="sourceLineNo">1658</span> * may still have references in hbase:meta to 'Unknown Servers' -- servers that<a name="line.1658"></a>
-<span class="sourceLineNo">1659</span> * are not online or in dead servers list, etc.)<a name="line.1659"></a>
-<span class="sourceLineNo">1660</span> * @param force Set if the request came in externally over RPC (via hbck2). Force means<a name="line.1660"></a>
-<span class="sourceLineNo">1661</span> * run the SCP even if it seems as though there might be an outstanding<a name="line.1661"></a>
-<span class="sourceLineNo">1662</span> * SCP running.<a name="line.1662"></a>
-<span class="sourceLineNo">1663</span> * @return pid of scheduled SCP or {@link Procedure#NO_PROC_ID} if none scheduled.<a name="line.1663"></a>
-<span class="sourceLineNo">1664</span> */<a name="line.1664"></a>
-<span class="sourceLineNo">1665</span> public long submitServerCrash(ServerName serverName, boolean shouldSplitWal, boolean force) {<a name="line.1665"></a>
-<span class="sourceLineNo">1666</span> // May be an 'Unknown Server' so handle case where serverNode is null.<a name="line.1666"></a>
-<span class="sourceLineNo">1667</span> ServerStateNode serverNode = regionStates.getServerNode(serverName);<a name="line.1667"></a>
-<span class="sourceLineNo">1668</span> // Remove the in-memory rsReports result<a name="line.1668"></a>
-<span class="sourceLineNo">1669</span> synchronized (rsReports) {<a name="line.1669"></a>
-<span class="sourceLineNo">1670</span> rsReports.remove(serverName);<a name="line.1670"></a>
-<span class="sourceLineNo">1671</span> }<a name="line.1671"></a>
-<span class="sourceLineNo">1672</span><a name="line.1672"></a>
-<span class="sourceLineNo">1673</span> // We hold the write lock here for fencing on reportRegionStateTransition. Once we set the<a name="line.1673"></a>
-<span class="sourceLineNo">1674</span> // server state to CRASHED, we will no longer accept the reportRegionStateTransition call from<a name="line.1674"></a>
-<span class="sourceLineNo">1675</span> // this server. This is used to simplify the implementation for TRSP and SCP, where we can make<a name="line.1675"></a>
-<span class="sourceLineNo">1676</span> // sure that, the region list fetched by SCP will not be changed any more.<a name="line.1676"></a>
-<span class="sourceLineNo">1677</span> if (serverNode != null) {<a name="line.1677"></a>
-<span class="sourceLineNo">1678</span> serverNode.writeLock().lock();<a name="line.1678"></a>
-<span class="sourceLineNo">1679</span> }<a name="line.1679"></a>
-<span class="sourceLineNo">1680</span> boolean carryingMeta;<a name="line.1680"></a>
-<span class="sourceLineNo">1681</span> long pid;<a name="line.1681"></a>
-<span class="sourceLineNo">1682</span> try {<a name="line.1682"></a>
-<span class="sourceLineNo">1683</span> ProcedureExecutor<MasterProcedureEnv> procExec = this.master.getMasterProcedureExecutor();<a name="line.1683"></a>
-<span class="sourceLineNo">1684</span> carryingMeta = isCarryingMeta(serverName);<a name="line.1684"></a>
-<span class="sourceLineNo">1685</span> if (!force && serverNode != null && !serverNode.isInState(ServerState.ONLINE)) {<a name="line.1685"></a>
-<span class="sourceLineNo">1686</span> LOG.info("Skip adding ServerCrashProcedure for {} (meta={}) -- running?",<a name="line.1686"></a>
-<span class="sourceLineNo">1687</span> serverNode, carryingMeta);<a name="line.1687"></a>
-<span class="sourceLineNo">1688</span> return Procedure.NO_PROC_ID;<a name="line.1688"></a>
-<span class="sourceLineNo">1689</span> } else {<a name="line.1689"></a>
-<span class="sourceLineNo">1690</span> MasterProcedureEnv mpe = procExec.getEnvironment();<a name="line.1690"></a>
-<span class="sourceLineNo">1691</span> // If serverNode == null, then 'Unknown Server'. Schedule HBCKSCP instead.<a name="line.1691"></a>
-<span class="sourceLineNo">1692</span> // HBCKSCP scours Master in-memory state AND hbase;meta for references to<a name="line.1692"></a>
-<span class="sourceLineNo">1693</span> // serverName just-in-case. An SCP that is scheduled when the server is<a name="line.1693"></a>
-<span class="sourceLineNo">1694</span> // 'Unknown' probably originated externally with HBCK2 fix-it tool.<a name="line.1694"></a>
-<span class="sourceLineNo">1695</span> ServerState oldState = null;<a name="line.1695"></a>
-<span class="sourceLineNo">1696</span> if (serverNode != null) {<a name="line.1696"></a>
-<span class="sourceLineNo">1697</span> oldState = serverNode.getState();<a name="line.1697"></a>
-<span class="sourceLineNo">1698</span> serverNode.setState(ServerState.CRASHED);<a name="line.1698"></a>
-<span class="sourceLineNo">1699</span> }<a name="line.1699"></a>
-<span class="sourceLineNo">1700</span><a name="line.1700"></a>
-<span class="sourceLineNo">1701</span> if (force) {<a name="line.1701"></a>
-<span class="sourceLineNo">1702</span> pid = procExec.submitProcedure(<a name="line.1702"></a>
-<span class="sourceLineNo">1703</span> new HBCKServerCrashProcedure(mpe, serverName, shouldSplitWal, carryingMeta));<a name="line.1703"></a>
-<span class="sourceLineNo">1704</span> } else {<a name="line.1704"></a>
-<span class="sourceLineNo">1705</span> pid = procExec.submitProcedure(<a name="line.1705"></a>
-<span class="sourceLineNo">1706</span> new ServerCrashProcedure(mpe, serverName, shouldSplitWal, carryingMeta));<a name="line.1706"></a>
-<span class="sourceLineNo">1707</span> }<a name="line.1707"></a>
-<span class="sourceLineNo">1708</span> LOG.info("Scheduled ServerCrashProcedure pid={} for {} (carryingMeta={}){}.",<a name="line.1708"></a>
-<span class="sourceLineNo">1709</span> pid, serverName, carryingMeta,<a name="line.1709"></a>
-<span class="sourceLineNo">1710</span> serverNode == null? "": " " + serverNode.toString() + ", oldState=" + oldState);<a name="line.1710"></a>
-<span class="sourceLineNo">1711</span> }<a name="line.1711"></a>
-<span class="sourceLineNo">1712</span> } finally {<a name="line.1712"></a>
-<span class="sourceLineNo">1713</span> if (serverNode != null) {<a name="line.1713"></a>
-<span class="sourceLineNo">1714</span> serverNode.writeLock().unlock();<a name="line.1714"></a>
-<span class="sourceLineNo">1715</span> }<a name="line.1715"></a>
-<span class="sourceLineNo">1716</span> }<a name="line.1716"></a>
-<span class="sourceLineNo">1717</span> return pid;<a name="line.1717"></a>
-<span class="sourceLineNo">1718</span> }<a name="line.1718"></a>
-<span class="sourceLineNo">1719</span><a name="line.1719"></a>
-<span class="sourceLineNo">1720</span> public void offlineRegion(final RegionInfo regionInfo) {<a name="line.1720"></a>
-<span class="sourceLineNo">1721</span> // TODO used by MasterRpcServices<a name="line.1721"></a>
-<span class="sourceLineNo">1722</span> RegionStateNode node = regionStates.getRegionStateNode(regionInfo);<a name="line.1722"></a>
-<span class="sourceLineNo">1723</span> if (node != null) {<a name="line.1723"></a>
-<span class="sourceLineNo">1724</span> node.offline();<a name="line.1724"></a>
-<span class="sourceLineNo">1725</span> }<a name="line.1725"></a>
-<span class="sourceLineNo">1726</span> }<a name="line.1726"></a>
-<span class="sourceLineNo">1727</span><a name="line.1727"></a>
-<span class="sourceLineNo">1728</span> public void onlineRegion(final RegionInfo regionInfo, final ServerName serverName) {<a name="line.1728"></a>
-<span class="sourceLineNo">1729</span> // TODO used by TestSplitTransactionOnCluster.java<a name="line.1729"></a>
-<span class="sourceLineNo">1730</span> }<a name="line.1730"></a>
-<span class="sourceLineNo">1731</span><a name="line.1731"></a>
-<span class="sourceLineNo">1732</span> public Map<ServerName, List<RegionInfo>> getSnapShotOfAssignment(<a name="line.1732"></a>
-<span class="sourceLineNo">1733</span> final Collection<RegionInfo> regions) {<a name="line.1733"></a>
-<span class="sourceLineNo">1734</span> return regionStates.getSnapShotOfAssignment(regions);<a name="line.1734"></a>
-<span class="sourceLineNo">1735</span> }<a name="line.1735"></a>
-<span class="sourceLineNo">1736</span><a name="line.1736"></a>
-<span class="sourceLineNo">1737</span> // ============================================================================================<a name="line.1737"></a>
-<span class="sourceLineNo">1738</span> // TODO: UTILS/HELPERS?<a name="line.1738"></a>
-<span class="sourceLineNo">1739</span> // ============================================================================================<a name="line.1739"></a>
-<span class="sourceLineNo">1740</span> /**<a name="line.1740"></a>
-<span class="sourceLineNo">1741</span> * Used by the client (via master) to identify if all regions have the schema updates<a name="line.1741"></a>
-<span class="sourceLineNo">1742</span> * @return Pair indicating the status of the alter command (pending/total)<a name="line.1742"></a>
-<span class="sourceLineNo">1743</span> */<a name="line.1743"></a>
-<span class="sourceLineNo">1744</span> public Pair<Integer, Integer> getReopenStatus(TableName tableName) {<a name="line.1744"></a>
-<span class="sourceLineNo">1745</span> if (isTableDisabled(tableName)) {<a name="line.1745"></a>
-<span class="sourceLineNo">1746</span> return new Pair<Integer, Integer>(0, 0);<a name="line.1746"></a>
-<span class="sourceLineNo">1747</span> }<a name="line.1747"></a>
-<span class="sourceLineNo">1748</span><a name="line.1748"></a>
-<span class="sourceLineNo">1749</span> final List<RegionState> states = regionStates.getTableRegionStates(tableName);<a name="line.1749"></a>
-<span class="sourceLineNo">1750</span> int ritCount = 0;<a name="line.1750"></a>
-<span class="sourceLineNo">1751</span> for (RegionState regionState: states) {<a name="line.1751"></a>
-<span class="sourceLineNo">1752</span> if (!regionState.isOpened() && !regionState.isSplit()) {<a name="line.1752"></a>
-<span class="sourceLineNo">1753</span> ritCount++;<a name="line.1753"></a>
-<span class="sourceLineNo">1754</span> }<a name="line.1754"></a>
-<span class="sourceLineNo">1755</span> }<a name="line.1755"></a>
-<span class="sourceLineNo">1756</span> return new Pair<Integer, Integer>(ritCount, states.size());<a name="line.1756"></a>
-<span class="sourceLineNo">1757</span> }<a name="line.1757"></a>
-<span class="sourceLineNo">1758</span><a name="line.1758"></a>
-<span class="sourceLineNo">1759</span> // ============================================================================================<a name="line.1759"></a>
-<span class="sourceLineNo">1760</span> // TODO: Region State In Transition<a name="line.1760"></a>
-<span class="sourceLineNo">1761</span> // ============================================================================================<a name="line.1761"></a>
-<span class="sourceLineNo">1762</span> public boolean hasRegionsInTransition() {<a name="line.1762"></a>
-<span class="sourceLineNo">1763</span> return regionStates.hasRegionsInTransition();<a name="line.1763"></a>
-<span class="sourceLineNo">1764</span> }<a name="line.1764"></a>
-<span class="sourceLineNo">1765</span><a name="line.1765"></a>
-<span class="sourceLineNo">1766</span> public List<RegionStateNode> getRegionsInTransition() {<a name="line.1766"></a>
-<span class="sourceLineNo">1767</span> return regionStates.getRegionsInTransition();<a name="line.1767"></a>
-<span class="sourceLineNo">1768</span> }<a name="line.1768"></a>
-<span class="sourceLineNo">1769</span><a name="line.1769"></a>
-<span class="sourceLineNo">1770</span> public List<RegionInfo> getAssignedRegions() {<a name="line.1770"></a>
-<span class="sourceLineNo">1771</span> return regionStates.getAssignedRegions();<a name="line.1771"></a>
-<span class="sourceLineNo">1772</span> }<a name="line.1772"></a>
-<span class="sourceLineNo">1773</span><a name="line.1773"></a>
-<span class="sourceLineNo">1774</span> public RegionInfo getRegionInfo(final byte[] regionName) {<a name="line.1774"></a>
-<span class="sourceLineNo">1775</span> final RegionStateNode regionState = regionStates.getRegionStateNodeFromName(regionName);<a name="line.1775"></a>
-<span class="sourceLineNo">1776</span> return regionState != null ? regionState.getRegionInfo() : null;<a name="line.1776"></a>
-<span class="sourceLineNo">1777</span> }<a name="line.1777"></a>
-<span class="sourceLineNo">1778</span><a name="line.1778"></a>
-<span class="sourceLineNo">1779</span> // ============================================================================================<a name="line.1779"></a>
-<span class="sourceLineNo">1780</span> // Expected states on region state transition.<a name="line.1780"></a>
-<span class="sourceLineNo">1781</span> // Notice that there is expected states for transiting to OPENING state, this is because SCP.<a name="line.1781"></a>
-<span class="sourceLineNo">1782</span> // See the comments in regionOpening method for more details.<a name="line.1782"></a>
-<span class="sourceLineNo">1783</span> // ============================================================================================<a name="line.1783"></a>
-<span class="sourceLineNo">1784</span> private static final State[] STATES_EXPECTED_ON_OPEN = {<a name="line.1784"></a>
-<span class="sourceLineNo">1785</span> State.OPENING, // Normal case<a name="line.1785"></a>
-<span class="sourceLineNo">1786</span> State.OPEN // Retrying<a name="line.1786"></a>
-<span class="sourceLineNo">1787</span> };<a name="line.1787"></a>
-<span class="sourceLineNo">1788</span><a name="line.1788"></a>
-<span class="sourceLineNo">1789</span> private static final State[] STATES_EXPECTED_ON_CLOSING = {<a name="line.1789"></a>
-<span class="sourceLineNo">1790</span> State.OPEN, // Normal case<a name="line.1790"></a>
-<span class="sourceLineNo">1791</span> State.CLOSING, // Retrying<a name="line.1791"></a>
-<span class="sourceLineNo">1792</span> State.SPLITTING, // Offline the split parent<a name="line.1792"></a>
-<span class="sourceLineNo">1793</span> State.MERGING // Offline the merge parents<a name="line.1793"></a>
-<span class="sourceLineNo">1794</span> };<a name="line.1794"></a>
-<span class="sourceLineNo">1795</span><a name="line.1795"></a>
-<span class="sourceLineNo">1796</span> private static final State[] STATES_EXPECTED_ON_CLOSED = {<a name="line.1796"></a>
-<span class="sourceLineNo">1797</span> State.CLOSING, // Normal case<a name="line.1797"></a>
-<span class="sourceLineNo">1798</span> State.CLOSED // Retrying<a name="line.1798"></a>
-<span class="sourceLineNo">1799</span> };<a name="line.1799"></a>
-<span class="sourceLineNo">1800</span><a name="line.1800"></a>
-<span class="sourceLineNo">1801</span> // This is for manually scheduled region assign, can add other states later if we find out other<a name="line.1801"></a>
-<span class="sourceLineNo">1802</span> // usages<a name="line.1802"></a>
-<span class="sourceLineNo">1803</span> private static final State[] STATES_EXPECTED_ON_ASSIGN = { State.CLOSED, State.OFFLINE };<a name="line.1803"></a>
+<span class="sourceLineNo">1512</span> // Scan hbase:meta to build list of existing regions, servers, and assignment.<a name="line.1512"></a>
+<span class="sourceLineNo">1513</span> // hbase:meta is online now or will be. Inside loadMeta, we keep trying. Can't make progress<a name="line.1513"></a>
+<span class="sourceLineNo">1514</span> // w/o meta.<a name="line.1514"></a>
+<span class="sourceLineNo">1515</span> loadMeta();<a name="line.1515"></a>
+<span class="sourceLineNo">1516</span><a name="line.1516"></a>
+<span class="sourceLineNo">1517</span> while (master.getServerManager().countOfRegionServers() < 1) {<a name="line.1517"></a>
+<span class="sourceLineNo">1518</span> LOG.info("Waiting for RegionServers to join; current count={}",<a name="line.1518"></a>
+<span class="sourceLineNo">1519</span> master.getServerManager().countOfRegionServers());<a name="line.1519"></a>
+<span class="sourceLineNo">1520</span> Threads.sleep(250);<a name="line.1520"></a>
+<span class="sourceLineNo">1521</span> }<a name="line.1521"></a>
+<span class="sourceLineNo">1522</span> LOG.info("Number of RegionServers={}", master.getServerManager().countOfRegionServers());<a name="line.1522"></a>
+<span class="sourceLineNo">1523</span><a name="line.1523"></a>
+<span class="sourceLineNo">1524</span> // Start the chores<a name="line.1524"></a>
+<span class="sourceLineNo">1525</span> master.getMasterProcedureExecutor().addChore(this.ritChore);<a name="line.1525"></a>
+<span class="sourceLineNo">1526</span> master.getMasterProcedureExecutor().addChore(this.deadMetricChore);<a name="line.1526"></a>
+<span class="sourceLineNo">1527</span><a name="line.1527"></a>
+<span class="sourceLineNo">1528</span> long costMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);<a name="line.1528"></a>
+<span class="sourceLineNo">1529</span> LOG.info("Joined the cluster in {}", StringUtils.humanTimeDiff(costMs));<a name="line.1529"></a>
+<span class="sourceLineNo">1530</span> }<a name="line.1530"></a>
+<span class="sourceLineNo">1531</span><a name="line.1531"></a>
+<span class="sourceLineNo">1532</span> /**<a name="line.1532"></a>
+<span class="sourceLineNo">1533</span> * Create assign procedure for offline regions.<a name="line.1533"></a>
+<span class="sourceLineNo">1534</span> * Just follow the old processofflineServersWithOnlineRegions method. Since now we do not need to<a name="line.1534"></a>
+<span class="sourceLineNo">1535</span> * deal with dead server any more, we only deal with the regions in OFFLINE state in this method.<a name="line.1535"></a>
+<span class="sourceLineNo">1536</span> * And this is a bit strange, that for new regions, we will add it in CLOSED state instead of<a name="line.1536"></a>
+<span class="sourceLineNo">1537</span> * OFFLINE state, and usually there will be a procedure to track them. The<a name="line.1537"></a>
+<span class="sourceLineNo">1538</span> * processofflineServersWithOnlineRegions is a legacy from long ago, as things are going really<a name="line.1538"></a>
+<span class="sourceLineNo">1539</span> * different now, maybe we do not need this method any more. Need to revisit later.<a name="line.1539"></a>
+<span class="sourceLineNo">1540</span> */<a name="line.1540"></a>
+<span class="sourceLineNo">1541</span> // Public so can be run by the Master as part of the startup. Needs hbase:meta to be online.<a name="line.1541"></a>
+<span class="sourceLineNo">1542</span> // Needs to be done after the table state manager has been started.<a name="line.1542"></a>
+<span class="sourceLineNo">1543</span> public void processOfflineRegions() {<a name="line.1543"></a>
+<span class="sourceLineNo">1544</span> TransitRegionStateProcedure[] procs =<a name="line.1544"></a>
+<span class="sourceLineNo">1545</span> regionStates.getRegionStateNodes().stream().filter(rsn -> rsn.isInState(State.OFFLINE))<a name="line.1545"></a>
+<span class="sourceLineNo">1546</span> .filter(rsn -> isTableEnabled(rsn.getRegionInfo().getTable())).map(rsn -> {<a name="line.1546"></a>
+<span class="sourceLineNo">1547</span> rsn.lock();<a name="line.1547"></a>
+<span class="sourceLineNo">1548</span> try {<a name="line.1548"></a>
+<span class="sourceLineNo">1549</span> if (rsn.getProcedure() != null) {<a name="line.1549"></a>
+<span class="sourceLineNo">1550</span> return null;<a name="line.1550"></a>
+<span class="sourceLineNo">1551</span> } else {<a name="line.1551"></a>
+<span class="sourceLineNo">1552</span> return rsn.setProcedure(TransitRegionStateProcedure.assign(getProcedureEnvironment(),<a name="line.1552"></a>
+<span class="sourceLineNo">1553</span> rsn.getRegionInfo(), null));<a name="line.1553"></a>
+<span class="sourceLineNo">1554</span> }<a name="line.1554"></a>
+<span class="sourceLineNo">1555</span> } finally {<a name="line.1555"></a>
+<span class="sourceLineNo">1556</span> rsn.unlock();<a name="line.1556"></a>
+<span class="sourceLineNo">1557</span> }<a name="line.1557"></a>
+<span class="sourceLineNo">1558</span> }).filter(p -> p != null).toArray(TransitRegionStateProcedure[]::new);<a name="line.1558"></a>
+<span class="sourceLineNo">1559</span> if (procs.length > 0) {<a name="line.1559"></a>
+<span class="sourceLineNo">1560</span> master.getMasterProcedureExecutor().submitProcedures(procs);<a name="line.1560"></a>
+<span class="sourceLineNo">1561</span> }<a name="line.1561"></a>
+<span class="sourceLineNo">1562</span> }<a name="line.1562"></a>
+<span class="sourceLineNo">1563</span><a name="line.1563"></a>
+<span class="sourceLineNo">1564</span> /* AM internal RegionStateStore.RegionStateVisitor implementation. To be used when<a name="line.1564"></a>
+<span class="sourceLineNo">1565</span> * scanning META table for region rows, using RegionStateStore utility methods. RegionStateStore<a name="line.1565"></a>
+<span class="sourceLineNo">1566</span> * methods will convert Result into proper RegionInfo instances, but those would still need to be<a name="line.1566"></a>
+<span class="sourceLineNo">1567</span> * added into AssignmentManager.regionStates in-memory cache.<a name="line.1567"></a>
+<span class="sourceLineNo">1568</span> * RegionMetaLoadingVisitor.visitRegionState method provides the logic for adding RegionInfo<a name="line.1568"></a>
+<span class="sourceLineNo">1569</span> * instances as loaded from latest META scan into AssignmentManager.regionStates.<a name="line.1569"></a>
+<span class="sourceLineNo">1570</span> */<a name="line.1570"></a>
+<span class="sourceLineNo">1571</span> private class RegionMetaLoadingVisitor implements RegionStateStore.RegionStateVisitor {<a name="line.1571"></a>
+<span class="sourceLineNo">1572</span><a name="line.1572"></a>
+<span class="sourceLineNo">1573</span> @Override<a name="line.1573"></a>
+<span class="sourceLineNo">1574</span> public void visitRegionState(Result result, final RegionInfo regionInfo, final State state,<a name="line.1574"></a>
+<span class="sourceLineNo">1575</span> final ServerName regionLocation, final ServerName lastHost, final long openSeqNum) {<a name="line.1575"></a>
+<span class="sourceLineNo">1576</span> if (state == null && regionLocation == null && lastHost == null &&<a name="line.1576"></a>
+<span class="sourceLineNo">1577</span> openSeqNum == SequenceId.NO_SEQUENCE_ID) {<a name="line.1577"></a>
+<span class="sourceLineNo">1578</span> // This is a row with nothing in it.<a name="line.1578"></a>
+<span class="sourceLineNo">1579</span> LOG.warn("Skipping empty row={}", result);<a name="line.1579"></a>
+<span class="sourceLineNo">1580</span> return;<a name="line.1580"></a>
+<span class="sourceLineNo">1581</span> }<a name="line.1581"></a>
+<span class="sourceLineNo">1582</span> State localState = state;<a name="line.1582"></a>
+<span class="sourceLineNo">1583</span> if (localState == null) {<a name="line.1583"></a>
+<span class="sourceLineNo">1584</span> // No region state column data in hbase:meta table! Are I doing a rolling upgrade from<a name="line.1584"></a>
+<span class="sourceLineNo">1585</span> // hbase1 to hbase2? Am I restoring a SNAPSHOT or otherwise adding a region to hbase:meta?<a name="line.1585"></a>
+<span class="sourceLineNo">1586</span> // In any of these cases, state is empty. For now, presume OFFLINE but there are probably<a name="line.1586"></a>
+<span class="sourceLineNo">1587</span> // cases where we need to probe more to be sure this correct; TODO informed by experience.<a name="line.1587"></a>
+<span class="sourceLineNo">1588</span> LOG.info(regionInfo.getEncodedName() + " regionState=null; presuming " + State.OFFLINE);<a name="line.1588"></a>
+<span class="sourceLineNo">1589</span> localState = State.OFFLINE;<a name="line.1589"></a>
+<span class="sourceLineNo">1590</span> }<a name="line.1590"></a>
+<span class="sourceLineNo">1591</span> RegionStateNode regionNode = regionStates.getOrCreateRegionStateNode(regionInfo);<a name="line.1591"></a>
+<span class="sourceLineNo">1592</span> // Do not need to lock on regionNode, as we can make sure that before we finish loading<a name="line.1592"></a>
+<span class="sourceLineNo">1593</span> // meta, all the related procedures can not be executed. The only exception is for meta<a name="line.1593"></a>
+<span class="sourceLineNo">1594</span> // region related operations, but here we do not load the informations for meta region.<a name="line.1594"></a>
+<span class="sourceLineNo">1595</span> regionNode.setState(localState);<a name="line.1595"></a>
+<span class="sourceLineNo">1596</span> regionNode.setLastHost(lastHost);<a name="line.1596"></a>
+<span class="sourceLineNo">1597</span> regionNode.setRegionLocation(regionLocation);<a name="line.1597"></a>
+<span class="sourceLineNo">1598</span> regionNode.setOpenSeqNum(openSeqNum);<a name="line.1598"></a>
+<span class="sourceLineNo">1599</span><a name="line.1599"></a>
+<span class="sourceLineNo">1600</span> // Note: keep consistent with other methods, see region(Opening|Opened|Closing)<a name="line.1600"></a>
+<span class="sourceLineNo">1601</span> // RIT/ServerCrash handling should take care of the transiting regions.<a name="line.1601"></a>
+<span class="sourceLineNo">1602</span> if (localState.matches(State.OPEN, State.OPENING, State.CLOSING, State.SPLITTING,<a name="line.1602"></a>
+<span class="sourceLineNo">1603</span> State.MERGING)) {<a name="line.1603"></a>
+<span class="sourceLineNo">1604</span> assert regionLocation != null : "found null region location for " + regionNode;<a name="line.1604"></a>
+<span class="sourceLineNo">1605</span> regionStates.addRegionToServer(regionNode);<a name="line.1605"></a>
+<span class="sourceLineNo">1606</span> } else if (localState == State.OFFLINE || regionInfo.isOffline()) {<a name="line.1606"></a>
+<span class="sourceLineNo">1607</span> regionStates.addToOfflineRegions(regionNode);<a name="line.1607"></a>
+<span class="sourceLineNo">1608</span> }<a name="line.1608"></a>
+<span class="sourceLineNo">1609</span> if (regionNode.getProcedure() != null) {<a name="line.1609"></a>
+<span class="sourceLineNo">1610</span> regionNode.getProcedure().stateLoaded(AssignmentManager.this, regionNode);<a name="line.1610"></a>
+<span class="sourceLineNo">1611</span> }<a name="line.1611"></a>
+<span class="sourceLineNo">1612</span> }<a name="line.1612"></a>
+<span class="sourceLineNo">1613</span> };<a name="line.1613"></a>
+<span class="sourceLineNo">1614</span><a name="line.1614"></a>
+<span class="sourceLineNo">1615</span> /**<a name="line.1615"></a>
+<span class="sourceLineNo">1616</span> * Query META if the given <code>RegionInfo</code> exists, adding to<a name="line.1616"></a>
+<span class="sourceLineNo">1617</span> * <code>AssignmentManager.regionStateStore</code> cache if the region is found in META.<a name="line.1617"></a>
+<span class="sourceLineNo">1618</span> * @param regionEncodedName encoded name for the region to be loaded from META into<a name="line.1618"></a>
+<span class="sourceLineNo">1619</span> * <code>AssignmentManager.regionStateStore</code> cache<a name="line.1619"></a>
+<span class="sourceLineNo">1620</span> * @return <code>RegionInfo</code> instance for the given region if it is present in META<a name="line.1620"></a>
+<span class="sourceLineNo">1621</span> * and got successfully loaded into <code>AssignmentManager.regionStateStore</code><a name="line.1621"></a>
+<span class="sourceLineNo">1622</span> * cache, <b>null</b> otherwise.<a name="line.1622"></a>
+<span class="sourceLineNo">1623</span> * @throws UnknownRegionException if any errors occur while querying meta.<a name="line.1623"></a>
+<span class="sourceLineNo">1624</span> */<a name="line.1624"></a>
+<span class="sourceLineNo">1625</span> public RegionInfo loadRegionFromMeta(String regionEncodedName) throws UnknownRegionException {<a name="line.1625"></a>
+<span class="sourceLineNo">1626</span> try {<a name="line.1626"></a>
+<span class="sourceLineNo">1627</span> RegionMetaLoadingVisitor visitor = new RegionMetaLoadingVisitor();<a name="line.1627"></a>
+<span class="sourceLineNo">1628</span> regionStateStore.visitMetaForRegion(regionEncodedName, visitor);<a name="line.1628"></a>
+<span class="sourceLineNo">1629</span> return regionStates.getRegionState(regionEncodedName) == null ? null :<a name="line.1629"></a>
+<span class="sourceLineNo">1630</span> regionStates.getRegionState(regionEncodedName).getRegion();<a name="line.1630"></a>
+<span class="sourceLineNo">1631</span> } catch(IOException e) {<a name="line.1631"></a>
+<span class="sourceLineNo">1632</span> LOG.error("Error trying to load region {} from META", regionEncodedName, e);<a name="line.1632"></a>
+<span class="sourceLineNo">1633</span> throw new UnknownRegionException("Error while trying load region from meta");<a name="line.1633"></a>
+<span class="sourceLineNo">1634</span> }<a name="line.1634"></a>
+<span class="sourceLineNo">1635</span> }<a name="line.1635"></a>
+<span class="sourceLineNo">1636</span><a name="line.1636"></a>
+<span class="sourceLineNo">1637</span> private void loadMeta() throws IOException {<a name="line.1637"></a>
+<span class="sourceLineNo">1638</span> // TODO: use a thread pool<a name="line.1638"></a>
+<span class="sourceLineNo">1639</span> regionStateStore.visitMeta(new RegionMetaLoadingVisitor());<a name="line.1639"></a>
+<span class="sourceLineNo">1640</span> }<a name="line.1640"></a>
+<span class="sourceLineNo">1641</span><a name="line.1641"></a>
+<span class="sourceLineNo">1642</span> /**<a name="line.1642"></a>
+<span class="sourceLineNo">1643</span> * Used to check if the meta loading is done.<a name="line.1643"></a>
+<span class="sourceLineNo">1644</span> * <p/><a name="line.1644"></a>
+<span class="sourceLineNo">1645</span> * if not we throw PleaseHoldException since we are rebuilding the RegionStates<a name="line.1645"></a>
+<span class="sourceLineNo">1646</span> * @param hri region to check if it is already rebuild<a name="line.1646"></a>
+<span class="sourceLineNo">1647</span> * @throws PleaseHoldException if meta has not been loaded yet<a name="line.1647"></a>
+<span class="sourceLineNo">1648</span> */<a name="line.1648"></a>
+<span class="sourceLineNo">1649</span> private void checkMetaLoaded(RegionInfo hri) throws PleaseHoldException {<a name="line.1649"></a>
+<span class="sourceLineNo">1650</span> if (!isRunning()) {<a name="line.1650"></a>
+<span class="sourceLineNo">1651</span> throw new PleaseHoldException("AssignmentManager not running");<a name="line.1651"></a>
+<span class="sourceLineNo">1652</span> }<a name="line.1652"></a>
+<span class="sourceLineNo">1653</span> boolean meta = isMetaRegion(hri);<a name="line.1653"></a>
+<span class="sourceLineNo">1654</span> boolean metaLoaded = isMetaLoaded();<a name="line.1654"></a>
+<span class="sourceLineNo">1655</span> if (!meta && !metaLoaded) {<a name="line.1655"></a>
+<span class="sourceLineNo">1656</span> throw new PleaseHoldException(<a name="line.1656"></a>
+<span class="sourceLineNo">1657</span> "Master not fully online; hbase:meta=" + meta + ", metaLoaded=" + metaLoaded);<a name="line.1657"></a>
+<span class="sourceLineNo">1658</span> }<a name="line.1658"></a>
+<span class="sourceLineNo">1659</span> }<a name="line.1659"></a>
+<span class="sourceLineNo">1660</span><a name="line.1660"></a>
+<span class="sourceLineNo">1661</span> // ============================================================================================<a name="line.1661"></a>
+<span class="sourceLineNo">1662</span> // TODO: Metrics<a name="line.1662"></a>
+<span class="sourceLineNo">1663</span> // ============================================================================================<a name="line.1663"></a>
+<span class="sourceLineNo">1664</span> public int getNumRegionsOpened() {<a name="line.1664"></a>
+<span class="sourceLineNo">1665</span> // TODO: Used by TestRegionPlacement.java and assume monotonically increasing value<a name="line.1665"></a>
+<span class="sourceLineNo">1666</span> return 0;<a name="line.1666"></a>
+<span class="sourceLineNo">1667</span> }<a name="line.1667"></a>
+<span class="sourceLineNo">1668</span><a name="line.1668"></a>
+<span class="sourceLineNo">1669</span> /**<a name="line.1669"></a>
+<span class="sourceLineNo">1670</span> * Usually run by the Master in reaction to server crash during normal processing.<a name="line.1670"></a>
+<span class="sourceLineNo">1671</span> * Can also be invoked via external RPC to effect repair; in the latter case,<a name="line.1671"></a>
+<span class="sourceLineNo">1672</span> * the 'force' flag is set so we push through the SCP though context may indicate<a name="line.1672"></a>
+<span class="sourceLineNo">1673</span> * already-running-SCP (An old SCP may have exited abnormally, or damaged cluster<a name="line.1673"></a>
+<span class="sourceLineNo">1674</span> * may still have references in hbase:meta to 'Unknown Servers' -- servers that<a name="line.1674"></a>
+<span class="sourceLineNo">1675</span> * are not online or in dead servers list, etc.)<a name="line.1675"></a>
+<span class="sourceLineNo">1676</span> * @param force Set if the request came in externally over RPC (via hbck2). Force means<a name="line.1676"></a>
+<span class="sourceLineNo">1677</span> * run the SCP even if it seems as though there might be an outstanding<a name="line.1677"></a>
+<span class="sourceLineNo">1678</span> * SCP running.<a name="line.1678"></a>
+<span class="sourceLineNo">1679</span> * @return pid of scheduled SCP or {@link Procedure#NO_PROC_ID} if none scheduled.<a name="line.1679"></a>
+<span class="sourceLineNo">1680</span> */<a name="line.1680"></a>
+<span class="sourceLineNo">1681</span> public long submitServerCrash(ServerName serverName, boolean shouldSplitWal, boolean force) {<a name="line.1681"></a>
+<span class="sourceLineNo">1682</span> // May be an 'Unknown Server' so handle case where serverNode is null.<a name="line.1682"></a>
+<span class="sourceLineNo">1683</span> ServerStateNode serverNode = regionStates.getServerNode(serverName);<a name="line.1683"></a>
+<span class="sourceLineNo">1684</span> // Remove the in-memory rsReports result<a name="line.1684"></a>
+<span class="sourceLineNo">1685</span> synchronized (rsReports) {<a name="line.1685"></a>
+<span class="sourceLineNo">1686</span> rsReports.remove(serverName);<a name="line.1686"></a>
+<span class="sourceLineNo">1687</span> }<a name="line.1687"></a>
+<span class="sourceLineNo">1688</span><a name="line.1688"></a>
+<span class="sourceLineNo">1689</span> // We hold the write lock here for fencing on reportRegionStateTransition. Once we set the<a name="line.1689"></a>
+<span class="sourceLineNo">1690</span> // server state to CRASHED, we will no longer accept the reportRegionStateTransition call from<a name="line.1690"></a>
+<span class="sourceLineNo">1691</span> // this server. This is used to simplify the implementation for TRSP and SCP, where we can make<a name="line.1691"></a>
+<span class="sourceLineNo">1692</span> // sure that, the region list fetched by SCP will not be changed any more.<a name="line.1692"></a>
+<span class="sourceLineNo">1693</span> if (serverNode != null) {<a name="line.1693"></a>
+<span class="sourceLineNo">1694</span> serverNode.writeLock().lock();<a name="line.1694"></a>
+<span class="sourceLineNo">1695</span> }<a name="line.1695"></a>
+<span class="sourceLineNo">1696</span> boolean carryingMeta;<a name="line.1696"></a>
+<span class="sourceLineNo">1697</span> long pid;<a name="line.1697"></a>
+<span class="sourceLineNo">1698</span> try {<a name="line.1698"></a>
+<span class="sourceLineNo">1699</span> ProcedureExecutor<MasterProcedureEnv> procExec = this.master.getMasterProcedureExecutor();<a name="line.1699"></a>
+<span class="sourceLineNo">1700</span> carryingMeta = isCarryingMeta(serverName);<a name="line.1700"></a>
+<span class="sourceLineNo">1701</span> if (!force && serverNode != null && !serverNode.isInState(ServerState.ONLINE)) {<a name="line.1701"></a>
+<span class="sourceLineNo">1702</span> LOG.info("Skip adding ServerCrashProcedure for {} (meta={}) -- running?",<a name="line.1702"></a>
+<span class="sourceLineNo">1703</span> serverNode, carryingMeta);<a name="line.1703"></a>
+<span class="sourceLineNo">1704</span> return Procedure.NO_PROC_ID;<a name="line.1704"></a>
+<span class="sourceLineNo">1705</span> } else {<a name="line.1705"></a>
+<span class="sourceLineNo">1706</span> MasterProcedureEnv mpe = procExec.getEnvironment();<a name="line.1706"></a>
+<span class="sourceLineNo">1707</span> // If serverNode == null, then 'Unknown Server'. Schedule HBCKSCP instead.<a name="line.1707"></a>
+<span class="sourceLineNo">1708</span> // HBCKSCP scours Master in-memory state AND hbase;meta for references to<a name="line.1708"></a>
+<span class="sourceLineNo">1709</span> // serverName just-in-case. An SCP that is scheduled when the server is<a name="line.1709"></a>
+<span class="sourceLineNo">1710</span> // 'Unknown' probably originated externally with HBCK2 fix-it tool.<a name="line.1710"></a>
+<span class="sourceLineNo">1711</span> ServerState oldState = null;<a name="line.1711"></a>
+<span class="sourceLineNo">1712</span> if (serverNode != null) {<a name="line.1712"></a>
+<span class="sourceLineNo">1713</span> oldState = serverNode.getState();<a name="line.1713"></a>
+<span class="sourceLineNo">1714</span> serverNode.setState(ServerState.CRASHED);<a name="line.1714"></a>
+<span class="sourceLineNo">1715</span> }<a name="line.1715"></a>
+<span class="sourceLineNo">1716</span><a name="line.1716"></a>
+<span class="sourceLineNo">1717</span> if (force) {<a name="line.1717"></a>
+<span class="sourceLineNo">1718</span> pid = procExec.submitProcedure(<a name="line.1718"></a>
+<span class="sourceLineNo">1719</span> new HBCKServerCrashProcedure(mpe, serverName, shouldSplitWal, carryingMeta));<a name="line.1719"></a>
+<span class="sourceLineNo">1720</span> } else {<a name="line.1720"></a>
+<span class="sourceLineNo">1721</span> pid = procExec.submitProcedure(<a name="line.1721"></a>
+<span class="sourceLineNo">1722</span> new ServerCrashProcedure(mpe, serverName, shouldSplitWal, carryingMeta));<a name="line.1722"></a>
+<span class="sourceLineNo">1723</span> }<a name="line.1723"></a>
+<span class="sourceLineNo">1724</span> LOG.info("Scheduled ServerCrashProcedure pid={} for {} (carryingMeta={}){}.",<a name="line.1724"></a>
+<span class="sourceLineNo">1725</span> pid, serverName, carryingMeta,<a name="line.1725"></a>
+<span class="sourceLineNo">1726</span> serverNode == null? "": " " + serverNode.toString() + ", oldState=" + oldState);<a name="line.1726"></a>
+<span class="sourceLineNo">1727</span> }<a name="line.1727"></a>
+<span class="sourceLineNo">1728</span> } finally {<a name="line.1728"></a>
+<span class="sourceLineNo">1729</span> if (serverNode != null) {<a name="line.1729"></a>
+<span class="sourceLineNo">1730</span> serverNode.writeLock().unlock();<a name="line.1730"></a>
+<span class="sourceLineNo">1731</span> }<a name="line.1731"></a>
+<span class="sourceLineNo">1732</span> }<a name="line.1732"></a>
+<span class="sourceLineNo">1733</span> return pid;<a name="line.1733"></a>
+<span class="sourceLineNo">1734</span> }<a name="line.1734"></a>
+<span class="sourceLineNo">1735</span><a name="line.1735"></a>
+<span class="sourceLineNo">1736</span> public void offlineRegion(final RegionInfo regionInfo) {<a name="line.1736"></a>
+<span class="sourceLineNo">1737</span> // TODO used by MasterRpcServices<a name="line.1737"></a>
+<span class="sourceLineNo">1738</span> RegionStateNode node = regionStates.getRegionStateNode(regionInfo);<a name="line.1738"></a>
+<span class="sourceLineNo">1739</span> if (node != null) {<a name="line.1739"></a>
+<span class="sourceLineNo">1740</span> node.offline();<a name="line.1740"></a>
+<span class="sourceLineNo">1741</span> }<a name="line.1741"></a>
+<span class="sourceLineNo">1742</span> }<a name="line.1742"></a>
+<span class="sourceLineNo">1743</span><a name="line.1743"></a>
+<span class="sourceLineNo">1744</span> public void onlineRegion(final RegionInfo regionInfo, final ServerName serverName) {<a name="line.1744"></a>
+<span class="sourceLineNo">1745</span> // TODO used by TestSplitTransactionOnCluster.java<a name="line.1745"></a>
+<span class="sourceLineNo">1746</span> }<a name="line.1746"></a>
+<span class="sourceLineNo">1747</span><a name="line.1747"></a>
+<span class="sourceLineNo">1748</span> public Map<ServerName, List<RegionInfo>> getSnapShotOfAssignment(<a name="line.1748"></a>
+<span class="sourceLineNo">1749</span> final Collection<RegionInfo> regions) {<a name="line.1749"></a>
+<span class="sourceLineNo">1750</span> return regionStates.getSnapShotOfAssignment(regions);<a name="line.1750"></a>
+<span class="sourceLineNo">1751</span> }<a name="line.1751"></a>
+<span class="sourceLineNo">1752</span><a name="line.1752"></a>
+<span class="sourceLineNo">1753</span> // ============================================================================================<a name="line.1753"></a>
+<span class="sourceLineNo">1754</span> // TODO: UTILS/HELPERS?<a name="line.1754"></a>
+<span class="sourceLineNo">1755</span> // ============================================================================================<a name="line.1755"></a>
+<span class="sourceLineNo">1756</span> /**<a name="line.1756"></a>
+<span class="sourceLineNo">1757</span> * Used by the client (via master) to identify if all regions have the schema updates<a name="line.1757"></a>
+<span class="sourceLineNo">1758</span> * @return Pair indicating the status of the alter command (pending/total)<a name="line.1758"></a>
+<span class="sourceLineNo">1759</span> */<a name="line.1759"></a>
+<span class="sourceLineNo">1760</span> public Pair<Integer, Integer> getReopenStatus(TableName tableName) {<a name="line.1760"></a>
+<span class="sourceLineNo">1761</span> if (isTableDisabled(tableName)) {<a name="line.1761"></a>
+<span class="sourceLineNo">1762</span> return new Pair<Integer, Integer>(0, 0);<a name="line.1762"></a>
+<span class="sourceLineNo">1763</span> }<a name="line.1763"></a>
+<span class="sourceLineNo">1764</span><a name="line.1764"></a>
+<span class="sourceLineNo">1765</span> final List<RegionState> states = regionStates.getTableRegionStates(tableName);<a name="line.1765"></a>
+<span class="sourceLineNo">1766</span> int ritCount = 0;<a name="line.1766"></a>
+<span class="sourceLineNo">1767</span> for (RegionState regionState: states) {<a name="line.1767"></a>
+<span class="sourceLineNo">1768</span> if (!regionState.isOpened() && !regionState.isSplit()) {<a name="line.1768"></a>
+<span class="sourceLineNo">1769</span> ritCount++;<a name="line.1769"></a>
+<span class="sourceLineNo">1770</span> }<a name="line.1770"></a>
+<span class="sourceLineNo">1771</span> }<a name="line.1771"></a>
+<span class="sourceLineNo">1772</span> return new Pair<Integer, Integer>(ritCount, states.size());<a name="line.1772"></a>
+<span class="sourceLineNo">1773</span> }<a name="line.1773"></a>
+<span class="sourceLineNo">1774</span><a name="line.1774"></a>
+<span class="sourceLineNo">1775</span> // ============================================================================================<a name="line.1775"></a>
+<span class="sourceLineNo">1776</span> // TODO: Region State In Transition<a name="line.1776"></a>
+<span class="sourceLineNo">1777</span> // ============================================================================================<a name="line.1777"></a>
+<span class="sourceLineNo">1778</span> public boolean hasRegionsInTransition() {<a name="line.1778"></a>
+<span class="sourceLineNo">1779</span> return regionStates.hasRegionsInTransition();<a name="line.1779"></a>
+<span class="sourceLineNo">1780</span> }<a name="line.1780"></a>
+<span class="sourceLineNo">1781</span><a name="line.1781"></a>
+<span class="sourceLineNo">1782</span> public List<RegionStateNode> getRegionsInTransition() {<a name="line.1782"></a>
+<span class="sourceLineNo">1783</span> return regionStates.getRegionsInTransition();<a name="line.1783"></a>
+<span class="sourceLineNo">1784</span> }<a name="line.1784"></a>
+<span class="sourceLineNo">1785</span><a name="line.1785"></a>
+<span class="sourceLineNo">1786</span> public List<RegionInfo> getAssignedRegions() {<a name="line.1786"></a>
+<span class="sourceLineNo">1787</span> return regionStates.getAssignedRegions();<a name="line.1787"></a>
+<span class="sourceLineNo">1788</span> }<a name="line.1788"></a>
+<span class="sourceLineNo">1789</span><a name="line.1789"></a>
+<span class="sourceLineNo">1790</span> public RegionInfo getRegionInfo(final byte[] regionName) {<a name="line.1790"></a>
+<span class="sourceLineNo">1791</span> final RegionStateNode regionState = regionStates.getRegionStateNodeFromName(regionName);<a name="line.1791"></a>
+<span class="sourceLineNo">1792</span> return regionState != null ? regionState.getRegionInfo() : null;<a name="line.1792"></a>
+<span class="sourceLineNo">1793</span> }<a name="line.1793"></a>
+<span class="sourceLineNo">1794</span><a name="line.1794"></a>
+<span class="sourceLineNo">1795</span> // ============================================================================================<a name="line.1795"></a>
+<span class="sourceLineNo">1796</span> // Expected states on region state transition.<a name="line.1796"></a>
+<span class="sourceLineNo">1797</span> // Notice that there is expected states for transiting to OPENING state, this is because SCP.<a name="line.1797"></a>
+<span class="sourceLineNo">1798</span> // See the comments in regionOpening method for more details.<a name="line.1798"></a>
+<span class="sourceLineNo">1799</span> // ============================================================================================<a name="line.1799"></a>
+<span class="sourceLineNo">1800</span> private static final State[] STATES_EXPECTED_ON_OPEN = {<a name="line.1800"></a>
+<span class="sourceLineNo">1801</span> State.OPENING, // Normal case<a name="line.1801"></a>
+<span class="sourceLineNo">1802</span> State.OPEN // Retrying<a name="line.1802"></a>
+<span class="sourceLineNo">1803</span> };<a name="line.1803"></a>
<span class="sourceLineNo">1804</span><a name="line.1804"></a>
-<span class="sourceLineNo">1805</span> // We only allow unassign or move a region which is in OPEN state.<a name="line.1805"></a>
-<span class="sourceLineNo">1806</span> private static final State[] STATES_EXPECTED_ON_UNASSIGN_OR_MOVE = { State.OPEN };<a name="line.1806"></a>
-<span class="sourceLineNo">1807</span><a name="line.1807"></a>
-<span class="sourceLineNo">1808</span> // ============================================================================================<a name="line.1808"></a>
-<span class="sourceLineNo">1809</span> // Region Status update<a name="line.1809"></a>
-<span class="sourceLineNo">1810</span> // Should only be called in TransitRegionStateProcedure(and related procedures), as the locking<a name="line.1810"></a>
-<span class="sourceLineNo">1811</span> // and pre-assumptions are very tricky.<a name="line.1811"></a>
-<span class="sourceLineNo">1812</span> // ============================================================================================<a name="line.1812"></a>
-<span class="sourceLineNo">1813</span> private void transitStateAndUpdate(RegionStateNode regionNode, RegionState.State newState,<a name="line.1813"></a>
-<span class="sourceLineNo">1814</span> RegionState.State... expectedStates) throws IOException {<a name="line.1814"></a>
-<span class="sourceLineNo">1815</span> RegionState.State state = regionNode.getState();<a name="line.1815"></a>
-<span class="sourceLineNo">1816</span> regionNode.transitionState(newState, expectedStates);<a name="line.1816"></a>
-<span class="sourceLineNo">1817</span> boolean succ = false;<a name="line.1817"></a>
-<span class="sourceLineNo">1818</span> try {<a name="line.1818"></a>
-<span class="sourceLineNo">1819</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1819"></a>
-<span class="sourceLineNo">1820</span> succ = true;<a name="line.1820"></a>
-<span class="sourceLineNo">1821</span> } finally {<a name="line.1821"></a>
-<span class="sourceLineNo">1822</span> if (!succ) {<a name="line.1822"></a>
-<span class="sourceLineNo">1823</span> // revert<a name="line.1823"></a>
-<span class="sourceLineNo">1824</span> regionNode.setState(state);<a name="line.1824"></a>
-<span class="sourceLineNo">1825</span> }<a name="line.1825"></a>
-<span class="sourceLineNo">1826</span> }<a name="line.1826"></a>
-<span class="sourceLineNo">1827</span> }<a name="line.1827"></a>
-<span class="sourceLineNo">1828</span><a name="line.1828"></a>
-<span class="sourceLineNo">1829</span> // should be called within the synchronized block of RegionStateNode<a name="line.1829"></a>
-<span class="sourceLineNo">1830</span> void regionOpening(RegionStateNode regionNode) throws IOException {<a name="line.1830"></a>
-<span class="sourceLineNo">1831</span> // As in SCP, for performance reason, there is no TRSP attached with this region, we will not<a name="line.1831"></a>
-<span class="sourceLineNo">1832</span> // update the region state, which means that the region could be in any state when we want to<a name="line.1832"></a>
-<span class="sourceLineNo">1833</span> // assign it after a RS crash. So here we do not pass the expectedStates parameter.<a name="line.1833"></a>
-<span class="sourceLineNo">1834</span> transitStateAndUpdate(regionNode, State.OPENING);<a name="line.1834"></a>
-<span class="sourceLineNo">1835</span> regionStates.addRegionToServer(regionNode);<a name="line.1835"></a>
-<span class="sourceLineNo">1836</span> // update the operation count metrics<a name="line.1836"></a>
-<span class="sourceLineNo">1837</span> metrics.incrementOperationCounter();<a name="line.1837"></a>
-<span class="sourceLineNo">1838</span> }<a name="line.1838"></a>
-<span class="sourceLineNo">1839</span><a name="line.1839"></a>
-<span class="sourceLineNo">1840</span> // should be called under the RegionStateNode lock<a name="line.1840"></a>
-<span class="sourceLineNo">1841</span> // The parameter 'giveUp' means whether we will try to open the region again, if it is true, then<a name="line.1841"></a>
-<span class="sourceLineNo">1842</span> // we will persist the FAILED_OPEN state into hbase:meta.<a name="line.1842"></a>
-<span class="sourceLineNo">1843</span> void regionFailedOpen(RegionStateNode regionNode, boolean giveUp) throws IOException {<a name="line.1843"></a>
-<span class="sourceLineNo">1844</span> RegionState.State state = regionNode.getState();<a name="line.1844"></a>
-<span class="sourceLineNo">1845</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1845"></a>
-<span class="sourceLineNo">1846</span> if (giveUp) {<a name="line.1846"></a>
-<span class="sourceLineNo">1847</span> regionNode.setState(State.FAILED_OPEN);<a name="line.1847"></a>
-<span class="sourceLineNo">1848</span> regionNode.setRegionLocation(null);<a name="line.1848"></a>
-<span class="sourceLineNo">1849</span> boolean succ = false;<a name="line.1849"></a>
-<span class="sourceLineNo">1850</span> try {<a name="line.1850"></a>
-<span class="sourceLineNo">1851</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1851"></a>
-<span class="sourceLineNo">1852</span> succ = true;<a name="line.1852"></a>
-<span class="sourceLineNo">1853</span> } finally {<a name="line.1853"></a>
-<span class="sourceLineNo">1854</span> if (!succ) {<a name="line.1854"></a>
-<span class="sourceLineNo">1855</span> // revert<a name="line.1855"></a>
-<span class="sourceLineNo">1856</span> regionNode.setState(state);<a name="line.1856"></a>
-<span class="sourceLineNo">1857</span> regionNode.setRegionLocation(regionLocation);<a name="line.1857"></a>
-<span class="sourceLineNo">1858</span> }<a name="line.1858"></a>
-<span class="sourceLineNo">1859</span> }<a name="line.1859"></a>
-<span class="sourceLineNo">1860</span> }<a name="line.1860"></a>
-<span class="sourceLineNo">1861</span> if (regionLocation != null) {<a name="line.1861"></a>
-<span class="sourceLineNo">1862</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1862"></a>
-<span class="sourceLineNo">1863</span> }<a name="line.1863"></a>
-<span class="sourceLineNo">1864</span> }<a name="line.1864"></a>
-<span class="sourceLineNo">1865</span><a name="line.1865"></a>
-<span class="sourceLineNo">1866</span> // should be called under the RegionStateNode lock<a name="line.1866"></a>
-<span class="sourceLineNo">1867</span> void regionClosing(RegionStateNode regionNode) throws IOException {<a name="line.1867"></a>
-<span class="sourceLineNo">1868</span> transitStateAndUpdate(regionNode, State.CLOSING, STATES_EXPECTED_ON_CLOSING);<a name="line.1868"></a>
-<span class="sourceLineNo">1869</span><a name="line.1869"></a>
-<span class="sourceLineNo">1870</span> RegionInfo hri = regionNode.getRegionInfo();<a name="line.1870"></a>
-<span class="sourceLineNo">1871</span> // Set meta has not initialized early. so people trying to create/edit tables will wait<a name="line.1871"></a>
-<span class="sourceLineNo">1872</span> if (isMetaRegion(hri)) {<a name="line.1872"></a>
-<span class="sourceLineNo">1873</span> setMetaAssigned(hri, false);<a name="line.1873"></a>
-<span class="sourceLineNo">1874</span> }<a name="line.1874"></a>
-<span class="sourceLineNo">1875</span> regionStates.addRegionToServer(regionNode);<a name="line.1875"></a>
-<span class="sourceLineNo">1876</span> // update the operation count metrics<a name="line.1876"></a>
-<span class="sourceLineNo">1877</span> metrics.incrementOperationCounter();<a name="line.1877"></a>
-<span class="sourceLineNo">1878</span> }<a name="line.1878"></a>
-<span class="sourceLineNo">1879</span><a name="line.1879"></a>
-<span class="sourceLineNo">1880</span> // for open and close, they will first be persist to the procedure store in<a name="line.1880"></a>
-<span class="sourceLineNo">1881</span> // RegionRemoteProcedureBase. So here we will first change the in memory state as it is considered<a name="line.1881"></a>
-<span class="sourceLineNo">1882</span> // as succeeded if the persistence to procedure store is succeeded, and then when the<a name="line.1882"></a>
-<span class="sourceLineNo">1883</span> // RegionRemoteProcedureBase is woken up, we will persist the RegionStateNode to hbase:meta.<a name="line.1883"></a>
-<span class="sourceLineNo">1884</span><a name="line.1884"></a>
-<span class="sourceLineNo">1885</span> // should be called under the RegionStateNode lock<a name="line.1885"></a>
-<span class="sourceLineNo">1886</span> void regionOpenedWithoutPersistingToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1886"></a>
-<span class="sourceLineNo">1887</span> regionNode.transitionState(State.OPEN, STATES_EXPECTED_ON_OPEN);<a name="line.1887"></a>
-<span class="sourceLineNo">1888</span> RegionInfo regionInfo = regionNode.getRegionInfo();<a name="line.1888"></a>
-<span class="sourceLineNo">1889</span> regionStates.addRegionToServer(regionNode);<a name="line.1889"></a>
-<span class="sourceLineNo">1890</span> regionStates.removeFromFailedOpen(regionInfo);<a name="line.1890"></a>
-<span class="sourceLineNo">1891</span> }<a name="line.1891"></a>
-<span class="sourceLineNo">1892</span><a name="line.1892"></a>
-<span class="sourceLineNo">1893</span> // should be called under the RegionStateNode lock<a name="line.1893"></a>
-<span class="sourceLineNo">1894</span> void regionClosedWithoutPersistingToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1894"></a>
-<span class="sourceLineNo">1895</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1895"></a>
-<span class="sourceLineNo">1896</span> regionNode.transitionState(State.CLOSED, STATES_EXPECTED_ON_CLOSED);<a name="line.1896"></a>
-<span class="sourceLineNo">1897</span> regionNode.setRegionLocation(null);<a name="line.1897"></a>
-<span class="sourceLineNo">1898</span> if (regionLocation != null) {<a name="line.1898"></a>
-<span class="sourceLineNo">1899</span> regionNode.setLastHost(regionLocation);<a name="line.1899"></a>
-<span class="sourceLineNo">1900</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1900"></a>
-<span class="sourceLineNo">1901</span> }<a name="line.1901"></a>
-<span class="sourceLineNo">1902</span> }<a name="line.1902"></a>
-<span class="sourceLineNo">1903</span><a name="line.1903"></a>
-<span class="sourceLineNo">1904</span> // should be called under the RegionStateNode lock<a name="line.1904"></a>
-<span class="sourceLineNo">1905</span> // for SCP<a name="line.1905"></a>
-<span class="sourceLineNo">1906</span> public void regionClosedAbnormally(RegionStateNode regionNode) throws IOException {<a name="line.1906"></a>
-<span class="sourceLineNo">1907</span> RegionState.State state = regionNode.getState();<a name="line.1907"></a>
-<span class="sourceLineNo">1908</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1908"></a>
-<span class="sourceLineNo">1909</span> regionNode.transitionState(State.ABNORMALLY_CLOSED);<a name="line.1909"></a>
-<span class="sourceLineNo">1910</span> regionNode.setRegionLocation(null);<a name="line.1910"></a>
-<span class="sourceLineNo">1911</span> boolean succ = false;<a name="line.1911"></a>
-<span class="sourceLineNo">1912</span> try {<a name="line.1912"></a>
-<span class="sourceLineNo">1913</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1913"></a>
-<span class="sourceLineNo">1914</span> succ = true;<a name="line.1914"></a>
-<span class="sourceLineNo">1915</span> } finally {<a name="line.1915"></a>
-<span class="sourceLineNo">1916</span> if (!succ) {<a name="line.1916"></a>
-<span class="sourceLineNo">1917</span> // revert<a name="line.1917"></a>
-<span class="sourceLineNo">1918</span> regionNode.setState(state);<a name="line.1918"></a>
-<span class="sourceLineNo">1919</span> regionNode.setRegionLocation(regionLocation);<a name="line.1919"></a>
-<span class="sourceLineNo">1920</span> }<a name="line.1920"></a>
-<span class="sourceLineNo">1921</span> }<a name="line.1921"></a>
-<span class="sourceLineNo">1922</span> if (regionLocation != null) {<a name="line.1922"></a>
-<span class="sourceLineNo">1923</span> regionNode.setLastHost(regionLocation);<a name="line.1923"></a>
-<span class="sourceLineNo">1924</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1924"></a>
-<span class="sourceLineNo">1925</span> }<a name="line.1925"></a>
-<span class="sourceLineNo">1926</span> }<a name="line.1926"></a>
-<span class="sourceLineNo">1927</span><a name="line.1927"></a>
-<span class="sourceLineNo">1928</span> void persistToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1928"></a>
-<span class="sourceLineNo">1929</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1929"></a>
-<span class="sourceLineNo">1930</span> RegionInfo regionInfo = regionNode.getRegionInfo();<a name="line.1930"></a>
-<span class="sourceLineNo">1931</span> if (isMetaRegion(regionInfo) && regionNode.getState() == State.OPEN) {<a name="line.1931"></a>
-<span class="sourceLineNo">1932</span> // Usually we'd set a table ENABLED at this stage but hbase:meta is ALWAYs enabled, it<a name="line.1932"></a>
-<span class="sourceLineNo">1933</span> // can't be disabled -- so skip the RPC (besides... enabled is managed by TableStateManager<a name="line.1933"></a>
-<span class="sourceLineNo">1934</span> // which is backed by hbase:meta... Avoid setting ENABLED to avoid having to update state<a name="line.1934"></a>
-<span class="sourceLineNo">1935</span> // on table that contains state.<a name="line.1935"></a>
-<span class="sourceLineNo">1936</span> setMetaAssigned(regionInfo, true);<a name="line.1936"></a>
+<span class="sourceLineNo">1805</span> private static final State[] STATES_EXPECTED_ON_CLOSING = {<a name="line.1805"></a>
+<span class="sourceLineNo">1806</span> State.OPEN, // Normal case<a name="line.1806"></a>
+<span class="sourceLineNo">1807</span> State.CLOSING, // Retrying<a name="line.1807"></a>
+<span class="sourceLineNo">1808</span> State.SPLITTING, // Offline the split parent<a name="line.1808"></a>
+<span class="sourceLineNo">1809</span> State.MERGING // Offline the merge parents<a name="line.1809"></a>
+<span class="sourceLineNo">1810</span> };<a name="line.1810"></a>
+<span class="sourceLineNo">1811</span><a name="line.1811"></a>
+<span class="sourceLineNo">1812</span> private static final State[] STATES_EXPECTED_ON_CLOSED = {<a name="line.1812"></a>
+<span class="sourceLineNo">1813</span> State.CLOSING, // Normal case<a name="line.1813"></a>
+<span class="sourceLineNo">1814</span> State.CLOSED // Retrying<a name="line.1814"></a>
+<span class="sourceLineNo">1815</span> };<a name="line.1815"></a>
+<span class="sourceLineNo">1816</span><a name="line.1816"></a>
+<span class="sourceLineNo">1817</span> // This is for manually scheduled region assign, can add other states later if we find out other<a name="line.1817"></a>
+<span class="sourceLineNo">1818</span> // usages<a name="line.1818"></a>
+<span class="sourceLineNo">1819</span> private static final State[] STATES_EXPECTED_ON_ASSIGN = { State.CLOSED, State.OFFLINE };<a name="line.1819"></a>
+<span class="sourceLineNo">1820</span><a name="line.1820"></a>
+<span class="sourceLineNo">1821</span> // We only allow unassign or move a region which is in OPEN state.<a name="line.1821"></a>
+<span class="sourceLineNo">1822</span> private static final State[] STATES_EXPECTED_ON_UNASSIGN_OR_MOVE = { State.OPEN };<a name="line.1822"></a>
+<span class="sourceLineNo">1823</span><a name="line.1823"></a>
+<span class="sourceLineNo">1824</span> // ============================================================================================<a name="line.1824"></a>
+<span class="sourceLineNo">1825</span> // Region Status update<a name="line.1825"></a>
+<span class="sourceLineNo">1826</span> // Should only be called in TransitRegionStateProcedure(and related procedures), as the locking<a name="line.1826"></a>
+<span class="sourceLineNo">1827</span> // and pre-assumptions are very tricky.<a name="line.1827"></a>
+<span class="sourceLineNo">1828</span> // ============================================================================================<a name="line.1828"></a>
+<span class="sourceLineNo">1829</span> private void transitStateAndUpdate(RegionStateNode regionNode, RegionState.State newState,<a name="line.1829"></a>
+<span class="sourceLineNo">1830</span> RegionState.State... expectedStates) throws IOException {<a name="line.1830"></a>
+<span class="sourceLineNo">1831</span> RegionState.State state = regionNode.getState();<a name="line.1831"></a>
+<span class="sourceLineNo">1832</span> regionNode.transitionState(newState, expectedStates);<a name="line.1832"></a>
+<span class="sourceLineNo">1833</span> boolean succ = false;<a name="line.1833"></a>
+<span class="sourceLineNo">1834</span> try {<a name="line.1834"></a>
+<span class="sourceLineNo">1835</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1835"></a>
+<span class="sourceLineNo">1836</span> succ = true;<a name="line.1836"></a>
+<span class="sourceLineNo">1837</span> } finally {<a name="line.1837"></a>
+<span class="sourceLineNo">1838</span> if (!succ) {<a name="line.1838"></a>
+<span class="sourceLineNo">1839</span> // revert<a name="line.1839"></a>
+<span class="sourceLineNo">1840</span> regionNode.setState(state);<a name="line.1840"></a>
+<span class="sourceLineNo">1841</span> }<a name="line.1841"></a>
+<span class="sourceLineNo">1842</span> }<a name="line.1842"></a>
+<span class="sourceLineNo">1843</span> }<a name="line.1843"></a>
+<span class="sourceLineNo">1844</span><a name="line.1844"></a>
+<span class="sourceLineNo">1845</span> // should be called within the synchronized block of RegionStateNode<a name="line.1845"></a>
+<span class="sourceLineNo">1846</span> void regionOpening(RegionStateNode regionNode) throws IOException {<a name="line.1846"></a>
+<span class="sourceLineNo">1847</span> // As in SCP, for performance reason, there is no TRSP attached with this region, we will not<a name="line.1847"></a>
+<span class="sourceLineNo">1848</span> // update the region state, which means that the region could be in any state when we want to<a name="line.1848"></a>
+<span class="sourceLineNo">1849</span> // assign it after a RS crash. So here we do not pass the expectedStates parameter.<a name="line.1849"></a>
+<span class="sourceLineNo">1850</span> transitStateAndUpdate(regionNode, State.OPENING);<a name="line.1850"></a>
+<span class="sourceLineNo">1851</span> regionStates.addRegionToServer(regionNode);<a name="line.1851"></a>
+<span class="sourceLineNo">1852</span> // update the operation count metrics<a name="line.1852"></a>
+<span class="sourceLineNo">1853</span> metrics.incrementOperationCounter();<a name="line.1853"></a>
+<span class="sourceLineNo">1854</span> }<a name="line.1854"></a>
+<span class="sourceLineNo">1855</span><a name="line.1855"></a>
+<span class="sourceLineNo">1856</span> // should be called under the RegionStateNode lock<a name="line.1856"></a>
+<span class="sourceLineNo">1857</span> // The parameter 'giveUp' means whether we will try to open the region again, if it is true, then<a name="line.1857"></a>
+<span class="sourceLineNo">1858</span> // we will persist the FAILED_OPEN state into hbase:meta.<a name="line.1858"></a>
+<span class="sourceLineNo">1859</span> void regionFailedOpen(RegionStateNode regionNode, boolean giveUp) throws IOException {<a name="line.1859"></a>
+<span class="sourceLineNo">1860</span> RegionState.State state = regionNode.getState();<a name="line.1860"></a>
+<span class="sourceLineNo">1861</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1861"></a>
+<span class="sourceLineNo">1862</span> if (giveUp) {<a name="line.1862"></a>
+<span class="sourceLineNo">1863</span> regionNode.setState(State.FAILED_OPEN);<a name="line.1863"></a>
+<span class="sourceLineNo">1864</span> regionNode.setRegionLocation(null);<a name="line.1864"></a>
+<span class="sourceLineNo">1865</span> boolean succ = false;<a name="line.1865"></a>
+<span class="sourceLineNo">1866</span> try {<a name="line.1866"></a>
+<span class="sourceLineNo">1867</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1867"></a>
+<span class="sourceLineNo">1868</span> succ = true;<a name="line.1868"></a>
+<span class="sourceLineNo">1869</span> } finally {<a name="line.1869"></a>
+<span class="sourceLineNo">1870</span> if (!succ) {<a name="line.1870"></a>
+<span class="sourceLineNo">1871</span> // revert<a name="line.1871"></a>
+<span class="sourceLineNo">1872</span> regionNode.setState(state);<a name="line.1872"></a>
+<span class="sourceLineNo">1873</span> regionNode.setRegionLocation(regionLocation);<a name="line.1873"></a>
+<span class="sourceLineNo">1874</span> }<a name="line.1874"></a>
+<span class="sourceLineNo">1875</span> }<a name="line.1875"></a>
+<span class="sourceLineNo">1876</span> }<a name="line.1876"></a>
+<span class="sourceLineNo">1877</span> if (regionLocation != null) {<a name="line.1877"></a>
+<span class="sourceLineNo">1878</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1878"></a>
+<span class="sourceLineNo">1879</span> }<a name="line.1879"></a>
+<span class="sourceLineNo">1880</span> }<a name="line.1880"></a>
+<span class="sourceLineNo">1881</span><a name="line.1881"></a>
+<span class="sourceLineNo">1882</span> // should be called under the RegionStateNode lock<a name="line.1882"></a>
+<span class="sourceLineNo">1883</span> void regionClosing(RegionStateNode regionNode) throws IOException {<a name="line.1883"></a>
+<span class="sourceLineNo">1884</span> transitStateAndUpdate(regionNode, State.CLOSING, STATES_EXPECTED_ON_CLOSING);<a name="line.1884"></a>
+<span class="sourceLineNo">1885</span><a name="line.1885"></a>
+<span class="sourceLineNo">1886</span> RegionInfo hri = regionNode.getRegionInfo();<a name="line.1886"></a>
+<span class="sourceLineNo">1887</span> // Set meta has not initialized early. so people trying to create/edit tables will wait<a name="line.1887"></a>
+<span class="sourceLineNo">1888</span> if (isMetaRegion(hri)) {<a name="line.1888"></a>
+<span class="sourceLineNo">1889</span> setMetaAssigned(hri, false);<a name="line.1889"></a>
+<span class="sourceLineNo">1890</span> }<a name="line.1890"></a>
+<span class="sourceLineNo">1891</span> regionStates.addRegionToServer(regionNode);<a name="line.1891"></a>
+<span class="sourceLineNo">1892</span> // update the operation count metrics<a name="line.1892"></a>
+<span class="sourceLineNo">1893</span> metrics.incrementOperationCounter();<a name="line.1893"></a>
+<span class="sourceLineNo">1894</span> }<a name="line.1894"></a>
+<span class="sourceLineNo">1895</span><a name="line.1895"></a>
+<span class="sourceLineNo">1896</span> // for open and close, they will first be persist to the procedure store in<a name="line.1896"></a>
+<span class="sourceLineNo">1897</span> // RegionRemoteProcedureBase. So here we will first change the in memory state as it is considered<a name="line.1897"></a>
+<span class="sourceLineNo">1898</span> // as succeeded if the persistence to procedure store is succeeded, and then when the<a name="line.1898"></a>
+<span class="sourceLineNo">1899</span> // RegionRemoteProcedureBase is woken up, we will persist the RegionStateNode to hbase:meta.<a name="line.1899"></a>
+<span class="sourceLineNo">1900</span><a name="line.1900"></a>
+<span class="sourceLineNo">1901</span> // should be called under the RegionStateNode lock<a name="line.1901"></a>
+<span class="sourceLineNo">1902</span> void regionOpenedWithoutPersistingToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1902"></a>
+<span class="sourceLineNo">1903</span> regionNode.transitionState(State.OPEN, STATES_EXPECTED_ON_OPEN);<a name="line.1903"></a>
+<span class="sourceLineNo">1904</span> RegionInfo regionInfo = regionNode.getRegionInfo();<a name="line.1904"></a>
+<span class="sourceLineNo">1905</span> regionStates.addRegionToServer(regionNode);<a name="line.1905"></a>
+<span class="sourceLineNo">1906</span> regionStates.removeFromFailedOpen(regionInfo);<a name="line.1906"></a>
+<span class="sourceLineNo">1907</span> }<a name="line.1907"></a>
+<span class="sourceLineNo">1908</span><a name="line.1908"></a>
+<span class="sourceLineNo">1909</span> // should be called under the RegionStateNode lock<a name="line.1909"></a>
+<span class="sourceLineNo">1910</span> void regionClosedWithoutPersistingToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1910"></a>
+<span class="sourceLineNo">1911</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1911"></a>
+<span class="sourceLineNo">1912</span> regionNode.transitionState(State.CLOSED, STATES_EXPECTED_ON_CLOSED);<a name="line.1912"></a>
+<span class="sourceLineNo">1913</span> regionNode.setRegionLocation(null);<a name="line.1913"></a>
+<span class="sourceLineNo">1914</span> if (regionLocation != null) {<a name="line.1914"></a>
+<span class="sourceLineNo">1915</span> regionNode.setLastHost(regionLocation);<a name="line.1915"></a>
+<span class="sourceLineNo">1916</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1916"></a>
+<span class="sourceLineNo">1917</span> }<a name="line.1917"></a>
+<span class="sourceLineNo">1918</span> }<a name="line.1918"></a>
+<span class="sourceLineNo">1919</span><a name="line.1919"></a>
+<span class="sourceLineNo">1920</span> // should be called under the RegionStateNode lock<a name="line.1920"></a>
+<span class="sourceLineNo">1921</span> // for SCP<a name="line.1921"></a>
+<span class="sourceLineNo">1922</span> public void regionClosedAbnormally(RegionStateNode regionNode) throws IOException {<a name="line.1922"></a>
+<span class="sourceLineNo">1923</span> RegionState.State state = regionNode.getState();<a name="line.1923"></a>
+<span class="sourceLineNo">1924</span> ServerName regionLocation = regionNode.getRegionLocation();<a name="line.1924"></a>
+<span class="sourceLineNo">1925</span> regionNode.transitionState(State.ABNORMALLY_CLOSED);<a name="line.1925"></a>
+<span class="sourceLineNo">1926</span> regionNode.setRegionLocation(null);<a name="line.1926"></a>
+<span class="sourceLineNo">1927</span> boolean succ = false;<a name="line.1927"></a>
+<span class="sourceLineNo">1928</span> try {<a name="line.1928"></a>
+<span class="sourceLineNo">1929</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1929"></a>
+<span class="sourceLineNo">1930</span> succ = true;<a name="line.1930"></a>
+<span class="sourceLineNo">1931</span> } finally {<a name="line.1931"></a>
+<span class="sourceLineNo">1932</span> if (!succ) {<a name="line.1932"></a>
+<span class="sourceLineNo">1933</span> // revert<a name="line.1933"></a>
+<span class="sourceLineNo">1934</span> regionNode.setState(state);<a name="line.1934"></a>
+<span class="sourceLineNo">1935</span> regionNode.setRegionLocation(regionLocation);<a name="line.1935"></a>
+<span class="sourceLineNo">1936</span> }<a name="line.1936"></a>
<span class="sourceLineNo">1937</span> }<a name="line.1937"></a>
-<span class="sourceLineNo">1938</span> }<a name="line.1938"></a>
-<span class="sourceLineNo">1939</span><a name="line.1939"></a>
-<span class="sourceLineNo">1940</span> // ============================================================================================<a name="line.1940"></a>
-<span class="sourceLineNo">1941</span> // The above methods can only be called in TransitRegionStateProcedure(and related procedures)<a name="line.1941"></a>
-<span class="sourceLineNo">1942</span> // ============================================================================================<a name="line.1942"></a>
+<span class="sourceLineNo">1938</span> if (regionLocation != null) {<a name="line.1938"></a>
+<span class="sourceLineNo">1939</span> regionNode.setLastHost(regionLocation);<a name="line.1939"></a>
+<span class="sourceLineNo">1940</span> regionStates.removeRegionFromServer(regionLocation, regionNode);<a name="line.1940"></a>
+<span class="sourceLineNo">1941</span> }<a name="line.1941"></a>
+<span class="sourceLineNo">1942</span> }<a name="line.1942"></a>
<span class="sourceLineNo">1943</span><a name="line.1943"></a>
-<span class="sourceLineNo">1944</span> public void markRegionAsSplit(final RegionInfo parent, final ServerName serverName,<a name="line.1944"></a>
-<span class="sourceLineNo">1945</span> final RegionInfo daughterA, final RegionInfo daughterB) throws IOException {<a name="line.1945"></a>
-<span class="sourceLineNo">1946</span> // Update hbase:meta. Parent will be marked offline and split up in hbase:meta.<a name="line.1946"></a>
-<span class="sourceLineNo">1947</span> // The parent stays in regionStates until cleared when removed by CatalogJanitor.<a name="line.1947"></a>
-<span class="sourceLineNo">1948</span> // Update its state in regionStates to it shows as offline and split when read<a name="line.1948"></a>
-<span class="sourceLineNo">1949</span> // later figuring what regions are in a table and what are not: see<a name="line.1949"></a>
-<span class="sourceLineNo">1950</span> // regionStates#getRegionsOfTable<a name="line.1950"></a>
-<span class="sourceLineNo">1951</span> final RegionStateNode node = regionStates.getOrCreateRegionStateNode(parent);<a name="line.1951"></a>
-<span class="sourceLineNo">1952</span> node.setState(State.SPLIT);<a name="line.1952"></a>
-<span class="sourceLineNo">1953</span> final RegionStateNode nodeA = regionStates.getOrCreateRegionStateNode(daughterA);<a name="line.1953"></a>
-<span class="sourceLineNo">1954</span> nodeA.setState(State.SPLITTING_NEW);<a name="line.1954"></a>
-<span class="sourceLineNo">1955</span> final RegionStateNode nodeB = regionStates.getOrCreateRegionStateNode(daughterB);<a name="line.1955"></a>
-<span class="sourceLineNo">1956</span> nodeB.setState(State.SPLITTING_NEW);<a name="line.1956"></a>
-<span class="sourceLineNo">1957</span><a name="line.1957"></a>
-<span class="sourceLineNo">1958</span> TableDescriptor td = master.getTableDescriptors().get(parent.getTable());<a name="line.1958"></a>
-<span class="sourceLineNo">1959</span> // TODO: here we just update the parent region info in meta, to set split and offline to true,<a name="line.1959"></a>
-<span class="sourceLineNo">1960</span> // without changing the one in the region node. This is a bit confusing but the region info<a name="line.1960"></a>
-<span class="sourceLineNo">1961</span> // field in RegionStateNode is not expected to be changed in the current design. Need to find a<a name="line.1961"></a>
-<span class="sourceLineNo">1962</span> // possible way to address this problem, or at least adding more comments about the trick to<a name="line.1962"></a>
-<span class="sourceLineNo">1963</span> // deal with this problem, that when you want to filter out split parent, you need to check both<a name="line.1963"></a>
-<span class="sourceLineNo">1964</span> // the RegionState on whether it is split, and also the region info. If one of them matches then<a name="line.1964"></a>
-<span class="sourceLineNo">1965</span> // it is a split parent. And usually only one of them can match, as after restart, the region<a name="line.1965"></a>
-<span class="sourceLineNo">1966</span> // state will be changed from SPLIT to CLOSED.<a name="line.1966"></a>
-<span class="sourceLineNo">1967</span> regionStateStore.splitRegion(parent, daughterA, daughterB, serverName, td);<a name="line.1967"></a>
-<span class="sourceLineNo">1968</span> if (shouldAssignFavoredNodes(parent)) {<a name="line.1968"></a>
-<span class="sourceLineNo">1969</span> List<ServerName> onlineServers = this.master.getServerManager().getOnlineServersList();<a name="line.1969"></a>
-<span class="sourceLineNo">1970</span> getFavoredNodePromoter().generateFavoredNodesForDaughter(onlineServers, parent, daughterA,<a name="line.1970"></a>
-<span class="sourceLineNo">1971</span> daughterB);<a name="line.1971"></a>
-<span class="sourceLineNo">1972</span> }<a name="line.1972"></a>
-<span class="sourceLineNo">1973</span> }<a name="line.1973"></a>
-<span class="sourceLineNo">1974</span><a name="line.1974"></a>
-<span class="sourceLineNo">1975</span> /**<a name="line.1975"></a>
-<span class="sourceLineNo">1976</span> * When called here, the merge has happened. The merged regions have been<a name="line.1976"></a>
-<span class="sourceLineNo">1977</span> * unassigned and the above markRegionClosed has been called on each so they have been<a name="line.1977"></a>
-<span class="sourceLineNo">1978</span> * disassociated from a hosting Server. The merged region will be open after this call. The<a name="line.1978"></a>
-<span class="sourceLineNo">1979</span> * merged regions are removed from hbase:meta below. Later they are deleted from the filesystem<a name="line.1979"></a>
-<span class="sourceLineNo">1980</span> * by the catalog janitor running against hbase:meta. It notices when the merged region no<a name="line.1980"></a>
-<span class="sourceLineNo">1981</span> * longer holds references to the old regions (References are deleted after a compaction<a name="line.1981"></a>
-<span class="sourceLineNo">1982</span> * rewrites what the Reference points at but not until the archiver chore runs, are the<a name="line.1982"></a>
-<span class="sourceLineNo">1983</span> * References removed).<a name="line.1983"></a>
-<span class="sourceLineNo">1984</span> */<a name="line.1984"></a>
-<span class="sourceLineNo">1985</span> public void markRegionAsMerged(final RegionInfo child, final ServerName serverName,<a name="line.1985"></a>
-<span class="sourceLineNo">1986</span> RegionInfo [] mergeParents)<a name="line.1986"></a>
-<span class="sourceLineNo">1987</span> throws IOException {<a name="line.1987"></a>
-<span class="sourceLineNo">1988</span> final RegionStateNode node = regionStates.getOrCreateRegionStateNode(child);<a name="line.1988"></a>
-<span class="sourceLineNo">1989</span> node.setState(State.MERGED);<a name="line.1989"></a>
-<span class="sourceLineNo">1990</span> for (RegionInfo ri: mergeParents) {<a name="line.1990"></a>
-<span class="sourceLineNo">1991</span> regionStates.deleteRegion(ri);<a name="line.1991"></a>
-<span class="sourceLineNo">1992</span> }<a name="line.1992"></a>
-<span class="sourceLineNo">1993</span> TableDescriptor td = master.getTableDescriptors().get(child.getTable());<a name="line.1993"></a>
-<span class="sourceLineNo">1994</span> regionStateStore.mergeRegions(child, mergeParents, serverName, td);<a name="line.1994"></a>
-<span class="sourceLineNo">1995</span> if (shouldAssignFavoredNodes(child)) {<a name="line.1995"></a>
-<span class="sourceLineNo">1996</span> getFavoredNodePromoter().generateFavoredNodesForMergedRegion(child, mergeParents);<a name="line.1996"></a>
-<span class="sourceLineNo">1997</span> }<a name="line.1997"></a>
-<span class="sourceLineNo">1998</span> }<a name="line.1998"></a>
-<span class="sourceLineNo">1999</span><a name="line.1999"></a>
-<span class="sourceLineNo">2000</span> /*<a name="line.2000"></a>
-<span class="sourceLineNo">2001</span> * Favored nodes should be applied only when FavoredNodes balancer is configured and the region<a name="line.2001"></a>
-<span class="sourceLineNo">2002</span> * belongs to a non-system table.<a name="line.2002"></a>
-<span class="sourceLineNo">2003</span> */<a name="line.2003"></a>
-<span class="sourceLineNo">2004</span> private boolean shouldAssignFavoredNodes(RegionInfo region) {<a name="line.2004"></a>
-<span class="sourceLineNo">2005</span> return this.shouldAssignRegionsWithFavoredNodes &&<a name="line.2005"></a>
-<span class="sourceLineNo">2006</span> FavoredNodesManager.isFavoredNodeApplicable(region);<a name="line.2006"></a>
-<span class="sourceLineNo">2007</span> }<a name="line.2007"></a>
-<span class="sourceLineNo">2008</span><a name="line.2008"></a>
-<span class="sourceLineNo">2009</span> // ============================================================================================<a name="line.2009"></a>
-<span class="sourceLineNo">2010</span> // Assign Queue (Assign/Balance)<a name="line.2010"></a>
-<span class="sourceLineNo">2011</span> // ============================================================================================<a name="line.2011"></a>
-<span class="sourceLineNo">2012</span> private final ArrayList<RegionStateNode> pendingAssignQueue = new ArrayList<RegionStateNode>();<a name="line.2012"></a>
-<span class="sourceLineNo">2013</span> private final ReentrantLock assignQueueLock = new ReentrantLock();<a name="line.2013"></a>
-<span class="sourceLineNo">2014</span> private final Condition assignQueueFullCond = assignQueueLock.newCondition();<a name="line.2014"></a>
+<span class="sourceLineNo">1944</span> void persistToMeta(RegionStateNode regionNode) throws IOException {<a name="line.1944"></a>
+<span class="sourceLineNo">1945</span> regionStateStore.updateRegionLocation(regionNode);<a name="line.1945"></a>
+<span class="sourceLineNo">1946</span> RegionInfo regionInfo = regionNode.getRegionInfo();<a name="line.1946"></a>
+<span class="sourceLineNo">1947</span> if (isMetaRegion(regionInfo) && regionNode.getState() == State.OPEN) {<a name="line.1947"></a>
+<span class="sourceLineNo">1948</span> // Usually we'd set a table ENABLED at this stage but hbase:meta is ALWAYs enabled, it<a name="line.1948"></a>
+<span class="sourceLineNo">1949</span> // can't be disabled -- so skip the RPC (besides... enabled is managed by TableStateManager<a name="line.1949"></a>
+<span class="sourceLineNo">1950</span> // which is backed by hbase:meta... Avoid setting ENABLED to avoid having to update state<a name="line.1950"></a>
+<span class="sourceLineNo">1951</span> // on table that contains state.<a name="line.1951"></a>
+<span class="sourceLineNo">1952</span> setMetaAssigned(regionInfo, true);<a name="line.1952"></a>
+<span class="sourceLineNo">1953</span> }<a name="line.1953"></a>
+<span class="sourceLineNo">1954</span> }<a name="line.1954"></a>
+<span class="sourceLineNo">1955</span><a name="line.1955"></a>
+<span class="sourceLineNo">1956</span> // ============================================================================================<a name="line.1956"></a>
+<span class="sourceLineNo">1957</span> // The above methods can only be called in TransitRegionStateProcedure(and related procedures)<a name="line.1957"></a>
+<span class="sourceLineNo">1958</span> // ============================================================================================<a name="line.1958"></a>
+<span class="sourceLineNo">1959</span><a name="line.1959"></a>
+<span class="sourceLineNo">1960</span> public void markRegionAsSplit(final RegionInfo parent, final ServerName serverName,<a name="line.1960"></a>
+<span class="sourceLineNo">1961</span> final RegionInfo daughterA, final RegionInfo daughterB) throws IOException {<a name="line.1961"></a>
+<span class="sourceLineNo">1962</span> // Update hbase:meta. Parent will be marked offline and split up in hbase:meta.<a name="line.1962"></a>
+<span class="sourceLineNo">1963</span> // The parent stays in regionStates until cleared when removed by CatalogJanitor.<a name="line.1963"></a>
+<span class="sourceLineNo">1964</span> // Update its state in regionStates to it shows as offline and split when read<a name="line.1964"></a>
+<span class="sourceLineNo">1965</span> // later figuring what regions are in a table and what are not: see<a name="line.1965"></a>
+<span class="sourceLineNo">1966</span> // regionStates#getRegionsOfTable<a name="line.1966"></a>
+<span class="sourceLineNo">1967</span> final RegionStateNode node = regionStates.getOrCreateRegionStateNode(parent);<a name="line.1967"></a>
+<span class="sourceLineNo">1968</span> node.setState(State.SPLIT);<a name="line.1968"></a>
+<span class="sourceLineNo">1969</span> final RegionStateNode nodeA = regionStates.getOrCreateRegionStateNode(daughterA);<a name="line.1969"></a>
+<span class="sourceLineNo">1970</span> nodeA.setState(State.SPLITTING_NEW);<a name="line.1970"></a>
+<span class="sourceLineNo">1971</span> final RegionStateNode nodeB = regionStates.getOrCreateRegionStateNode(daughterB);<a name="line.1971"></a>
+<span class="sourceLineNo">1972</span> nodeB.setState(State.SPLITTING_NEW);<a name="line.1972"></a>
+<span class="sourceLineNo">1973</span><a name="line.1973"></a>
+<span class="sourceLineNo">1974</span> TableDescriptor td = master.getTableDescriptors().get(parent.getTable());<a name="line.1974"></a>
+<span class="sourceLineNo">1975</span> // TODO: here we just update the parent region info in meta, to set split and offline to true,<a name="line.1975"></a>
+<span class="sourceLineNo">1976</span> // without changing the one in the region node. This is a bit confusing but the region info<a name="line.1976"></a>
+<span class="sourceLineNo">1977</span> // field in RegionStateNode is not expected to be changed in the current design. Need to find a<a name="line.1977"></a>
+<span class="sourceLineNo">1978</span> // possible way to address this problem, or at least adding more comments about the trick to<a name="line.1978"></a>
+<span class="sourceLineNo">1979</span> // deal with this problem, that when you want to filter out split parent, you need to check both<a name="line.1979"></a>
+<span class="sourceLineNo">1980</span> // the RegionState on whether it is split, and also the region info. If one of them matches then<a name="line.1980"></a>
+<span class="sourceLineNo">1981</span> // it is a split parent. And usually only one of them can match, as after restart, the region<a name="line.1981"></a>
+<span class="sourceLineNo">1982</span> // state will be changed from SPLIT to CLOSED.<a name="line.1982"></a>
+<span class="sourceLineNo">1983</span> regionStateStore.splitRegion(parent, daughterA, daughterB, serverName, td);<a name="line.1983"></a>
+<span class="sourceLineNo">1984</span> if (shouldAssignFavoredNodes(parent)) {<a name="line.1984"></a>
+<span class="sourceLineNo">1985</span> List<ServerName> onlineServers = this.master.getServerManager().getOnlineServersList();<a name="line.1985"></a>
+<span class="sourceLineNo">1986</span> getFavoredNodePromoter().generateFavoredNodesForDaughter(onlineServers, parent, daughterA,<a name="line.1986"></a>
+<span class="sourceLineNo">1987</span> daughterB);<a name="line.1987"></a>
+<span class="sourceLineNo">1988</span> }<a name="line.1988"></a>
+<span class="sourceLineNo">1989</span> }<a name="line.1989"></a>
+<span class="sourceLineNo">1990</span><a name="line.1990"></a>
+<span class="sourceLineNo">1991</span> /**<a name="line.1991"></a>
+<span class="sourceLineNo">1992</span> * When called here, the merge has happened. The merged regions have been<a name="line.1992"></a>
+<span class="sourceLineNo">1993</span> * unassigned and the above markRegionClosed has been called on each so they have been<a name="line.1993"></a>
+<span class="sourceLineNo">1994</span> * disassociated from a hosting Server. The merged region will be open after this call. The<a name="line.1994"></a>
+<span class="sourceLineNo">1995</span> * merged regions are removed from hbase:meta below. Later they are deleted from the filesystem<a name="line.1995"></a>
+<span class="sourceLineNo">1996</span> * by the catalog janitor running against hbase:meta. It notices when the merged region no<a name="line.1996"></a>
+<span class="sourceLineNo">1997</span> * longer holds references to the old regions (References are deleted after a compaction<a name="line.1997"></a>
+<span class="sourceLineNo">1998</span> * rewrites what the Reference points at but not until the archiver chore runs, are the<a name="line.1998"></a>
+<span class="sourceLineNo">1999</span> * References removed).<a name="line.1999"></a>
+<span class="sourceLineNo">2000</span> */<a name="line.2000"></a>
+<span class="sourceLineNo">2001</span> public void markRegionAsMerged(final RegionInfo child, final ServerName serverName,<a name="line.2001"></a>
+<span class="sourceLineNo">2002</span> RegionInfo [] mergeParents)<a name="line.2002"></a>
+<span class="sourceLineNo">2003</span> throws IOException {<a name="line.2003"></a>
+<span class="sourceLineNo">2004</span> final RegionStateNode node = regionStates.getOrCreateRegionStateNode(child);<a name="line.2004"></a>
+<span class="sourceLineNo">2005</span> node.setState(State.MERGED);<a name="line.2005"></a>
+<span class="sourceLineNo">2006</span> for (RegionInfo ri: mergeParents) {<a name="line.2006"></a>
+<span class="sourceLineNo">2007</span> regionStates.deleteRegion(ri);<a name="line.2007"></a>
+<span class="sourceLineNo">2008</span> }<a name="line.2008"></a>
+<span class="sourceLineNo">2009</span> TableDescriptor td = master.getTableDescriptors().get(child.getTable());<a name="line.2009"></a>
+<span class="sourceLineNo">2010</span> regionStateStore.mergeRegions(child, mergeParents, serverName, td);<a name="line.2010"></a>
+<span class="sourceLineNo">2011</span> if (shouldAssignFavoredNodes(child)) {<a name="line.2011"></a>
+<span class="sourceLineNo">2012</span> getFavoredNodePromoter().generateFavoredNodesForMergedRegion(child, mergeParents);<a name="line.2012"></a>
+<span class="sourceLineNo">2013</span> }<a name="line.2013"></a>
+<span class="sourceLineNo">2014</span> }<a name="line.2014"></a>
<span class="sourceLineNo">2015</span><a name="line.2015"></a>
-<span class="sourceLineNo">2016</span> /**<a name="line.2016"></a>
-<span class="sourceLineNo">2017</span> * Add the assign operation to the assignment queue.<a name="line.2017"></a>
-<span class="sourceLineNo">2018</span> * The pending assignment operation will be processed,<a name="line.2018"></a>
-<span class="sourceLineNo">2019</span> * and each region will be assigned by a server using the balancer.<a name="line.2019"></a>
-<span class="sourceLineNo">2020</span> */<a name="line.2020"></a>
-<span class="sourceLineNo">2021</span> protected void queueAssign(final RegionStateNode regionNode) {<a name="line.2021"></a>
-<span class="sourceLineNo">2022</span> regionNode.getProcedureEvent().suspend();<a name="line.2022"></a>
-<span class="sourceLineNo">2023</span><a name="line.2023"></a>
-<span class="sourceLineNo">2024</span> // TODO: quick-start for meta and the other sys-tables?<a name="line.2024"></a>
-<span class="sourceLineNo">2025</span> assignQueueLock.lock();<a name="line.2025"></a>
-<span class="sourceLineNo">2026</span> try {<a name="line.2026"></a>
-<span class="sourceLineNo">2027</span> pendingAssignQueue.add(regionNode);<a name="line.2027"></a>
-<span class="sourceLineNo">2028</span> if (regionNode.isSystemTable() ||<a name="line.2028"></a>
-<span class="sourceLineNo">2029</span> pendingAssignQueue.size() == 1 ||<a name="line.2029"></a>
-<span class="sourceLineNo">2030</span> pendingAssignQueue.size() >= assignDispatchWaitQueueMaxSize) {<a name="line.2030"></a>
-<span class="sourceLineNo">2031</span> assignQueueFullCond.signal();<a name="line.2031"></a>
-<span class="sourceLineNo">2032</span> }<a name="line.2032"></a>
-<span class="sourceLineNo">2033</span> } finally {<a name="line.2033"></a>
-<span class="sourceLineNo">2034</span> assignQueueLock.unlock();<a name="line.2034"></a>
-<span class="sourceLineNo">2035</span> }<a name="line.2035"></a>
-<span class="sourceLineNo">2036</span> }<a name="line.2036"></a>
-<span class="sourceLineNo">2037</span><a name="line.2037"></a>
-<span class="sourceLineNo">2038</span> private void startAssignmentThread() {<a name="line.2038"></a>
-<span class="sourceLineNo">2039</span> assignThread = new Thread(master.getServerName().toShortString()) {<a name="line.2039"></a>
-<span class="sourceLineNo">2040</span> @Override<a name="line.2040"></a>
-<span class="sourceLineNo">2041</span> public void run() {<a name="line.2041"></a>
-<span class="sourceLineNo">2042</span> while (isRunning()) {<a name="line.2042"></a>
-<span class="sourceLineNo">2043</span> processAssignQueue();<a name="line.2043"></a>
-<span class="sourceLineNo">2044</span> }<a name="line.2044"></a>
-<span class="sourceLineNo">2045</span> pendingAssignQueue.clear();<a name="line.2045"></a>
-<span class="sourceLineNo">2046</span> }<a name="line.2046"></a>
-<span class="sourceLineNo">2047</span> };<a name="line.2047"></a>
-<span class="sourceLineNo">2048</span> assignThread.setDaemon(true);<a name="line.2048"></a>
-<span class="sourceLineNo">2049</span> assignThread.start();<a name="line.2049"></a>
-<span class="sourceLineNo">2050</span> }<a name="line.2050"></a>
-<span class="sourceLineNo">2051</span><a name="line.2051"></a>
-<span class="sourceLineNo">2052</span> private void stopAssignmentThread() {<a name="line.2052"></a>
-<span class="sourceLineNo">2053</span> assignQueueSignal();<a name="line.2053"></a>
-<span class="sourceLineNo">2054</span> try {<a name="line.2054"></a>
-<span class="sourceLineNo">2055</span> while (assignThread.isAlive()) {<a name="line.2055"></a>
-<span class="sourceLineNo">2056</span> assignQueueSignal();<a name="line.2056"></a>
-<span class="sourceLineNo">2057</span> assignThread.join(250);<a name="line.2057"></a>
-<span class="sourceLineNo">2058</span> }<a name="line.2058"></a>
-<span class="sourceLineNo">2059</span> } catch (InterruptedException e) {<a name="line.2059"></a>
-<span class="sourceLineNo">2060</span> LOG.warn("join interrupted", e);<a name="line.2060"></a>
-<span class="sourceLineNo">2061</span> Thread.currentThread().interrupt();<a name="line.2061"></a>
-<span class="sourceLineNo">2062</span> }<a name="line.2062"></a>
-<span class="sourceLineNo">2063</span> }<a name="line.2063"></a>
-<span class="sourceLineNo">2064</span><a name="line.2064"></a>
-<span class="sourceLineNo">2065</span> private void assignQueueSignal() {<a name="line.2065"></a>
-<span class="sourceLineNo">2066</span> assignQueueLock.lock();<a name="line.2066"></a>
-<span class="sourceLineNo">2067</span> try {<a name="line.2067"></a>
-<span class="sourceLineNo">2068</span> assignQueueFullCond.signal();<a name="line.2068"></a>
-<span class="sourceLineNo">2069</span> } finally {<a name="line.2069"></a>
-<span class="sourceLineNo">2070</span> assignQueueLock.unlock();<a name="line.2070"></a>
-<span class="sourceLineNo">2071</span> }<a name="line.2071"></a>
-<span class="sourceLineNo">2072</span> }<a name="line.2072"></a>
-<span class="sourceLineNo">2073</span><a name="line.2073"></a>
-<span class="sourceLineNo">2074</span> @edu.umd.cs.findbugs.annotations.SuppressWarnings("WA_AWAIT_NOT_IN_LOOP")<a name="line.2074"></a>
-<span class="sourceLineNo">2075</span> private HashMap<RegionInfo, RegionStateNode> waitOnAssignQueue() {<a name="line.2075"></a>
-<span class="sourceLineNo">2076</span> HashMap<RegionInfo, RegionStateNode> regions = null;<a name="line.2076"></a>
-<span class="sourceLineNo">2077</span><a name="line.2077"></a>
-<span class="sourceLineNo">2078</span> assignQueueLock.lock();<a name="line.2078"></a>
-<span class="sourceLineNo">2079</span> try {<a name="line.2079"></a>
-<span class="sourceLineNo">2080</span> if (pendingAssignQueue.isEmpty() && isRunning()) {<a name="line.2080"></a>
-<span class="sourceLineNo">2081</span> assignQueueFullCond.await();<a name="line.2081"></a>
-<span class="sourceLineNo">2082</span> }<a name="line.2082"></a>
-<span class="sourceLineNo">2083</span><a name="line.2083"></a>
-<span class="sourceLineNo">2084</span> if (!isRunning()) {<a name="line.2084"></a>
-<span class="sourceLineNo">2085</span> return null;<a name="line.2085"></a>
-<span class="sourceLineNo">2086</span> }<a name="line.2086"></a>
-<span class="sourceLineNo">2087</span> assignQueueFullCond.await(assignDispatchWaitMillis, TimeUnit.MILLISECONDS);<a name="line.2087"></a>
-<span class="sourceLineNo">2088</span> regions = new HashMap<RegionInfo, RegionStateNode>(pendingAssignQueue.size());<a name="line.2088"></a>
-<span class="sourceLineNo">2089</span> for (RegionStateNode regionNode: pendingAssignQueue) {<a name="line.2089"></a>
-<span class="sourceLineNo">2090</span> regions.put(regionNode.getRegionInfo(), regionNode);<a name="line.2090"></a>
-<span class="sourceLineNo">2091</span> }<a name="line.2091"></a>
-<span class="sourceLineNo">2092</span> pendingAssignQueue.clear();<a name="line.2092"></a>
-<span class="sourceLineNo">2093</span> } catch (InterruptedException e) {<a name="line.2093"></a>
-<span class="sourceLineNo">2094</span> LOG.warn("got interrupted ", e);<a name="line.2094"></a>
-<span class="sourceLineNo">2095</span> Thread.currentThread().interrupt();<a name="line.2095"></a>
-<span class="sourceLineNo">2096</span> } finally {<a name="line.2096"></a>
-<span class="sourceLineNo">2097</span> assignQueueLock.unlock();<a name="line.2097"></a>
-<span class="sourceLineNo">2098</span> }<a name="line.2098"></a>
-<span class="sourceLineNo">2099</span> return regions;<a name="line.2099"></a>
-<span class="sourceLineNo">2100</span> }<a name="line.2100"></a>
-<span class="sourceLineNo">2101</span><a name="line.2101"></a>
-<span class="sourceLineNo">2102</span> private void processAssignQueue() {<a name="line.2102"></a>
-<span class="sourceLineNo">2103</span> final HashMap<RegionInfo, RegionStateNode> regions = waitOnAssignQueue();<a name="line.2103"></a>
-<span class="sourceLineNo">2104</span> if (regions == null || regions.size() == 0 || !isRunning()) {<a name="line.2104"></a>
-<span class="sourceLineNo">2105</span> return;<a name="line.2105"></a>
-<span class="sourceLineNo">2106</span> }<a name="line.2106"></a>
-<span class="sourceLineNo">2107</span><a name="line.2107"></a>
-<span class="sourceLineNo">2108</span> if (LOG.isTraceEnabled()) {<a name="line.2108"></a>
-<span class="sourceLineNo">2109</span> LOG.trace("PROCESS ASSIGN QUEUE regionCount=" + regions.size());<a name="line.2109"></a>
-<span class="sourceLineNo">2110</span> }<a name="line.2110"></a>
-<span class="sourceLineNo">2111</span><a name="line.2111"></a>
-<span class="sourceLineNo">2112</span> // TODO: Optimize balancer. pass a RegionPlan?<a name="line.2112"></a>
-<span class="sourceLineNo">2113</span> final HashMap<RegionInfo, ServerName> retainMap = new HashMap<>();<a name="line.2113"></a>
-<span class="sourceLineNo">2114</span> final List<RegionInfo> userHRIs = new ArrayList<>(regions.size());<a name="line.2114"></a>
-<span class="sourceLineNo">2115</span> // Regions for system tables requiring reassignment<a name="line.2115"></a>
-<span class="sourceLineNo">2116</span> final List<RegionInfo> systemHRIs = new ArrayList<>();<a name="line.2116"></a>
-<span class="sourceLineNo">2117</span> for (RegionStateNode regionStateNode: regions.values()) {<a name="line.2117"></a>
-<span class="sourceLineNo">2118</span> boolean sysTable = regionStateNode.isSystemTable();<a name="line.2118"></a>
-<span class="sourceLineNo">2119</span> final List<RegionInfo> hris = sysTable? systemHRIs: userHRIs;<a name="line.2119"></a>
-<span class="sourceLineNo">2120</span> if (regionStateNode.getRegionLocation() != null) {<a name="line.2120"></a>
-<span class="sourceLineNo">2121</span> retainMap.put(regionStateNode.getRegionInfo(), regionStateNode.getRegionLocation());<a name="line.2121"></a>
-<span class="sourceLineNo">2122</span> } else {<a name="line.2122"></a>
-<span class="sourceLineNo">2123</span> hris.add(regionStateNode.getRegionInfo());<a name="line.2123"></a>
-<span class="sourceLineNo">2124</span> }<a name="line.2124"></a>
-<span class="sourceLineNo">2125</span> }<a name="line.2125"></a>
-<span class="sourceLineNo">2126</span><a name="line.2126"></a>
-<span class="sourceLineNo">2127</span> // TODO: connect with the listener to invalidate the cache<a name="line.2127"></a>
-<span class="sourceLineNo">2128</span><a name="line.2128"></a>
-<span class="sourceLineNo">2129</span> // TODO use events<a name="line.2129"></a>
-<span class="sourceLineNo">2130</span> List<ServerName> servers = master.getServerManager().createDestinationServersList();<a name="line.2130"></a>
-<span class="sourceLineNo">2131</span> for (int i = 0; servers.size() < 1; ++i) {<a name="line.2131"></a>
-<span class="sourceLineNo">2132</span> // Report every fourth time around this loop; try not to flood log.<a name="line.2132"></a>
-<span class="sourceLineNo">2133</span> if (i % 4 == 0) {<a name="line.2133"></a>
-<span class="sourceLineNo">2134</span> LOG.warn("No servers available; cannot place " + regions.size() + " unassigned regions.");<a name="line.2134"></a>
-<span class="sourceLineNo">2135</span> }<a name="line.2135"></a>
-<span class="sourceLineNo">2136</span><a name="line.2136"></a>
-<span class="sourceLineNo">2137</span> if (!isRunning()) {<a name="line.2137"></a>
-<span class="sourceLineNo">2138</span> LOG.debug("Stopped! Dropping assign of " + regions.size() + " queued regions.");<a name="line.2138"></a>
-<span class="sourceLineNo">2139</span> return;<a name="line.2139"></a>
+<span class="sourceLineNo">2016</span> /*<a name="line.2016"></a>
+<span class="sourceLineNo">2017</span> * Favored nodes should be applied only when FavoredNodes balancer is configured and the region<a name="line.2017"></a>
+<span class="sourceLineNo">2018</span> * belongs to a non-system table.<a name="line.2018"></a>
+<span class="sourceLineNo">2019</span> */<a name="line.2019"></a>
+<span class="sourceLineNo">2020</span> private boolean shouldAssignFavoredNodes(RegionInfo region) {<a name="line.2020"></a>
+<span class="sourceLineNo">2021</span> return this.shouldAssignRegionsWithFavoredNodes &&<a name="line.2021"></a>
+<span class="sourceLineNo">2022</span> FavoredNodesManager.isFavoredNodeApplicable(region);<a name="line.2022"></a>
+<span class="sourceLineNo">2023</span> }<a name="line.2023"></a>
+<span class="sourceLineNo">2024</span><a name="line.2024"></a>
+<span class="sourceLineNo">2025</span> // ============================================================================================<a name="line.2025"></a>
+<span class="sourceLineNo">2026</span> // Assign Queue (Assign/Balance)<a name="line.2026"></a>
+<span class="sourceLineNo">2027</span> // ============================================================================================<a name="line.2027"></a>
+<span class="sourceLineNo">2028</span> private final ArrayList<RegionStateNode> pendingAssignQueue = new ArrayList<RegionStateNode>();<a name="line.2028"></a>
+<span class="sourceLineNo">2029</span> private final ReentrantLock assignQueueLock = new ReentrantLock();<a name="line.2029"></a>
+<span class="sourceLineNo">2030</span> private final Condition assignQueueFullCond = assignQueueLock.newCondition();<a name="line.2030"></a>
+<span class="sourceLineNo">2031</span><a name="line.2031"></a>
+<span class="sourceLineNo">2032</span> /**<a name="line.2032"></a>
+<span class="sourceLineNo">2033</span> * Add the assign operation to the assignment queue.<a name="line.2033"></a>
+<span class="sourceLineNo">2034</span> * The pending assignment operation will be processed,<a name="line.2034"></a>
+<span class="sourceLineNo">2035</span> * and each region will be assigned by a server using the balancer.<a name="line.2035"></a>
+<span class="sourceLineNo">2036</span> */<a name="line.2036"></a>
+<span class="sourceLineNo">2037</span> protected void queueAssign(final RegionStateNode regionNode) {<a name="line.2037"></a>
+<span class="sourceLineNo">2038</span> regionNode.getProcedureEvent().suspend();<a name="line.2038"></a>
+<span class="sourceLineNo">2039</span><a name="line.2039"></a>
+<span class="sourceLineNo">2040</span> // TODO: quick-start for meta and the other sys-tables?<a name="line.2040"></a>
+<span class="sourceLineNo">2041</span> assignQueueLock.lock();<a name="line.2041"></a>
+<span class="sourceLineNo">2042</span> try {<a name="line.2042"></a>
+<span class="sourceLineNo">2043</span> pendingAssignQueue.add(regionNode);<a name="line.2043"></a>
+<span class="sourceLineNo">2044</span> if (regionNode.isSystemTable() ||<a name="line.2044"></a>
+<span class="sourceLineNo">2045</span> pendingAssignQueue.size() == 1 ||<a name="line.2045"></a>
+<span class="sourceLineNo">2046</span> pendingAssignQueue.size() >= assignDispatchWaitQueueMaxSize) {<a name="line.2046"></a>
+<span class="sourceLineNo">2047</span> assignQueueFullCond.signal();<a name="line.2047"></a>
+<span class="sourceLineNo">2048</span> }<a name="line.2048"></a>
+<span class="sourceLineNo">2049</span> } finally {<a name="line.2049"></a>
+<span class="sourceLineNo">2050</span> assignQueueLock.unlock();<a name="line.2050"></a>
+<span class="sourceLineNo">2051</span> }<a name="line.2051"></a>
+<span class="sourceLineNo">2052</span> }<a name="line.2052"></a>
+<span class="sourceLineNo">2053</span><a name="line.2053"></a>
+<span class="sourceLineNo">2054</span> private void startAssignmentThread() {<a name="line.2054"></a>
+<span class="sourceLineNo">2055</span> assignThread = new Thread(master.getServerName().toShortString()) {<a name="line.2055"></a>
+<span class="sourceLineNo">2056</span> @Override<a name="line.2056"></a>
+<span class="sourceLineNo">2057</span> public void run() {<a name="line.2057"></a>
+<span class="sourceLineNo">2058</span> while (isRunning()) {<a name="line.2058"></a>
+<span class="sourceLineNo">2059</span> processAssignQueue();<a name="line.2059"></a>
+<span class="sourceLineNo">2060</span> }<a name="line.2060"></a>
+<span class="sourceLineNo">2061</span> pendingAssignQueue.clear();<a name="line.2061"></a>
+<span class="sourceLineNo">2062</span> }<a name="line.2062"></a>
+<span class="sourceLineNo">2063</span> };<a name="line.2063"></a>
+<span class="sourceLineNo">2064</span> assignThread.setDaemon(true);<a name="line.2064"></a>
+<span class="sourceLineNo">2065</span> assignThread.start();<a name="line.2065"></a>
+<span class="sourceLineNo">2066</span> }<a name="line.2066"></a>
+<span class="sourceLineNo">2067</span><a name="line.2067"></a>
+<span class="sourceLineNo">2068</span> private void stopAssignmentThread() {<a name="line.2068"></a>
+<span class="sourceLineNo">2069</span> assignQueueSignal();<a name="line.2069"></a>
+<span class="sourceLineNo">2070</span> try {<a name="line.2070"></a>
+<span class="sourceLineNo">2071</span> while (assignThread.isAlive()) {<a name="line.2071"></a>
+<span class="sourceLineNo">2072</span> assignQueueSignal();<a name="line.2072"></a>
+<span class="sourceLineNo">2073</span> assignThread.join(250);<a name="line.2073"></a>
+<span class="sourceLineNo">2074</span> }<a name="line.2074"></a>
+<span class="sourceLineNo">2075</span> } catch (InterruptedException e) {<a name="line.2075"></a>
+<span class="sourceLineNo">2076</span> LOG.warn("join interrupted", e);<a name="line.2076"></a>
+<span class="sourceLineNo">2077</span> Thread.currentThread().interrupt();<a name="line.2077"></a>
+<span class="sourceLineNo">2078</span> }<a name="line.2078"></a>
+<span class="sourceLineNo">2079</span> }<a name="line.2079"></a>
+<span class="sourceLineNo">2080</span><a name="line.2080"></a>
+<span class="sourceLineNo">2081</span> private void assignQueueSignal() {<a name="line.2081"></a>
+<span class="sourceLineNo">2082</span> assignQueueLock.lock();<a name="line.2082"></a>
+<span class="sourceLineNo">2083</span> try {<a name="line.2083"></a>
+<span class="sourceLineNo">2084</span> assignQueueFullCond.signal();<a name="line.2084"></a>
+<span class="sourceLineNo">2085</span> } finally {<a name="line.2085"></a>
+<span class="sourceLineNo">2086</span> assignQueueLock.unlock();<a name="line.2086"></a>
+<span class="sourceLineNo">2087</span> }<a name="line.2087"></a>
+<span class="sourceLineNo">2088</span> }<a name="line.2088"></a>
+<span class="sourceLineNo">2089</span><a name="line.2089"></a>
+<span class="sourceLineNo">2090</span> @edu.umd.cs.findbugs.annotations.SuppressWarnings("WA_AWAIT_NOT_IN_LOOP")<a name="line.2090"></a>
+<span class="sourceLineNo">2091</span> private HashMap<RegionInfo, RegionStateNode> waitOnAssignQueue() {<a name="line.2091"></a>
+<span class="sourceLineNo">2092</span> HashMap<RegionInfo, RegionStateNode> regions = null;<a name="line.2092"></a>
+<span class="sourceLineNo">2093</span><a name="line.2093"></a>
+<span class="sourceLineNo">2094</span> assignQueueLock.lock();<a name="line.2094"></a>
+<span class="sourceLineNo">2095</span> try {<a name="line.2095"></a>
+<span class="sourceLineNo">2096</span> if (pendingAssignQueue.isEmpty() && isRunning()) {<a name="line.2096"></a>
+<span class="sourceLineNo">2097</span> assignQueueFullCond.await();<a name="line.2097"></a>
+<span class="sourceLineNo">2098</span> }<a name="line.2098"></a>
+<span class="sourceLineNo">2099</span><a name="line.2099"></a>
+<span class="sourceLineNo">2100</span> if (!isRunning()) {<a name="line.2100"></a>
+<span class="sourceLineNo">2101</span> return null;<a name="line.2101"></a>
+<span class="sourceLineNo">2102</span> }<a name="line.2102"></a>
+<span class="sourceLineNo">2103</span> assignQueueFullCond.await(assignDispatchWaitMillis, TimeUnit.MILLISECONDS);<a name="line.2103"></a>
+<span class="sourceLineNo">2104</span> regions = new HashMap<RegionInfo, RegionStateNode>(pendingAssignQueue.size());<a name="line.2104"></a>
+<span class="sourceLineNo">2105</span> for (RegionStateNode regionNode: pendingAssignQueue) {<a name="line.2105"></a>
+<span class="sourceLineNo">2106</span> regions.put(regionNode.getRegionInfo(), regionNode);<a name="line.2106"></a>
+<span class="sourceLineNo">2107</span> }<a name="line.2107"></a>
+<span class="sourceLineNo">2108</span> pendingAssignQueue.clear();<a name="line.2108"></a>
+<span class="sourceLineNo">2109</span> } catch (InterruptedException e) {<a name="line.2109"></a>
+<span class="sourceLineNo">2110</span> LOG.warn("got interrupted ", e);<a name="line.2110"></a>
+<span class="sourceLineNo">2111</span> Thread.currentThread().interrupt();<a name="line.2111"></a>
+<span class="sourceLineNo">2112</span> } finally {<a name="line.2112"></a>
+<span class="sourceLineNo">2113</span> assignQueueLock.unlock();<a name="line.2113"></a>
+<span class="sourceLineNo">2114</span> }<a name="line.2114"></a>
+<span class="sourceLineNo">2115</span> return regions;<a name="line.2115"></a>
+<span class="sourceLineNo">2116</span> }<a name="line.2116"></a>
+<span class="sourceLineNo">2117</span><a name="line.2117"></a>
+<span class="sourceLineNo">2118</span> private void processAssignQueue() {<a name="line.2118"></a>
+<span class="sourceLineNo">2119</span> final HashMap<RegionInfo, RegionStateNode> regions = waitOnAssignQueue();<a name="line.2119"></a>
+<span class="sourceLineNo">2120</span> if (regions == null || regions.size() == 0 || !isRunning()) {<a name="line.2120"></a>
+<span class="sourceLineNo">2121</span> return;<a name="line.2121"></a>
+<span class="sourceLineNo">2122</span> }<a name="line.2122"></a>
+<span class="sourceLineNo">2123</span><a name="line.2123"></a>
+<span class="sourceLineNo">2124</span> if (LOG.isTraceEnabled()) {<a name="line.2124"></a>
+<span class="sourceLineNo">2125</span> LOG.trace("PROCESS ASSIGN QUEUE regionCount=" + regions.size());<a name="line.2125"></a>
+<span class="sourceLineNo">2126</span> }<a name="line.2126"></a>
+<span class="sourceLineNo">2127</span><a name="line.2127"></a>
+<span class="sourceLineNo">2128</span> // TODO: Optimize balancer. pass a RegionPlan?<a name="line.2128"></a>
+<span class="sourceLineNo">2129</span> final HashMap<RegionInfo, ServerName> retainMap = new HashMap<>();<a name="line.2129"></a>
+<span class="sourceLineNo">2130</span> final List<RegionInfo> userHRIs = new ArrayList<>(regions.size());<a name="line.2130"></a>
+<span class="sourceLineNo">2131</span> // Regions for system tables requiring reassignment<a name="line.2131"></a>
+<span class="sourceLineNo">2132</span> final List<RegionInfo> systemHRIs = new ArrayList<>();<a name="line.2132"></a>
+<span class="sourceLineNo">2133</span> for (RegionStateNode regionStateNode: regions.values()) {<a name="line.2133"></a>
+<span class="sourceLineNo">2134</span> boolean sysTable = regionStateNode.isSystemTable();<a name="line.2134"></a>
+<span class="sourceLineNo">2135</span> final List<RegionInfo> hris = sysTable? systemHRIs: userHRIs;<a name="line.2135"></a>
+<span class="sourceLineNo">2136</span> if (regionStateNode.getRegionLocation() != null) {<a name="line.2136"></a>
+<span class="sourceLineNo">2137</span> retainMap.put(regionStateNode.getRegionInfo(), regionStateNode.getRegionLocation());<a name="line.2137"></a>
+<span class="sourceLineNo">2138</span> } else {<a name="line.2138"></a>
+<span class="sourceLineNo">2139</span> hris.add(regionStateNode.getRegionInfo());<a name="line.2139"></a>
<span class="sourceLineNo">2140</span> }<a name="line.2140"></a>
-<span class="sourceLineNo">2141</span> Threads.sleep(250);<a name="line.2141"></a>
-<span class="sourceLineNo">2142</span> servers = master.getServerManager().createDestinationServersList();<a name="line.2142"></a>
-<span class="sourceLineNo">2143</span> }<a name="line.2143"></a>
+<span class="sourceLineNo">2141</span> }<a name="line.2141"></a>
+<span class="sourceLineNo">2142</span><a name="line.2142"></a>
+<span class="sourceLineNo">2143</span> // TODO: connect with the listener to invalidate the cache<a name="line.2143"></a>
<span class="sourceLineNo">2144</span><a name="line.2144"></a>
-<span class="sourceLineNo">2145</span> if (!systemHRIs.isEmpty()) {<a name="line.2145"></a>
-<span class="sourceLineNo">2146</span> // System table regions requiring reassignment are present, get region servers<a name="line.2146"></a>
-<span class="sourceLineNo">2147</span> // not available for system table regions<a name="line.2147"></a>
-<span class="sourceLineNo">2148</span> final List<ServerName> excludeServers = getExcludedServersForSystemTable();<a name="line.2148"></a>
-<span class="sourceLineNo">2149</span> List<ServerName> serversForSysTables = servers.stream()<a name="line.2149"></a>
-<span class="sourceLineNo">2150</span> .filter(s -> !excludeServers.contains(s)).collect(Collectors.toList());<a name="line.2150"></a>
-<span class="sourceLineNo">2151</span> if (serversForSysTables.isEmpty()) {<a name="line.2151"></a>
-<span class="sourceLineNo">2152</span> LOG.warn("Filtering old server versions and the excluded produced an empty set; " +<a name="line.2152"></a>
-<span class="sourceLineNo">2153</span> "instead considering all candidate servers!");<a name="line.2153"></a>
-<span class="sourceLineNo">2154</span> }<a name="line.2154"></a>
-<span class="sourceLineNo">2155</span> LOG.debug("Processing assignQueue; systemServersCount=" + serversForSysTables.size() +<a name="line.2155"></a>
-<span class="sourceLineNo">2156</span> ", allServersCount=" + servers.size());<a name="line.2156"></a>
-<span class="sourceLineNo">2157</span> processAssignmentPlans(regions, null, systemHRIs,<a name="line.2157"></a>
-<span class="sourceLineNo">2158</span> serversForSysTables.isEmpty() && !containsBogusAssignments(regions, systemHRIs) ?<a name="line.2158"></a>
-<span class="sourceLineNo">2159</span> servers: serversForSysTables);<a name="line.2159"></a>
-<span class="sourceLineNo">2160</span> }<a name="line.2160"></a>
-<span class="sourceLineNo">2161</span><a name="line.2161"></a>
-<span class="sourceLineNo">2162</span> processAssignmentPlans(regions, retainMap, userHRIs, servers);<a name="line.2162"></a>
-<span class="sourceLineNo">2163</span> }<a name="line.2163"></a>
-<span class="sourceLineNo">2164</span><a name="line.2164"></a>
-<span class="sourceLineNo">2165</span> private boolean containsBogusAssignments(Map<RegionInfo, RegionStateNode> regions,<a name="line.2165"></a>
-<span class="sourceLineNo">2166</span> List<RegionInfo> hirs) {<a name="line.2166"></a>
-<span class="sourceLineNo">2167</span> for (RegionInfo ri : hirs) {<a name="line.2167"></a>
-<span class="sourceLineNo">2168</span> if (regions.get(ri).getRegionLocation() != null &&<a name="line.2168"></a>
-<span class="sourceLineNo">2169</span> regions.get(ri).getRegionLocation().equals(LoadBalancer.BOGUS_SERVER_NAME)){<a name="line.2169"></a>
-<span class="sourceLineNo">2170</span> return true;<a name="line.2170"></a>
-<span class="sourceLineNo">2171</span> }<a name="line.2171"></a>
-<span class="sourceLineNo">2172</span> }<a name="line.2172"></a>
-<span class="sourceLineNo">2173</span> return false;<a name="line.2173"></a>
-<span class="sourceLineNo">2174</span> }<a name="line.2174"></a>
-<span class="sourceLineNo">2175</span><a name="line.2175"></a>
-<span class="sourceLineNo">2176</span> private void processAssignmentPlans(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2176"></a>
-<span class="sourceLineNo">2177</span> final HashMap<RegionInfo, ServerName> retainMap, final List<RegionInfo> hris,<a name="line.2177"></a>
-<span class="sourceLineNo">2178</span> final List<ServerName> servers) {<a name="line.2178"></a>
-<span class="sourceLineNo">2179</span> boolean isTraceEnabled = LOG.isTraceEnabled();<a name="line.2179"></a>
-<span class="sourceLineNo">2180</span> if (isTraceEnabled) {<a name="line.2180"></a>
-<span class="sourceLineNo">2181</span> LOG.trace("Available servers count=" + servers.size() + ": " + servers);<a name="line.2181"></a>
-<span class="sourceLineNo">2182</span> }<a name="line.2182"></a>
-<span class="sourceLineNo">2183</span><a name="line.2183"></a>
-<span class="sourceLineNo">2184</span> final LoadBalancer balancer = getBalancer();<a name="line.2184"></a>
-<span class="sourceLineNo">2185</span> // ask the balancer where to place regions<a name="line.2185"></a>
-<span class="sourceLineNo">2186</span> if (retainMap != null && !retainMap.isEmpty()) {<a name="line.2186"></a>
-<span class="sourceLineNo">2187</span> if (isTraceEnabled) {<a name="line.2187"></a>
-<span class="sourceLineNo">2188</span> LOG.trace("retain assign regions=" + retainMap);<a name="line.2188"></a>
-<span class="sourceLineNo">2189</span> }<a name="line.2189"></a>
-<span class="sourceLineNo">2190</span> try {<a name="line.2190"></a>
-<span class="sourceLineNo">2191</span> acceptPlan(regions, balancer.retainAssignment(retainMap, servers));<a name="line.2191"></a>
-<span class="sourceLineNo">2192</span> } catch (IOException e) {<a name="line.2192"></a>
-<span class="sourceLineNo">2193</span> LOG.warn("unable to retain assignment", e);<a name="line.2193"></a>
-<span class="sourceLineNo">2194</span> addToPendingAssignment(regions, retainMap.keySet());<a name="line.2194"></a>
-<span class="sourceLineNo">2195</span> }<a name="line.2195"></a>
-<span class="sourceLineNo">2196</span> }<a name="line.2196"></a>
-<span class="sourceLineNo">2197</span><a name="line.2197"></a>
-<span class="sourceLineNo">2198</span> // TODO: Do we need to split retain and round-robin?<a name="line.2198"></a>
-<span class="sourceLineNo">2199</span> // the retain seems to fallback to round-robin/random if the region is not in the map.<a name="line.2199"></a>
-<span class="sourceLineNo">2200</span> if (!hris.isEmpty()) {<a name="line.2200"></a>
-<span class="sourceLineNo">2201</span> Collections.sort(hris, RegionInfo.COMPARATOR);<a name="line.2201"></a>
-<span class="sourceLineNo">2202</span> if (isTraceEnabled) {<a name="line.2202"></a>
-<span class="sourceLineNo">2203</span> LOG.trace("round robin regions=" + hris);<a name="line.2203"></a>
-<span class="sourceLineNo">2204</span> }<a name="line.2204"></a>
-<span class="sourceLineNo">2205</span> try {<a name="line.2205"></a>
-<span class="sourceLineNo">2206</span> acceptPlan(regions, balancer.roundRobinAssignment(hris, servers));<a name="line.2206"></a>
-<span class="sourceLineNo">2207</span> } catch (IOException e) {<a name="line.2207"></a>
-<span class="sourceLineNo">2208</span> LOG.warn("unable to round-robin assignment", e);<a name="line.2208"></a>
-<span class="sourceLineNo">2209</span> addToPendingAssignment(regions, hris);<a name="line.2209"></a>
-<span class="sourceLineNo">2210</span> }<a name="line.2210"></a>
-<span class="sourceLineNo">2211</span> }<a name="line.2211"></a>
-<span class="sourceLineNo">2212</span> }<a name="line.2212"></a>
+<span class="sourceLineNo">2145</span> // TODO use events<a name="line.2145"></a>
+<span class="sourceLineNo">2146</span> List<ServerName> servers = master.getServerManager().createDestinationServersList();<a name="line.2146"></a>
+<span class="sourceLineNo">2147</span> for (int i = 0; servers.size() < 1; ++i) {<a name="line.2147"></a>
+<span class="sourceLineNo">2148</span> // Report every fourth time around this loop; try not to flood log.<a name="line.2148"></a>
+<span class="sourceLineNo">2149</span> if (i % 4 == 0) {<a name="line.2149"></a>
+<span class="sourceLineNo">2150</span> LOG.warn("No servers available; cannot place " + regions.size() + " unassigned regions.");<a name="line.2150"></a>
+<span class="sourceLineNo">2151</span> }<a name="line.2151"></a>
+<span class="sourceLineNo">2152</span><a name="line.2152"></a>
+<span class="sourceLineNo">2153</span> if (!isRunning()) {<a name="line.2153"></a>
+<span class="sourceLineNo">2154</span> LOG.debug("Stopped! Dropping assign of " + regions.size() + " queued regions.");<a name="line.2154"></a>
+<span class="sourceLineNo">2155</span> return;<a name="line.2155"></a>
+<span class="sourceLineNo">2156</span> }<a name="line.2156"></a>
+<span class="sourceLineNo">2157</span> Threads.sleep(250);<a name="line.2157"></a>
+<span class="sourceLineNo">2158</span> servers = master.getServerManager().createDestinationServersList();<a name="line.2158"></a>
+<span class="sourceLineNo">2159</span> }<a name="line.2159"></a>
+<span class="sourceLineNo">2160</span><a name="line.2160"></a>
+<span class="sourceLineNo">2161</span> if (!systemHRIs.isEmpty()) {<a name="line.2161"></a>
+<span class="sourceLineNo">2162</span> // System table regions requiring reassignment are present, get region servers<a name="line.2162"></a>
+<span class="sourceLineNo">2163</span> // not available for system table regions<a name="line.2163"></a>
+<span class="sourceLineNo">2164</span> final List<ServerName> excludeServers = getExcludedServersForSystemTable();<a name="line.2164"></a>
+<span class="sourceLineNo">2165</span> List<ServerName> serversForSysTables = servers.stream()<a name="line.2165"></a>
+<span class="sourceLineNo">2166</span> .filter(s -> !excludeServers.contains(s)).collect(Collectors.toList());<a name="line.2166"></a>
+<span class="sourceLineNo">2167</span> if (serversForSysTables.isEmpty()) {<a name="line.2167"></a>
+<span class="sourceLineNo">2168</span> LOG.warn("Filtering old server versions and the excluded produced an empty set; " +<a name="line.2168"></a>
+<span class="sourceLineNo">2169</span> "instead considering all candidate servers!");<a name="line.2169"></a>
+<span class="sourceLineNo">2170</span> }<a name="line.2170"></a>
+<span class="sourceLineNo">2171</span> LOG.debug("Processing assignQueue; systemServersCount=" + serversForSysTables.size() +<a name="line.2171"></a>
+<span class="sourceLineNo">2172</span> ", allServersCount=" + servers.size());<a name="line.2172"></a>
+<span class="sourceLineNo">2173</span> processAssignmentPlans(regions, null, systemHRIs,<a name="line.2173"></a>
+<span class="sourceLineNo">2174</span> serversForSysTables.isEmpty() && !containsBogusAssignments(regions, systemHRIs) ?<a name="line.2174"></a>
+<span class="sourceLineNo">2175</span> servers: serversForSysTables);<a name="line.2175"></a>
+<span class="sourceLineNo">2176</span> }<a name="line.2176"></a>
+<span class="sourceLineNo">2177</span><a name="line.2177"></a>
+<span class="sourceLineNo">2178</span> processAssignmentPlans(regions, retainMap, userHRIs, servers);<a name="line.2178"></a>
+<span class="sourceLineNo">2179</span> }<a name="line.2179"></a>
+<span class="sourceLineNo">2180</span><a name="line.2180"></a>
+<span class="sourceLineNo">2181</span> private boolean containsBogusAssignments(Map<RegionInfo, RegionStateNode> regions,<a name="line.2181"></a>
+<span class="sourceLineNo">2182</span> List<RegionInfo> hirs) {<a name="line.2182"></a>
+<span class="sourceLineNo">2183</span> for (RegionInfo ri : hirs) {<a name="line.2183"></a>
+<span class="sourceLineNo">2184</span> if (regions.get(ri).getRegionLocation() != null &&<a name="line.2184"></a>
+<span class="sourceLineNo">2185</span> regions.get(ri).getRegionLocation().equals(LoadBalancer.BOGUS_SERVER_NAME)){<a name="line.2185"></a>
+<span class="sourceLineNo">2186</span> return true;<a name="line.2186"></a>
+<span class="sourceLineNo">2187</span> }<a name="line.2187"></a>
+<span class="sourceLineNo">2188</span> }<a name="line.2188"></a>
+<span class="sourceLineNo">2189</span> return false;<a name="line.2189"></a>
+<span class="sourceLineNo">2190</span> }<a name="line.2190"></a>
+<span class="sourceLineNo">2191</span><a name="line.2191"></a>
+<span class="sourceLineNo">2192</span> private void processAssignmentPlans(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2192"></a>
+<span class="sourceLineNo">2193</span> final HashMap<RegionInfo, ServerName> retainMap, final List<RegionInfo> hris,<a name="line.2193"></a>
+<span class="sourceLineNo">2194</span> final List<ServerName> servers) {<a name="line.2194"></a>
+<span class="sourceLineNo">2195</span> boolean isTraceEnabled = LOG.isTraceEnabled();<a name="line.2195"></a>
+<span class="sourceLineNo">2196</span> if (isTraceEnabled) {<a name="line.2196"></a>
+<span class="sourceLineNo">2197</span> LOG.trace("Available servers count=" + servers.size() + ": " + servers);<a name="line.2197"></a>
+<span class="sourceLineNo">2198</span> }<a name="line.2198"></a>
+<span class="sourceLineNo">2199</span><a name="line.2199"></a>
+<span class="sourceLineNo">2200</span> final LoadBalancer balancer = getBalancer();<a name="line.2200"></a>
+<span class="sourceLineNo">2201</span> // ask the balancer where to place regions<a name="line.2201"></a>
+<span class="sourceLineNo">2202</span> if (retainMap != null && !retainMap.isEmpty()) {<a name="line.2202"></a>
+<span class="sourceLineNo">2203</span> if (isTraceEnabled) {<a name="line.2203"></a>
+<span class="sourceLineNo">2204</span> LOG.trace("retain assign regions=" + retainMap);<a name="line.2204"></a>
+<span class="sourceLineNo">2205</span> }<a name="line.2205"></a>
+<span class="sourceLineNo">2206</span> try {<a name="line.2206"></a>
+<span class="sourceLineNo">2207</span> acceptPlan(regions, balancer.retainAssignment(retainMap, servers));<a name="line.2207"></a>
+<span class="sourceLineNo">2208</span> } catch (IOException e) {<a name="line.2208"></a>
+<span class="sourceLineNo">2209</span> LOG.warn("unable to retain assignment", e);<a name="line.2209"></a>
+<span class="sourceLineNo">2210</span> addToPendingAssignment(regions, retainMap.keySet());<a name="line.2210"></a>
+<span class="sourceLineNo">2211</span> }<a name="line.2211"></a>
+<span class="sourceLineNo">2212</span> }<a name="line.2212"></a>
<span class="sourceLineNo">2213</span><a name="line.2213"></a>
-<span class="sourceLineNo">2214</span> private void acceptPlan(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2214"></a>
-<span class="sourceLineNo">2215</span> final Map<ServerName, List<RegionInfo>> plan) throws HBaseIOException {<a name="line.2215"></a>
-<span class="sourceLineNo">2216</span> final ProcedureEvent<?>[] events = new ProcedureEvent[regions.size()];<a name="line.2216"></a>
-<span class="sourceLineNo">2217</span> final long st = System.currentTimeMillis();<a name="line.2217"></a>
-<span class="sourceLineNo">2218</span><a name="line.2218"></a>
-<span class="sourceLineNo">2219</span> if (plan.isEmpty()) {<a name="line.2219"></a>
-<span class="sourceLineNo">2220</span> throw new HBaseIOException("unable to compute plans for regions=" + regions.size());<a name="line.2220"></a>
-<span class="sourceLineNo">2221</span> }<a name="line.2221"></a>
-<span class="sourceLineNo">2222</span><a name="line.2222"></a>
-<span class="sourceLineNo">2223</span> int evcount = 0;<a name="line.2223"></a>
-<span class="sourceLineNo">2224</span> for (Map.Entry<ServerName, List<RegionInfo>> entry: plan.entrySet()) {<a name="line.2224"></a>
-<span class="sourceLineNo">2225</span> final ServerName server = entry.getKey();<a name="line.2225"></a>
-<span class="sourceLineNo">2226</span> for (RegionInfo hri: entry.getValue()) {<a name="line.2226"></a>
-<span class="sourceLineNo">2227</span> final RegionStateNode regionNode = regions.get(hri);<a name="line.2227"></a>
-<span class="sourceLineNo">2228</span> regionNode.setRegionLocation(server);<a name="line.2228"></a>
-<span class="sourceLineNo">2229</span> if (server.equals(LoadBalancer.BOGUS_SERVER_NAME) && regionNode.isSystemTable()) {<a name="line.2229"></a>
-<span class="sourceLineNo">2230</span> assignQueueLock.lock();<a name="line.2230"></a>
-<span class="sourceLineNo">2231</span> try {<a name="line.2231"></a>
-<span class="sourceLineNo">2232</span> pendingAssignQueue.add(regionNode);<a name="line.2232"></a>
-<span class="sourceLineNo">2233</span> } finally {<a name="line.2233"></a>
-<span class="sourceLineNo">2234</span> assignQueueLock.unlock();<a name="line.2234"></a>
-<span class="sourceLineNo">2235</span> }<a name="line.2235"></a>
-<span class="sourceLineNo">2236</span> }else {<a name="line.2236"></a>
-<span class="sourceLineNo">2237</span> events[evcount++] = regionNode.getProcedureEvent();<a name="line.2237"></a>
-<span class="sourceLineNo">2238</span> }<a name="line.2238"></a>
-<span class="sourceLineNo">2239</span> }<a name="line.2239"></a>
-<span class="sourceLineNo">2240</span> }<a name="line.2240"></a>
-<span class="sourceLineNo">2241</span> ProcedureEvent.wakeEvents(getProcedureScheduler(), events);<a name="line.2241"></a>
-<span class="sourceLineNo">2242</span><a name="line.2242"></a>
-<span class="sourceLineNo">2243</span> final long et = System.currentTimeMillis();<a name="line.2243"></a>
-<span class="sourceLineNo">2244</span> if (LOG.isTraceEnabled()) {<a name="line.2244"></a>
-<span class="sourceLineNo">2245</span> LOG.trace("ASSIGN ACCEPT " + events.length + " -> " +<a name="line.2245"></a>
-<span class="sourceLineNo">2246</span> StringUtils.humanTimeDiff(et - st));<a name="line.2246"></a>
-<span class="sourceLineNo">2247</span> }<a name="line.2247"></a>
-<span class="sourceLineNo">2248</span> }<a name="line.2248"></a>
-<span class="sourceLineNo">2249</span><a name="line.2249"></a>
-<span class="sourceLineNo">2250</span> private void addToPendingAssignment(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2250"></a>
-<span class="sourceLineNo">2251</span> final Collection<RegionInfo> pendingRegions) {<a name="line.2251"></a>
-<span class="sourceLineNo">2252</span> assignQueueLock.lock();<a name="line.2252"></a>
-<span class="sourceLineNo">2253</span> try {<a name="line.2253"></a>
-<span class="sourceLineNo">2254</span> for (RegionInfo hri: pendingRegions) {<a name="line.2254"></a>
-<span class="sourceLineNo">2255</span> pendingAssignQueue.add(regions.get(hri));<a name="line.2255"></a>
-<span class="sourceLineNo">2256</span> }<a name="line.2256"></a>
-<span class="sourceLineNo">2257</span> } finally {<a name="line.2257"></a>
-<span class="sourceLineNo">2258</span> assignQueueLock.unlock();<a name="line.2258"></a>
-<span class="sourceLineNo">2259</span> }<a name="line.2259"></a>
-<span class="sourceLineNo">2260</span> }<a name="line.2260"></a>
-<span class="sourceLineNo">2261</span><a name="line.2261"></a>
-<span class="sourceLineNo">2262</span> /**<a name="line.2262"></a>
-<span class="sourceLineNo">2263</span> * Get a list of servers that this region cannot be assigned to.<a name="line.2263"></a>
-<span class="sourceLineNo">2264</span> * For system tables, we must assign them to a server with highest version.<a name="line.2264"></a>
-<span class="sourceLineNo">2265</span> */<a name="line.2265"></a>
-<span class="sourceLineNo">2266</span> public List<ServerName> getExcludedServersForSystemTable() {<a name="line.2266"></a>
-<span class="sourceLineNo">2267</span> // TODO: This should be a cached list kept by the ServerManager rather than calculated on each<a name="line.2267"></a>
-<span class="sourceLineNo">2268</span> // move or system region assign. The RegionServerTracker keeps list of online Servers with<a name="line.2268"></a>
-<span class="sourceLineNo">2269</span> // RegionServerInfo that includes Version.<a name="line.2269"></a>
-<span class="sourceLineNo">2270</span> List<Pair<ServerName, String>> serverList = master.getServerManager().getOnlineServersList()<a name="line.2270"></a>
-<span class="sourceLineNo">2271</span> .stream()<a name="line.2271"></a>
-<span class="sourceLineNo">2272</span> .map((s)->new Pair<>(s, master.getRegionServerVersion(s)))<a name="line.2272"></a>
-<span class="sourceLineNo">2273</span> .collect(Collectors.toList());<a name="line.2273"></a>
-<span class="sourceLineNo">2274</span> if (serverList.isEmpty()) {<a name="line.2274"></a>
-<span class="sourceLineNo">2275</span> return Collections.emptyList();<a name="line.2275"></a>
-<span class="sourceLineNo">2276</span> }<a name="line.2276"></a>
-<span class="sourceLineNo">2277</span> String highestVersion = Collections.max(serverList,<a name="line.2277"></a>
-<span class="sourceLineNo">2278</span> (o1, o2) -> VersionInfo.compareVersion(o1.getSecond(), o2.getSecond())).getSecond();<a name="line.2278"></a>
-<span class="sourceLineNo">2279</span> return serverList.stream()<a name="line.2279"></a>
-<span class="sourceLineNo">2280</span> .filter((p)->!p.getSecond().equals(highestVersion))<a name="line.2280"></a>
-<span class="sourceLineNo">2281</span> .map(Pair::getFirst)<a name="line.2281"></a>
-<span class="sourceLineNo">2282</span> .collect(Collectors.toList());<a name="line.2282"></a>
-<span class="sourceLineNo">2283</span> }<a name="line.2283"></a>
-<span class="sourceLineNo">2284</span><a name="line.2284"></a>
-<span class="sourceLineNo">2285</span> MasterServices getMaster() {<a name="line.2285"></a>
-<span class="sourceLineNo">2286</span> return master;<a name="line.2286"></a>
-<span class="sourceLineNo">2287</span> }<a name="line.2287"></a>
-<span class="sourceLineNo">2288</span><a name="line.2288"></a>
-<span class="sourceLineNo">2289</span> /**<a name="line.2289"></a>
-<span class="sourceLineNo">2290</span> * @return a snapshot of rsReports<a name="line.2290"></a>
-<span class="sourceLineNo">2291</span> */<a name="line.2291"></a>
-<span class="sourceLineNo">2292</span> public Map<ServerName, Set<byte[]>> getRSReports() {<a name="line.2292"></a>
-<span class="sourceLineNo">2293</span> Map<ServerName, Set<byte[]>> rsReportsSnapshot = new HashMap<>();<a name="line.2293"></a>
-<span class="sourceLineNo">2294</span> synchronized (rsReports) {<a name="line.2294"></a>
-<span class="sourceLineNo">2295</span> rsReports.entrySet().forEach(e -> rsReportsSnapshot.put(e.getKey(), e.getValue()));<a name="line.2295"></a>
-<span class="sourceLineNo">2296</span> }<a name="line.2296"></a>
-<span class="sourceLineNo">2297</span> return rsReportsSnapshot;<a name="line.2297"></a>
-<span class="sourceLineNo">2298</span> }<a name="line.2298"></a>
-<span class="sourceLineNo">2299</span><a name="line.2299"></a>
-<span class="sourceLineNo">2300</span> /**<a name="line.2300"></a>
-<span class="sourceLineNo">2301</span> * Provide regions state count for given table.<a name="line.2301"></a>
-<span class="sourceLineNo">2302</span> * e.g howmany regions of give table are opened/closed/rit etc<a name="line.2302"></a>
-<span class="sourceLineNo">2303</span> *<a name="line.2303"></a>
-<span class="sourceLineNo">2304</span> * @param tableName TableName<a name="line.2304"></a>
-<span class="sourceLineNo">2305</span> * @return region states count<a name="line.2305"></a>
-<span class="sourceLineNo">2306</span> */<a name="line.2306"></a>
-<span class="sourceLineNo">2307</span> public RegionStatesCount getRegionStatesCount(TableName tableName) {<a name="line.2307"></a>
-<span class="sourceLineNo">2308</span> int openRegionsCount = 0;<a name="line.2308"></a>
-<span class="sourceLineNo">2309</span> int closedRegionCount = 0;<a name="line.2309"></a>
-<span class="sourceLineNo">2310</span> int ritCount = 0;<a name="line.2310"></a>
-<span class="sourceLineNo">2311</span> int splitRegionCount = 0;<a name="line.2311"></a>
-<span class="sourceLineNo">2312</span> int totalRegionCount = 0;<a name="line.2312"></a>
-<span class="sourceLineNo">2313</span> if (!isTableDisabled(tableName)) {<a name="line.2313"></a>
-<span class="sourceLineNo">2314</span> final List<RegionState> states = regionStates.getTableRegionStates(tableName);<a name="line.2314"></a>
-<span class="sourceLineNo">2315</span> for (RegionState regionState : states) {<a name="line.2315"></a>
-<span class="sourceLineNo">2316</span> if (regionState.isOpened()) {<a name="line.2316"></a>
-<span class="sourceLineNo">2317</span> openRegionsCount++;<a name="line.2317"></a>
-<span class="sourceLineNo">2318</span> } else if (regionState.isClosed()) {<a name="line.2318"></a>
-<span class="sourceLineNo">2319</span> closedRegionCount++;<a name="line.2319"></a>
-<span class="sourceLineNo">2320</span> } else if (regionState.isSplit()) {<a name="line.2320"></a>
-<span class="sourceLineNo">2321</span> splitRegionCount++;<a name="line.2321"></a>
-<span class="sourceLineNo">2322</span> }<a name="line.2322"></a>
-<span class="sourceLineNo">2323</span> }<a name="line.2323"></a>
-<span class="sourceLineNo">2324</span> totalRegionCount = states.size();<a name="line.2324"></a>
-<span class="sourceLineNo">2325</span> ritCount = totalRegionCount - openRegionsCount - splitRegionCount;<a name="line.2325"></a>
-<span class="sourceLineNo">2326</span> }<a name="line.2326"></a>
-<span class="sourceLineNo">2327</span> return new RegionStatesCount.RegionStatesCountBuilder()<a name="line.2327"></a>
-<span class="sourceLineNo">2328</span> .setOpenRegions(openRegionsCount)<a name="line.2328"></a>
-<span class="sourceLineNo">2329</span> .setClosedRegions(closedRegionCount)<a name="line.2329"></a>
-<span class="sourceLineNo">2330</span> .setSplitRegions(splitRegionCount)<a name="line.2330"></a>
-<span class="sourceLineNo">2331</span> .setRegionsInTransition(ritCount)<a name="line.2331"></a>
-<span class="sourceLineNo">2332</span> .setTotalRegions(totalRegionCount)<a name="line.2332"></a>
-<span class="sourceLineNo">2333</span> .build();<a name="line.2333"></a>
-<span class="sourceLineNo">2334</span> }<a name="line.2334"></a>
-<span class="sourceLineNo">2335</span><a name="line.2335"></a>
-<span class="sourceLineNo">2336</span>}<a name="line.2336"></a>
+<span class="sourceLineNo">2214</span> // TODO: Do we need to split retain and round-robin?<a name="line.2214"></a>
+<span class="sourceLineNo">2215</span> // the retain seems to fallback to round-robin/random if the region is not in the map.<a name="line.2215"></a>
+<span class="sourceLineNo">2216</span> if (!hris.isEmpty()) {<a name="line.2216"></a>
+<span class="sourceLineNo">2217</span> Collections.sort(hris, RegionInfo.COMPARATOR);<a name="line.2217"></a>
+<span class="sourceLineNo">2218</span> if (isTraceEnabled) {<a name="line.2218"></a>
+<span class="sourceLineNo">2219</span> LOG.trace("round robin regions=" + hris);<a name="line.2219"></a>
+<span class="sourceLineNo">2220</span> }<a name="line.2220"></a>
+<span class="sourceLineNo">2221</span> try {<a name="line.2221"></a>
+<span class="sourceLineNo">2222</span> acceptPlan(regions, balancer.roundRobinAssignment(hris, servers));<a name="line.2222"></a>
+<span class="sourceLineNo">2223</span> } catch (IOException e) {<a name="line.2223"></a>
+<span class="sourceLineNo">2224</span> LOG.warn("unable to round-robin assignment", e);<a name="line.2224"></a>
+<span class="sourceLineNo">2225</span> addToPendingAssignment(regions, hris);<a name="line.2225"></a>
+<span class="sourceLineNo">2226</span> }<a name="line.2226"></a>
+<span class="sourceLineNo">2227</span> }<a name="line.2227"></a>
+<span class="sourceLineNo">2228</span> }<a name="line.2228"></a>
+<span class="sourceLineNo">2229</span><a name="line.2229"></a>
+<span class="sourceLineNo">2230</span> private void acceptPlan(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2230"></a>
+<span class="sourceLineNo">2231</span> final Map<ServerName, List<RegionInfo>> plan) throws HBaseIOException {<a name="line.2231"></a>
+<span class="sourceLineNo">2232</span> final ProcedureEvent<?>[] events = new ProcedureEvent[regions.size()];<a name="line.2232"></a>
+<span class="sourceLineNo">2233</span> final long st = System.currentTimeMillis();<a name="line.2233"></a>
+<span class="sourceLineNo">2234</span><a name="line.2234"></a>
+<span class="sourceLineNo">2235</span> if (plan.isEmpty()) {<a name="line.2235"></a>
+<span class="sourceLineNo">2236</span> throw new HBaseIOException("unable to compute plans for regions=" + regions.size());<a name="line.2236"></a>
+<span class="sourceLineNo">2237</span> }<a name="line.2237"></a>
+<span class="sourceLineNo">2238</span><a name="line.2238"></a>
+<span class="sourceLineNo">2239</span> int evcount = 0;<a name="line.2239"></a>
+<span class="sourceLineNo">2240</span> for (Map.Entry<ServerName, List<RegionInfo>> entry: plan.entrySet()) {<a name="line.2240"></a>
+<span class="sourceLineNo">2241</span> final ServerName server = entry.getKey();<a name="line.2241"></a>
+<span class="sourceLineNo">2242</span> for (RegionInfo hri: entry.getValue()) {<a name="line.2242"></a>
+<span class="sourceLineNo">2243</span> final RegionStateNode regionNode = regions.get(hri);<a name="line.2243"></a>
+<span class="sourceLineNo">2244</span> regionNode.setRegionLocation(server);<a name="line.2244"></a>
+<span class="sourceLineNo">2245</span> if (server.equals(LoadBalancer.BOGUS_SERVER_NAME) && regionNode.isSystemTable()) {<a name="line.2245"></a>
+<span class="sourceLineNo">2246</span> assignQueueLock.lock();<a name="line.2246"></a>
+<span class="sourceLineNo">2247</span> try {<a name="line.2247"></a>
+<span class="sourceLineNo">2248</span> pendingAssignQueue.add(regionNode);<a name="line.2248"></a>
+<span class="sourceLineNo">2249</span> } finally {<a name="line.2249"></a>
+<span class="sourceLineNo">2250</span> assignQueueLock.unlock();<a name="line.2250"></a>
+<span class="sourceLineNo">2251</span> }<a name="line.2251"></a>
+<span class="sourceLineNo">2252</span> }else {<a name="line.2252"></a>
+<span class="sourceLineNo">2253</span> events[evcount++] = regionNode.getProcedureEvent();<a name="line.2253"></a>
+<span class="sourceLineNo">2254</span> }<a name="line.2254"></a>
+<span class="sourceLineNo">2255</span> }<a name="line.2255"></a>
+<span class="sourceLineNo">2256</span> }<a name="line.2256"></a>
+<span class="sourceLineNo">2257</span> ProcedureEvent.wakeEvents(getProcedureScheduler(), events);<a name="line.2257"></a>
+<span class="sourceLineNo">2258</span><a name="line.2258"></a>
+<span class="sourceLineNo">2259</span> final long et = System.currentTimeMillis();<a name="line.2259"></a>
+<span class="sourceLineNo">2260</span> if (LOG.isTraceEnabled()) {<a name="line.2260"></a>
+<span class="sourceLineNo">2261</span> LOG.trace("ASSIGN ACCEPT " + events.length + " -> " +<a name="line.2261"></a>
+<span class="sourceLineNo">2262</span> StringUtils.humanTimeDiff(et - st));<a name="line.2262"></a>
+<span class="sourceLineNo">2263</span> }<a name="line.2263"></a>
+<span class="sourceLineNo">2264</span> }<a name="line.2264"></a>
+<span class="sourceLineNo">2265</span><a name="line.2265"></a>
+<span class="sourceLineNo">2266</span> private void addToPendingAssignment(final HashMap<RegionInfo, RegionStateNode> regions,<a name="line.2266"></a>
+<span class="sourceLineNo">2267</span> final Collection<RegionInfo> pendingRegions) {<a name="line.2267"></a>
+<span class="sourceLineNo">2268</span> assignQueueLock.lock();<a name="line.2268"></a>
+<span class="sourceLineNo">2269</span> try {<a name="line.2269"></a>
+<span class="sourceLineNo">2270</span> for (RegionInfo hri: pendingRegions) {<a name="line.2270"></a>
+<span class="sourceLineNo">2271</span> pendingAssignQueue.add(regions.get(hri));<a name="line.2271"></a>
+<span class="sourceLineNo">2272</span> }<a name="line.2272"></a>
+<span class="sourceLineNo">2273</span> } finally {<a name="line.2273"></a>
+<span class="sourceLineNo">2274</span> assignQueueLock.unlock();<a name="line.2274"></a>
+<span class="sourceLineNo">2275</span> }<a name="line.2275"></a>
+<span class="sourceLineNo">2276</span> }<a name="line.2276"></a>
+<span class="sourceLineNo">2277</span><a name="line.2277"></a>
+<span class="sourceLineNo">2278</span> /**<a name="line.2278"></a>
+<span class="sourceLineNo">2279</span> * Get a list of servers that this region cannot be assigned to.<a name="line.2279"></a>
+<span class="sourceLineNo">2280</span> * For system tables, we must assign them to a server with highest version.<a name="line.2280"></a>
+<span class="sourceLineNo">2281</span> */<a name="line.2281"></a>
+<span class="sourceLineNo">2282</span> public List<ServerName> getExcludedServersForSystemTable() {<a name="line.2282"></a>
+<span class="sourceLineNo">2283</span> // TODO: This should be a cached list kept by the ServerManager rather than calculated on each<a name="line.2283"></a>
+<span class="sourceLineNo">2284</span> // move or system region assign. The RegionServerTracker keeps list of online Servers with<a name="line.2284"></a>
+<span class="sourceLineNo">2285</span> // RegionServerInfo that includes Version.<a name="line.2285"></a>
+<span class="sourceLineNo">2286</span> List<Pair<ServerName, String>> serverList = master.getServerManager().getOnlineServersList()<a name="line.2286"></a>
+<span class="sourceLineNo">2287</span> .stream()<a name="line.2287"></a>
+<span class="sourceLineNo">2288</span> .map((s)->new Pair<>(s, master.getRegionServerVersion(s)))<a name="line.2288"></a>
+<span class="sourceLineNo">2289</span> .collect(Collectors.toList());<a name="line.2289"></a>
+<span class="sourceLineNo">2290</span> if (serverList.isEmpty()) {<a name="line.2290"></a>
+<span class="sourceLineNo">2291</span> return Collections.emptyList();<a name="line.2291"></a>
+<span class="sourceLineNo">2292</span> }<a name="line.2292"></a>
+<span class="sourceLineNo">2293</span> String highestVersion = Collections.max(serverList,<a name="line.2293"></a>
+<span class="sourceLineNo">2294</span> (o1, o2) -> VersionInfo.compareVersion(o1.getSecond(), o2.getSecond())).getSecond();<a name="line.2294"></a>
+<span class="sourceLineNo">2295</span> return serverList.stream()<a name="line.2295"></a>
+<span class="sourceLineNo">2296</span> .filter((p)->!p.getSecond().equals(highestVersion))<a name="line.2296"></a>
+<span class="sourceLineNo">2297</span> .map(Pair::getFirst)<a name="line.2297"></a>
+<span class="sourceLineNo">2298</span> .collect(Collectors.toList());<a name="line.2298"></a>
+<span class="sourceLineNo">2299</span> }<a name="line.2299"></a>
+<span class="sourceLineNo">2300</span><a name="line.2300"></a>
+<span class="sourceLineNo">2301</span> MasterServices getMaster() {<a name="line.2301"></a>
+<span class="sourceLineNo">2302</span> return master;<a name="line.2302"></a>
+<span class="sourceLineNo">2303</span> }<a name="line.2303"></a>
+<span class="sourceLineNo">2304</span><a name="line.2304"></a>
+<span class="sourceLineNo">2305</span> /**<a name="line.2305"></a>
+<span class="sourceLineNo">2306</span> * @return a snapshot of rsReports<a name="line.2306"></a>
+<span class="sourceLineNo">2307</span> */<a name="line.2307"></a>
+<span class="sourceLineNo">2308</span> public Map<ServerName, Set<byte[]>> getRSReports() {<a name="line.2308"></a>
+<span class="sourceLineNo">2309</span> Map<ServerName, Set<byte[]>> rsReportsSnapshot = new HashMap<>();<a name="line.2309"></a>
+<span class="sourceLineNo">2310</span> synchronized (rsReports) {<a name="line.2310"></a>
+<span class="sourceLineNo">2311</span> rsReports.entrySet().forEach(e -> rsReportsSnapshot.put(e.getKey(), e.getValue()));<a name="line.2311"></a>
+<span class="sourceLineNo">2312</span> }<a name="line.2312"></a>
+<span class="sourceLineNo">2313</span> return rsReportsSnapshot;<a name="line.2313"></a>
+<span class="sourceLineNo">2314</span> }<a name="line.2314"></a>
+<span class="sourceLineNo">2315</span><a name="line.2315"></a>
+<span class="sourceLineNo">2316</span> /**<a name="line.2316"></a>
+<span class="sourceLineNo">2317</span> * Provide regions state count for given table.<a name="line.2317"></a>
+<span class="sourceLineNo">2318</span> * e.g howmany regions of give table are opened/closed/rit etc<a name="line.2318"></a>
+<span class="sourceLineNo">2319</span> *<a name="line.2319"></a>
+<span class="sourceLineNo">2320</span> * @param tableName TableName<a name="line.2320"></a>
+<span class="sourceLineNo">2321</span> * @return region states count<a name="line.2321"></a>
+<span class="sourceLineNo">2322</span> */<a name="line.2322"></a>
+<span class="sourceLineNo">2323</span> public RegionStatesCount getRegionStatesCount(TableName tableName) {<a name="line.2323"></a>
+<span class="sourceLineNo">2324</span> int openRegionsCount = 0;<a name="line.2324"></a>
+<span class="sourceLineNo">2325</span> int closedRegionCount = 0;<a name="line.2325"></a>
+<span class="sourceLineNo">2326</span> int ritCount = 0;<a name="line.2326"></a>
+<span class="sourceLineNo">2327</span> int splitRegionCount = 0;<a name="line.2327"></a>
+<span class="sourceLineNo">2328</span> int totalRegionCount = 0;<a name="line.2328"></a>
+<span class="sourceLineNo">2329</span> if (!isTableDisabled(tableName)) {<a name="line.2329"></a>
+<span class="sourceLineNo">2330</span> final List<RegionState> states = regionStates.getTableRegionStates(tableName);<a name="line.2330"></a>
+<span class="sourceLineNo">2331</span> for (RegionState regionState : states) {<a name="line.2331"></a>
+<span class="sourceLineNo">2332</span> if (regionState.isOpened()) {<a name="line.2332"></a>
+<span class="sourceLineNo">2333</span> openRegionsCount++;<a name="line.2333"></a>
+<span class="sourceLineNo">2334</span> } else if (regionState.isClosed()) {<a name="line.2334"></a>
+<span class="sourceLineNo">2335</span> closedRegionCount++;<a name="line.2335"></a>
+<span class="sourceLineNo">2336</span> } else if (regionState.isSplit()) {<a name="line.2336"></a>
+<span class="sourceLineNo">2337</span> splitRegionCount++;<a name="line.2337"></a>
+<span class="sourceLineNo">2338</span> }<a name="line.2338"></a>
+<span class="sourceLineNo">2339</span> }<a name="line.2339"></a>
+<span class="sourceLineNo">2340</span> totalRegionCount = states.size();<a name="line.2340"></a>
+<span class="sourceLineNo">2341</span> ritCount = totalRegionCount - openRegionsCount - splitRegionCount;<a name="line.2341"></a>
+<span class="sourceLineNo">2342</span> }<a name="line.2342"></a>
+<span class="sourceLineNo">2343</span> return new RegionStatesCount.RegionStatesCountBuilder()<a name="line.2343"></a>
+<span class="sourceLineNo">2344</span> .setOpenRegions(openRegionsCount)<a name="line.2344"></a>
+<span class="sourceLineNo">2345</span> .setClosedRegions(closedRegionCount)<a name="line.2345"></a>
+<span class="sourceLineNo">2346</span> .setSplitRegions(splitRegionCount)<a name="line.2346"></a>
+<span class="sourceLineNo">2347</span> .setRegionsInTransition(ritCount)<a name="line.2347"></a>
+<span class="sourceLineNo">2348</span> .setTotalRegions(totalRegionCount)<a name="line.2348"></a>
+<span class="sourceLineNo">2349</span> .build();<a name="line.2349"></a>
+<span class="sourceLineNo">2350</span> }<a name="line.2350"></a>
+<span class="sourceLineNo">2351</span><a name="line.2351"></a>
+<span class="sourceLineNo">2352</span>}<a name="line.2352"></a>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionMetaLoadingVisitor.html b/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionMetaLoadingVisitor.html
index c00cc30..2c789f6 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionMetaLoadingVisitor.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/master/assignment/AssignmentManager.RegionMetaLoadingVisitor.html
@@ -1134,1214 +1134,1230 @@
<span class="sourceLineNo">1126</span> LOG.debug("Split request from " + serverName +<a name="line.1126"></a>
<span class="sourceLineNo">1127</span> ", parent=" + parent + " splitKey=" + Bytes.toStringBinary(splitKey));<a name="line.1127"></a>
<span class="sourceLineNo">1128</span> }<a name="line.1128"></a>
-<span class="sourceLineNo">1129</span> master.getMasterProcedureExecutor().submitProcedure(createSplitProcedure(parent, splitKey));<a name="line.1129"></a>
-<span class="sourceLineNo">1130</span><a name="line.1130"></a>
-<span class="sourceLineNo">1131</span> // If the RS is < 2.0 throw an exception to abort the operation, we are handling the split<a name="line.1131"></a>
-<span class="sourceLineNo">1132</span> if (master.getServerManager().getVersionNumber(serverName) < 0x0200000) {<a name="line.1132"></a>
-<span class="sourceLineNo">1133</span> throw new UnsupportedOperationException(String.format("Split handled by the master: " +<a name="line.1133"></a>
-<span class="sourceLineNo">1134</span> "parent=%s hriA=%s hriB=%s", parent.getShortNameToLog(), hriA, hriB));<a name="line.1134"></a>
-<span class="sourceLineNo">1135</span> }<a name="line.1135"></a>
-<span class="sourceLineNo">1136</span> }<a name="line.1136"></a>
-<span class="sourceLineNo">1137</span><a name="line.1137"></a>
-<span class="sourceLineNo">1138</span> private void updateRegionMergeTransition(final ServerName serverName, final TransitionCode state,<a name="line.1138"></a>
-<span class="sourceLineNo">1139</span> final RegionInfo merged, final RegionInfo hriA, final RegionInfo hriB) throws IOException {<a name="line.1139"></a>
-<span class="sourceLineNo">1140</span> checkMetaLoaded(merged);<a name="line.1140"></a>
-<span class="sourceLineNo">1141</span><a name="line.1141"></a>
-<span class="sourceLineNo">1142</span> if (state != TransitionCode.READY_TO_MERGE) {<a name="line.1142"></a>
-<span class="sourceLineNo">1143</span> throw new UnexpectedStateException("Unsupported merge regionState=" + state +<a name="line.1143"></a>
-<span class="sourceLineNo">1144</span> " for regionA=" + hriA + " regionB=" + hriB + " merged=" + merged +<a name="line.1144"></a>
-<span class="sourceLineNo">1145</span> " maybe an old RS (< 2.0) had the operation in progress");<a name="line.1145"></a>
-<span class="sourceLineNo">1146</span> }<a name="line.1146"></a>
-<span class="sourceLineNo">1147</span><a name="line.1147"></a>
-<span class="sourceLineNo">1148</span> if (!master.isSplitOrMergeEnabled(MasterSwitchType.MERGE)) {<a name="line.1148"></a>
-<span class="sourceLineNo">1149</span> LOG.warn("Merge switch is off! skip merge of regionA=" + hriA + " regionB=" + hriB);<a name="line.1149"></a>
-<span class="sourceLineNo">1150</span> throw new DoNotRetryIOException("Merge of regionA=" + hriA + " regionB=" + hriB +<a name="line.1150"></a>
-<span class="sourceLineNo">1151</span> " failed because merge switch is off");<a name="line.1151"></a>
-<span class="sourceLineNo">1152</span> }<a name="line.1152"></a>
+<span class="sourceLineNo">1129</span> // Processing this report happens asynchronously from other activities which can mutate<a name="line.1129"></a>
+<span class="sourceLineNo">1130</span> // the region state. For example, a split procedure may already be running for this parent.<a name="line.1130"></a>
+<span class="sourceLineNo">1131</span> // A split procedure cannot succeed if the parent region is no longer open, so we can<a name="line.1131"></a>
+<span class="sourceLineNo">1132</span> // ignore it in that case.<a name="line.1132"></a>
+<span class="sourceLineNo">1133</span> // Note that submitting more than one split procedure for a given region is<a name="line.1133"></a>
+<span class="sourceLineNo">1134</span> // harmless -- the split is fenced in the procedure handling -- but it would be noisy in<a name="line.1134"></a>
+<span class="sourceLineNo">1135</span> // the logs. Only one procedure can succeed. The other procedure(s) would abort during<a name="line.1135"></a>
+<span class="sourceLineNo">1136</span> // initialization and report failure with WARN level logging.<a name="line.1136"></a>
+<span class="sourceLineNo">1137</span> RegionState parentState = regionStates.getRegionState(parent);<a name="line.1137"></a>
+<span class="sourceLineNo">1138</span> if (parentState != null && parentState.isOpened()) {<a name="line.1138"></a>
+<span class="sourceLineNo">1139</span> master.getMasterProcedureExecutor().submitProcedure(createSplitProcedure(parent,<a name="line.1139"></a>
+<span class="sourceLineNo">1140</span> splitKey));<a name="line.1140"></a>
+<span class="sourceLineNo">1141</span> } else {<a name="line.1141"></a>
+<span class="sourceLineNo">1142</span> LOG.info("Ignoring split request from " + serverName +<a name="line.1142"></a>
+<span class="sourceLineNo">1143</span> ", parent=" + parent + " because parent is unknown or not open");<a name="line.1143"></a>
+<span class="sourceLineNo">1144</span> return;<a name="line.1144"></a>
+<span class="sourceLineNo">1145</span> }<a name="line.1145"></a>
+<span class="sourceLineNo">1146</span><a name="line.1146"></a>
+<span class="sourceLineNo">1147</span> // If the RS is < 2.0 throw an exception to abort the operation, we are handling the split<a name="line.1147"></a>
+<span class="sourceLineNo">1148</span> if (master.getServerManager().getVersionNumber(serverName) < 0x0200000) {<a name="line.1148"></a>
+<span class="sourceLineNo">1149</span> throw new UnsupportedOperationException(String.format("Split handled by the master: " +<a name="line.1149"></a>
+<span class="sourceLineNo">1150</span> "parent=%s hriA=%s hriB=%s", parent.getShortNameToLog(), hriA, hriB));<a name="line.1150"></a>
+<span class="sourceLineNo">1151</span> }<a name="line.1151"></a>
+<span class="sourceLineNo">1152</span> }<a name="line.1152"></a>
<span class="sourceLineNo">1153</span><a name="line.1153"></a>
-<span class="sourceLineNo">1154</span> // Submit the Merge procedure<a name="line.1154"></a>
-<span class="sourceLineNo">1155</span> if (LOG.isDebugEnabled()) {<a name="line.1155"></a>
-<span class="sourceLineNo">1156</span> LOG.debug("Handling merge request from RS=" + merged + ", merged=" + merged);<a name="line.1156"></a>
-<span class="sourceLineNo">1157</span> }<a name="line.1157"></a>
-<span class="sourceLineNo">1158</span> master.getMasterProcedureExecutor().submitProcedure(createMergeProcedure(hriA, hriB));<a name="line.1158"></a>
-<span class="sourceLineNo">1159</span><a name="line.1159"></a>
-<span class="sourceLineNo">1160</span> // If the RS is < 2.0 throw an exception to abort the operation, we are handling the merge<a name="line.1160"></a>
-<span class="sourceLineNo">1161</span> if (master.getServerManager().getVersionNumber(serverName) < 0x0200000) {<a name="line.1161"></a>
-<span class="sourceLineNo">1162</span> throw new UnsupportedOperationException(String.format(<a name="line.1162"></a>
-<span class="sourceLineNo">1163</span> "Merge not handled yet: regionState=%s merged=%s hriA=%s hriB=%s", state, merged, hriA,<a name="line.1163"></a>
-<span class="sourceLineNo">1164</span> hriB));<a name="line.1164"></a>
-<span class="sourceLineNo">1165</span> }<a name="line.1165"></a>
-<span class="sourceLineNo">1166</span> }<a name="line.1166"></a>
-<span class="sourceLineNo">1167</span><a name="line.1167"></a>
-<span class="sourceLineNo">1168</span> // ============================================================================================<a name="line.1168"></a>
-<span class="sourceLineNo">1169</span> // RS Status update (report online regions) helpers<a name="line.1169"></a>
-<span class="sourceLineNo">1170</span> // ============================================================================================<a name="line.1170"></a>
-<span class="sourceLineNo">1171</span> /**<a name="line.1171"></a>
-<span class="sourceLineNo">1172</span> * The master will call this method when the RS send the regionServerReport(). The report will<a name="line.1172"></a>
-<span class="sourceLineNo">1173</span> * contains the "online regions". This method will check the the online regions against the<a name="line.1173"></a>
-<span class="sourceLineNo">1174</span> * in-memory state of the AM, and we will log a warn message if there is a mismatch. This is<a name="line.1174"></a>
-<span class="sourceLineNo">1175</span> * because that there is no fencing between the reportRegionStateTransition method and<a name="line.1175"></a>
-<span class="sourceLineNo">1176</span> * regionServerReport method, so there could be race and introduce inconsistency here, but<a name="line.1176"></a>
-<span class="sourceLineNo">1177</span> * actually there is no problem.<a name="line.1177"></a>
-<span class="sourceLineNo">1178</span> * <p/><a name="line.1178"></a>
-<span class="sourceLineNo">1179</span> * Please see HBASE-21421 and HBASE-21463 for more details.<a name="line.1179"></a>
-<span class="sourceLineNo">1180</span> */<a name="line.1180"></a>
-<span class="sourceLineNo">1181</span> public void reportOnlineRegions(ServerName serverName, Set<byte[]> regionNames) {<a name="line.1181"></a>
-<span class="sourceLineNo">1182</span> if (!isRunning()) {<a name="line.1182"></a>
-<span class="sourceLineNo">1183</span> return;<a name="line.1183"></a>
-<span class="sourceLineNo">1184</span> }<a name="line.1184"></a>
-<span class="sourceLineNo">1185</span> if (LOG.isTraceEnabled()) {<a name="line.1185"></a>
-<span class="sourceLineNo">1186</span> LOG.trace("ReportOnlineRegions {} regionCount={}, metaLoaded={} {}", serverName,<a name="line.1186"></a>
-<span class="sourceLineNo">1187</span> regionNames.size(), isMetaLoaded(),<a name="line.1187"></a>
-<span class="sourceLineNo">1188</span> regionNames.stream().map(Bytes::toStringBinary).collect(Collectors.toList()));<a name="line.1188"></a>
-<span class="sourceLineNo">1189</span> }<a name="line.1189"></a>
-<span class="sourceLineNo">1190</span><a name="line.1190"></a>
-<span class="sourceLineNo">1191</span> ServerStateNode serverNode = regionStates.getOrCreateServer(serverName);<a name="line.1191"></a>
-<span class="sourceLineNo">1192</span> synchronized (serverNode) {<a name="line.1192"></a>
-<span class="sourceLineNo">1193</span> if (!serverNode.isInState(ServerState.ONLINE)) {<a name="line.1193"></a>
-<span class="sourceLineNo">1194</span> LOG.warn("Got a report from a server result in state " + serverNode.getState());<a name="line.1194"></a>
-<span class="sourceLineNo">1195</span> return;<a name="line.1195"></a>
-<span class="sourceLineNo">1196</span> }<a name="line.1196"></a>
-<span class="sourceLineNo">1197</span> }<a name="line.1197"></a>
-<span class="sourceLineNo">1198</span><a name="line.1198"></a>
-<span class="sourceLineNo">1199</span> // Track the regionserver reported online regions in memory.<a name="line.1199"></a>
-<span class="sourceLineNo">1200</span> synchronized (rsReports) {<a name="line.1200"></a>
-<span class="sourceLineNo">1201</span> rsReports.put(serverName, regionNames);<a name="line.1201"></a>
-<span class="sourceLineNo">1202</span> }<a name="line.1202"></a>
-<span class="sourceLineNo">1203</span><a name="line.1203"></a>
-<span class="sourceLineNo">1204</span> if (regionNames.isEmpty()) {<a name="line.1204"></a>
-<span class="sourceLineNo">1205</span> // nothing to do if we don't have regions<a name="line.1205"></a>
-<span class="sourceLineNo">1206</span> LOG.trace("no online region found on {}", serverName);<a name="line.1206"></a>
-<span class="sourceLineNo">1207</span> return;<a name="line.1207"></a>
-<span class="sourceLineNo">1208</span> }<a name="line.1208"></a>
-<span class="sourceLineNo">1209</span> if (!isMetaLoaded()) {<a name="line.1209"></a>
-<span class="sourceLineNo">1210</span> // we are still on startup, skip checking<a name="line.1210"></a>
-<span class="sourceLineNo">1211</span> return;<a name="line.1211"></a>
-<span class="sourceLineNo">1212</span> }<a name="line.1212"></a>
-<span class="sourceLineNo">1213</span> // The Heartbeat tells us of what regions are on the region serve, check the state.<a name="line.1213"></a>
-<span class="sourceLineNo">1214</span> checkOnlineRegionsReport(serverNode, regionNames);<a name="line.1214"></a>
-<span class="sourceLineNo">1215</span> }<a name="line.1215"></a>
-<span class="sourceLineNo">1216</span><a name="line.1216"></a>
-<span class="sourceLineNo">1217</span> /**<a name="line.1217"></a>
-<span class="sourceLineNo">1218</span> * Close <code>regionName</code> on <code>sn</code> silently and immediately without<a name="line.1218"></a>
-<span class="sourceLineNo">1219</span> * using a Procedure or going via hbase:meta. For case where a RegionServer's hosting<a name="line.1219"></a>
-<span class="sourceLineNo">1220</span> * of a Region is not aligned w/ the Master's accounting of Region state. This is for<a name="line.1220"></a>
-<span class="sourceLineNo">1221</span> * cleaning up an error in accounting.<a name="line.1221"></a>
-<span class="sourceLineNo">1222</span> */<a name="line.1222"></a>
-<span class="sourceLineNo">1223</span> private void closeRegionSilently(ServerName sn, byte [] regionName) {<a name="line.1223"></a>
-<span class="sourceLineNo">1224</span> try {<a name="line.1224"></a>
-<span class="sourceLineNo">1225</span> RegionInfo ri = CatalogFamilyFormat.parseRegionInfoFromRegionName(regionName);<a name="line.1225"></a>
-<span class="sourceLineNo">1226</span> // Pass -1 for timeout. Means do not wait.<a name="line.1226"></a>
-<span class="sourceLineNo">1227</span> ServerManager.closeRegionSilentlyAndWait(this.master.getAsyncClusterConnection(), sn, ri, -1);<a name="line.1227"></a>
-<span class="sourceLineNo">1228</span> } catch (Exception e) {<a name="line.1228"></a>
-<span class="sourceLineNo">1229</span> LOG.error("Failed trying to close {} on {}", Bytes.toStringBinary(regionName), sn, e);<a name="line.1229"></a>
-<span class="sourceLineNo">1230</span> }<a name="line.1230"></a>
+<span class="sourceLineNo">1154</span> private void updateRegionMergeTransition(final ServerName serverName, final TransitionCode state,<a name="line.1154"></a>
+<span class="sourceLineNo">1155</span> final RegionInfo merged, final RegionInfo hriA, final RegionInfo hriB) throws IOException {<a name="line.1155"></a>
+<span class="sourceLineNo">1156</span> checkMetaLoaded(merged);<a name="line.1156"></a>
+<span class="sourceLineNo">1157</span><a name="line.1157"></a>
+<span class="sourceLineNo">1158</span> if (state != TransitionCode.READY_TO_MERGE) {<a name="line.1158"></a>
+<span class="sourceLineNo">1159</span> throw new UnexpectedStateException("Unsupported merge regionState=" + state +<a name="line.1159"></a>
+<span class="sourceLineNo">1160</span> " for regionA=" + hriA + " regionB=" + hriB + " merged=" + merged +<a name="line.1160"></a>
+<span class="sourceLineNo">1161</span> " maybe an old RS (< 2.0) had the operation in progress");<a name="line.1161"></a>
+<span class="sourceLineNo">1162</span> }<a name="line.1162"></a>
+<span class="sourceLineNo">1163</span><a name="line.1163"></a>
+<span class="sourceLineNo">1164</span> if (!master.isSplitOrMergeEnabled(MasterSwitchType.MERGE)) {<a name="line.1164"></a>
+<span class="sourceLineNo">1165</span> LOG.warn("Merge switch is off! skip merge of regionA=" + hriA + " regionB=" + hriB);<a name="line.1165"></a>
+<span class="sourceLineNo">1166</span> throw new DoNotRetryIOException("Merge of regionA=" + hriA + " regionB=" + hriB +<a name="line.1166"></a>
+<span class="sourceLineNo">1167</span> " failed because merge switch is off");<a name="line.1167"></a>
+<span class="sourceLineNo">1168</span> }<a name="line.1168"></a>
+<span class="sourceLineNo">1169</span><a name="line.1169"></a>
+<span class="sourceLineNo">1170</span> // Submit the Merge procedure<a name="line.1170"></a>
+<span class="sourceLineNo">1171</span> if (LOG.isDebugEnabled()) {<a name="line.1171"></a>
+<span class="sourceLineNo">1172</span> LOG.debug("Handling merge request from RS=" + merged + ", merged=" + merged);<a name="line.1172"></a>
+<span class="sourceLineNo">1173</span> }<a name="line.1173"></a>
+<span class="sourceLineNo">1174</span> master.getMasterProcedureExecutor().submitProcedure(createMergeProcedure(hriA, hriB));<a name="line.1174"></a>
+<span class="sourceLineNo">1175</span><a name="line.1175"></a>
+<span class="sourceLineNo">1176</span> // If the RS is < 2.0 throw an exception to abort the operation, we are handling the merge<a name="line.1176"></a>
+<span class="sourceLineNo">1177</span> if (master.getServerManager().getVersionNumber(serverName) < 0x0200000) {<a name="line.1177"></a>
+<span class="sourceLineNo">1178</span> throw new UnsupportedOperationException(String.format(<a name="line.1178"></a>
+<span class="sourceLineNo">1179</span> "Merge not handled yet: regionState=%s merged=%s hriA=%s hriB=%s", state, merged, hriA,<a name="line.1179"></a>
+<span class="sourceLineNo">1180</span> hriB));<a name="line.1180"></a>
+<span class="sourceLineNo">1181</span> }<a name="line.1181"></a>
+<span class="sourceLineNo">1182</span> }<a name="line.1182"></a>
+<span class="sourceLineNo">1183</span><a name="line.1183"></a>
+<span class="sourceLineNo">1184</span> // ============================================================================================<a name="line.1184"></a>
+<span class="sourceLineNo">1185</span> // RS Status update (report online regions) helpers<a name="line.1185"></a>
+<span class="sourceLineNo">1186</span> // ============================================================================================<a name="line.1186"></a>
+<span class="sourceLineNo">1187</span> /**<a name="line.1187"></a>
+<span class="sourceLineNo">1188</span> * The master will call this method when the RS send the regionServerReport(). The report will<a name="line.1188"></a>
+<span class="sourceLineNo">1189</span> * contains the "online regions". This method will check the the online regions against the<a name="line.1189"></a>
+<span class="sourceLineNo">1190</span> * in-memory state of the AM, and we will log a warn message if there is a mismatch. This is<a name="line.1190"></a>
+<span class="sourceLineNo">1191</span> * because that there is no fencing between the reportRegionStateTransition method and<a name="line.1191"></a>
+<span class="sourceLineNo">1192</span> * regionServerReport method, so there could be race and introduce inconsistency here, but<a name="line.1192"></a>
+<span class="sourceLineNo">1193</span> * actually there is no problem.<a name="line.1193"></a>
+<span class="sourceLineNo">1194</span> * <p/><a name="line.1194"></a>
+<span class="sourceLineNo">1195</span> * Please see HBASE-21421 and HBASE-21463 for more details.<a name="line.1195"></a>
+<span class="sourceLineNo">1196</span> */<a name="line.1196"></a>
+<span class="sourceLineNo">1197</span> public void reportOnlineRegions(ServerName serverName, Set<byte[]> regionNames) {<a name="line.1197"></a>
+<span class="sourceLineNo">1198</span> if (!isRunning()) {<a name="line.1198"></a>
+<span class="sourceLineNo">1199</span> return;<a name="line.1199"></a>
+<span class="sourceLineNo">1200</span> }<a name="line.1200"></a>
+<span class="sourceLineNo">1201</span> if (LOG.isTraceEnabled()) {<a name="line.1201"></a>
+<span class="sourceLineNo">1202</span> LOG.trace("ReportOnlineRegions {} regionCount={}, metaLoaded={} {}", serverName,<a name="line.1202"></a>
+<span class="sourceLineNo">1203</span> regionNames.size(), isMetaLoaded(),<a name="line.1203"></a>
+<span class="sourceLineNo">1204</span> regionNames.stream().map(Bytes::toStringBinary).collect(Collectors.toList()));<a name="line.1204"></a>
+<span class="sourceLineNo">1205</span> }<a name="line.1205"></a>
+<span class="sourceLineNo">1206</span><a name="line.1206"></a>
+<span class="sourceLineNo">1207</span> ServerStateNode serverNode = regionStates.getOrCreateServer(serverName);<a name="line.1207"></a>
+<span class="sourceLineNo">1208</span> synchronized (serverNode) {<a name="line.1208"></a>
+<span class="sourceLineNo">1209</span> if (!serverNode.isInState(ServerState.ONLINE)) {<a name="line.1209"></a>
+<span class="sourceLineNo">1210</span> LOG.warn("Got a report from a server result in state " + serverNode.getState());<a name="line.1210"></a>
+<span class="sourceLineNo">1211</span> return;<a name="line.1211"></a>
+<span class="sourceLineNo">1212</span> }<a name="line.1212"></a>
+<span class="sourceLineNo">1213</span> }<a name="line.1213"></a>
+<span class="sourceLineNo">1214</span><a name="line.1214"></a>
+<span class="sourceLineNo">1215</span> // Track the regionserver reported online regions in memory.<a name="line.1215"></a>
+<span class="sourceLineNo">1216</span> synchronized (rsReports) {<a name="line.1216"></a>
+<span class="sourceLineNo">1217</span> rsReports.put(serverName, regionNames);<a name="line.1217"></a>
+<span class="sourceLineNo">1218</span> }<a name="line.1218"></a>
+<span class="sourceLineNo">1219</span><a name="line.1219"></a>
+<span class="sourceLineNo">1220</span> if (regionNames.isEmpty()) {<a name="line.1220"></a>
+<span class="sourceLineNo">1221</span> // nothing to do if we don't have regions<a name="line.1221"></a>
+<span class="sourceLineNo">1222</span> LOG.trace("no online region found on {}", serverName);<a name="line.1222"></a>
+<span class="sourceLineNo">1223</span> return;<a name="line.1223"></a>
+<span class="sourceLineNo">1224</span> }<a name="line.1224"></a>
+<span class="sourceLineNo">1225</span> if (!isMetaLoaded()) {<a name="line.1225"></a>
+<span class="sourceLineNo">1226</span> // we are still on startup, skip checking<a name="line.1226"></a>
+<span class="sourceLineNo">1227</span> return;<a name="line.1227"></a>
+<span class="sourceLineNo">1228</span> }<a name="line.1228"></a>
+<span class="sourceLineNo">1229</span> // The Heartbeat tells us of what regions are on the region serve, check the state.<a name="line.1229"></a>
+<span class="sourceLineNo">1230</span> checkOnlineRegionsReport(serverNode, regionNames);<a name="line.1230"></a>
<span class="sourceLineNo">1231</span> }<a name="line.1231"></a>
<span class="sourceLineNo">1232</span><a name="line.1232"></a>
<span class="sourceLineNo">1233</span> /**<a name="line.1233"></a>
-<span class="sourceLineNo">1234</span> * Check that what the RegionServer reports aligns with the Master's image.<a name="line.1234"></a>
-<span class="sourceLineNo">1235</span> * If disagreement, we will tell the RegionServer to expediently close<a name="line.1235"></a>
-<span class="sourceLineNo">1236</span> * a Region we do not think it should have.<a name="line.1236"></a>
-<span class="sourceLineNo">1237</span> */<a name="line.1237"></a>
-<span class="sourceLineNo">1238</span> private void checkOnlineRegionsReport(ServerStateNode serverNode, Set<byte[]> regionNames) {<a name="line.1238"></a>
-<span class="sourceLineNo">1239</span> ServerName serverName = serverNode.getServerName();<a name="line.1239"></a>
-<span class="sourceLineNo">1240</span> for (byte[] regionName : regionNames) {<a name="line.1240"></a>
-<span class="sourceLineNo">1241</span> if (!isRunning()) {<a name="line.1241"></a>
-<span class="sourceLineNo">1242</span> return;<a name="line.1242"></a>
-<span class="sourceLineNo">1243</span> }<a name="line.1243"></a>
-<span class="sourceLineNo">1244</span> RegionStateNode regionNode = regionStates.getRegionStateNodeFromName(regionName);<a name="line.1244"></a>
-<span class="sourceLineNo">1245</span> if (regionNode == null) {<a name="line.1245"></a>
-<span class="sourceLineNo">1246</span> String regionNameAsStr = Bytes.toStringBinary(regionName);<a name="line.1246"></a>
-<span class="sourceLineNo">1247</span> LOG.warn("No RegionStateNode for {} but reported as up on {}; closing...",<a name="line.1247"></a>
-<span class="sourceLineNo">1248</span> regionNameAsStr, serverName);<a name="line.1248"></a>
-<span class="sourceLineNo">1249</span> closeRegionSilently(serverNode.getServerName(), regionName);<a name="line.1249"></a>
-<span class="sourceLineNo">1250</span> continue;<a name="line.1250"></a>
-<span class="sourceLineNo">1251</span> }<a name="line.1251"></a>
-<span class="sourceLineNo">1252</span> final long lag = 1000;<a name="line.1252"></a>
-<span class="sourceLineNo">1253</span> regionNode.lock();<a name="line.1253"></a>
-<span class="sourceLineNo">1254</span> try {<a name="line.1254"></a>
-<span class="sourceLineNo">1255</span> long diff = EnvironmentEdgeManager.currentTime() - regionNode.getLastUpdate();<a name="line.1255"></a>
-<span class="sourceLineNo">1256</span> if (regionNode.isInState(State.OPENING, State.OPEN)) {<a name="line.1256"></a>
-<span class="sourceLineNo">1257</span> // This is possible as a region server has just closed a region but the region server<a name="line.1257"></a>
-<span class="sourceLineNo">1258</span> // report is generated before the closing, but arrive after the closing. Make sure there<a name="line.1258"></a>
-<span class="sourceLineNo">1259</span> // is some elapsed time so less false alarms.<a name="line.1259"></a>
-<span class="sourceLineNo">1260</span> if (!regionNode.getRegionLocation().equals(serverName) && diff > lag) {<a name="line.1260"></a>
-<span class="sourceLineNo">1261</span> LOG.warn("Reporting {} server does not match {} (time since last " +<a name="line.1261"></a>
-<span class="sourceLineNo">1262</span> "update={}ms); closing...",<a name="line.1262"></a>
-<span class="sourceLineNo">1263</span> serverName, regionNode, diff);<a name="line.1263"></a>
-<span class="sourceLineNo">1264</span> closeRegionSilently(serverNode.getServerName(), regionName);<a name="line.1264"></a>
-<span class="sourceLineNo">1265</span> }<a name="line.1265"></a>
-<span class="sourceLineNo">1266</span> } else if (!regionNode.isInState(State.CLOSING, State.SPLITTING)) {<a name="line.1266"></a>
-<span class="sourceLineNo">1267</span> // So, we can get report that a region is CLOSED or SPLIT because a heartbeat<a name="line.1267"></a>
-<span class="sourceLineNo">1268</span> // came in at about same time as a region transition. Make sure there is some<a name="line.1268"></a>
-<span class="sourceLineNo">1269</span> // elapsed time so less false alarms.<a name="line.1269"></a>
-<span class="sourceLineNo">1270</span> if (diff > lag) {<a name="line.1270"></a>
-<span class="sourceLineNo">1271</span> LOG.warn("Reporting {} state does not match {} (time since last update={}ms)",<a name="line.1271"></a>
-<span class="sourceLineNo">1272</span> serverName, regionNode, diff);<a name="line.1272"></a>
-<span class="sourceLineNo">1273</span> }<a name="line.1273"></a>
-<span class="sourceLineNo">1274</span> }<a name="line.1274"></a>
-<span class="sourceLineNo">1275</span> } finally {<a name="line.1275"></a>
-<span class="sourceLineNo">1276</span> regionNode.unlock();<a name="line.1276"></a>
-<span class="sourceLineNo">1277</span> }<a name="line.1277"></a>
-<span class="sourceLineNo">1278</span> }<a name="line.1278"></a>
-<span class="sourceLineNo">1279</span> }<a name="line.1279"></a>
-<span class="sourceLineNo">1280</span><a name="line.1280"></a>
-<span class="sourceLineNo">1281</span> // ============================================================================================<a name="line.1281"></a>
-<span class="sourceLineNo">1282</span> // RIT chore<a name="line.1282"></a>
-<span class="sourceLineNo">1283</span> // ============================================================================================<a name="line.1283"></a>
-<span class="sourceLineNo">1284</span> private static class RegionInTransitionChore extends ProcedureInMemoryChore<MasterProcedureEnv> {<a name="line.1284"></a>
-<span class="sourceLineNo">1285</span> public RegionInTransitionChore(final int timeoutMsec) {<a name="line.1285"></a>
-<span class="sourceLineNo">1286</span> super(timeoutMsec);<a name="line.1286"></a>
-<span class="sourceLineNo">1287</span> }<a name="line.1287"></a>
-<span class="sourceLineNo">1288</span><a name="line.1288"></a>
-<span class="sourceLineNo">1289</span> @Override<a name="line.1289"></a>
-<span class="sourceLineNo">1290</span> protected void periodicExecute(final MasterProcedureEnv env) {<a name="line.1290"></a>
-<span class="sourceLineNo">1291</span> final AssignmentManager am = env.getAssignmentManager();<a name="line.1291"></a>
-<span class="sourceLineNo">1292</span><a name="line.1292"></a>
-<span class="sourceLineNo">1293</span> final RegionInTransitionStat ritStat = am.computeRegionInTransitionStat();<a name="line.1293"></a>
-<span class="sourceLineNo">1294</span> if (ritStat.hasRegionsOverThreshold()) {<a name="line.1294"></a>
-<span class="sourceLineNo">1295</span> for (RegionState hri: ritStat.getRegionOverThreshold()) {<a name="line.1295"></a>
-<span class="sourceLineNo">1296</span> am.handleRegionOverStuckWarningThreshold(hri.getRegion());<a name="line.1296"></a>
-<span class="sourceLineNo">1297</span> }<a name="line.1297"></a>
-<span class="sourceLineNo">1298</span> }<a name="line.1298"></a>
-<span class="sourceLineNo">1299</span><a name="line.1299"></a>
-<span class="sourceLineNo">1300</span> // update metrics<a name="line.1300"></a>
-<span class="sourceLineNo">1301</span> am.updateRegionsInTransitionMetrics(ritStat);<a name="line.1301"></a>
-<span class="sourceLineNo">1302</span> }<a name="line.1302"></a>
-<span class="sourceLineNo">1303</span> }<a name="line.1303"></a>
+<span class="sourceLineNo">1234</span> * Close <code>regionName</code> on <code>sn</code> silently and immediately without<a name="line.1234"></a>
+<span class="sourceLineNo">1235</span> * using a Procedure or going via hbase:meta. For case where a RegionServer's hosting<a name="line.1235"></a>
+<span class="sourceLineNo">1236</span> * of a Region is not aligned w/ the Master's accounting of Region state. This is for<a name="line.1236"></a>
+<span class="sourceLineNo">1237</span> * cleaning up an error in accounting.<a name="line.1237"></a>
+<span class="sourceLineNo">1238</span> */<a name="line.1238"></a>
+<span class="sourceLineNo">1239</span> private void closeRegionSilently(ServerName sn, byte [] regionName) {<a name="line.1239"></a>
+<span class="sourceLineNo">1240</span> try {<a name="line.1240"></a>
+<span class="sourceLineNo">1241</span> RegionInfo ri = CatalogFamilyFormat.parseRegionInfoFromRegionName(regionName);<a name="line.1241"></a>
+<span class="sourceLineNo">1242</span> // Pass -1 for timeout. Means do not wait.<a name="line.1242"></a>
+<span class="sourceLineNo">1243</span> ServerManager.closeRegionSilentlyAndWait(this.master.getAsyncClusterConnection(), sn, ri, -1);<a name="line.1243"></a>
+<span class="sourceLineNo">1244</span> } catch (Exception e) {<a name="line.1244"></a>
+<span class="sourceLineNo">1245</span> LOG.error("Failed trying to close {} on {}", Bytes.toStringBinary(regionName), sn, e);<a name="line.1245"></a>
+<span class="sourceLineNo">1246</span> }<a name="line.1246"></a>
+<span class="sourceLineNo">1247</span> }<a name="line.1247"></a>
+<span class="sourceLineNo">1248</span><a name="line.1248"></a>
+<span class="sourceLineNo">1249</span> /**<a name="line.1249"></a>
+<span class="sourceLineNo">1250</span> * Check that what the RegionServer reports aligns with the Master's image.<a name="line.1250"></a>
+<span class="sourceLineNo">1251</span> * If disagreement, we will tell the RegionServer to expediently close<a name="line.1251"></a>
+<span class="sourceLineNo">1252</span> * a Region we do not think it should have.<a name="line.1252"></a>
+<span class="sourceLineNo">1253</span> */<a name="line.1253"></a>
+<span class="sourceLineNo">1254</span> private void checkOnlineRegionsReport(ServerStateNode serverNode, Set<byte[]> regionNames) {<a name="line.1254"></a>
+<span class="sourceLineNo">1255</span> ServerName serverName = serverNode.getServerName();<a name="line.1255"></a>
+<span class="sourceLineNo">1256</span> for (byte[] regionName : regionNames) {<a name="line.1256"></a>
+<span class="sourceLineNo">1257</span> if (!isRunning()) {<a name="line.1257"></a>
+<span class="sourceLineNo">1258</span> return;<a name="line.1258"></a>
+<span class="sourceLineNo">1259</span> }<a name="line.1259"></a>
+<span class="sourceLineNo">1260</span> RegionStateNode regionNode = regionStates.getRegionStateNodeFromName(regionName);<a name="line.1260"></a>
+<span class="sourceLineNo">1261</span> if (regionNode == null) {<a name="line.1261"></a>
+<span class="sourceLineNo">1262</span> String regionNameAsStr = Bytes.toStringBinary(regionName);<a name="line.1262"></a>
+<span class="sourceLineNo">1263</span> LOG.warn("No RegionStateNode for {} but reported as up on {}; closing...",<a name="line.1263"></a>
+<span class="sourceLineNo">1264</span> regionNameAsStr, serverName);<a name="line.1264"></a>
+<span class="sourceLineNo">1265</span> closeRegionSilently(serverNode.getServerName(), regionName);<a name="line.1265"></a>
+<span class="sourceLineNo">1266</span> continue;<a name="line.1266"></a>
+<span class="sourceLineNo">1267</span> }<a name="line.1267"></a>
+<span class="sourceLineNo">1268</span> final long lag = 1000;<a name="line.1268"></a>
+<span class="sourceLineNo">1269</span> regionNode.lock();<a name="line.1269"></a>
+<span class="sourceLineNo">1270</span> try {<a name="line.1270"></a>
+<span class="sourceLineNo">1271</span> long diff = EnvironmentEdgeManager.currentTime() - regionNode.getLastUpdate();<a name="line.1271"></a>
+<span class="sourceLineNo">1272</span> if (regionNode.isInState(State.OPENING, State.OPEN)) {<a name="line.1272"></a>
+<span class="sourceLineNo">1273</span> // This is possible as a region server has just closed a region but the region server<a name="line.1273"></a>
+<span class="sourceLineNo">1274</span> // report is generated before the closing, but arrive after the closing. Make sure there<a name="line.1274"></a>
+<span class="sourceLineNo">1275</span> // is some elapsed time so less false alarms.<a name="line.1275"></a>
+<span class="sourceLineNo">1276</span> if (!regionNode.getRegionLocation().equals(serverName) && diff > lag) {<a name="line.1276"></a>
+<span class="sourceLineNo">1277</span> LOG.warn("Reporting {} server does not match {} (time since last " +<a name="line.1277"></a>
+<span class="sourceLineNo">1278</span> "update={}ms); closing...",<a name="line.1278"></a>
+<span class="sourceLineNo">1279</span> serverName, regionNode, diff);<a name="line.1279"></a>
+<span class="sourceLineNo">1280</span> closeRegionSilently(serverNode.getServerName(), regionName);<a name="line.1280"></a>
+<span class="sourceLineNo">1281</span> }<a name="line.1281"></a>
+<span class="sourceLineNo">1282</span> } else if (!regionNode.isInState(State.CLOSING, State.SPLITTING)) {<a name="line.1282"></a>
+<span class="sourceLineNo">1283</span> // So, we can get report that a region is CLOSED or SPLIT because a heartbeat<a name="line.1283"></a>
+<span class="sourceLineNo">1284</span> // came in at about same time as a region transition. Make sure there is some<a name="line.1284"></a>
+<span class="sourceLineNo">1285</span> // elapsed time so less false alarms.<a name="line.1285"></a>
+<span class="sourceLineNo">1286</span> if (diff > lag) {<a name="line.1286"></a>
+<span class="sourceLineNo">1287</span> LOG.warn("Reporting {} state does not match {} (time since last update={}ms)",<a name="line.1287"></a>
+<span class="sourceLineNo">1288</span> serverName, regionNode, diff);<a name="line.1288"></a>
+<span class="sourceLineNo">1289</span> }<a name="line.1289"></a>
+<span class="sourceLineNo">1290</span> }<a name="line.1290"></a>
+<span class="sourceLineNo">1291</span> } finally {<a name="line.1291"></a>
+<span class="sourceLineNo">1292</span> regionNode.unlock();<a name="line.1292"></a>
+<span class="sourceLineNo">1293</span> }<a name="line.1293"></a>
+<span class="sourceLineNo">1294</span> }<a name="line.1294"></a>
+<span class="sourceLineNo">1295</span> }<a name="line.1295"></a>
+<span class="sourceLineNo">1296</span><a name="line.1296"></a>
+<span class="sourceLineNo">1297</span> // ============================================================================================<a name="line.1297"></a>
+<span class="sourceLineNo">1298</span> // RIT chore<a name="line.1298"></a>
+<span class="sourceLineNo">1299</span> // ============================================================================================<a name="line.1299"></a>
+<span class="sourceLineNo">1300</span> private static class RegionInTransitionChore extends ProcedureInMemoryChore<MasterProcedureEnv> {<a name="line.1300"></a>
+<span class="sourceLineNo">1301</span> public RegionInTransitionChore(final int timeoutMsec) {<a name="line.1301"></a>
+<span class="sourceLineNo">1302</span> super(timeoutMsec);<a name="line.1302"></a>
+<span class="sourceLineNo">1303</span> }<a name="line.1303"></a>
<span class="sourceLineNo">1304</span><a name="line.1304"></a>
-<span class="sourceLineNo">1305</span> private static class DeadServerMetricRegionChore<a name="line.1305"></a>
-<span class="sourceLineNo">1306</span> extends ProcedureInMemoryChore<MasterProcedureEnv> {<a name="line.1306"></a>
-<span class="sourceLineNo">1307</span> public DeadServerMetricRegionChore(final int timeoutMsec) {<a name="line.1307"></a>
-<span class="sourceLineNo">1308</span> super(timeoutMsec);<a name="line.1308"></a>
-<span class="sourceLineNo">1309</span> }<a name="line.1309"></a>
-<span class="sourceLineNo">1310</span><a name="line.1310"></a>
-<span class="sourceLineNo">1311</span> @Override<a name="line.1311"></a>
-<span class="sourceLineNo">1312</span> protected void periodicExecute(final MasterProcedureEnv env) {<a name="line.1312"></a>
-<span class="sourceLineNo">1313</span> final ServerManager sm = env.getMasterServices().getServerManager();<a name="line.1313"></a>
-<span class="sourceLineNo">1314</span> final AssignmentManager am = env.getAssignmentManager();<a name="line.1314"></a>
-<span class="sourceLineNo">1315</span> // To minimize inconsistencies we are not going to snapshot live servers in advance in case<a name="line.1315"></a>
-<span class="sourceLineNo">1316</span> // new servers are added; OTOH we don't want to add heavy sync for a consistent view since<a name="line.1316"></a>
-<span class="sourceLineNo">1317</span> // this is for metrics. Instead, we're going to check each regions as we go; to avoid making<a name="line.1317"></a>
-<span class="sourceLineNo">1318</span> // too many checks, we maintain a local lists of server, limiting us to false negatives. If<a name="line.1318"></a>
-<span class="sourceLineNo">1319</span> // we miss some recently-dead server, we'll just see it next time.<a name="line.1319"></a>
-<span class="sourceLineNo">1320</span> Set<ServerName> recentlyLiveServers = new HashSet<>();<a name="line.1320"></a>
-<span class="sourceLineNo">1321</span> int deadRegions = 0, unknownRegions = 0;<a name="line.1321"></a>
-<span class="sourceLineNo">1322</span> for (RegionStateNode rsn : am.getRegionStates().getRegionStateNodes()) {<a name="line.1322"></a>
-<span class="sourceLineNo">1323</span> if (rsn.getState() != State.OPEN) {<a name="line.1323"></a>
-<span class="sourceLineNo">1324</span> continue; // Opportunistic check, should quickly skip RITs, offline tables, etc.<a name="line.1324"></a>
-<span class="sourceLineNo">1325</span> }<a name="line.1325"></a>
-<span class="sourceLineNo">1326</span> // Do not need to acquire region state lock as this is only for showing metrics.<a name="line.1326"></a>
-<span class="sourceLineNo">1327</span> ServerName sn = rsn.getRegionLocation();<a name="line.1327"></a>
-<span class="sourceLineNo">1328</span> State state = rsn.getState();<a name="line.1328"></a>
-<span class="sourceLineNo">1329</span> if (state != State.OPEN) {<a name="line.1329"></a>
-<span class="sourceLineNo">1330</span> continue; // Mostly skipping RITs that are already being take care of.<a name="line.1330"></a>
-<span class="sourceLineNo">1331</span> }<a name="line.1331"></a>
-<span class="sourceLineNo">1332</span> if (sn == null) {<a name="line.1332"></a>
-<span class="sourceLineNo">1333</span> ++unknownRegions; // Opened on null?<a name="line.1333"></a>
-<span class="sourceLineNo">1334</span> continue;<a name="line.1334"></a>
-<span class="sourceLineNo">1335</span> }<a name="line.1335"></a>
-<span class="sourceLineNo">1336</span> if (recentlyLiveServers.contains(sn)) {<a name="line.1336"></a>
-<span class="sourceLineNo">1337</span> continue;<a name="line.1337"></a>
-<span class="sourceLineNo">1338</span> }<a name="line.1338"></a>
-<span class="sourceLineNo">1339</span> ServerManager.ServerLiveState sls = sm.isServerKnownAndOnline(sn);<a name="line.1339"></a>
-<span class="sourceLineNo">1340</span> switch (sls) {<a name="line.1340"></a>
-<span class="sourceLineNo">1341</span> case LIVE:<a name="line.1341"></a>
-<span class="sourceLineNo">1342</span> recentlyLiveServers.add(sn);<a name="line.1342"></a>
-<span class="sourceLineNo">1343</span> break;<a name="line.1343"></a>
-<span class="sourceLineNo">1344</span> case DEAD:<a name="line.1344"></a>
-<span class="sourceLineNo">1345</span> ++deadRegions;<a name="line.1345"></a>
-<span class="sourceLineNo">1346</span> break;<a name="line.1346"></a>
-<span class="sourceLineNo">1347</span> case UNKNOWN:<a name="line.1347"></a>
-<span class="sourceLineNo">1348</span> ++unknownRegions;<a name="line.1348"></a>
-<span class="sourceLineNo">1349</span> break;<a name="line.1349"></a>
-<span class="sourceLineNo">1350</span> default: throw new AssertionError("Unexpected " + sls);<a name="line.1350"></a>
+<span class="sourceLineNo">1305</span> @Override<a name="line.1305"></a>
+<span class="sourceLineNo">1306</span> protected void periodicExecute(final MasterProcedureEnv env) {<a name="line.1306"></a>
+<span class="sourceLineNo">1307</span> final AssignmentManager am = env.getAssignmentManager();<a name="line.1307"></a>
+<span class="sourceLineNo">1308</span><a name="line.1308"></a>
+<span class="sourceLineNo">1309</span> final RegionInTransitionStat ritStat = am.computeRegionInTransitionStat();<a name="line.1309"></a>
+<span class="sourceLineNo">1310</span> if (ritStat.hasRegionsOverThreshold()) {<a name="line.1310"></a>
+<span class="sourceLineNo">1311</span> for (RegionState hri: ritStat.getRegionOverThreshold()) {<a name="line.1311"></a>
+<span class="sourceLineNo">1312</span> am.handleRegionOverStuckWarningThreshold(hri.getRegion());<a name="line.1312"></a>
+<span class="sourceLineNo">1313</span> }<a name="line.1313"></a>
+<span class="sourceLineNo">1314</span> }<a name="line.1314"></a>
+<span class="sourceLineNo">1315</span><a name="line.1315"></a>
+<span class="sourceLineNo">1316</span> // update metrics<a name="line.1316"></a>
+<span class="sourceLineNo">1317</span> am.updateRegionsInTransitionMetrics(ritStat);<a name="line.1317"></a>
+<span class="sourceLineNo">1318</span> }<a name="line.1318"></a>
+<span class="sourceLineNo">1319</span> }<a name="line.1319"></a>
+<span class="sourceLineNo">1320</span><a name="line.1320"></a>
+<span class="sourceLineNo">1321</span> private static class DeadServerMetricRegionChore<a name="line.1321"></a>
+<span class="sourceLineNo">1322</span> extends ProcedureInMemoryChore<MasterProcedureEnv> {<a name="line.1322"></a>
+<span class="sourceLineNo">1323</span> public DeadServerMetricRegionChore(final int timeoutMsec) {<a name="line.1323"></a>
+<span class="sourceLineNo">1324</span> super(timeoutMsec);<a name="line.1324"></a>
+<span class="sourceLineNo">1325</span> }<a name="line.1325"></a>
+<span class="sourceLineNo">1326</span><a name="line.1326"></a>
+<span class="sourceLineNo">1327</span> @Override<a name="line.1327"></a>
+<span class="sourceLineNo">1328</span> protected void periodicExecute(final MasterProcedureEnv env) {<a name="line.1328"></a>
+<span class="sourceLineNo">1329</span> final ServerManager sm = env.getMasterServices().getServerManager();<a name="line.1329"></a>
+<span class="sourceLineNo">1330</span> final AssignmentManager am = env.getAssignmentManager();<a name="line.1330"></a>
+<span class="sourceLineNo">1331</span> // To minimize inconsistencies we are not going to snapshot live servers in advance in case<a name="line.1331"></a>
+<span class="sourceLineNo">1332</span> // new servers are added; OTOH we don't want to add heavy sync for a consistent view since<a name="line.1332"></a>
+<span class="sourceLineNo">1333</span> // this is for metrics. Instead, we're going to check each regions as we go; to avoid making<a name="line.1333"></a>
+<span class="sourceLineNo">1334</span> // too many checks, we maintain a local lists of server, limiting us to false negatives. If<a name="line.1334"></a>
+<span class="sourceLineNo">1335</span> // we miss some recently-dead server, we'll just see it next time.<a name="line.1335"></a>
+<span class="sourceLineNo">1336</span> Set<ServerName> recentlyLiveServers = new HashSet<>();<a name="line.1336"></a>
+<span class="sourceLineNo">1337</span> int deadRegions = 0, unknownRegions = 0;<a name="line.1337"></a>
+<span class="sourceLineNo">1338</span> for (RegionStateNode rsn : am.getRegionStates().getRegionStateNodes()) {<a name="line.1338"></a>
+<span class="sourceLineNo">1339</span> if (rsn.getState() != State.OPEN) {<a name="line.1339"></a>
+<span class="sourceLineNo">1340</span> continue; // Opportunistic check, should quickly skip RITs, offline tables, etc.<a name="line.1340"></a>
+<span class="sourceLineNo">1341</span> }<a name="line.1341"></a>
+<span class="sourceLineNo">1342</span> // Do not need to acquire region state lock as this is only for showing metrics.<a name="line.1342"></a>
+<span class="sourceLineNo">1343</span> ServerName sn = rsn.getRegionLocation();<a name="line.1343"></a>
+<span class="sourceLineNo">1344</span> State state = rsn.getState();<a name="line.1344"></a>
+<span class="sourceLineNo">1345</span> if (state != State.OPEN) {<a name="line.1345"></a>
+<span class="sourceLineNo">1346</span> continue; // Mostly skipping RITs that are already being take care of.<a name="line.1346"></a>
+<span class="sourceLineNo">1347</span> }<a name="line.1347"></a>
+<span class="sourceLineNo">1348</span> if (sn == null) {<a name="line.1348"></a>
+<span class="sourceLineNo">1349</span> ++unknownRegions; // Opened on null?<a name="line.1349"></a>
+<span class="sourceLineNo">1350</span> continue;<a name="line.1350"></a>
<span class="sourceLineNo">1351</span> }<a name="line.1351"></a>
-<span class="sourceLineNo">1352</span> }<a name="line.1352"></a>
-<span class="sourceLineNo">1353</span> if (deadRegions > 0 || unknownRegions > 0) {<a name="line.1353"></a>
-<span class="sourceLineNo">1354</span> LOG.info("Found {} OPEN regions on dead servers and {} OPEN regions on unknown servers",<a name="line.1354"></a>
-<span class="sourceLineNo">1355</span> deadRegions, unknownRegions);<a name="line.1355"></a>
-<span class="sourceLineNo">1356</span> }<a name="line.1356"></a>
-<span class="sourceLineNo">1357</span><a name="line.1357"></a>
-<span class="sourceLineNo">1358</span> am.updateDeadServerRegionMetrics(deadRegions, unknownRegions);<a name="line.1358"></a>
-<span class="sourceLineNo">1359</span> }<a name="line.1359"></a>
-<span class="sourceLineNo">1360</span> }<a name="line.1360"></a>
-<span class="sourceLineNo">1361</span><a name="line.1361"></a>
-<span class="sourceLineNo">1362</span> public RegionInTransitionStat computeRegionInTransitionStat() {<a name="line.1362"></a>
-<span class="sourceLineNo">1363</span> final RegionInTransitionStat rit = new RegionInTransitionStat(getConfiguration());<a name="line.1363"></a>
-<span class="sourceLineNo">1364</span> rit.update(this);<a name="line.1364"></a>
-<span class="sourceLineNo">1365</span> return rit;<a name="line.1365"></a>
-<span class="sourceLineNo">1366</span> }<a name="line.1366"></a>
-<span class="sourceLineNo">1367</span><a name="line.1367"></a>
-<span class="sourceLineNo">1368</span> public static class RegionInTransitionStat {<a name="line.1368"></a>
-<span class="sourceLineNo">1369</span> private final int ritThreshold;<a name="line.1369"></a>
-<span class="sourceLineNo">1370</span><a name="line.1370"></a>
-<span class="sourceLineNo">1371</span> private HashMap<String, RegionState> ritsOverThreshold = null;<a name="line.1371"></a>
-<span class="sourceLineNo">1372</span> private long statTimestamp;<a name="line.1372"></a>
-<span class="sourceLineNo">1373</span> private long oldestRITTime = 0;<a name="line.1373"></a>
-<span class="sourceLineNo">1374</span> private int totalRITsTwiceThreshold = 0;<a name="line.1374"></a>
-<span class="sourceLineNo">1375</span> private int totalRITs = 0;<a name="line.1375"></a>
-<span class="sourceLineNo">1376</span><a name="line.1376"></a>
-<span class="sourceLineNo">1377</span> public RegionInTransitionStat(final Configuration conf) {<a name="line.1377"></a>
-<span class="sourceLineNo">1378</span> this.ritThreshold =<a name="line.1378"></a>
-<span class="sourceLineNo">1379</span> conf.getInt(METRICS_RIT_STUCK_WARNING_THRESHOLD, DEFAULT_RIT_STUCK_WARNING_THRESHOLD);<a name="line.1379"></a>
-<span class="sourceLineNo">1380</span> }<a name="line.1380"></a>
-<span class="sourceLineNo">1381</span><a name="line.1381"></a>
-<span class="sourceLineNo">1382</span> public int getRITThreshold() {<a name="line.1382"></a>
-<span class="sourceLineNo">1383</span> return ritThreshold;<a name="line.1383"></a>
-<span class="sourceLineNo">1384</span> }<a name="line.1384"></a>
-<span class="sourceLineNo">1385</span><a name="line.1385"></a>
-<span class="sourceLineNo">1386</span> public long getTimestamp() {<a name="line.1386"></a>
-<span class="sourceLineNo">1387</span> return statTimestamp;<a name="line.1387"></a>
-<span class="sourceLineNo">1388</span> }<a name="line.1388"></a>
-<span class="sourceLineNo">1389</span><a name="line.1389"></a>
-<span class="sourceLineNo">1390</span> public int getTotalRITs() {<a name="line.1390"></a>
-<span class="sourceLineNo">1391</span> return totalRITs;<a name="line.1391"></a>
-<span class="sourceLineNo">1392</span> }<a name="line.1392"></a>
-<span class="sourceLineNo">1393</span><a name="line.1393"></a>
-<span class="sourceLineNo">1394</span> public long getOldestRITTime() {<a name="line.1394"></a>
-<span class="sourceLineNo">1395</span> return oldestRITTime;<a name="line.1395"></a>
+<span class="sourceLineNo">1352</span> if (recentlyLiveServers.contains(sn)) {<a name="line.1352"></a>
+<span class="sourceLineNo">1353</span> continue;<a name="line.1353"></a>
+<span class="sourceLineNo">1354</span> }<a name="line.1354"></a>
+<span class="sourceLineNo">1355</span> ServerManager.ServerLiveState sls = sm.isServerKnownAndOnline(sn);<a name="line.1355"></a>
+<span class="sourceLineNo">1356</span> switch (sls) {<a name="line.1356"></a>
+<span class="sourceLineNo">1357</span> case LIVE:<a name="line.1357"></a>
+<span class="sourceLineNo">1358</span> recentlyLiveServers.add(sn);<a name="line.1358"></a>
+<span class="sourceLineNo">1359</span> break;<a name="line.1359"></a>
+<span class="sourceLineNo">1360</span> case DEAD:<a name="line.1360"></a>
+<span class="sourceLineNo">1361</span> ++deadRegions;<a name="line.1361"></a>
+<span class="sourceLineNo">1362</span> break;<a name="line.1362"></a>
+<span class="sourceLineNo">1363</span> case UNKNOWN:<a name="line.1363"></a>
+<span class="sourceLineNo">1364</span> ++unknownRegions;<a name="line.1364"></a>
+<span class="sourceLineNo">1365</span> break;<a name="line.1365"></a>
+<span class="sourceLineNo">1366</span> default: throw new AssertionError("Unexpected " + sls);<a name="line.1366"></a>
+<span class="sourceLineNo">1367</span> }<a name="line.1367"></a>
+<span class="sourceLineNo">1368</span> }<a name="line.1368"></a>
+<span class="sourceLineNo">1369</span> if (deadRegions > 0 || unknownRegions > 0) {<a name="line.1369"></a>
+<span class="sourceLineNo">1370</span> LOG.info("Found {} OPEN regions on dead servers and {} OPEN regions on unknown servers",<a name="line.1370"></a>
+<span class="sourceLineNo">1371</span> deadRegions, unknownRegions);<a name="line.1371"></a>
+<span class="sourceLineNo">1372</span> }<a name="line.1372"></a>
+<span class="sourceLineNo">1373</span><a name="line.1373"></a>
+<span class="sourceLineNo">1374</span> am.updateDeadServerRegionMetrics(deadRegions, unknownRegions);<a name="line.1374"></a>
+<span class="sourceLineNo">1375</span> }<a name="line.1375"></a>
+<span class="sourceLineNo">1376</span> }<a name="line.1376"></a>
+<span class="sourceLineNo">1377</span><a name="line.1377"></a>
+<span class="sourceLineNo">1378</span> public RegionInTransitionStat computeRegionInTransitionStat() {<a name="line.1378"></a>
+<span class="sourceLineNo">1379</span> final RegionInTransitionStat rit = new RegionInTransitionStat(getConfiguration());<a name="line.1379"></a>
+<span class="sourceLineNo">1380</span> rit.update(this);<a name="line.1380"></a>
+<span class="sourceLineNo">1381</span> return rit;<a name="line.1381"></a>
+<span class="sourceLineNo">1382</span> }<a name="line.1382"></a>
+<span class="sourceLineNo">1383</span><a name="line.1383"></a>
+<span class="sourceLineNo">1384</span> public static class RegionInTransitionStat {<a name="line.1384"></a>
+<span class="sourceLineNo">1385</span> private final int ritThreshold;<a name="line.1385"></a>
+<span class="sourceLineNo">1386</span><a name="line.1386"></a>
+<span class="sourceLineNo">1387</span> private HashMap<String, RegionState> ritsOverThreshold = null;<a name="line.1387"></a>
+<span class="sourceLineNo">1388</span> private long statTimestamp;<a name="line.1388"></a>
+<span class="sourceLineNo">1389</span> private long oldestRITTime = 0;<a name="line.1389"></a>
+<span class="sourceLineNo">1390</span> private int totalRITsTwiceThreshold = 0;<a name="line.1390"></a>
+<span class="sourceLineNo">1391</span> private int totalRITs = 0;<a name="line.1391"></a>
+<span class="sourceLineNo">1392</span><a name="line.1392"></a>
+<span class="sourceLineNo">1393</span> public RegionInTransitionStat(final Configuration conf) {<a name="line.1393"></a>
+<span class="sourceLineNo">1394</span> this.ritThreshold =<a name="line.1394"></a>
+<span class="sourceLineNo">1395</span> conf.getInt(METRICS_RIT_STUCK_WARNING_THRESHOLD, DEFAULT_RIT_STUCK_WARNING_THRESHOLD);<a name="line.1395"></a>
<span class="sourceLineNo">1396</span> }<a name="line.1396"></a>
<span class="sourceLineNo">1397</span><a name="line.1397"></a>
-<span class="sourceLineNo">1398</span> public int getTotalRITsOverThreshold() {<a name="line.1398"></a>
-<span class="sourceLineNo">1399</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1399"></a>
-<span class="sourceLineNo">1400</span> return m != null ? m.size() : 0;<a name="line.1400"></a>
-<span class="sourceLineNo">1401</span> }<a name="line.1401"></a>
-<span class="sourceLineNo">1402</span><a name="line.1402"></a>
-<span class="sourceLineNo">1403</span> public boolean hasRegionsTwiceOverThreshold() {<a name="line.1403"></a>
-<span class="sourceLineNo">1404</span> return totalRITsTwiceThreshold > 0;<a name="line.1404"></a>
-<span class="sourceLineNo">1405</span> }<a name="line.1405"></a>
-<span class="sourceLineNo">1406</span><a name="line.1406"></a>
-<span class="sourceLineNo">1407</span> public boolean hasRegionsOverThreshold() {<a name="line.1407"></a>
-<span class="sourceLineNo">1408</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1408"></a>
-<span class="sourceLineNo">1409</span> return m != null && !m.isEmpty();<a name="line.1409"></a>
-<span class="sourceLineNo">1410</span> }<a name="line.1410"></a>
-<span class="sourceLineNo">1411</span><a name="line.1411"></a>
-<span class="sourceLineNo">1412</span> public Collection<RegionState> getRegionOverThreshold() {<a name="line.1412"></a>
-<span class="sourceLineNo">1413</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1413"></a>
-<span class="sourceLineNo">1414</span> return m != null? m.values(): Collections.emptySet();<a name="line.1414"></a>
-<span class="sourceLineNo">1415</span> }<a name="line.1415"></a>
-<span class="sourceLineNo">1416</span><a name="line.1416"></a>
-<span class="sourceLineNo">1417</span> public boolean isRegionOverThreshold(final RegionInfo regionInfo) {<a name="line.1417"></a>
-<span class="sourceLineNo">1418</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1418"></a>
-<span class="sourceLineNo">1419</span> return m != null && m.containsKey(regionInfo.getEncodedName());<a name="line.1419"></a>
-<span class="sourceLineNo">1420</span> }<a name="line.1420"></a>
-<span class="sourceLineNo">1421</span><a name="line.1421"></a>
-<span class="sourceLineNo">1422</span> public boolean isRegionTwiceOverThreshold(final RegionInfo regionInfo) {<a name="line.1422"></a>
-<span class="sourceLineNo">1423</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1423"></a>
-<span class="sourceLineNo">1424</span> if (m == null) {<a name="line.1424"></a>
-<span class="sourceLineNo">1425</span> return false;<a name="line.1425"></a>
-<span class="sourceLineNo">1426</span> }<a name="line.1426"></a>
-<span class="sourceLineNo">1427</span> final RegionState state = m.get(regionInfo.getEncodedName());<a name="line.1427"></a>
-<span class="sourceLineNo">1428</span> if (state == null) {<a name="line.1428"></a>
-<span class="sourceLineNo">1429</span> return false;<a name="line.1429"></a>
-<span class="sourceLineNo">1430</span> }<a name="line.1430"></a>
-<span class="sourceLineNo">1431</span> return (statTimestamp - state.getStamp()) > (ritThreshold * 2);<a name="line.1431"></a>
-<span class="sourceLineNo">1432</span> }<a name="line.1432"></a>
-<span class="sourceLineNo">1433</span><a name="line.1433"></a>
-<span class="sourceLineNo">1434</span> protected void update(final AssignmentManager am) {<a name="line.1434"></a>
-<span class="sourceLineNo">1435</span> final RegionStates regionStates = am.getRegionStates();<a name="line.1435"></a>
-<span class="sourceLineNo">1436</span> this.statTimestamp = EnvironmentEdgeManager.currentTime();<a name="line.1436"></a>
-<span class="sourceLineNo">1437</span> update(regionStates.getRegionsStateInTransition(), statTimestamp);<a name="line.1437"></a>
-<span class="sourceLineNo">1438</span> update(regionStates.getRegionFailedOpen(), statTimestamp);<a name="line.1438"></a>
-<span class="sourceLineNo">1439</span><a name="line.1439"></a>
-<span class="sourceLineNo">1440</span> if (LOG.isDebugEnabled() && ritsOverThreshold != null && !ritsOverThreshold.isEmpty()) {<a name="line.1440"></a>
-<span class="sourceLineNo">1441</span> LOG.debug("RITs over threshold: {}",<a name="line.1441"></a>
-<span class="sourceLineNo">1442</span> ritsOverThreshold.entrySet().stream()<a name="line.1442"></a>
-<span class="sourceLineNo">1443</span> .map(e -> e.getKey() + ":" + e.getValue().getState().name())<a name="line.1443"></a>
-<span class="sourceLineNo">1444</span> .collect(Collectors.joining("\n")));<a name="line.1444"></a>
-<span class="sourceLineNo">1445</span> }<a name="line.1445"></a>
-<span class="sourceLineNo">1446</span> }<a name="line.1446"></a>
-<span class="sourceLineNo">1447</span><a name="line.1447"></a>
-<span class="sourceLineNo">1448</span> private void update(final Collection<RegionState> regions, final long currentTime) {<a name="line.1448"></a>
-<span class="sourceLineNo">1449</span> for (RegionState state: regions) {<a name="line.1449"></a>
-<span class="sourceLineNo">1450</span> totalRITs++;<a name="line.1450"></a>
-<span class="sourceLineNo">1451</span> final long ritStartedMs = state.getStamp();<a name="line.1451"></a>
-<span class="sourceLineNo">1452</span> if (ritStartedMs == 0) {<a name="line.1452"></a>
-<span class="sourceLineNo">1453</span> // Don't output bogus values to metrics if they accidentally make it here.<a name="line.1453"></a>
-<span class="sourceLineNo">1454</span> LOG.warn("The RIT {} has no start time", state.getRegion());<a name="line.1454"></a>
-<span class="sourceLineNo">1455</span> continue;<a name="line.1455"></a>
-<span class="sourceLineNo">1456</span> }<a name="line.1456"></a>
-<span class="sourceLineNo">1457</span> final long ritTime = currentTime - ritStartedMs;<a name="line.1457"></a>
-<span class="sourceLineNo">1458</span> if (ritTime > ritThreshold) {<a name="line.1458"></a>
-<span class="sourceLineNo">1459</span> if (ritsOverThreshold == null) {<a name="line.1459"></a>
-<span class="sourceLineNo">1460</span> ritsOverThreshold = new HashMap<String, RegionState>();<a name="line.1460"></a>
-<span class="sourceLineNo">1461</span> }<a name="line.1461"></a>
-<span class="sourceLineNo">1462</span> ritsOverThreshold.put(state.getRegion().getEncodedName(), state);<a name="line.1462"></a>
-<span class="sourceLineNo">1463</span> totalRITsTwiceThreshold += (ritTime > (ritThreshold * 2)) ? 1 : 0;<a name="line.1463"></a>
-<span class="sourceLineNo">1464</span> }<a name="line.1464"></a>
-<span class="sourceLineNo">1465</span> if (oldestRITTime < ritTime) {<a name="line.1465"></a>
-<span class="sourceLineNo">1466</span> oldestRITTime = ritTime;<a name="line.1466"></a>
-<span class="sourceLineNo">1467</span> }<a name="line.1467"></a>
-<span class="sourceLineNo">1468</span> }<a name="line.1468"></a>
-<span class="sourceLineNo">1469</span> }<a name="line.1469"></a>
-<span class="sourceLineNo">1470</span> }<a name="line.1470"></a>
-<span class="sourceLineNo">1471</span><a name="line.1471"></a>
-<span class="sourceLineNo">1472</span> private void updateRegionsInTransitionMetrics(final RegionInTransitionStat ritStat) {<a name="line.1472"></a>
-<span class="sourceLineNo">1473</span> metrics.updateRITOldestAge(ritStat.getOldestRITTime());<a name="line.1473"></a>
-<span class="sourceLineNo">1474</span> metrics.updateRITCount(ritStat.getTotalRITs());<a name="line.1474"></a>
-<span class="sourceLineNo">1475</span> metrics.updateRITCountOverThreshold(ritStat.getTotalRITsOverThreshold());<a name="line.1475"></a>
-<span class="sourceLineNo">1476</span> }<a name="line.1476"></a>
-<span class="sourceLineNo">1477</span><a name="line.1477"></a>
-<span class="sourceLineNo">1478</span> private void updateDeadServerRegionMetrics(int deadRegions, int unknownRegions) {<a name="line.1478"></a>
-<span class="sourceLineNo">1479</span> metrics.updateDeadServerOpenRegions(deadRegions);<a name="line.1479"></a>
-<span class="sourceLineNo">1480</span> metrics.updateUnknownServerOpenRegions(unknownRegions);<a name="line.1480"></a>
-<span class="sourceLineNo">1481</span> }<a name="line.1481"></a>
-<span class="sourceLineNo">1482</span><a name="line.1482"></a>
-<span class="sourceLineNo">1483</span> private void handleRegionOverStuckWarningThreshold(final RegionInfo regionInfo) {<a name="line.1483"></a>
-<span class="sourceLineNo">1484</span> final RegionStateNode regionNode = regionStates.getRegionStateNode(regionInfo);<a name="line.1484"></a>
-<span class="sourceLineNo">1485</span> //if (regionNode.isStuck()) {<a name="line.1485"></a>
-<span class="sourceLineNo">1486</span> LOG.warn("STUCK Region-In-Transition {}", regionNode);<a name="line.1486"></a>
-<span class="sourceLineNo">1487</span> }<a name="line.1487"></a>
-<span class="sourceLineNo">1488</span><a name="line.1488"></a>
-<span class="sourceLineNo">1489</span> // ============================================================================================<a name="line.1489"></a>
-<span class="sourceLineNo">1490</span> // TODO: Master load/bootstrap<a name="line.1490"></a>
-<span class="sourceLineNo">1491</span> // ============================================================================================<a name="line.1491"></a>
-<span class="sourceLineNo">1492</span> public void joinCluster() throws IOException {<a name="line.1492"></a>
-<span class="sourceLineNo">1493</span> long startTime = System.nanoTime();<a name="line.1493"></a>
-<span class="sourceLineNo">1494</span> LOG.debug("Joining cluster...");<a name="line.1494"></a>
-<span class="sourceLineNo">1495</span><a name="line.1495"></a>
-<span class="sourceLineNo">1496</span> // Scan hbase:meta to build list of existing regions, servers, and assignment.<a name="line.1496"></a>
-<span class="sourceLineNo">1497</span> // hbase:meta is online now or will be. Inside loadMeta, we keep trying. Can't make progress<a name="line.1497"></a>
-<span class="sourceLineNo">1498</span> // w/o meta.<a name="line.1498"></a>
-<span class="sourceLineNo">1499</span> loadMeta();<a name="line.1499"></a>
-<span class="sourceLineNo">1500</span><a name="line.1500"></a>
-<span class="sourceLineNo">1501</span> while (master.getServerManager().countOfRegionServers() < 1) {<a name="line.1501"></a>
-<span class="sourceLineNo">1502</span> LOG.info("Waiting for RegionServers to join; current count={}",<a name="line.1502"></a>
-<span class="sourceLineNo">1503</span> master.getServerManager().countOfRegionServers());<a name="line.1503"></a>
-<span class="sourceLineNo">1504</span> Threads.sleep(250);<a name="line.1504"></a>
-<span class="sourceLineNo">1505</span> }<a name="line.1505"></a>
-<span class="sourceLineNo">1506</span> LOG.info("Number of RegionServers={}", master.getServerManager().countOfRegionServers());<a name="line.1506"></a>
-<span class="sourceLineNo">1507</span><a name="line.1507"></a>
-<span class="sourceLineNo">1508</span> // Start the chores<a name="line.1508"></a>
-<span class="sourceLineNo">1509</span> master.getMasterProcedureExecutor().addChore(this.ritChore);<a name="line.1509"></a>
-<span class="sourceLineNo">1510</span> master.getMasterProcedureExecutor().addChore(this.deadMetricChore);<a name="line.1510"></a>
+<span class="sourceLineNo">1398</span> public int getRITThreshold() {<a name="line.1398"></a>
+<span class="sourceLineNo">1399</span> return ritThreshold;<a name="line.1399"></a>
+<span class="sourceLineNo">1400</span> }<a name="line.1400"></a>
+<span class="sourceLineNo">1401</span><a name="line.1401"></a>
+<span class="sourceLineNo">1402</span> public long getTimestamp() {<a name="line.1402"></a>
+<span class="sourceLineNo">1403</span> return statTimestamp;<a name="line.1403"></a>
+<span class="sourceLineNo">1404</span> }<a name="line.1404"></a>
+<span class="sourceLineNo">1405</span><a name="line.1405"></a>
+<span class="sourceLineNo">1406</span> public int getTotalRITs() {<a name="line.1406"></a>
+<span class="sourceLineNo">1407</span> return totalRITs;<a name="line.1407"></a>
+<span class="sourceLineNo">1408</span> }<a name="line.1408"></a>
+<span class="sourceLineNo">1409</span><a name="line.1409"></a>
+<span class="sourceLineNo">1410</span> public long getOldestRITTime() {<a name="line.1410"></a>
+<span class="sourceLineNo">1411</span> return oldestRITTime;<a name="line.1411"></a>
+<span class="sourceLineNo">1412</span> }<a name="line.1412"></a>
+<span class="sourceLineNo">1413</span><a name="line.1413"></a>
+<span class="sourceLineNo">1414</span> public int getTotalRITsOverThreshold() {<a name="line.1414"></a>
+<span class="sourceLineNo">1415</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1415"></a>
+<span class="sourceLineNo">1416</span> return m != null ? m.size() : 0;<a name="line.1416"></a>
+<span class="sourceLineNo">1417</span> }<a name="line.1417"></a>
+<span class="sourceLineNo">1418</span><a name="line.1418"></a>
+<span class="sourceLineNo">1419</span> public boolean hasRegionsTwiceOverThreshold() {<a name="line.1419"></a>
+<span class="sourceLineNo">1420</span> return totalRITsTwiceThreshold > 0;<a name="line.1420"></a>
+<span class="sourceLineNo">1421</span> }<a name="line.1421"></a>
+<span class="sourceLineNo">1422</span><a name="line.1422"></a>
+<span class="sourceLineNo">1423</span> public boolean hasRegionsOverThreshold() {<a name="line.1423"></a>
+<span class="sourceLineNo">1424</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1424"></a>
+<span class="sourceLineNo">1425</span> return m != null && !m.isEmpty();<a name="line.1425"></a>
+<span class="sourceLineNo">1426</span> }<a name="line.1426"></a>
+<span class="sourceLineNo">1427</span><a name="line.1427"></a>
+<span class="sourceLineNo">1428</span> public Collection<RegionState> getRegionOverThreshold() {<a name="line.1428"></a>
+<span class="sourceLineNo">1429</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1429"></a>
+<span class="sourceLineNo">1430</span> return m != null? m.values(): Collections.emptySet();<a name="line.1430"></a>
+<span class="sourceLineNo">1431</span> }<a name="line.1431"></a>
+<span class="sourceLineNo">1432</span><a name="line.1432"></a>
+<span class="sourceLineNo">1433</span> public boolean isRegionOverThreshold(final RegionInfo regionInfo) {<a name="line.1433"></a>
+<span class="sourceLineNo">1434</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1434"></a>
+<span class="sourceLineNo">1435</span> return m != null && m.containsKey(regionInfo.getEncodedName());<a name="line.1435"></a>
+<span class="sourceLineNo">1436</span> }<a name="line.1436"></a>
+<span class="sourceLineNo">1437</span><a name="line.1437"></a>
+<span class="sourceLineNo">1438</span> public boolean isRegionTwiceOverThreshold(final RegionInfo regionInfo) {<a name="line.1438"></a>
+<span class="sourceLineNo">1439</span> Map<String, RegionState> m = this.ritsOverThreshold;<a name="line.1439"></a>
+<span class="sourceLineNo">1440</span> if (m == null) {<a name="line.1440"></a>
+<span class="sourceLineNo">1441</span> return false;<a name="line.1441"></a>
+<span class="sourceLineNo">1442</span> }<a name="line.1442"></a>
+<span class="sourceLineNo">1443</span> final RegionState state = m.get(regionInfo.getEncodedName());<a name="line.1443"></a>
+<span class="sourceLineNo">1444</span> if (state == null) {<a name="line.1444"></a>
+<span class="sourceLineNo">1445</span> return false;<a name="line.1445"></a>
+<span class="sourceLineNo">1446</span> }<a name="line.1446"></a>
+<span class="sourceLineNo">1447</span> return (statTimestamp - state.getStamp()) > (ritThreshold * 2);<a name="line.1447"></a>
+<span class="sourceLineNo">1448</span> }<a name="line.1448"></a>
+<span class="sourceLineNo">1449</span><a name="line.1449"></a>
+<span class="sourceLineNo">1450</span> protected void update(final AssignmentManager am) {<a name="line.1450"></a>
+<span class="sourceLineNo">1451</span> final RegionStates regionStates = am.getRegionStates();<a name="line.1451"></a>
+<span class="sourceLineNo">1452</span> this.statTimestamp = EnvironmentEdgeManager.currentTime();<a name="line.1452"></a>
+<span class="sourceLineNo">1453</span> update(regionStates.getRegionsStateInTransition(), statTimestamp);<a name="line.1453"></a>
+<span class="sourceLineNo">1454</span> update(regionStates.getRegionFailedOpen(), statTimestamp);<a name="line.1454"></a>
+<span class="sourceLineNo">1455</span><a name="line.1455"></a>
+<span class="sourceLineNo">1456</span> if (LOG.isDebugEnabled() && ritsOverThreshold != null && !ritsOverThreshold.isEmpty()) {<a name="line.1456"></a>
+<span class="sourceLineNo">1457</span> LOG.debug("RITs over threshold: {}",<a name="line.1457"></a>
+<span class="sourceLineNo">1458</span> ritsOverThreshold.entrySet().stream()<a name="line.1458"></a>
+<span class="sourceLineNo">1459</span> .map(e -> e.getKey() + ":" + e.getValue().getState().name())<a name="line.1459"></a>
+<span class="sourceLineNo">1460</span> .collect(Collectors.joining("\n")));<a name="line.1460"></a>
+<span class="sourceLineNo">1461</span> }<a name="line.1461"></a>
+<span class="sourceLineNo">1462</span> }<a name="line.1462"></a>
+<span class="sourceLineNo">1463</span><a name="line.1463"></a>
+<span class="sourceLineNo">1464</span> private void update(final Collection<RegionState> regions, final long currentTime) {<a name="line.1464"></a>
+<span class="sourceLineNo">1465</span> for (RegionState state: regions) {<a name="line.1465"></a>
+<span class="sourceLineNo">1466</span> totalRITs++;<a name="line.1466"></a>
+<span class="sourceLineNo">1467</span> final long ritStartedMs = state.getStamp();<a name="line.1467"></a>
+<span class="sourceLineNo">1468</span> if (ritStartedMs == 0) {<a name="line.1468"></a>
+<span class="sourceLineNo">1469</span> // Don't output bogus values to metrics if they accidentally make it here.<a name="line.1469"></a>
+<span class="sourceLineNo">1470</span> LOG.warn("The RIT {} has no start time", state.getRegion());<a name="line.1470"></a>
+<span class="sourceLineNo">1471</span> continue;<a name="line.1471"></a>
+<span class="sourceLineNo">1472</span> }<a name="line.1472"></a>
+<span class="sourceLineNo">1473</span> final long ritTime = currentTime - ritStartedMs;<a name="line.1473"></a>
+<span class="sourceLineNo">1474</span> if (ritTime > ritThreshold) {<a name="line.1474"></a>
+<span class="sourceLineNo">1475</span> if (ritsOverThreshold == null) {<a name="line.1475"></a>
+<span class="sourceLineNo">1476</span> ritsOverThreshold = new HashMap<String, RegionState>();<a name="line.1476"></a>
+<span class="sourceLineNo">1477</span> }<a name="line.1477"></a>
+<span class="sourceLineNo">1478</span> ritsOverThreshold.put(state.getRegion().getEncodedName(), state);<a name="line.1478"></a>
+<span class="sourceLineNo">1479</span> totalRITsTwiceThreshold += (ritTime > (ritThreshold * 2)) ? 1 : 0;<a name="line.1479"></a>
+<span class="sourceLineNo">1480</span> }<a name="line.1480"></a>
+<span class="sourceLineNo">1481</span> if (oldestRITTime < ritTime) {<a name="line.1481"></a>
+<span class="sourceLineNo">1482</span> oldestRITTime = ritTime;<a name="line.1482"></a>
+<span class="sourceLineNo">1483</span> }<a name="line.1483"></a>
+<span class="sourceLineNo">1484</span> }<a name="line.1484"></a>
+<span class="sourceLineNo">1485</span> }<a name="line.1485"></a>
+<span class="sourceLineNo">1486</span> }<a name="line.1486"></a>
+<span class="sourceLineNo">1487</span><a name="line.1487"></a>
+<span class="sourceLineNo">1488</span> private void updateRegionsInTransitionMetrics(final RegionInTransitionStat ritStat) {<a name="line.1488"></a>
+<span class="sourceLineNo">1489</span> metrics.updateRITOldestAge(ritStat.getOldestRITTime());<a name="line.1489"></a>
+<span class="sourceLineNo">1490</span> metrics.updateRITCount(ritStat.getTotalRITs());<a name="line.1490"></a>
+<span class="sourceLineNo">1491</span> metrics.updateRITCountOverThreshold(ritStat.getTotalRITsOverThreshold());<a name="line.1491"></a>
+<span class="sourceLineNo">1492</span> }<a name="line.1492"></a>
+<span class="sourceLineNo">1493</span><a name="line.1493"></a>
+<span class="sourceLineNo">1494</span> private void updateDeadServerRegionMetrics(int deadRegions, int unknownRegions) {<a name="line.1494"></a>
+<span class="sourceLineNo">1495</span> metrics.updateDeadServerOpenRegions(deadRegions);<a name="line.1495"></a>
+<span class="sourceLineNo">1496</span> metrics.updateUnknownServerOpenRegions(unknownRegions);<a name="line.1496"></a>
+<span class="sourceLineNo">1497</span> }<a name="line.1497"></a>
+<span class="sourceLineNo">1498</span><a name="line.1498"></a>
+<span class="sourceLineNo">1499</span> private void handleRegionOverStuckWarningThreshold(final RegionInfo regionInfo) {<a name="line.1499"></a>
+<span class="sourceLineNo">1500</span> final RegionStateNode regionNode = regionStates.getRegionStateNode(regionInfo);<a name="line.1500"></a>
+<span class="sourceLineNo">1501</span> //if (regionNode.isStuck()) {<a name="line.1501"></a>
+<span class="sourceLineNo">1502</span> LOG.warn("STUCK Region-In-Transition {}", regionNode);<a name="line.1502"></a>
+<span class="sourceLineNo">1503</span> }<a name="line.1503"></a>
+<span class="sourceLineNo">1504</span><a name="line.1504"></a>
+<span class="sourceLineNo">1505</span> // ============================================================================================<a name="line.1505"></a>
+<span class="sourceLineNo">1506</span> // TODO: Master load/bootstrap<a name="line.1506"></a>
+<span class="sourceLineNo">1507</span> // ============================================================================================<a name="line.1507"></a>
+<span class="sourceLineNo">1508</span> public void joinCluster() throws IOException {<a name="line.1508"></a>
+<span class="sourceLineNo">1509</span> long startTime = System.nanoTime();<a name="line.1509"></a>
+<span class="sourceLineNo">1510</span> LOG.debug("Joining cluster...");<a name="line.1510"></a>
<span class="sourceLineNo">1511</span><a name="line.1511"></a>
-<span class="sourceLineNo">1512</span> long costMs = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime);<a name="line.1512"></a>
-<span class="sourceLineNo">1513</span> LOG.info("Joined the cluster in {}", StringUtils.humanTimeDiff(costMs));<a name="line.1513"></a>
-<span class="sourceLineNo">1514</span> }<a name="line.1514"></a>
-<span class="sourceLineNo">1515</span><a name="line.1515"></a>
-<span class="sourceLineNo">1516</span> /**<a name="line.1516"></a>
-<span class="sourceLineNo">1517</span> * Create assign procedure for offline regions.<a name="line.1517"></a>
-<span class="sourceLineNo">1518</span> * Just follow the old processofflineServersWithOnlineRegions method. Since now we do not need to<a name="line.1518"></a>
-<span class="sourceLineNo">1519</span> * deal with dead server any more, we only deal with the regions in OFFLINE state in this method.<a name="line.1519"></a>
-<span class="sourceLineNo">1520</span> * And this is a bit strange, that for new regions, we will add it in CLOSED state instead of<a name="line.1520"></a>
-<span class="sourceLineNo">1521</span> * OFFLINE state, and usually there will be a procedure to track them. The<a name="line.1521"></a>
-<span class="sourceLineNo">1522</span> * processofflineServersWithOnlineRegions is a legacy from long ago, as things are going really<a name="line.1522"></a>
-<span class="sourceLineNo">1523</span> * different now, maybe we do not need this method any more. Need to revisit later.<a name="line.1523"></a>
-<span class="sourceLineNo">1524</span> */<a name="line.1524"></a>
-<span class="sourceLineNo">1525</span> // Public so can be run by the Master as part of the startup. Needs hbase:meta to be online.<a name="line.1525"></a>
-<span class="sourceLineNo">1526</span> // Needs to be done after the table state manager has been started.<a name="line.1526"></a>
-<span class="sourceLineNo">1527</span> public void processOfflineRegions() {<a name="line.1527"></a>
-<span class="sourceLineNo">1528</span> TransitRegionStateProcedure[] procs =<a name="line.1528"></a>
-<span class="sourceLineNo">1529</span> regionStates.getRegionStateNodes().stream().filter(rsn -> rsn.isInState(State.OFFLINE))<a name="line.1529"></a>
-<span class="sourceLineNo">1530</span> .filter(rsn -> isTableEnabled(rsn.getRegionInfo().getTable())).map(rsn -> {<a name="line.1530"></a>
-<span class="sourceLineNo">1531</span> rsn.lock();<a name="line.1531"></a>
-<span class="sourceLineNo">1532</span> try {<a name="line.1532"></a>
-<span class="sourceLineNo">1533</span> if (rsn.getProcedure() != null) {<a name="line.1533"></a>
-<span class="sourceLineNo">1534</span> return null;<a name="line.1534"></a>
-<span class="sourceLineNo">1535</span> } else {<a name="line.1535"></a>
-<span class="sourceLineNo">1536</span> return rsn.setProcedure(TransitRegionStateProcedure.assign(getProcedureEnvironment(),<a name="line.1536"></a>
-<span class="sourceLineNo">1537</span> rsn.getRegionInfo(), null));<a name="line.1537"></a>
-<span class="sourceLineNo">1538</span> }<a name="line.1538"></a>
-<span class="sourceLineNo">1539</span> } finally {<a name="line.1539"></a>
-<span class="sourceLineNo">1540</span> rsn.unlock();<a name="line.1540"></a>
-<span class="sourceLineNo">1541</span> }<a name="line.1541"></a>
-<span class="sourceLineNo">1542</span> }).filter(p -> p != null).toArray(TransitRegionStateProcedure[]::new);<a name="line.1542"></a>
-<span class="sourceLineNo">1543</span> if (procs.length > 0) {<a name="line.1543"></a>
-<span class="sourceLineNo">1544</span> master.getMasterProcedureExecutor().submitProcedures(procs);<a name="line.1544"></a>
-<span class="sourceLineNo">1545</span> }<a name="line.1545"></a>
-<span class="sourceLineNo">1546</span> }<a name="line.1546"></a>
-<span class="sourceLineNo">1547</span><a name="line.1547"></a>
-<span class="sourceLineNo">1548</span> /* AM internal RegionStateStore.RegionStateVisitor implementation. To be used when<a name="line.1548"></a>
-<span class="sourceLineNo">1549</span> * scanning META table for region rows, using RegionStateStore utility methods. RegionStateStore<a name="line.1549"></a>
-<span class="sourceLineNo">1550</span> * methods will convert Result into proper RegionInfo instances, but those would still need to be<a name="line.1550"></a>
-<span class="sourceLineNo">1551</span> * added into AssignmentManager.regionStates in-memory cache.<a name="line.1551"></a>
-<span class="sourceLineNo">1552</span> * RegionMetaLoadingVisitor.visitRegionState method provides the logic for adding RegionInfo<a name="line.1552"></a>
-<span class="sourceLineNo">1553</span> * instances as loaded from latest META scan into AssignmentManager.regionStates.<a name="line.1553"></a>
-<span class="sourceLineNo">1554</span> */<a name="line.1554"></a>
-<span class="sourceLineNo">1555</span> private class RegionMetaLoadingVisitor implements RegionStateStore.RegionStateVisitor {<a name="line.1555"></a>
-<span class="sourceLineNo">1556</span><a name="line.1556"></a>
-<span class="sourceLineNo">1557</span> @Override<a name="line.1557"></a>
-<span class="sourceLineNo">1558</span> public void visitRegionState(Result result, final RegionInfo regionInfo, final State state,<a name="line.1558"></a>
-<span class="sourceLineNo">1559</span> final ServerName regionLocation, final ServerName lastHost, final long openSeqNum) {<a name="line.1559"></a>
-<span class="sourceLineNo">1560</span> if (state == null && regionLocation == null && lastHost == null &&<a name="line.1560"></a>
-<span class="sourceLineNo">1561</span> openSeqNum == SequenceId.NO_SEQUENCE_ID) {<a name="line.1561"></a>
-<span class="sourceLineNo">1562</span> // This is a row with nothing in it.<a name="line.1562"></a>
-<span class="sourceLineNo">1563</span> LOG.warn("Skipping empty row={}", result);<a name="line.1563"></a>
-<span class="sourceLineNo">1564</span> return;<a name="line.1564"></a>
-<span class="sourceLineNo">1565</span> }<a name="line.1565"></a>
-<span class="sourceLineNo">1566</span> State localState = state;<a name="line.1566"></a>
-<span class="sourceLineNo">1567</span> if (localState == null) {<a name="line.1567"></a>
-<span class="sourceLineNo">1568</span> // No region state column data in hbase:meta table! Are I doing a rolling upgrade from<a name="line.1568"></a>
-<span class="sourceLineNo">1569</span> // hbase1 to hbase2? Am I restoring a SNAPSHOT or otherwise adding a region to hbase:meta?<a name="line.1569"></a>
-<span class="sourceLineNo">1570</span> // In any of these cases, state is empty. For now, presume OFFLINE but there are probably<a name="line.1570"></a>
-<span class="sourceLineNo">1571</span> // cases where we need to probe more to be sure this correct; TODO informed by experience.<a name="line.1571"></a>
-<span class="sourceLineNo">1572</span> LOG.info(regionInfo.getEncodedName() + " regionState=null; presuming " + State.OFFLINE);<a name="line.1572"></a>
-<span class="sourceLineNo">1573</span> localState = State.OFFLINE;<a name="line.1573"></a>
-<span class="sourceLineNo">1574</span> }<a name="line.1574"></a>
-<span class="sourceLineNo">1575</span> RegionStateNode regionNode = regionStates.getOrCreateRegionStateNode(regionInfo);<a name="line.1575"></a>
-<span class="sourceLineNo">1576</span> // Do not need to lock on regionNode, as we can make sure that before we finish loading<a name="line.1576"></a>
-<span class="sourceLineNo">1577</span> // meta, all the related procedures can not be executed. The only exception is for meta<a name="line.1577"></a>
-<span class="sourceLineNo">1578</span> // region related operations, but here we do not load the informations for meta region.<a name="line.1578"></a>
-<span class="sourceLineNo">1579</span> regionNode.setState(localState);<a name="line.1579"></a>
-<span class="sourceLineNo">1580</span> regionNode.setLastHost(lastHost);<a name="line.1580"></a>
-<span class="sourceLineNo">1581</span> regionNode.setRegionLocation(regionLocation);<a name="line.1581"></a>
-<span class="sourceLineNo">1582</span> regionNode.setOpenSeqNum(openSeqNum);<a name="line.1582"></a>
... 34016 lines suppressed ...