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 2020/07/14 17:51:54 UTC

[hbase-site] branch asf-site updated: Published site at ee226de6080abead6e9b1749f07cfbd274bd89f1.

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 dec12f8  Published site at ee226de6080abead6e9b1749f07cfbd274bd89f1.
dec12f8 is described below

commit dec12f88190b7b780203dfa089882d9066a0415b
Author: jenkins <bu...@apache.org>
AuthorDate: Tue Jul 14 17:51:40 2020 +0000

    Published site at ee226de6080abead6e9b1749f07cfbd274bd89f1.
---
 acid-semantics.html                                |   11 +
 apache_hbase_reference_guide.pdf                   |    4 +-
 book.html                                          |    2 +-
 bulk-loads.html                                    |   11 +
 checkstyle-aggregate.html                          |   39 +-
 coc.html                                           |   11 +
 dependencies.html                                  |   11 +
 dependency-convergence.html                        |   11 +
 dependency-info.html                               |   11 +
 dependency-management.html                         |   11 +
 .../hadoop/hbase/master/MasterMetaBootstrap.html   |    2 +-
 .../ServerManager.FlushedSequenceIdFlusher.html    |    6 +-
 .../master/ServerManager.ServerLiveState.html      |    8 +-
 .../apache/hadoop/hbase/master/ServerManager.html  |  156 +-
 .../hbase/rsgroup/RSGroupInfoManagerImpl.html      |    2 +-
 .../hadoop/hbase/master/MasterMetaBootstrap.html   |  110 +-
 .../ServerManager.FlushedSequenceIdFlusher.html    | 2222 ++++++++++----------
 .../master/ServerManager.ServerLiveState.html      | 2222 ++++++++++----------
 .../apache/hadoop/hbase/master/ServerManager.html  | 2222 ++++++++++----------
 .../RSGroupInfoManagerImpl.RSGroupInfoHolder.html  |   52 +-
 ...SGroupInfoManagerImpl.RSGroupMappingScript.html |   52 +-
 ...SGroupInfoManagerImpl.RSGroupStartupWorker.html |   52 +-
 .../hbase/rsgroup/RSGroupInfoManagerImpl.html      |   52 +-
 downloads.html                                     |   48 +-
 export_control.html                                |   11 +
 index.html                                         |   11 +
 issue-tracking.html                                |   11 +
 mail-lists.html                                    |   11 +
 metrics.html                                       |   11 +
 old_news.html                                      |   11 +
 plugin-management.html                             |   11 +
 plugins.html                                       |   11 +
 poweredbyhbase.html                                |   11 +
 project-info.html                                  |   11 +
 project-reports.html                               |   11 +
 project-summary.html                               |   11 +
 pseudo-distributed.html                            |   11 +
 replication.html                                   |   11 +
 resources.html                                     |   11 +
 source-repository.html                             |   11 +
 sponsors.html                                      |   11 +
 supportingprojects.html                            |   11 +
 team-list.html                                     |   11 +
 testdevapidocs/index-all.html                      |    4 +
 .../apache/hadoop/hbase/backup/package-tree.html   |    2 +-
 .../hadoop/hbase/chaos/actions/package-tree.html   |    2 +-
 .../hbase/client/TestMetaWithReplicasBasic.html    |   34 +-
 .../apache/hadoop/hbase/io/hfile/package-tree.html |    2 +-
 .../org/apache/hadoop/hbase/package-tree.html      |   12 +-
 .../hadoop/hbase/procedure2/package-tree.html      |    4 +-
 .../hadoop/hbase/regionserver/package-tree.html    |    4 +-
 .../hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html   |   66 +-
 .../org/apache/hadoop/hbase/test/package-tree.html |    4 +-
 .../org/apache/hadoop/hbase/wal/package-tree.html  |    2 +-
 .../hbase/client/TestMetaWithReplicasBasic.html    |  149 +-
 .../hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html   | 1082 +++++-----
 56 files changed, 4691 insertions(+), 4213 deletions(-)

diff --git a/acid-semantics.html b/acid-semantics.html
index a7b0979..bef2fb2 100644
--- a/acid-semantics.html
+++ b/acid-semantics.html
@@ -113,6 +113,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/apache_hbase_reference_guide.pdf b/apache_hbase_reference_guide.pdf
index 9e78b13..66116b6 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.0.rc.2, based on Prawn 2.2.2)
 /Producer (Apache HBase Team)
-/ModDate (D:20200714143158+00'00')
-/CreationDate (D:20200714144232+00'00')
+/ModDate (D:20200714173546+00'00')
+/CreationDate (D:20200714174812+00'00')
 >>
 endobj
 2 0 obj
diff --git a/book.html b/book.html
index 0d2b39f..92f4829 100644
--- a/book.html
+++ b/book.html
@@ -45975,7 +45975,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 2020-07-14 14:31:58 UTC
+Last updated 2020-07-14 17:35:46 UTC
 </div>
 </div>
 <script type="text/x-mathjax-config">
diff --git a/bulk-loads.html b/bulk-loads.html
index 03f08e8..f8cd920 100644
--- a/bulk-loads.html
+++ b/bulk-loads.html
@@ -113,6 +113,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/checkstyle-aggregate.html b/checkstyle-aggregate.html
index ae4388c..92cffcf 100644
--- a/checkstyle-aggregate.html
+++ b/checkstyle-aggregate.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
@@ -40614,85 +40625,85 @@
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>212</td></tr>
+<td>213</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>238</td></tr>
+<td>239</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>239</td></tr>
+<td>240</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>359</td></tr>
+<td>360</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>457</td></tr>
+<td>458</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>blocks</td>
 <td>NeedBraces</td>
 <td>'if' construct must use '{}'s.</td>
-<td>551</td></tr>
+<td>552</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>indentation</td>
 <td>Indentation</td>
 <td>'throws' has incorrect indentation level 2, expected level should be 4.</td>
-<td>560</td></tr>
+<td>561</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 107).</td>
-<td>599</td></tr>
+<td>600</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>667</td></tr>
+<td>668</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>javadoc</td>
 <td>NonEmptyAtclauseDescription</td>
 <td>At-clause should have a non-empty description.</td>
-<td>765</td></tr>
+<td>769</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 106).</td>
-<td>794</td></tr>
+<td>798</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 106).</td>
-<td>807</td></tr>
+<td>811</td></tr>
 <tr class="b">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 107).</td>
-<td>808</td></tr>
+<td>812</td></tr>
 <tr class="a">
 <td><img src="images/icon_error_sml.gif" alt="" />&#160;Error</td>
 <td>sizes</td>
 <td>LineLength</td>
 <td>Line is longer than 100 characters (found 103).</td>
-<td>830</td></tr></table></div>
+<td>834</td></tr></table></div>
 <div class="section">
 <h3 id="org.apache.hadoop.hbase.master.SnapshotOfRegionAssignmentFromMeta.java">org/apache/hadoop/hbase/master/SnapshotOfRegionAssignmentFromMeta.java</h3>
 <table border="0" class="table table-striped">
diff --git a/coc.html b/coc.html
index 7a511f4..4f2cebe 100644
--- a/coc.html
+++ b/coc.html
@@ -113,6 +113,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/dependencies.html b/dependencies.html
index 0592bec..18db652 100644
--- a/dependencies.html
+++ b/dependencies.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/dependency-convergence.html b/dependency-convergence.html
index 5cb99b6..6ad3b9d 100644
--- a/dependency-convergence.html
+++ b/dependency-convergence.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/dependency-info.html b/dependency-info.html
index 14d32de..e7d3fa2 100644
--- a/dependency-info.html
+++ b/dependency-info.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/dependency-management.html b/dependency-management.html
index e08e205..a104c41 100644
--- a/dependency-management.html
+++ b/dependency-management.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/devapidocs/org/apache/hadoop/hbase/master/MasterMetaBootstrap.html b/devapidocs/org/apache/hadoop/hbase/master/MasterMetaBootstrap.html
index f934dc1..c4d627a 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/MasterMetaBootstrap.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/MasterMetaBootstrap.html
@@ -273,7 +273,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>unassignExcessMetaReplica</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/MasterMetaBootstrap.html#line.92">unassignExcessMetaReplica</a>(int&nbsp;numMetaReplicasConfigured)</pre>
+<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/MasterMetaBootstrap.html#line.88">unassignExcessMetaReplica</a>(int&nbsp;numMetaReplicasConfigured)</pre>
 </li>
 </ul>
 </li>
diff --git a/devapidocs/org/apache/hadoop/hbase/master/ServerManager.FlushedSequenceIdFlusher.html b/devapidocs/org/apache/hadoop/hbase/master/ServerManager.FlushedSequenceIdFlusher.html
index 9689502..7afe808 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/ServerManager.FlushedSequenceIdFlusher.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/ServerManager.FlushedSequenceIdFlusher.html
@@ -122,7 +122,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>private class <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.1157">ServerManager.FlushedSequenceIdFlusher</a>
+<pre>private class <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.1161">ServerManager.FlushedSequenceIdFlusher</a>
 extends <a href="../../../../../org/apache/hadoop/hbase/ScheduledChore.html" title="class in org.apache.hadoop.hbase">ScheduledChore</a></pre>
 </li>
 </ul>
@@ -201,7 +201,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/ScheduledChore.html" tit
 <ul class="blockListLast">
 <li class="blockList">
 <h4>FlushedSequenceIdFlusher</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.FlushedSequenceIdFlusher.html#line.1159">FlushedSequenceIdFlusher</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>&nbsp;name,
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.FlushedSequenceIdFlusher.html#line.1163">FlushedSequenceIdFlusher</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>&nbsp;name,
                                 int&nbsp;p)</pre>
 </li>
 </ul>
@@ -219,7 +219,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/ScheduledChore.html" tit
 <ul class="blockListLast">
 <li class="blockList">
 <h4>chore</h4>
-<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.FlushedSequenceIdFlusher.html#line.1164">chore</a>()</pre>
+<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.FlushedSequenceIdFlusher.html#line.1168">chore</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from class:&nbsp;<code><a href="../../../../../org/apache/hadoop/hbase/ScheduledChore.html#chore--">ScheduledChore</a></code></span></div>
 <div class="block">The task to execute on each scheduled execution of the Chore</div>
 <dl>
diff --git a/devapidocs/org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html b/devapidocs/org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html
index e2810ab..c8f7ee5 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html
@@ -122,7 +122,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>public static enum <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.879">ServerManager.ServerLiveState</a>
+<pre>public static enum <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.883">ServerManager.ServerLiveState</a>
 extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang">Enum</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html" title="enum in org.apache.hadoop.hbase.master">ServerManager.ServerLiveState</a>&gt;</pre>
 </li>
 </ul>
@@ -213,7 +213,7 @@ the order they are declared.</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>LIVE</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html" title="enum in org.apache.hadoop.hbase.master">ServerManager.ServerLiveState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html#line.880">LIVE</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html" title="enum in org.apache.hadoop.hbase.master">ServerManager.ServerLiveState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html#line.884">LIVE</a></pre>
 </li>
 </ul>
 <a name="DEAD">
@@ -222,7 +222,7 @@ the order they are declared.</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>DEAD</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html" title="enum in org.apache.hadoop.hbase.master">ServerManager.ServerLiveState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html#line.881">DEAD</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html" title="enum in org.apache.hadoop.hbase.master">ServerManager.ServerLiveState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html#line.885">DEAD</a></pre>
 </li>
 </ul>
 <a name="UNKNOWN">
@@ -231,7 +231,7 @@ the order they are declared.</div>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>UNKNOWN</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html" title="enum in org.apache.hadoop.hbase.master">ServerManager.ServerLiveState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html#line.882">UNKNOWN</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html" title="enum in org.apache.hadoop.hbase.master">ServerManager.ServerLiveState</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html#line.886">UNKNOWN</a></pre>
 </li>
 </ul>
 </li>
diff --git a/devapidocs/org/apache/hadoop/hbase/master/ServerManager.html b/devapidocs/org/apache/hadoop/hbase/master/ServerManager.html
index 48d0c5d..74fda36 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/ServerManager.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/ServerManager.html
@@ -110,7 +110,7 @@ var activeTableTab = "activeTableTab";
 <hr>
 <br>
 <pre>@InterfaceAudience.Private
-public class <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.105">ServerManager</a>
+public class <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.106">ServerManager</a>
 extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a></pre>
 <div class="block">The ServerManager class manages info about region servers.
  <p>
@@ -637,7 +637,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>WAIT_ON_REGIONSERVERS_MAXTOSTART</h4>
-<pre>public static final&nbsp;<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/ServerManager.html#line.106">WAIT_ON_REGIONSERVERS_MAXTOSTART</a></pre>
+<pre>public static final&nbsp;<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/ServerManager.html#line.107">WAIT_ON_REGIONSERVERS_MAXTOSTART</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.master.ServerManager.WAIT_ON_REGIONSERVERS_MAXTOSTART">Constant Field Values</a></dd>
@@ -650,7 +650,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>WAIT_ON_REGIONSERVERS_MINTOSTART</h4>
-<pre>public static final&nbsp;<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/ServerManager.html#line.109">WAIT_ON_REGIONSERVERS_MINTOSTART</a></pre>
+<pre>public static final&nbsp;<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/ServerManager.html#line.110">WAIT_ON_REGIONSERVERS_MINTOSTART</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.master.ServerManager.WAIT_ON_REGIONSERVERS_MINTOSTART">Constant Field Values</a></dd>
@@ -663,7 +663,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>WAIT_ON_REGIONSERVERS_TIMEOUT</h4>
-<pre>public static final&nbsp;<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/ServerManager.html#line.112">WAIT_ON_REGIONSERVERS_TIMEOUT</a></pre>
+<pre>public static final&nbsp;<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/ServerManager.html#line.113">WAIT_ON_REGIONSERVERS_TIMEOUT</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.master.ServerManager.WAIT_ON_REGIONSERVERS_TIMEOUT">Constant Field Values</a></dd>
@@ -676,7 +676,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>WAIT_ON_REGIONSERVERS_INTERVAL</h4>
-<pre>public static final&nbsp;<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/ServerManager.html#line.115">WAIT_ON_REGIONSERVERS_INTERVAL</a></pre>
+<pre>public static final&nbsp;<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/ServerManager.html#line.116">WAIT_ON_REGIONSERVERS_INTERVAL</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.master.ServerManager.WAIT_ON_REGIONSERVERS_INTERVAL">Constant Field Values</a></dd>
@@ -689,7 +689,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>PERSIST_FLUSHEDSEQUENCEID</h4>
-<pre>public static final&nbsp;<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/ServerManager.html#line.123">PERSIST_FLUSHEDSEQUENCEID</a></pre>
+<pre>public static final&nbsp;<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/ServerManager.html#line.124">PERSIST_FLUSHEDSEQUENCEID</a></pre>
 <div class="block">see HBASE-20727
  if set to true, flushedSequenceIdByRegion and storeFlushedSequenceIdsByRegion
  will be persisted to HDFS and loaded when master restart to speed up log split</div>
@@ -705,7 +705,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>PERSIST_FLUSHEDSEQUENCEID_DEFAULT</h4>
-<pre>public static final&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.126">PERSIST_FLUSHEDSEQUENCEID_DEFAULT</a></pre>
+<pre>public static final&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.127">PERSIST_FLUSHEDSEQUENCEID_DEFAULT</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.master.ServerManager.PERSIST_FLUSHEDSEQUENCEID_DEFAULT">Constant Field Values</a></dd>
@@ -718,7 +718,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>FLUSHEDSEQUENCEID_FLUSHER_INTERVAL</h4>
-<pre>public static final&nbsp;<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/ServerManager.html#line.128">FLUSHEDSEQUENCEID_FLUSHER_INTERVAL</a></pre>
+<pre>public static final&nbsp;<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/ServerManager.html#line.129">FLUSHEDSEQUENCEID_FLUSHER_INTERVAL</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.master.ServerManager.FLUSHEDSEQUENCEID_FLUSHER_INTERVAL">Constant Field Values</a></dd>
@@ -731,7 +731,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>FLUSHEDSEQUENCEID_FLUSHER_INTERVAL_DEFAULT</h4>
-<pre>public static final&nbsp;int <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.131">FLUSHEDSEQUENCEID_FLUSHER_INTERVAL_DEFAULT</a></pre>
+<pre>public static final&nbsp;int <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.132">FLUSHEDSEQUENCEID_FLUSHER_INTERVAL_DEFAULT</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.master.ServerManager.FLUSHEDSEQUENCEID_FLUSHER_INTERVAL_DEFAULT">Constant Field Values</a></dd>
@@ -744,7 +744,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>MAX_CLOCK_SKEW_MS</h4>
-<pre>public static final&nbsp;<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/ServerManager.html#line.134">MAX_CLOCK_SKEW_MS</a></pre>
+<pre>public static final&nbsp;<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/ServerManager.html#line.135">MAX_CLOCK_SKEW_MS</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.master.ServerManager.MAX_CLOCK_SKEW_MS">Constant Field Values</a></dd>
@@ -757,7 +757,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>LOG</h4>
-<pre>private static final&nbsp;org.slf4j.Logger <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.136">LOG</a></pre>
+<pre>private static final&nbsp;org.slf4j.Logger <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.137">LOG</a></pre>
 </li>
 </ul>
 <a name="clusterShutdown">
@@ -766,7 +766,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>clusterShutdown</h4>
-<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicBoolean.html?is-external=true" title="class or interface in java.util.concurrent.atomic">AtomicBoolean</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.139">clusterShutdown</a></pre>
+<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/atomic/AtomicBoolean.html?is-external=true" title="class or interface in java.util.concurrent.atomic">AtomicBoolean</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.140">clusterShutdown</a></pre>
 </li>
 </ul>
 <a name="flushedSequenceIdByRegion">
@@ -775,7 +775,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>flushedSequenceIdByRegion</h4>
-<pre>private final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentNavigableMap.html?is-external=true" title="class or interface in java.util.concurrent">ConcurrentNavigableMap</a>&lt;byte[],<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html?is-external=true" title="class or interface in java.lang">Long</a>&gt; <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.144">flushedSequenceIdByRegion</ [...]
+<pre>private final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentNavigableMap.html?is-external=true" title="class or interface in java.util.concurrent">ConcurrentNavigableMap</a>&lt;byte[],<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html?is-external=true" title="class or interface in java.lang">Long</a>&gt; <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.145">flushedSequenceIdByRegion</ [...]
 <div class="block">The last flushed sequence id for a region.</div>
 </li>
 </ul>
@@ -785,7 +785,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>persistFlushedSequenceId</h4>
-<pre>private&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.147">persistFlushedSequenceId</a></pre>
+<pre>private&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.148">persistFlushedSequenceId</a></pre>
 </li>
 </ul>
 <a name="isFlushSeqIdPersistInProgress">
@@ -794,7 +794,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>isFlushSeqIdPersistInProgress</h4>
-<pre>private volatile&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.148">isFlushSeqIdPersistInProgress</a></pre>
+<pre>private volatile&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.149">isFlushSeqIdPersistInProgress</a></pre>
 </li>
 </ul>
 <a name="LAST_FLUSHED_SEQ_ID_FILE">
@@ -803,7 +803,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>LAST_FLUSHED_SEQ_ID_FILE</h4>
-<pre>private static final&nbsp;<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/ServerManager.html#line.150">LAST_FLUSHED_SEQ_ID_FILE</a></pre>
+<pre>private static final&nbsp;<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/ServerManager.html#line.151">LAST_FLUSHED_SEQ_ID_FILE</a></pre>
 <div class="block">File on hdfs to store last flushed sequence id of regions</div>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
@@ -817,7 +817,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>flushedSeqIdFlusher</h4>
-<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/master/ServerManager.FlushedSequenceIdFlusher.html" title="class in org.apache.hadoop.hbase.master">ServerManager.FlushedSequenceIdFlusher</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.151">flushedSeqIdFlusher</a></pre>
+<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/master/ServerManager.FlushedSequenceIdFlusher.html" title="class in org.apache.hadoop.hbase.master">ServerManager.FlushedSequenceIdFlusher</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.152">flushedSeqIdFlusher</a></pre>
 </li>
 </ul>
 <a name="storeFlushedSequenceIdsByRegion">
@@ -826,7 +826,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>storeFlushedSequenceIdsByRegion</h4>
-<pre>private final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentNavigableMap.html?is-external=true" title="class or interface in java.util.concurrent">ConcurrentNavigableMap</a>&lt;byte[],<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentNavigableMap.html?is-external=true" title="class or interface in java.util.concurrent">ConcurrentNavigableMap</a>&lt;byte[],<a href="https://docs.oracle.com/javase/8/docs/api/java/ [...]
+<pre>private final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentNavigableMap.html?is-external=true" title="class or interface in java.util.concurrent">ConcurrentNavigableMap</a>&lt;byte[],<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentNavigableMap.html?is-external=true" title="class or interface in java.util.concurrent">ConcurrentNavigableMap</a>&lt;byte[],<a href="https://docs.oracle.com/javase/8/docs/api/java/ [...]
 <div class="block">The last flushed sequence id for a store in a region.</div>
 </li>
 </ul>
@@ -836,7 +836,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>onlineServers</h4>
-<pre>private final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentNavigableMap.html?is-external=true" title="class or interface in java.util.concurrent">ConcurrentNavigableMap</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>,<a href="../../../../../org/apache/hadoop/hbase/ServerMetrics.html" title="interface in org.apache.hadoop.hbase">ServerMetrics</a>&gt; <a href="../. [...]
+<pre>private final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentNavigableMap.html?is-external=true" title="class or interface in java.util.concurrent">ConcurrentNavigableMap</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>,<a href="../../../../../org/apache/hadoop/hbase/ServerMetrics.html" title="interface in org.apache.hadoop.hbase">ServerMetrics</a>&gt; <a href="../. [...]
 <div class="block">Map of registered servers to their current load</div>
 </li>
 </ul>
@@ -846,7 +846,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>drainingServers</h4>
-<pre>private final&nbsp;<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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&gt; <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.165">drainingServers</a></pre>
+<pre>private final&nbsp;<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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&gt; <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.166">drainingServers</a></pre>
 <div class="block">List of region servers that should not get any more new regions.</div>
 </li>
 </ul>
@@ -856,7 +856,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>master</h4>
-<pre>private final&nbsp;<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/ServerManager.html#line.167">master</a></pre>
+<pre>private final&nbsp;<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/ServerManager.html#line.168">master</a></pre>
 </li>
 </ul>
 <a name="deadservers">
@@ -865,7 +865,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>deadservers</h4>
-<pre>private final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/master/DeadServer.html" title="class in org.apache.hadoop.hbase.master">DeadServer</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.169">deadservers</a></pre>
+<pre>private final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/master/DeadServer.html" title="class in org.apache.hadoop.hbase.master">DeadServer</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.170">deadservers</a></pre>
 </li>
 </ul>
 <a name="maxSkew">
@@ -874,7 +874,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>maxSkew</h4>
-<pre>private final&nbsp;long <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.171">maxSkew</a></pre>
+<pre>private final&nbsp;long <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.172">maxSkew</a></pre>
 </li>
 </ul>
 <a name="warningSkew">
@@ -883,7 +883,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>warningSkew</h4>
-<pre>private final&nbsp;long <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.172">warningSkew</a></pre>
+<pre>private final&nbsp;long <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.173">warningSkew</a></pre>
 </li>
 </ul>
 <a name="listeners">
@@ -892,7 +892,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>listeners</h4>
-<pre>private&nbsp;<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>&lt;<a href="../../../../../org/apache/hadoop/hbase/master/ServerListener.html" title="interface in org.apache.hadoop.hbase.master">ServerListener</a>&gt; <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.175">listeners</a></pre>
+<pre>private&nbsp;<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>&lt;<a href="../../../../../org/apache/hadoop/hbase/master/ServerListener.html" title="interface in org.apache.hadoop.hbase.master">ServerListener</a>&gt; <a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.176">listeners</a></pre>
 <div class="block">Listeners that are called on server events.</div>
 </li>
 </ul>
@@ -910,7 +910,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>ServerManager</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.180">ServerManager</a>(<a href="../../../../../org/apache/hadoop/hbase/master/MasterServices.html" title="interface in org.apache.hadoop.hbase.master">MasterServices</a>&nbsp;master)</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.181">ServerManager</a>(<a href="../../../../../org/apache/hadoop/hbase/master/MasterServices.html" title="interface in org.apache.hadoop.hbase.master">MasterServices</a>&nbsp;master)</pre>
 <div class="block">Constructor.</div>
 </li>
 </ul>
@@ -928,7 +928,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>registerListener</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.193">registerListener</a>(<a href="../../../../../org/apache/hadoop/hbase/master/ServerListener.html" title="interface in org.apache.hadoop.hbase.master">ServerListener</a>&nbsp;listener)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.194">registerListener</a>(<a href="../../../../../org/apache/hadoop/hbase/master/ServerListener.html" title="interface in org.apache.hadoop.hbase.master">ServerListener</a>&nbsp;listener)</pre>
 <div class="block">Add the listener to the notification list.</div>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
@@ -942,7 +942,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>unregisterListener</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.201">unregisterListener</a>(<a href="../../../../../org/apache/hadoop/hbase/master/ServerListener.html" title="interface in org.apache.hadoop.hbase.master">ServerListener</a>&nbsp;listener)</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.202">unregisterListener</a>(<a href="../../../../../org/apache/hadoop/hbase/master/ServerListener.html" title="interface in org.apache.hadoop.hbase.master">ServerListener</a>&nbsp;listener)</pre>
 <div class="block">Remove the listener from the notification list.</div>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
@@ -956,7 +956,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>regionServerStartup</h4>
-<pre><a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.214">regionServerStartup</a>(org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest&nbsp;request,
+<pre><a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.215">regionServerStartup</a>(org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest&nbsp;request,
                                int&nbsp;versionNumber,
                                <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>&nbsp;version,
                                <a href="https://docs.oracle.com/javase/8/docs/api/java/net/InetAddress.html?is-external=true" title="class or interface in java.net">InetAddress</a>&nbsp;ia)
@@ -981,7 +981,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>updateLastFlushedSequenceIds</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.241">updateLastFlushedSequenceIds</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;sn,
+<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.242">updateLastFlushedSequenceIds</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;sn,
                                           <a href="../../../../../org/apache/hadoop/hbase/ServerMetrics.html" title="interface in org.apache.hadoop.hbase">ServerMetrics</a>&nbsp;hsl)</pre>
 <div class="block">Updates last flushed sequence Ids for the regions on server sn</div>
 <dl>
@@ -997,7 +997,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>regionServerReport</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.278">regionServerReport</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;sn,
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.279">regionServerReport</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;sn,
                                <a href="../../../../../org/apache/hadoop/hbase/ServerMetrics.html" title="interface in org.apache.hadoop.hbase">ServerMetrics</a>&nbsp;sl)
                         throws <a href="../../../../../org/apache/hadoop/hbase/YouAreDeadException.html" title="class in org.apache.hadoop.hbase">YouAreDeadException</a></pre>
 <dl>
@@ -1012,7 +1012,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>checkAndRecordNewServer</h4>
-<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.304">checkAndRecordNewServer</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName,
+<pre>boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.305">checkAndRecordNewServer</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName,
                                 <a href="../../../../../org/apache/hadoop/hbase/ServerMetrics.html" title="interface in org.apache.hadoop.hbase">ServerMetrics</a>&nbsp;sl)</pre>
 <div class="block">Check is a server of same host and port already exists,
  if not, or the existed one got a smaller start code, record it.</div>
@@ -1031,7 +1031,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>findDeadServersAndProcess</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.347">findDeadServersAndProcess</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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&gt;&nbsp;deadServersFromPE,
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.348">findDeadServersAndProcess</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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&gt;&nbsp;deadServersFromPE,
                                <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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&gt;&nbsp;liveServersFromWALDir)</pre>
 <div class="block">Find out the region servers crashed between the crash of the previous master instance and the
  current master instance and schedule SCP for them.
@@ -1055,7 +1055,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>checkClockSkew</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.362">checkClockSkew</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName,
+<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.363">checkClockSkew</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName,
                             long&nbsp;serverCurrentTime)
                      throws <a href="../../../../../org/apache/hadoop/hbase/ClockOutOfSyncException.html" title="class in org.apache.hadoop.hbase">ClockOutOfSyncException</a></pre>
 <div class="block">Checks if the clock skew between the server and the master. If the clock skew exceeds the
@@ -1076,7 +1076,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>checkIsDead</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.387">checkIsDead</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName,
+<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.388">checkIsDead</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName,
                          <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>&nbsp;what)
                   throws <a href="../../../../../org/apache/hadoop/hbase/YouAreDeadException.html" title="class in org.apache.hadoop.hbase">YouAreDeadException</a></pre>
 <div class="block">Called when RegionServer first reports in for duty and thereafter each
@@ -1098,7 +1098,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>findServerWithSameHostnamePortWithLock</h4>
-<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.411">findServerWithSameHostnamePortWithLock</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
+<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.412">findServerWithSameHostnamePortWithLock</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
 <div class="block">Assumes onlineServers is locked.</div>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
@@ -1112,7 +1112,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>recordNewServerWithLock</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.430">recordNewServerWithLock</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName,
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.431">recordNewServerWithLock</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName,
                              <a href="../../../../../org/apache/hadoop/hbase/ServerMetrics.html" title="interface in org.apache.hadoop.hbase">ServerMetrics</a>&nbsp;sl)</pre>
 <div class="block">Adds the onlineServers list. onlineServers should be locked.</div>
 <dl>
@@ -1127,7 +1127,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getFlushedSequenceIdByRegion</h4>
-<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentNavigableMap.html?is-external=true" title="class or interface in java.util.concurrent">ConcurrentNavigableMap</a>&lt;byte[],<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html?is-external=true" title="class or interface in java.lang">Long</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.436">getFlushedSequenceIdByRegion< [...]
+<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentNavigableMap.html?is-external=true" title="class or interface in java.util.concurrent">ConcurrentNavigableMap</a>&lt;byte[],<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Long.html?is-external=true" title="class or interface in java.lang">Long</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.437">getFlushedSequenceIdByRegion< [...]
 </li>
 </ul>
 <a name="getLastFlushedSequenceId-byte:A-">
@@ -1136,7 +1136,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getLastFlushedSequenceId</h4>
-<pre>public&nbsp;org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.RegionStoreSequenceIds&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.440">getLastFlushedSequenceId</a>(byte[]&nbsp;encodedRegionName)</pre>
+<pre>public&nbsp;org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.RegionStoreSequenceIds&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.441">getLastFlushedSequenceId</a>(byte[]&nbsp;encodedRegionName)</pre>
 </li>
 </ul>
 <a name="getLoad-org.apache.hadoop.hbase.ServerName-">
@@ -1145,7 +1145,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getLoad</h4>
-<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/ServerMetrics.html" title="interface in org.apache.hadoop.hbase">ServerMetrics</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.460">getLoad</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
+<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/ServerMetrics.html" title="interface in org.apache.hadoop.hbase">ServerMetrics</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.461">getLoad</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>serverName</code> - </dd>
@@ -1160,7 +1160,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&nbsp;double&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.470">getAverageLoad</a>()</pre>
+<pre>public&nbsp;double&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.471">getAverageLoad</a>()</pre>
 <div class="block">Compute the average load across all region servers.
  Currently, this uses a very naive computation - just uses the number of
  regions being served, ignoring stats about number of requests.</div>
@@ -1176,7 +1176,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>countOfRegionServers</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.482">countOfRegionServers</a>()</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.483">countOfRegionServers</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>the count of active regionservers</dd>
@@ -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>getOnlineServers</h4>
-<pre>public&nbsp;<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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>,<a href="../../../../../org/apache/hadoop/hbase/ServerMetrics.html" title="interface in org.apache.hadoop.hbase">ServerMetrics</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManag [...]
+<pre>public&nbsp;<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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>,<a href="../../../../../org/apache/hadoop/hbase/ServerMetrics.html" title="interface in org.apache.hadoop.hbase">ServerMetrics</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManag [...]
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>Read-only map of servers to serverinfo</dd>
@@ -1202,7 +1202,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getDeadServers</h4>
-<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/master/DeadServer.html" title="class in org.apache.hadoop.hbase.master">DeadServer</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.497">getDeadServers</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/master/DeadServer.html" title="class in org.apache.hadoop.hbase.master">DeadServer</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.498">getDeadServers</a>()</pre>
 </li>
 </ul>
 <a name="areDeadServersInProgress--">
@@ -1211,7 +1211,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>areDeadServersInProgress</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.505">areDeadServersInProgress</a>()</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.506">areDeadServersInProgress</a>()</pre>
 <div class="block">Checks if any dead servers are currently in progress.</div>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
@@ -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>letRegionServersShutdown</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.509">letRegionServersShutdown</a>()</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.510">letRegionServersShutdown</a>()</pre>
 </li>
 </ul>
 <a name="getRegionServersInZK-org.apache.hadoop.hbase.zookeeper.ZKWatcher-">
@@ -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>getRegionServersInZK</h4>
-<pre>private&nbsp;<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>&lt;<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>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.559">getRegionServersInZK</a>(<a href="../../../../../org/apache/hadoop/hbase/zookeeper/ZKWatc [...]
+<pre>private&nbsp;<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>&lt;<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>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.560">getRegionServersInZK</a>(<a href="../../../../../org/apache/hadoop/hbase/zookeeper/ZKWatc [...]
                                    throws org.apache.zookeeper.KeeperException</pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -1248,7 +1248,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>expireServer</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.572">expireServer</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.573">expireServer</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
 <div class="block">Expire the passed server. Add it to list of dead servers and queue a shutdown processing.</div>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
@@ -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>expireServer</h4>
-<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.577">expireServer</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName,
+<pre>long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.578">expireServer</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName,
                   boolean&nbsp;force)</pre>
 </li>
 </ul>
@@ -1275,7 +1275,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>moveFromOnlineToDeadServers</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.631">moveFromOnlineToDeadServers</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;sn)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.632">moveFromOnlineToDeadServers</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;sn)</pre>
 <div class="block">Called when server has expired.</div>
 </li>
 </ul>
@@ -1285,7 +1285,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>removeServerFromDrainList</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.653">removeServerFromDrainList</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;sn)</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.654">removeServerFromDrainList</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;sn)</pre>
 </li>
 </ul>
 <a name="addServerToDrainList-org.apache.hadoop.hbase.ServerName-">
@@ -1294,7 +1294,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>addServerToDrainList</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.670">addServerToDrainList</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;sn)</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.671">addServerToDrainList</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;sn)</pre>
 <div class="block">Add the server to the drain list.</div>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
@@ -1310,7 +1310,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>closeRegionSilentlyAndWait</h4>
-<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.695">closeRegionSilentlyAndWait</a>(<a href="../../../../../org/apache/hadoop/hbase/client/AsyncClusterConnection.html" title="interface in org.apache.hadoop.hbase.client">AsyncClusterConnection</a>&nbsp;connection,
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.696">closeRegionSilentlyAndWait</a>(<a href="../../../../../org/apache/hadoop/hbase/client/AsyncClusterConnection.html" title="interface in org.apache.hadoop.hbase.client">AsyncClusterConnection</a>&nbsp;connection,
                                               <a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;server,
                                               <a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>&nbsp;region,
                                               long&nbsp;timeout)
@@ -1332,7 +1332,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getMinToStart</h4>
-<pre>private&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.735">getMinToStart</a>()</pre>
+<pre>private&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.739">getMinToStart</a>()</pre>
 <div class="block">Calculate min necessary to start. This is not an absolute. It is just
  a friction that will cause us hang around a bit longer waiting on
  RegionServers to check-in.</div>
@@ -1344,7 +1344,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>waitForRegionServers</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.767">waitForRegionServers</a>(<a href="../../../../../org/apache/hadoop/hbase/monitoring/MonitoredTask.html" title="interface in org.apache.hadoop.hbase.monitoring">MonitoredTask</a>&nbsp;status)
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.771">waitForRegionServers</a>(<a href="../../../../../org/apache/hadoop/hbase/monitoring/MonitoredTask.html" title="interface in org.apache.hadoop.hbase.monitoring">MonitoredTask</a>&nbsp;status)
                           throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InterruptedException.html?is-external=true" title="class or interface in java.lang">InterruptedException</a></pre>
 <div class="block">Wait for the region servers to report in.
  We will wait until one of this condition is met:
@@ -1367,7 +1367,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getStrForMax</h4>
-<pre>private&nbsp;<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>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.834">getStrForMax</a>(int&nbsp;max)</pre>
+<pre>private&nbsp;<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>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.838">getStrForMax</a>(int&nbsp;max)</pre>
 </li>
 </ul>
 <a name="getOnlineServersList--">
@@ -1376,7 +1376,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getOnlineServersList</h4>
-<pre>public&nbsp;<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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.841">getOnlineServersList</a>()</pre>
+<pre>public&nbsp;<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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.845">getOnlineServersList</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>A copy of the internal list of online servers.</dd>
@@ -1389,7 +1389,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getOnlineServersListWithPredicator</h4>
-<pre>public&nbsp;<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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.852">getOnlineServersListWithPredicator</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?i [...]
+<pre>public&nbsp;<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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.856">getOnlineServersListWithPredicator</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?i [...]
                                                            <a href="https://docs.oracle.com/javase/8/docs/api/java/util/function/Predicate.html?is-external=true" title="class or interface in java.util.function">Predicate</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerMetrics.html" title="interface in org.apache.hadoop.hbase">ServerMetrics</a>&gt;&nbsp;idleServerPredicator)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
@@ -1406,7 +1406,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getDrainingServersList</h4>
-<pre>public&nbsp;<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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.871">getDrainingServersList</a>()</pre>
+<pre>public&nbsp;<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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.875">getDrainingServersList</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>A copy of the internal list of draining servers.</dd>
@@ -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>isServerOnline</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.875">isServerOnline</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.879">isServerOnline</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
 </li>
 </ul>
 <a name="isServerKnownAndOnline-org.apache.hadoop.hbase.ServerName-">
@@ -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>isServerKnownAndOnline</h4>
-<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html" title="enum in org.apache.hadoop.hbase.master">ServerManager.ServerLiveState</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.888">isServerKnownAndOnline</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
+<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html" title="enum in org.apache.hadoop.hbase.master">ServerManager.ServerLiveState</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.892">isServerKnownAndOnline</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>whether the server is online, dead, or unknown.</dd>
@@ -1441,7 +1441,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>isServerDead</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.899">isServerDead</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.903">isServerDead</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
 <div class="block">Check if a server is known to be dead.  A server can be online,
  or known to be dead, or unknown to this manager (i.e, not online,
  not known to be dead either; it is simply not tracked by the
@@ -1454,7 +1454,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>shutdownCluster</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.903">shutdownCluster</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.907">shutdownCluster</a>()</pre>
 </li>
 </ul>
 <a name="isClusterShutdown--">
@@ -1463,7 +1463,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>isClusterShutdown</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.913">isClusterShutdown</a>()</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.917">isClusterShutdown</a>()</pre>
 </li>
 </ul>
 <a name="startChore--">
@@ -1472,7 +1472,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>startChore</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.920">startChore</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.924">startChore</a>()</pre>
 <div class="block">start chore in ServerManager</div>
 </li>
 </ul>
@@ -1482,7 +1482,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>stop</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.936">stop</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.940">stop</a>()</pre>
 <div class="block">Stop the ServerManager.</div>
 </li>
 </ul>
@@ -1492,7 +1492,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>createDestinationServersList</h4>
-<pre>public&nbsp;<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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.955">createDestinationServersList</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-exte [...]
+<pre>public&nbsp;<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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.959">createDestinationServersList</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-exte [...]
 <div class="block">Creates a list of possible destinations for a region. It contains the online servers, but not
   the draining or dying servers.</div>
 <dl>
@@ -1507,7 +1507,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>createDestinationServersList</h4>
-<pre>public&nbsp;<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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.972">createDestinationServersList</a>()</pre>
+<pre>public&nbsp;<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>&lt;<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.976">createDestinationServersList</a>()</pre>
 <div class="block">Calls <a href="../../../../../org/apache/hadoop/hbase/master/ServerManager.html#createDestinationServersList-java.util.List-"><code>createDestinationServersList(java.util.List&lt;org.apache.hadoop.hbase.ServerName&gt;)</code></a> without server to exclude.</div>
 </li>
 </ul>
@@ -1517,7 +1517,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>clearDeadServersWithSameHostNameAndPortOfOnlineServer</h4>
-<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.979">clearDeadServersWithSameHostNameAndPortOfOnlineServer</a>()</pre>
+<pre>void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.983">clearDeadServersWithSameHostNameAndPortOfOnlineServer</a>()</pre>
 <div class="block">To clear any dead server with same host name and port of any online server</div>
 </li>
 </ul>
@@ -1527,7 +1527,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>removeRegion</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.988">removeRegion</a>(<a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>&nbsp;regionInfo)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.992">removeRegion</a>(<a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>&nbsp;regionInfo)</pre>
 <div class="block">Called by delete table and similar to notify the ServerManager that a region was removed.</div>
 </li>
 </ul>
@@ -1537,7 +1537,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>isRegionInServerManagerStates</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.995">isRegionInServerManagerStates</a>(<a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>&nbsp;hri)</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.999">isRegionInServerManagerStates</a>(<a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>&nbsp;hri)</pre>
 </li>
 </ul>
 <a name="removeRegions-java.util.List-">
@@ -1546,7 +1546,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>removeRegions</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.1004">removeRegions</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>&lt;<a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>&gt;&nbsp;regions)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.1008">removeRegions</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>&lt;<a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>&gt;&nbsp;regions)</pre>
 <div class="block">Called by delete table and similar to notify the ServerManager that a region was removed.</div>
 </li>
 </ul>
@@ -1556,7 +1556,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getVersionNumber</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.1013">getVersionNumber</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.1017">getVersionNumber</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
 <div class="block">May return 0 when server is not online.</div>
 </li>
 </ul>
@@ -1566,7 +1566,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getVersion</h4>
-<pre>public&nbsp;<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>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.1021">getVersion</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
+<pre>public&nbsp;<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>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.1025">getVersion</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
 <div class="block">May return "0.0.0" when server is not online</div>
 </li>
 </ul>
@@ -1576,7 +1576,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getInfoPort</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.1026">getInfoPort</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.1030">getInfoPort</a>(<a href="../../../../../org/apache/hadoop/hbase/ServerName.html" title="class in org.apache.hadoop.hbase">ServerName</a>&nbsp;serverName)</pre>
 </li>
 </ul>
 <a name="persistRegionLastFlushedSequenceIds--">
@@ -1585,7 +1585,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>persistRegionLastFlushedSequenceIds</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.1035">persistRegionLastFlushedSequenceIds</a>()
+<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.1039">persistRegionLastFlushedSequenceIds</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">Persist last flushed sequence id of each region to HDFS</div>
 <dl>
@@ -1600,7 +1600,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>loadLastFlushedSequenceIds</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.1092">loadLastFlushedSequenceIds</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.1096">loadLastFlushedSequenceIds</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">Load last flushed sequence id of each region from HDFS, if persisted</div>
 <dl>
@@ -1615,7 +1615,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>removeDeletedRegionFromLoadedFlushedSequenceIds</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.1145">removeDeletedRegionFromLoadedFlushedSequenceIds</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/master/ServerManager.html#line.1149">removeDeletedRegionFromLoadedFlushedSequenceIds</a>()</pre>
 <div class="block">Regions may have been removed between latest persist of FlushedSequenceIds
  and master abort. So after loading FlushedSequenceIds from file, and after
  meta loaded, we need to remove the deleted region according to RegionStates.</div>
diff --git a/devapidocs/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.html b/devapidocs/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.html
index 5540283..1fd785d 100644
--- a/devapidocs/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.html
+++ b/devapidocs/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.html
@@ -1439,7 +1439,7 @@ implements <a href="../../../../../org/apache/hadoop/hbase/rsgroup/RSGroupInfoMa
 <ul class="blockListLast">
 <li class="blockList">
 <h4>updateRSGroupConfig</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.html#line.1248">updateRSGroupConfig</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>&nbsp;groupName,
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.html#line.1252">updateRSGroupConfig</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>&nbsp;groupName,
                                 <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>&lt;<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="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&gt;&nbsp;configuration)
                          throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from interface:&nbsp;<code><a href="../../../../../org/apache/hadoop/hbase/rsgroup/RSGroupInfoManager.html#updateRSGroupConfig-java.lang.String-java.util.Map-">RSGroupInfoManager</a></code></span></div>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/master/MasterMetaBootstrap.html b/devapidocs/src-html/org/apache/hadoop/hbase/master/MasterMetaBootstrap.html
index 7d30304..8aa11be 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/master/MasterMetaBootstrap.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/master/MasterMetaBootstrap.html
@@ -64,63 +64,59 @@
 <span class="sourceLineNo">056</span>      throws IOException, InterruptedException, KeeperException {<a name="line.56"></a>
 <span class="sourceLineNo">057</span>    int numReplicas = master.getConfiguration().getInt(HConstants.META_REPLICAS_NUM,<a name="line.57"></a>
 <span class="sourceLineNo">058</span>           HConstants.DEFAULT_META_REPLICA_NUM);<a name="line.58"></a>
-<span class="sourceLineNo">059</span>    if (numReplicas &lt;= 1) {<a name="line.59"></a>
-<span class="sourceLineNo">060</span>      // No replicaas to assign. Return.<a name="line.60"></a>
-<span class="sourceLineNo">061</span>      return;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>    }<a name="line.62"></a>
-<span class="sourceLineNo">063</span>    final AssignmentManager assignmentManager = master.getAssignmentManager();<a name="line.63"></a>
-<span class="sourceLineNo">064</span>    if (!assignmentManager.isMetaLoaded()) {<a name="line.64"></a>
-<span class="sourceLineNo">065</span>      throw new IllegalStateException("hbase:meta must be initialized first before we can " +<a name="line.65"></a>
-<span class="sourceLineNo">066</span>          "assign out its replicas");<a name="line.66"></a>
-<span class="sourceLineNo">067</span>    }<a name="line.67"></a>
-<span class="sourceLineNo">068</span>    ServerName metaServername = MetaTableLocator.getMetaRegionLocation(this.master.getZooKeeper());<a name="line.68"></a>
-<span class="sourceLineNo">069</span>    for (int i = 1; i &lt; numReplicas; i++) {<a name="line.69"></a>
-<span class="sourceLineNo">070</span>      // Get current meta state for replica from zk.<a name="line.70"></a>
-<span class="sourceLineNo">071</span>      RegionState metaState = MetaTableLocator.getMetaRegionState(master.getZooKeeper(), i);<a name="line.71"></a>
-<span class="sourceLineNo">072</span>      RegionInfo hri = RegionReplicaUtil.getRegionInfoForReplica(<a name="line.72"></a>
-<span class="sourceLineNo">073</span>          RegionInfoBuilder.FIRST_META_REGIONINFO, i);<a name="line.73"></a>
-<span class="sourceLineNo">074</span>      LOG.debug(hri.getRegionNameAsString() + " replica region state from zookeeper=" + metaState);<a name="line.74"></a>
-<span class="sourceLineNo">075</span>      if (metaServername.equals(metaState.getServerName())) {<a name="line.75"></a>
-<span class="sourceLineNo">076</span>        metaState = null;<a name="line.76"></a>
-<span class="sourceLineNo">077</span>        LOG.info(hri.getRegionNameAsString() +<a name="line.77"></a>
-<span class="sourceLineNo">078</span>          " old location is same as current hbase:meta location; setting location as null...");<a name="line.78"></a>
-<span class="sourceLineNo">079</span>      }<a name="line.79"></a>
-<span class="sourceLineNo">080</span>      // These assigns run inline. All is blocked till they complete. Only interrupt is shutting<a name="line.80"></a>
-<span class="sourceLineNo">081</span>      // down hosting server which calls AM#stop.<a name="line.81"></a>
-<span class="sourceLineNo">082</span>      if (metaState != null &amp;&amp; metaState.getServerName() != null) {<a name="line.82"></a>
-<span class="sourceLineNo">083</span>        // Try to retain old assignment.<a name="line.83"></a>
-<span class="sourceLineNo">084</span>        assignmentManager.assignAsync(hri, metaState.getServerName());<a name="line.84"></a>
-<span class="sourceLineNo">085</span>      } else {<a name="line.85"></a>
-<span class="sourceLineNo">086</span>        assignmentManager.assignAsync(hri);<a name="line.86"></a>
-<span class="sourceLineNo">087</span>      }<a name="line.87"></a>
-<span class="sourceLineNo">088</span>    }<a name="line.88"></a>
-<span class="sourceLineNo">089</span>    unassignExcessMetaReplica(numReplicas);<a name="line.89"></a>
-<span class="sourceLineNo">090</span>  }<a name="line.90"></a>
-<span class="sourceLineNo">091</span><a name="line.91"></a>
-<span class="sourceLineNo">092</span>  private void unassignExcessMetaReplica(int numMetaReplicasConfigured) {<a name="line.92"></a>
-<span class="sourceLineNo">093</span>    final ZKWatcher zooKeeper = master.getZooKeeper();<a name="line.93"></a>
-<span class="sourceLineNo">094</span>    // unassign the unneeded replicas (for e.g., if the previous master was configured<a name="line.94"></a>
-<span class="sourceLineNo">095</span>    // with a replication of 3 and now it is 2, we need to unassign the 1 unneeded replica)<a name="line.95"></a>
-<span class="sourceLineNo">096</span>    try {<a name="line.96"></a>
-<span class="sourceLineNo">097</span>      List&lt;String&gt; metaReplicaZnodes = zooKeeper.getMetaReplicaNodes();<a name="line.97"></a>
-<span class="sourceLineNo">098</span>      for (String metaReplicaZnode : metaReplicaZnodes) {<a name="line.98"></a>
-<span class="sourceLineNo">099</span>        int replicaId = zooKeeper.getZNodePaths().getMetaReplicaIdFromZnode(metaReplicaZnode);<a name="line.99"></a>
-<span class="sourceLineNo">100</span>        if (replicaId &gt;= numMetaReplicasConfigured) {<a name="line.100"></a>
-<span class="sourceLineNo">101</span>          RegionState r = MetaTableLocator.getMetaRegionState(zooKeeper, replicaId);<a name="line.101"></a>
-<span class="sourceLineNo">102</span>          LOG.info("Closing excess replica of meta region " + r.getRegion());<a name="line.102"></a>
-<span class="sourceLineNo">103</span>          // send a close and wait for a max of 30 seconds<a name="line.103"></a>
-<span class="sourceLineNo">104</span>          ServerManager.closeRegionSilentlyAndWait(master.getAsyncClusterConnection(),<a name="line.104"></a>
-<span class="sourceLineNo">105</span>              r.getServerName(), r.getRegion(), 30000);<a name="line.105"></a>
-<span class="sourceLineNo">106</span>          ZKUtil.deleteNode(zooKeeper, zooKeeper.getZNodePaths().getZNodeForReplica(replicaId));<a name="line.106"></a>
-<span class="sourceLineNo">107</span>        }<a name="line.107"></a>
-<span class="sourceLineNo">108</span>      }<a name="line.108"></a>
-<span class="sourceLineNo">109</span>    } catch (Exception ex) {<a name="line.109"></a>
-<span class="sourceLineNo">110</span>      // ignore the exception since we don't want the master to be wedged due to potential<a name="line.110"></a>
-<span class="sourceLineNo">111</span>      // issues in the cleanup of the extra regions. We can do that cleanup via hbck or manually<a name="line.111"></a>
-<span class="sourceLineNo">112</span>      LOG.warn("Ignoring exception " + ex);<a name="line.112"></a>
-<span class="sourceLineNo">113</span>    }<a name="line.113"></a>
-<span class="sourceLineNo">114</span>  }<a name="line.114"></a>
-<span class="sourceLineNo">115</span>}<a name="line.115"></a>
+<span class="sourceLineNo">059</span>    final AssignmentManager assignmentManager = master.getAssignmentManager();<a name="line.59"></a>
+<span class="sourceLineNo">060</span>    if (!assignmentManager.isMetaLoaded()) {<a name="line.60"></a>
+<span class="sourceLineNo">061</span>      throw new IllegalStateException("hbase:meta must be initialized first before we can " +<a name="line.61"></a>
+<span class="sourceLineNo">062</span>          "assign out its replicas");<a name="line.62"></a>
+<span class="sourceLineNo">063</span>    }<a name="line.63"></a>
+<span class="sourceLineNo">064</span>    ServerName metaServername = MetaTableLocator.getMetaRegionLocation(this.master.getZooKeeper());<a name="line.64"></a>
+<span class="sourceLineNo">065</span>    for (int i = 1; i &lt; numReplicas; i++) {<a name="line.65"></a>
+<span class="sourceLineNo">066</span>      // Get current meta state for replica from zk.<a name="line.66"></a>
+<span class="sourceLineNo">067</span>      RegionState metaState = MetaTableLocator.getMetaRegionState(master.getZooKeeper(), i);<a name="line.67"></a>
+<span class="sourceLineNo">068</span>      RegionInfo hri = RegionReplicaUtil.getRegionInfoForReplica(<a name="line.68"></a>
+<span class="sourceLineNo">069</span>          RegionInfoBuilder.FIRST_META_REGIONINFO, i);<a name="line.69"></a>
+<span class="sourceLineNo">070</span>      LOG.debug(hri.getRegionNameAsString() + " replica region state from zookeeper=" + metaState);<a name="line.70"></a>
+<span class="sourceLineNo">071</span>      if (metaServername.equals(metaState.getServerName())) {<a name="line.71"></a>
+<span class="sourceLineNo">072</span>        metaState = null;<a name="line.72"></a>
+<span class="sourceLineNo">073</span>        LOG.info(hri.getRegionNameAsString() +<a name="line.73"></a>
+<span class="sourceLineNo">074</span>          " old location is same as current hbase:meta location; setting location as null...");<a name="line.74"></a>
+<span class="sourceLineNo">075</span>      }<a name="line.75"></a>
+<span class="sourceLineNo">076</span>      // These assigns run inline. All is blocked till they complete. Only interrupt is shutting<a name="line.76"></a>
+<span class="sourceLineNo">077</span>      // down hosting server which calls AM#stop.<a name="line.77"></a>
+<span class="sourceLineNo">078</span>      if (metaState != null &amp;&amp; metaState.getServerName() != null) {<a name="line.78"></a>
+<span class="sourceLineNo">079</span>        // Try to retain old assignment.<a name="line.79"></a>
+<span class="sourceLineNo">080</span>        assignmentManager.assignAsync(hri, metaState.getServerName());<a name="line.80"></a>
+<span class="sourceLineNo">081</span>      } else {<a name="line.81"></a>
+<span class="sourceLineNo">082</span>        assignmentManager.assignAsync(hri);<a name="line.82"></a>
+<span class="sourceLineNo">083</span>      }<a name="line.83"></a>
+<span class="sourceLineNo">084</span>    }<a name="line.84"></a>
+<span class="sourceLineNo">085</span>    unassignExcessMetaReplica(numReplicas);<a name="line.85"></a>
+<span class="sourceLineNo">086</span>  }<a name="line.86"></a>
+<span class="sourceLineNo">087</span><a name="line.87"></a>
+<span class="sourceLineNo">088</span>  private void unassignExcessMetaReplica(int numMetaReplicasConfigured) {<a name="line.88"></a>
+<span class="sourceLineNo">089</span>    final ZKWatcher zooKeeper = master.getZooKeeper();<a name="line.89"></a>
+<span class="sourceLineNo">090</span>    // unassign the unneeded replicas (for e.g., if the previous master was configured<a name="line.90"></a>
+<span class="sourceLineNo">091</span>    // with a replication of 3 and now it is 2, we need to unassign the 1 unneeded replica)<a name="line.91"></a>
+<span class="sourceLineNo">092</span>    try {<a name="line.92"></a>
+<span class="sourceLineNo">093</span>      List&lt;String&gt; metaReplicaZnodes = zooKeeper.getMetaReplicaNodes();<a name="line.93"></a>
+<span class="sourceLineNo">094</span>      for (String metaReplicaZnode : metaReplicaZnodes) {<a name="line.94"></a>
+<span class="sourceLineNo">095</span>        int replicaId = zooKeeper.getZNodePaths().getMetaReplicaIdFromZnode(metaReplicaZnode);<a name="line.95"></a>
+<span class="sourceLineNo">096</span>        if (replicaId &gt;= numMetaReplicasConfigured) {<a name="line.96"></a>
+<span class="sourceLineNo">097</span>          RegionState r = MetaTableLocator.getMetaRegionState(zooKeeper, replicaId);<a name="line.97"></a>
+<span class="sourceLineNo">098</span>          LOG.info("Closing excess replica of meta region " + r.getRegion());<a name="line.98"></a>
+<span class="sourceLineNo">099</span>          // send a close and wait for a max of 30 seconds<a name="line.99"></a>
+<span class="sourceLineNo">100</span>          ServerManager.closeRegionSilentlyAndWait(master.getAsyncClusterConnection(),<a name="line.100"></a>
+<span class="sourceLineNo">101</span>              r.getServerName(), r.getRegion(), 30000);<a name="line.101"></a>
+<span class="sourceLineNo">102</span>          ZKUtil.deleteNode(zooKeeper, zooKeeper.getZNodePaths().getZNodeForReplica(replicaId));<a name="line.102"></a>
+<span class="sourceLineNo">103</span>        }<a name="line.103"></a>
+<span class="sourceLineNo">104</span>      }<a name="line.104"></a>
+<span class="sourceLineNo">105</span>    } catch (Exception ex) {<a name="line.105"></a>
+<span class="sourceLineNo">106</span>      // ignore the exception since we don't want the master to be wedged due to potential<a name="line.106"></a>
+<span class="sourceLineNo">107</span>      // issues in the cleanup of the extra regions. We can do that cleanup via hbck or manually<a name="line.107"></a>
+<span class="sourceLineNo">108</span>      LOG.warn("Ignoring exception " + ex);<a name="line.108"></a>
+<span class="sourceLineNo">109</span>    }<a name="line.109"></a>
+<span class="sourceLineNo">110</span>  }<a name="line.110"></a>
+<span class="sourceLineNo">111</span>}<a name="line.111"></a>
 
 
 
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/master/ServerManager.FlushedSequenceIdFlusher.html b/devapidocs/src-html/org/apache/hadoop/hbase/master/ServerManager.FlushedSequenceIdFlusher.html
index 7f98dd8..99dd552 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/master/ServerManager.FlushedSequenceIdFlusher.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/master/ServerManager.FlushedSequenceIdFlusher.html
@@ -59,1126 +59,1130 @@
 <span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.client.AsyncClusterConnection;<a name="line.51"></a>
 <span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.client.AsyncRegionServerAdmin;<a name="line.52"></a>
 <span class="sourceLineNo">053</span>import org.apache.hadoop.hbase.client.RegionInfo;<a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.apache.hadoop.hbase.master.assignment.RegionStates;<a name="line.54"></a>
-<span class="sourceLineNo">055</span>import org.apache.hadoop.hbase.monitoring.MonitoredTask;<a name="line.55"></a>
-<span class="sourceLineNo">056</span>import org.apache.hadoop.hbase.procedure2.Procedure;<a name="line.56"></a>
-<span class="sourceLineNo">057</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.57"></a>
-<span class="sourceLineNo">058</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.58"></a>
-<span class="sourceLineNo">059</span>import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;<a name="line.59"></a>
-<span class="sourceLineNo">060</span>import org.apache.hadoop.hbase.util.FutureUtils;<a name="line.60"></a>
-<span class="sourceLineNo">061</span>import org.apache.hadoop.hbase.zookeeper.ZKUtil;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>import org.apache.hadoop.hbase.zookeeper.ZKWatcher;<a name="line.62"></a>
-<span class="sourceLineNo">063</span>import org.apache.hadoop.hbase.zookeeper.ZNodePaths;<a name="line.63"></a>
-<span class="sourceLineNo">064</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.64"></a>
-<span class="sourceLineNo">065</span>import org.apache.zookeeper.KeeperException;<a name="line.65"></a>
-<span class="sourceLineNo">066</span>import org.slf4j.Logger;<a name="line.66"></a>
-<span class="sourceLineNo">067</span>import org.slf4j.LoggerFactory;<a name="line.67"></a>
-<span class="sourceLineNo">068</span><a name="line.68"></a>
-<span class="sourceLineNo">069</span>import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;<a name="line.69"></a>
-<span class="sourceLineNo">070</span>import org.apache.hbase.thirdparty.com.google.protobuf.ByteString;<a name="line.70"></a>
-<span class="sourceLineNo">071</span>import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations;<a name="line.71"></a>
-<span class="sourceLineNo">072</span><a name="line.72"></a>
-<span class="sourceLineNo">073</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.73"></a>
-<span class="sourceLineNo">074</span>import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter;<a name="line.74"></a>
-<span class="sourceLineNo">075</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.RegionStoreSequenceIds;<a name="line.75"></a>
-<span class="sourceLineNo">076</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.StoreSequenceId;<a name="line.76"></a>
-<span class="sourceLineNo">077</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedRegionSequenceId;<a name="line.77"></a>
-<span class="sourceLineNo">078</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedSequenceId;<a name="line.78"></a>
-<span class="sourceLineNo">079</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedStoreSequenceId;<a name="line.79"></a>
-<span class="sourceLineNo">080</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest;<a name="line.80"></a>
-<span class="sourceLineNo">081</span><a name="line.81"></a>
-<span class="sourceLineNo">082</span>/**<a name="line.82"></a>
-<span class="sourceLineNo">083</span> * The ServerManager class manages info about region servers.<a name="line.83"></a>
-<span class="sourceLineNo">084</span> * &lt;p&gt;<a name="line.84"></a>
-<span class="sourceLineNo">085</span> * Maintains lists of online and dead servers.  Processes the startups,<a name="line.85"></a>
-<span class="sourceLineNo">086</span> * shutdowns, and deaths of region servers.<a name="line.86"></a>
-<span class="sourceLineNo">087</span> * &lt;p&gt;<a name="line.87"></a>
-<span class="sourceLineNo">088</span> * Servers are distinguished in two different ways.  A given server has a<a name="line.88"></a>
-<span class="sourceLineNo">089</span> * location, specified by hostname and port, and of which there can only be one<a name="line.89"></a>
-<span class="sourceLineNo">090</span> * online at any given time.  A server instance is specified by the location<a name="line.90"></a>
-<span class="sourceLineNo">091</span> * (hostname and port) as well as the startcode (timestamp from when the server<a name="line.91"></a>
-<span class="sourceLineNo">092</span> * was started).  This is used to differentiate a restarted instance of a given<a name="line.92"></a>
-<span class="sourceLineNo">093</span> * server from the original instance.<a name="line.93"></a>
-<span class="sourceLineNo">094</span> * &lt;p&gt;<a name="line.94"></a>
-<span class="sourceLineNo">095</span> * If a sever is known not to be running any more, it is called dead. The dead<a name="line.95"></a>
-<span class="sourceLineNo">096</span> * server needs to be handled by a ServerShutdownHandler.  If the handler is not<a name="line.96"></a>
-<span class="sourceLineNo">097</span> * enabled yet, the server can't be handled right away so it is queued up.<a name="line.97"></a>
-<span class="sourceLineNo">098</span> * After the handler is enabled, the server will be submitted to a handler to handle.<a name="line.98"></a>
-<span class="sourceLineNo">099</span> * However, the handler may be just partially enabled.  If so,<a name="line.99"></a>
-<span class="sourceLineNo">100</span> * the server cannot be fully processed, and be queued up for further processing.<a name="line.100"></a>
-<span class="sourceLineNo">101</span> * A server is fully processed only after the handler is fully enabled<a name="line.101"></a>
-<span class="sourceLineNo">102</span> * and has completed the handling.<a name="line.102"></a>
-<span class="sourceLineNo">103</span> */<a name="line.103"></a>
-<span class="sourceLineNo">104</span>@InterfaceAudience.Private<a name="line.104"></a>
-<span class="sourceLineNo">105</span>public class ServerManager {<a name="line.105"></a>
-<span class="sourceLineNo">106</span>  public static final String WAIT_ON_REGIONSERVERS_MAXTOSTART =<a name="line.106"></a>
-<span class="sourceLineNo">107</span>      "hbase.master.wait.on.regionservers.maxtostart";<a name="line.107"></a>
-<span class="sourceLineNo">108</span><a name="line.108"></a>
-<span class="sourceLineNo">109</span>  public static final String WAIT_ON_REGIONSERVERS_MINTOSTART =<a name="line.109"></a>
-<span class="sourceLineNo">110</span>      "hbase.master.wait.on.regionservers.mintostart";<a name="line.110"></a>
-<span class="sourceLineNo">111</span><a name="line.111"></a>
-<span class="sourceLineNo">112</span>  public static final String WAIT_ON_REGIONSERVERS_TIMEOUT =<a name="line.112"></a>
-<span class="sourceLineNo">113</span>      "hbase.master.wait.on.regionservers.timeout";<a name="line.113"></a>
-<span class="sourceLineNo">114</span><a name="line.114"></a>
-<span class="sourceLineNo">115</span>  public static final String WAIT_ON_REGIONSERVERS_INTERVAL =<a name="line.115"></a>
-<span class="sourceLineNo">116</span>      "hbase.master.wait.on.regionservers.interval";<a name="line.116"></a>
-<span class="sourceLineNo">117</span><a name="line.117"></a>
-<span class="sourceLineNo">118</span>  /**<a name="line.118"></a>
-<span class="sourceLineNo">119</span>   * see HBASE-20727<a name="line.119"></a>
-<span class="sourceLineNo">120</span>   * if set to true, flushedSequenceIdByRegion and storeFlushedSequenceIdsByRegion<a name="line.120"></a>
-<span class="sourceLineNo">121</span>   * will be persisted to HDFS and loaded when master restart to speed up log split<a name="line.121"></a>
-<span class="sourceLineNo">122</span>   */<a name="line.122"></a>
-<span class="sourceLineNo">123</span>  public static final String PERSIST_FLUSHEDSEQUENCEID =<a name="line.123"></a>
-<span class="sourceLineNo">124</span>      "hbase.master.persist.flushedsequenceid.enabled";<a name="line.124"></a>
-<span class="sourceLineNo">125</span><a name="line.125"></a>
-<span class="sourceLineNo">126</span>  public static final boolean PERSIST_FLUSHEDSEQUENCEID_DEFAULT = true;<a name="line.126"></a>
-<span class="sourceLineNo">127</span><a name="line.127"></a>
-<span class="sourceLineNo">128</span>  public static final String FLUSHEDSEQUENCEID_FLUSHER_INTERVAL =<a name="line.128"></a>
-<span class="sourceLineNo">129</span>      "hbase.master.flushedsequenceid.flusher.interval";<a name="line.129"></a>
-<span class="sourceLineNo">130</span><a name="line.130"></a>
-<span class="sourceLineNo">131</span>  public static final int FLUSHEDSEQUENCEID_FLUSHER_INTERVAL_DEFAULT =<a name="line.131"></a>
-<span class="sourceLineNo">132</span>      3 * 60 * 60 * 1000; // 3 hours<a name="line.132"></a>
-<span class="sourceLineNo">133</span><a name="line.133"></a>
-<span class="sourceLineNo">134</span>  public static final String MAX_CLOCK_SKEW_MS = "hbase.master.maxclockskew";<a name="line.134"></a>
-<span class="sourceLineNo">135</span><a name="line.135"></a>
-<span class="sourceLineNo">136</span>  private static final Logger LOG = LoggerFactory.getLogger(ServerManager.class);<a name="line.136"></a>
-<span class="sourceLineNo">137</span><a name="line.137"></a>
-<span class="sourceLineNo">138</span>  // Set if we are to shutdown the cluster.<a name="line.138"></a>
-<span class="sourceLineNo">139</span>  private AtomicBoolean clusterShutdown = new AtomicBoolean(false);<a name="line.139"></a>
-<span class="sourceLineNo">140</span><a name="line.140"></a>
-<span class="sourceLineNo">141</span>  /**<a name="line.141"></a>
-<span class="sourceLineNo">142</span>   * The last flushed sequence id for a region.<a name="line.142"></a>
-<span class="sourceLineNo">143</span>   */<a name="line.143"></a>
-<span class="sourceLineNo">144</span>  private final ConcurrentNavigableMap&lt;byte[], Long&gt; flushedSequenceIdByRegion =<a name="line.144"></a>
-<span class="sourceLineNo">145</span>    new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.145"></a>
-<span class="sourceLineNo">146</span><a name="line.146"></a>
-<span class="sourceLineNo">147</span>  private boolean persistFlushedSequenceId = true;<a name="line.147"></a>
-<span class="sourceLineNo">148</span>  private volatile boolean isFlushSeqIdPersistInProgress = false;<a name="line.148"></a>
-<span class="sourceLineNo">149</span>  /** File on hdfs to store last flushed sequence id of regions */<a name="line.149"></a>
-<span class="sourceLineNo">150</span>  private static final String LAST_FLUSHED_SEQ_ID_FILE = ".lastflushedseqids";<a name="line.150"></a>
-<span class="sourceLineNo">151</span>  private  FlushedSequenceIdFlusher flushedSeqIdFlusher;<a name="line.151"></a>
-<span class="sourceLineNo">152</span><a name="line.152"></a>
+<span class="sourceLineNo">054</span>import org.apache.hadoop.hbase.ipc.RemoteWithExtrasException;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>import org.apache.hadoop.hbase.master.assignment.RegionStates;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>import org.apache.hadoop.hbase.monitoring.MonitoredTask;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>import org.apache.hadoop.hbase.procedure2.Procedure;<a name="line.57"></a>
+<span class="sourceLineNo">058</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.58"></a>
+<span class="sourceLineNo">059</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.59"></a>
+<span class="sourceLineNo">060</span>import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;<a name="line.60"></a>
+<span class="sourceLineNo">061</span>import org.apache.hadoop.hbase.util.FutureUtils;<a name="line.61"></a>
+<span class="sourceLineNo">062</span>import org.apache.hadoop.hbase.zookeeper.ZKUtil;<a name="line.62"></a>
+<span class="sourceLineNo">063</span>import org.apache.hadoop.hbase.zookeeper.ZKWatcher;<a name="line.63"></a>
+<span class="sourceLineNo">064</span>import org.apache.hadoop.hbase.zookeeper.ZNodePaths;<a name="line.64"></a>
+<span class="sourceLineNo">065</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.65"></a>
+<span class="sourceLineNo">066</span>import org.apache.zookeeper.KeeperException;<a name="line.66"></a>
+<span class="sourceLineNo">067</span>import org.slf4j.Logger;<a name="line.67"></a>
+<span class="sourceLineNo">068</span>import org.slf4j.LoggerFactory;<a name="line.68"></a>
+<span class="sourceLineNo">069</span><a name="line.69"></a>
+<span class="sourceLineNo">070</span>import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;<a name="line.70"></a>
+<span class="sourceLineNo">071</span>import org.apache.hbase.thirdparty.com.google.protobuf.ByteString;<a name="line.71"></a>
+<span class="sourceLineNo">072</span>import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations;<a name="line.72"></a>
+<span class="sourceLineNo">073</span><a name="line.73"></a>
+<span class="sourceLineNo">074</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.74"></a>
+<span class="sourceLineNo">075</span>import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter;<a name="line.75"></a>
+<span class="sourceLineNo">076</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.RegionStoreSequenceIds;<a name="line.76"></a>
+<span class="sourceLineNo">077</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.StoreSequenceId;<a name="line.77"></a>
+<span class="sourceLineNo">078</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedRegionSequenceId;<a name="line.78"></a>
+<span class="sourceLineNo">079</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedSequenceId;<a name="line.79"></a>
+<span class="sourceLineNo">080</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedStoreSequenceId;<a name="line.80"></a>
+<span class="sourceLineNo">081</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest;<a name="line.81"></a>
+<span class="sourceLineNo">082</span><a name="line.82"></a>
+<span class="sourceLineNo">083</span>/**<a name="line.83"></a>
+<span class="sourceLineNo">084</span> * The ServerManager class manages info about region servers.<a name="line.84"></a>
+<span class="sourceLineNo">085</span> * &lt;p&gt;<a name="line.85"></a>
+<span class="sourceLineNo">086</span> * Maintains lists of online and dead servers.  Processes the startups,<a name="line.86"></a>
+<span class="sourceLineNo">087</span> * shutdowns, and deaths of region servers.<a name="line.87"></a>
+<span class="sourceLineNo">088</span> * &lt;p&gt;<a name="line.88"></a>
+<span class="sourceLineNo">089</span> * Servers are distinguished in two different ways.  A given server has a<a name="line.89"></a>
+<span class="sourceLineNo">090</span> * location, specified by hostname and port, and of which there can only be one<a name="line.90"></a>
+<span class="sourceLineNo">091</span> * online at any given time.  A server instance is specified by the location<a name="line.91"></a>
+<span class="sourceLineNo">092</span> * (hostname and port) as well as the startcode (timestamp from when the server<a name="line.92"></a>
+<span class="sourceLineNo">093</span> * was started).  This is used to differentiate a restarted instance of a given<a name="line.93"></a>
+<span class="sourceLineNo">094</span> * server from the original instance.<a name="line.94"></a>
+<span class="sourceLineNo">095</span> * &lt;p&gt;<a name="line.95"></a>
+<span class="sourceLineNo">096</span> * If a sever is known not to be running any more, it is called dead. The dead<a name="line.96"></a>
+<span class="sourceLineNo">097</span> * server needs to be handled by a ServerShutdownHandler.  If the handler is not<a name="line.97"></a>
+<span class="sourceLineNo">098</span> * enabled yet, the server can't be handled right away so it is queued up.<a name="line.98"></a>
+<span class="sourceLineNo">099</span> * After the handler is enabled, the server will be submitted to a handler to handle.<a name="line.99"></a>
+<span class="sourceLineNo">100</span> * However, the handler may be just partially enabled.  If so,<a name="line.100"></a>
+<span class="sourceLineNo">101</span> * the server cannot be fully processed, and be queued up for further processing.<a name="line.101"></a>
+<span class="sourceLineNo">102</span> * A server is fully processed only after the handler is fully enabled<a name="line.102"></a>
+<span class="sourceLineNo">103</span> * and has completed the handling.<a name="line.103"></a>
+<span class="sourceLineNo">104</span> */<a name="line.104"></a>
+<span class="sourceLineNo">105</span>@InterfaceAudience.Private<a name="line.105"></a>
+<span class="sourceLineNo">106</span>public class ServerManager {<a name="line.106"></a>
+<span class="sourceLineNo">107</span>  public static final String WAIT_ON_REGIONSERVERS_MAXTOSTART =<a name="line.107"></a>
+<span class="sourceLineNo">108</span>      "hbase.master.wait.on.regionservers.maxtostart";<a name="line.108"></a>
+<span class="sourceLineNo">109</span><a name="line.109"></a>
+<span class="sourceLineNo">110</span>  public static final String WAIT_ON_REGIONSERVERS_MINTOSTART =<a name="line.110"></a>
+<span class="sourceLineNo">111</span>      "hbase.master.wait.on.regionservers.mintostart";<a name="line.111"></a>
+<span class="sourceLineNo">112</span><a name="line.112"></a>
+<span class="sourceLineNo">113</span>  public static final String WAIT_ON_REGIONSERVERS_TIMEOUT =<a name="line.113"></a>
+<span class="sourceLineNo">114</span>      "hbase.master.wait.on.regionservers.timeout";<a name="line.114"></a>
+<span class="sourceLineNo">115</span><a name="line.115"></a>
+<span class="sourceLineNo">116</span>  public static final String WAIT_ON_REGIONSERVERS_INTERVAL =<a name="line.116"></a>
+<span class="sourceLineNo">117</span>      "hbase.master.wait.on.regionservers.interval";<a name="line.117"></a>
+<span class="sourceLineNo">118</span><a name="line.118"></a>
+<span class="sourceLineNo">119</span>  /**<a name="line.119"></a>
+<span class="sourceLineNo">120</span>   * see HBASE-20727<a name="line.120"></a>
+<span class="sourceLineNo">121</span>   * if set to true, flushedSequenceIdByRegion and storeFlushedSequenceIdsByRegion<a name="line.121"></a>
+<span class="sourceLineNo">122</span>   * will be persisted to HDFS and loaded when master restart to speed up log split<a name="line.122"></a>
+<span class="sourceLineNo">123</span>   */<a name="line.123"></a>
+<span class="sourceLineNo">124</span>  public static final String PERSIST_FLUSHEDSEQUENCEID =<a name="line.124"></a>
+<span class="sourceLineNo">125</span>      "hbase.master.persist.flushedsequenceid.enabled";<a name="line.125"></a>
+<span class="sourceLineNo">126</span><a name="line.126"></a>
+<span class="sourceLineNo">127</span>  public static final boolean PERSIST_FLUSHEDSEQUENCEID_DEFAULT = true;<a name="line.127"></a>
+<span class="sourceLineNo">128</span><a name="line.128"></a>
+<span class="sourceLineNo">129</span>  public static final String FLUSHEDSEQUENCEID_FLUSHER_INTERVAL =<a name="line.129"></a>
+<span class="sourceLineNo">130</span>      "hbase.master.flushedsequenceid.flusher.interval";<a name="line.130"></a>
+<span class="sourceLineNo">131</span><a name="line.131"></a>
+<span class="sourceLineNo">132</span>  public static final int FLUSHEDSEQUENCEID_FLUSHER_INTERVAL_DEFAULT =<a name="line.132"></a>
+<span class="sourceLineNo">133</span>      3 * 60 * 60 * 1000; // 3 hours<a name="line.133"></a>
+<span class="sourceLineNo">134</span><a name="line.134"></a>
+<span class="sourceLineNo">135</span>  public static final String MAX_CLOCK_SKEW_MS = "hbase.master.maxclockskew";<a name="line.135"></a>
+<span class="sourceLineNo">136</span><a name="line.136"></a>
+<span class="sourceLineNo">137</span>  private static final Logger LOG = LoggerFactory.getLogger(ServerManager.class);<a name="line.137"></a>
+<span class="sourceLineNo">138</span><a name="line.138"></a>
+<span class="sourceLineNo">139</span>  // Set if we are to shutdown the cluster.<a name="line.139"></a>
+<span class="sourceLineNo">140</span>  private AtomicBoolean clusterShutdown = new AtomicBoolean(false);<a name="line.140"></a>
+<span class="sourceLineNo">141</span><a name="line.141"></a>
+<span class="sourceLineNo">142</span>  /**<a name="line.142"></a>
+<span class="sourceLineNo">143</span>   * The last flushed sequence id for a region.<a name="line.143"></a>
+<span class="sourceLineNo">144</span>   */<a name="line.144"></a>
+<span class="sourceLineNo">145</span>  private final ConcurrentNavigableMap&lt;byte[], Long&gt; flushedSequenceIdByRegion =<a name="line.145"></a>
+<span class="sourceLineNo">146</span>    new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.146"></a>
+<span class="sourceLineNo">147</span><a name="line.147"></a>
+<span class="sourceLineNo">148</span>  private boolean persistFlushedSequenceId = true;<a name="line.148"></a>
+<span class="sourceLineNo">149</span>  private volatile boolean isFlushSeqIdPersistInProgress = false;<a name="line.149"></a>
+<span class="sourceLineNo">150</span>  /** File on hdfs to store last flushed sequence id of regions */<a name="line.150"></a>
+<span class="sourceLineNo">151</span>  private static final String LAST_FLUSHED_SEQ_ID_FILE = ".lastflushedseqids";<a name="line.151"></a>
+<span class="sourceLineNo">152</span>  private  FlushedSequenceIdFlusher flushedSeqIdFlusher;<a name="line.152"></a>
 <span class="sourceLineNo">153</span><a name="line.153"></a>
-<span class="sourceLineNo">154</span>  /**<a name="line.154"></a>
-<span class="sourceLineNo">155</span>   * The last flushed sequence id for a store in a region.<a name="line.155"></a>
-<span class="sourceLineNo">156</span>   */<a name="line.156"></a>
-<span class="sourceLineNo">157</span>  private final ConcurrentNavigableMap&lt;byte[], ConcurrentNavigableMap&lt;byte[], Long&gt;&gt;<a name="line.157"></a>
-<span class="sourceLineNo">158</span>    storeFlushedSequenceIdsByRegion = new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.158"></a>
-<span class="sourceLineNo">159</span><a name="line.159"></a>
-<span class="sourceLineNo">160</span>  /** Map of registered servers to their current load */<a name="line.160"></a>
-<span class="sourceLineNo">161</span>  private final ConcurrentNavigableMap&lt;ServerName, ServerMetrics&gt; onlineServers =<a name="line.161"></a>
-<span class="sourceLineNo">162</span>    new ConcurrentSkipListMap&lt;&gt;();<a name="line.162"></a>
-<span class="sourceLineNo">163</span><a name="line.163"></a>
-<span class="sourceLineNo">164</span>  /** List of region servers that should not get any more new regions. */<a name="line.164"></a>
-<span class="sourceLineNo">165</span>  private final ArrayList&lt;ServerName&gt; drainingServers = new ArrayList&lt;&gt;();<a name="line.165"></a>
-<span class="sourceLineNo">166</span><a name="line.166"></a>
-<span class="sourceLineNo">167</span>  private final MasterServices master;<a name="line.167"></a>
-<span class="sourceLineNo">168</span><a name="line.168"></a>
-<span class="sourceLineNo">169</span>  private final DeadServer deadservers = new DeadServer();<a name="line.169"></a>
-<span class="sourceLineNo">170</span><a name="line.170"></a>
-<span class="sourceLineNo">171</span>  private final long maxSkew;<a name="line.171"></a>
-<span class="sourceLineNo">172</span>  private final long warningSkew;<a name="line.172"></a>
-<span class="sourceLineNo">173</span><a name="line.173"></a>
-<span class="sourceLineNo">174</span>  /** Listeners that are called on server events. */<a name="line.174"></a>
-<span class="sourceLineNo">175</span>  private List&lt;ServerListener&gt; listeners = new CopyOnWriteArrayList&lt;&gt;();<a name="line.175"></a>
-<span class="sourceLineNo">176</span><a name="line.176"></a>
-<span class="sourceLineNo">177</span>  /**<a name="line.177"></a>
-<span class="sourceLineNo">178</span>   * Constructor.<a name="line.178"></a>
-<span class="sourceLineNo">179</span>   */<a name="line.179"></a>
-<span class="sourceLineNo">180</span>  public ServerManager(final MasterServices master) {<a name="line.180"></a>
-<span class="sourceLineNo">181</span>    this.master = master;<a name="line.181"></a>
-<span class="sourceLineNo">182</span>    Configuration c = master.getConfiguration();<a name="line.182"></a>
-<span class="sourceLineNo">183</span>    maxSkew = c.getLong(MAX_CLOCK_SKEW_MS, 30000);<a name="line.183"></a>
-<span class="sourceLineNo">184</span>    warningSkew = c.getLong("hbase.master.warningclockskew", 10000);<a name="line.184"></a>
-<span class="sourceLineNo">185</span>    persistFlushedSequenceId = c.getBoolean(PERSIST_FLUSHEDSEQUENCEID,<a name="line.185"></a>
-<span class="sourceLineNo">186</span>        PERSIST_FLUSHEDSEQUENCEID_DEFAULT);<a name="line.186"></a>
-<span class="sourceLineNo">187</span>  }<a name="line.187"></a>
-<span class="sourceLineNo">188</span><a name="line.188"></a>
-<span class="sourceLineNo">189</span>  /**<a name="line.189"></a>
-<span class="sourceLineNo">190</span>   * Add the listener to the notification list.<a name="line.190"></a>
-<span class="sourceLineNo">191</span>   * @param listener The ServerListener to register<a name="line.191"></a>
-<span class="sourceLineNo">192</span>   */<a name="line.192"></a>
-<span class="sourceLineNo">193</span>  public void registerListener(final ServerListener listener) {<a name="line.193"></a>
-<span class="sourceLineNo">194</span>    this.listeners.add(listener);<a name="line.194"></a>
-<span class="sourceLineNo">195</span>  }<a name="line.195"></a>
-<span class="sourceLineNo">196</span><a name="line.196"></a>
-<span class="sourceLineNo">197</span>  /**<a name="line.197"></a>
-<span class="sourceLineNo">198</span>   * Remove the listener from the notification list.<a name="line.198"></a>
-<span class="sourceLineNo">199</span>   * @param listener The ServerListener to unregister<a name="line.199"></a>
-<span class="sourceLineNo">200</span>   */<a name="line.200"></a>
-<span class="sourceLineNo">201</span>  public boolean unregisterListener(final ServerListener listener) {<a name="line.201"></a>
-<span class="sourceLineNo">202</span>    return this.listeners.remove(listener);<a name="line.202"></a>
-<span class="sourceLineNo">203</span>  }<a name="line.203"></a>
-<span class="sourceLineNo">204</span><a name="line.204"></a>
-<span class="sourceLineNo">205</span>  /**<a name="line.205"></a>
-<span class="sourceLineNo">206</span>   * Let the server manager know a new regionserver has come online<a name="line.206"></a>
-<span class="sourceLineNo">207</span>   * @param request the startup request<a name="line.207"></a>
-<span class="sourceLineNo">208</span>   * @param versionNumber the version number of the new regionserver<a name="line.208"></a>
-<span class="sourceLineNo">209</span>   * @param version the version of the new regionserver, could contain strings like "SNAPSHOT"<a name="line.209"></a>
-<span class="sourceLineNo">210</span>   * @param ia the InetAddress from which request is received<a name="line.210"></a>
-<span class="sourceLineNo">211</span>   * @return The ServerName we know this server as.<a name="line.211"></a>
-<span class="sourceLineNo">212</span>   * @throws IOException<a name="line.212"></a>
-<span class="sourceLineNo">213</span>   */<a name="line.213"></a>
-<span class="sourceLineNo">214</span>  ServerName regionServerStartup(RegionServerStartupRequest request, int versionNumber,<a name="line.214"></a>
-<span class="sourceLineNo">215</span>      String version, InetAddress ia) throws IOException {<a name="line.215"></a>
-<span class="sourceLineNo">216</span>    // Test for case where we get a region startup message from a regionserver<a name="line.216"></a>
-<span class="sourceLineNo">217</span>    // that has been quickly restarted but whose znode expiration handler has<a name="line.217"></a>
-<span class="sourceLineNo">218</span>    // not yet run, or from a server whose fail we are currently processing.<a name="line.218"></a>
-<span class="sourceLineNo">219</span>    // Test its host+port combo is present in serverAddressToServerInfo. If it<a name="line.219"></a>
-<span class="sourceLineNo">220</span>    // is, reject the server and trigger its expiration. The next time it comes<a name="line.220"></a>
-<span class="sourceLineNo">221</span>    // in, it should have been removed from serverAddressToServerInfo and queued<a name="line.221"></a>
-<span class="sourceLineNo">222</span>    // for processing by ProcessServerShutdown.<a name="line.222"></a>
-<span class="sourceLineNo">223</span><a name="line.223"></a>
-<span class="sourceLineNo">224</span>    final String hostname =<a name="line.224"></a>
-<span class="sourceLineNo">225</span>      request.hasUseThisHostnameInstead() ? request.getUseThisHostnameInstead() : ia.getHostName();<a name="line.225"></a>
-<span class="sourceLineNo">226</span>    ServerName sn = ServerName.valueOf(hostname, request.getPort(), request.getServerStartCode());<a name="line.226"></a>
-<span class="sourceLineNo">227</span>    checkClockSkew(sn, request.getServerCurrentTime());<a name="line.227"></a>
-<span class="sourceLineNo">228</span>    checkIsDead(sn, "STARTUP");<a name="line.228"></a>
-<span class="sourceLineNo">229</span>    if (!checkAndRecordNewServer(sn, ServerMetricsBuilder.of(sn, versionNumber, version))) {<a name="line.229"></a>
-<span class="sourceLineNo">230</span>      LOG.warn(<a name="line.230"></a>
-<span class="sourceLineNo">231</span>        "THIS SHOULD NOT HAPPEN, RegionServerStartup" + " could not record the server: " + sn);<a name="line.231"></a>
-<span class="sourceLineNo">232</span>    }<a name="line.232"></a>
-<span class="sourceLineNo">233</span>    return sn;<a name="line.233"></a>
-<span class="sourceLineNo">234</span>  }<a name="line.234"></a>
-<span class="sourceLineNo">235</span><a name="line.235"></a>
-<span class="sourceLineNo">236</span>  /**<a name="line.236"></a>
-<span class="sourceLineNo">237</span>   * Updates last flushed sequence Ids for the regions on server sn<a name="line.237"></a>
-<span class="sourceLineNo">238</span>   * @param sn<a name="line.238"></a>
-<span class="sourceLineNo">239</span>   * @param hsl<a name="line.239"></a>
-<span class="sourceLineNo">240</span>   */<a name="line.240"></a>
-<span class="sourceLineNo">241</span>  private void updateLastFlushedSequenceIds(ServerName sn, ServerMetrics hsl) {<a name="line.241"></a>
-<span class="sourceLineNo">242</span>    for (Entry&lt;byte[], RegionMetrics&gt; entry : hsl.getRegionMetrics().entrySet()) {<a name="line.242"></a>
-<span class="sourceLineNo">243</span>      byte[] encodedRegionName = Bytes.toBytes(RegionInfo.encodeRegionName(entry.getKey()));<a name="line.243"></a>
-<span class="sourceLineNo">244</span>      Long existingValue = flushedSequenceIdByRegion.get(encodedRegionName);<a name="line.244"></a>
-<span class="sourceLineNo">245</span>      long l = entry.getValue().getCompletedSequenceId();<a name="line.245"></a>
-<span class="sourceLineNo">246</span>      // Don't let smaller sequence ids override greater sequence ids.<a name="line.246"></a>
-<span class="sourceLineNo">247</span>      if (LOG.isTraceEnabled()) {<a name="line.247"></a>
-<span class="sourceLineNo">248</span>        LOG.trace(Bytes.toString(encodedRegionName) + ", existingValue=" + existingValue +<a name="line.248"></a>
-<span class="sourceLineNo">249</span>          ", completeSequenceId=" + l);<a name="line.249"></a>
-<span class="sourceLineNo">250</span>      }<a name="line.250"></a>
-<span class="sourceLineNo">251</span>      if (existingValue == null || (l != HConstants.NO_SEQNUM &amp;&amp; l &gt; existingValue)) {<a name="line.251"></a>
-<span class="sourceLineNo">252</span>        flushedSequenceIdByRegion.put(encodedRegionName, l);<a name="line.252"></a>
-<span class="sourceLineNo">253</span>      } else if (l != HConstants.NO_SEQNUM &amp;&amp; l &lt; existingValue) {<a name="line.253"></a>
-<span class="sourceLineNo">254</span>        LOG.warn("RegionServer " + sn + " indicates a last flushed sequence id ("<a name="line.254"></a>
-<span class="sourceLineNo">255</span>            + l + ") that is less than the previous last flushed sequence id ("<a name="line.255"></a>
-<span class="sourceLineNo">256</span>            + existingValue + ") for region " + Bytes.toString(entry.getKey()) + " Ignoring.");<a name="line.256"></a>
-<span class="sourceLineNo">257</span>      }<a name="line.257"></a>
-<span class="sourceLineNo">258</span>      ConcurrentNavigableMap&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.258"></a>
-<span class="sourceLineNo">259</span>          computeIfAbsent(storeFlushedSequenceIdsByRegion, encodedRegionName,<a name="line.259"></a>
-<span class="sourceLineNo">260</span>            () -&gt; new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR));<a name="line.260"></a>
-<span class="sourceLineNo">261</span>      for (Entry&lt;byte[], Long&gt; storeSeqId : entry.getValue().getStoreSequenceId().entrySet()) {<a name="line.261"></a>
-<span class="sourceLineNo">262</span>        byte[] family = storeSeqId.getKey();<a name="line.262"></a>
-<span class="sourceLineNo">263</span>        existingValue = storeFlushedSequenceId.get(family);<a name="line.263"></a>
-<span class="sourceLineNo">264</span>        l = storeSeqId.getValue();<a name="line.264"></a>
-<span class="sourceLineNo">265</span>        if (LOG.isTraceEnabled()) {<a name="line.265"></a>
-<span class="sourceLineNo">266</span>          LOG.trace(Bytes.toString(encodedRegionName) + ", family=" + Bytes.toString(family) +<a name="line.266"></a>
-<span class="sourceLineNo">267</span>            ", existingValue=" + existingValue + ", completeSequenceId=" + l);<a name="line.267"></a>
-<span class="sourceLineNo">268</span>        }<a name="line.268"></a>
-<span class="sourceLineNo">269</span>        // Don't let smaller sequence ids override greater sequence ids.<a name="line.269"></a>
-<span class="sourceLineNo">270</span>        if (existingValue == null || (l != HConstants.NO_SEQNUM &amp;&amp; l &gt; existingValue.longValue())) {<a name="line.270"></a>
-<span class="sourceLineNo">271</span>          storeFlushedSequenceId.put(family, l);<a name="line.271"></a>
-<span class="sourceLineNo">272</span>        }<a name="line.272"></a>
-<span class="sourceLineNo">273</span>      }<a name="line.273"></a>
-<span class="sourceLineNo">274</span>    }<a name="line.274"></a>
-<span class="sourceLineNo">275</span>  }<a name="line.275"></a>
-<span class="sourceLineNo">276</span><a name="line.276"></a>
-<span class="sourceLineNo">277</span>  @VisibleForTesting<a name="line.277"></a>
-<span class="sourceLineNo">278</span>  public void regionServerReport(ServerName sn,<a name="line.278"></a>
-<span class="sourceLineNo">279</span>    ServerMetrics sl) throws YouAreDeadException {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>    checkIsDead(sn, "REPORT");<a name="line.280"></a>
-<span class="sourceLineNo">281</span>    if (null == this.onlineServers.replace(sn, sl)) {<a name="line.281"></a>
-<span class="sourceLineNo">282</span>      // Already have this host+port combo and its just different start code?<a name="line.282"></a>
-<span class="sourceLineNo">283</span>      // Just let the server in. Presume master joining a running cluster.<a name="line.283"></a>
-<span class="sourceLineNo">284</span>      // recordNewServer is what happens at the end of reportServerStartup.<a name="line.284"></a>
-<span class="sourceLineNo">285</span>      // The only thing we are skipping is passing back to the regionserver<a name="line.285"></a>
-<span class="sourceLineNo">286</span>      // the ServerName to use. Here we presume a master has already done<a name="line.286"></a>
-<span class="sourceLineNo">287</span>      // that so we'll press on with whatever it gave us for ServerName.<a name="line.287"></a>
-<span class="sourceLineNo">288</span>      if (!checkAndRecordNewServer(sn, sl)) {<a name="line.288"></a>
-<span class="sourceLineNo">289</span>        LOG.info("RegionServerReport ignored, could not record the server: " + sn);<a name="line.289"></a>
-<span class="sourceLineNo">290</span>        return; // Not recorded, so no need to move on<a name="line.290"></a>
-<span class="sourceLineNo">291</span>      }<a name="line.291"></a>
-<span class="sourceLineNo">292</span>    }<a name="line.292"></a>
-<span class="sourceLineNo">293</span>    updateLastFlushedSequenceIds(sn, sl);<a name="line.293"></a>
-<span class="sourceLineNo">294</span>  }<a name="line.294"></a>
-<span class="sourceLineNo">295</span><a name="line.295"></a>
-<span class="sourceLineNo">296</span>  /**<a name="line.296"></a>
-<span class="sourceLineNo">297</span>   * Check is a server of same host and port already exists,<a name="line.297"></a>
-<span class="sourceLineNo">298</span>   * if not, or the existed one got a smaller start code, record it.<a name="line.298"></a>
-<span class="sourceLineNo">299</span>   *<a name="line.299"></a>
-<span class="sourceLineNo">300</span>   * @param serverName the server to check and record<a name="line.300"></a>
-<span class="sourceLineNo">301</span>   * @param sl the server load on the server<a name="line.301"></a>
-<span class="sourceLineNo">302</span>   * @return true if the server is recorded, otherwise, false<a name="line.302"></a>
-<span class="sourceLineNo">303</span>   */<a name="line.303"></a>
-<span class="sourceLineNo">304</span>  boolean checkAndRecordNewServer(final ServerName serverName, final ServerMetrics sl) {<a name="line.304"></a>
-<span class="sourceLineNo">305</span>    ServerName existingServer = null;<a name="line.305"></a>
-<span class="sourceLineNo">306</span>    synchronized (this.onlineServers) {<a name="line.306"></a>
-<span class="sourceLineNo">307</span>      existingServer = findServerWithSameHostnamePortWithLock(serverName);<a name="line.307"></a>
-<span class="sourceLineNo">308</span>      if (existingServer != null &amp;&amp; (existingServer.getStartcode() &gt; serverName.getStartcode())) {<a name="line.308"></a>
-<span class="sourceLineNo">309</span>        LOG.info("Server serverName=" + serverName + " rejected; we already have "<a name="line.309"></a>
-<span class="sourceLineNo">310</span>            + existingServer.toString() + " registered with same hostname and port");<a name="line.310"></a>
-<span class="sourceLineNo">311</span>        return false;<a name="line.311"></a>
-<span class="sourceLineNo">312</span>      }<a name="line.312"></a>
-<span class="sourceLineNo">313</span>      recordNewServerWithLock(serverName, sl);<a name="line.313"></a>
-<span class="sourceLineNo">314</span>    }<a name="line.314"></a>
-<span class="sourceLineNo">315</span><a name="line.315"></a>
-<span class="sourceLineNo">316</span>    // Tell our listeners that a server was added<a name="line.316"></a>
-<span class="sourceLineNo">317</span>    if (!this.listeners.isEmpty()) {<a name="line.317"></a>
-<span class="sourceLineNo">318</span>      for (ServerListener listener : this.listeners) {<a name="line.318"></a>
-<span class="sourceLineNo">319</span>        listener.serverAdded(serverName);<a name="line.319"></a>
-<span class="sourceLineNo">320</span>      }<a name="line.320"></a>
-<span class="sourceLineNo">321</span>    }<a name="line.321"></a>
-<span class="sourceLineNo">322</span><a name="line.322"></a>
-<span class="sourceLineNo">323</span>    // Note that we assume that same ts means same server, and don't expire in that case.<a name="line.323"></a>
-<span class="sourceLineNo">324</span>    //  TODO: ts can theoretically collide due to clock shifts, so this is a bit hacky.<a name="line.324"></a>
-<span class="sourceLineNo">325</span>    if (existingServer != null &amp;&amp;<a name="line.325"></a>
-<span class="sourceLineNo">326</span>        (existingServer.getStartcode() &lt; serverName.getStartcode())) {<a name="line.326"></a>
-<span class="sourceLineNo">327</span>      LOG.info("Triggering server recovery; existingServer " +<a name="line.327"></a>
-<span class="sourceLineNo">328</span>          existingServer + " looks stale, new server:" + serverName);<a name="line.328"></a>
-<span class="sourceLineNo">329</span>      expireServer(existingServer);<a name="line.329"></a>
-<span class="sourceLineNo">330</span>    }<a name="line.330"></a>
-<span class="sourceLineNo">331</span>    return true;<a name="line.331"></a>
-<span class="sourceLineNo">332</span>  }<a name="line.332"></a>
-<span class="sourceLineNo">333</span><a name="line.333"></a>
-<span class="sourceLineNo">334</span>  /**<a name="line.334"></a>
-<span class="sourceLineNo">335</span>   * Find out the region servers crashed between the crash of the previous master instance and the<a name="line.335"></a>
-<span class="sourceLineNo">336</span>   * current master instance and schedule SCP for them.<a name="line.336"></a>
-<span class="sourceLineNo">337</span>   * &lt;p/&gt;<a name="line.337"></a>
-<span class="sourceLineNo">338</span>   * Since the {@code RegionServerTracker} has already helped us to construct the online servers set<a name="line.338"></a>
-<span class="sourceLineNo">339</span>   * by scanning zookeeper, now we can compare the online servers with {@code liveServersFromWALDir}<a name="line.339"></a>
-<span class="sourceLineNo">340</span>   * to find out whether there are servers which are already dead.<a name="line.340"></a>
-<span class="sourceLineNo">341</span>   * &lt;p/&gt;<a name="line.341"></a>
-<span class="sourceLineNo">342</span>   * Must be called inside the initialization method of {@code RegionServerTracker} to avoid<a name="line.342"></a>
-<span class="sourceLineNo">343</span>   * concurrency issue.<a name="line.343"></a>
-<span class="sourceLineNo">344</span>   * @param deadServersFromPE the region servers which already have a SCP associated.<a name="line.344"></a>
-<span class="sourceLineNo">345</span>   * @param liveServersFromWALDir the live region servers from wal directory.<a name="line.345"></a>
-<span class="sourceLineNo">346</span>   */<a name="line.346"></a>
-<span class="sourceLineNo">347</span>  void findDeadServersAndProcess(Set&lt;ServerName&gt; deadServersFromPE,<a name="line.347"></a>
-<span class="sourceLineNo">348</span>      Set&lt;ServerName&gt; liveServersFromWALDir) {<a name="line.348"></a>
-<span class="sourceLineNo">349</span>    deadServersFromPE.forEach(deadservers::putIfAbsent);<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    liveServersFromWALDir.stream().filter(sn -&gt; !onlineServers.containsKey(sn))<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      .forEach(this::expireServer);<a name="line.351"></a>
-<span class="sourceLineNo">352</span>  }<a name="line.352"></a>
-<span class="sourceLineNo">353</span><a name="line.353"></a>
-<span class="sourceLineNo">354</span>  /**<a name="line.354"></a>
-<span class="sourceLineNo">355</span>   * Checks if the clock skew between the server and the master. If the clock skew exceeds the<a name="line.355"></a>
-<span class="sourceLineNo">356</span>   * configured max, it will throw an exception; if it exceeds the configured warning threshold,<a name="line.356"></a>
-<span class="sourceLineNo">357</span>   * it will log a warning but start normally.<a name="line.357"></a>
-<span class="sourceLineNo">358</span>   * @param serverName Incoming servers's name<a name="line.358"></a>
-<span class="sourceLineNo">359</span>   * @param serverCurrentTime<a name="line.359"></a>
-<span class="sourceLineNo">360</span>   * @throws ClockOutOfSyncException if the skew exceeds the configured max value<a name="line.360"></a>
-<span class="sourceLineNo">361</span>   */<a name="line.361"></a>
-<span class="sourceLineNo">362</span>  private void checkClockSkew(final ServerName serverName, final long serverCurrentTime)<a name="line.362"></a>
-<span class="sourceLineNo">363</span>      throws ClockOutOfSyncException {<a name="line.363"></a>
-<span class="sourceLineNo">364</span>    long skew = Math.abs(EnvironmentEdgeManager.currentTime() - serverCurrentTime);<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    if (skew &gt; maxSkew) {<a name="line.365"></a>
-<span class="sourceLineNo">366</span>      String message = "Server " + serverName + " has been " +<a name="line.366"></a>
-<span class="sourceLineNo">367</span>        "rejected; Reported time is too far out of sync with master.  " +<a name="line.367"></a>
-<span class="sourceLineNo">368</span>        "Time difference of " + skew + "ms &gt; max allowed of " + maxSkew + "ms";<a name="line.368"></a>
-<span class="sourceLineNo">369</span>      LOG.warn(message);<a name="line.369"></a>
-<span class="sourceLineNo">370</span>      throw new ClockOutOfSyncException(message);<a name="line.370"></a>
-<span class="sourceLineNo">371</span>    } else if (skew &gt; warningSkew){<a name="line.371"></a>
-<span class="sourceLineNo">372</span>      String message = "Reported time for server " + serverName + " is out of sync with master " +<a name="line.372"></a>
-<span class="sourceLineNo">373</span>        "by " + skew + "ms. (Warning threshold is " + warningSkew + "ms; " +<a name="line.373"></a>
-<span class="sourceLineNo">374</span>        "error threshold is " + maxSkew + "ms)";<a name="line.374"></a>
-<span class="sourceLineNo">375</span>      LOG.warn(message);<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    }<a name="line.376"></a>
-<span class="sourceLineNo">377</span>  }<a name="line.377"></a>
-<span class="sourceLineNo">378</span><a name="line.378"></a>
-<span class="sourceLineNo">379</span>  /**<a name="line.379"></a>
-<span class="sourceLineNo">380</span>   * Called when RegionServer first reports in for duty and thereafter each<a name="line.380"></a>
-<span class="sourceLineNo">381</span>   * time it heartbeats to make sure it is has not been figured for dead.<a name="line.381"></a>
-<span class="sourceLineNo">382</span>   * If this server is on the dead list, reject it with a YouAreDeadException.<a name="line.382"></a>
-<span class="sourceLineNo">383</span>   * If it was dead but came back with a new start code, remove the old entry<a name="line.383"></a>
-<span class="sourceLineNo">384</span>   * from the dead list.<a name="line.384"></a>
-<span class="sourceLineNo">385</span>   * @param what START or REPORT<a name="line.385"></a>
-<span class="sourceLineNo">386</span>   */<a name="line.386"></a>
-<span class="sourceLineNo">387</span>  private void checkIsDead(final ServerName serverName, final String what)<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      throws YouAreDeadException {<a name="line.388"></a>
-<span class="sourceLineNo">389</span>    if (this.deadservers.isDeadServer(serverName)) {<a name="line.389"></a>
-<span class="sourceLineNo">390</span>      // Exact match: host name, port and start code all match with existing one of the<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      // dead servers. So, this server must be dead. Tell it to kill itself.<a name="line.391"></a>
-<span class="sourceLineNo">392</span>      String message = "Server " + what + " rejected; currently processing " +<a name="line.392"></a>
-<span class="sourceLineNo">393</span>          serverName + " as dead server";<a name="line.393"></a>
-<span class="sourceLineNo">394</span>      LOG.debug(message);<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      throw new YouAreDeadException(message);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    }<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    // Remove dead server with same hostname and port of newly checking in rs after master<a name="line.397"></a>
-<span class="sourceLineNo">398</span>    // initialization. See HBASE-5916 for more information.<a name="line.398"></a>
-<span class="sourceLineNo">399</span>    if ((this.master == null || this.master.isInitialized()) &amp;&amp;<a name="line.399"></a>
-<span class="sourceLineNo">400</span>        this.deadservers.cleanPreviousInstance(serverName)) {<a name="line.400"></a>
-<span class="sourceLineNo">401</span>      // This server has now become alive after we marked it as dead.<a name="line.401"></a>
-<span class="sourceLineNo">402</span>      // We removed it's previous entry from the dead list to reflect it.<a name="line.402"></a>
-<span class="sourceLineNo">403</span>      LOG.debug("{} {} came back up, removed it from the dead servers list", what, serverName);<a name="line.403"></a>
-<span class="sourceLineNo">404</span>    }<a name="line.404"></a>
-<span class="sourceLineNo">405</span>  }<a name="line.405"></a>
-<span class="sourceLineNo">406</span><a name="line.406"></a>
-<span class="sourceLineNo">407</span>  /**<a name="line.407"></a>
-<span class="sourceLineNo">408</span>   * Assumes onlineServers is locked.<a name="line.408"></a>
-<span class="sourceLineNo">409</span>   * @return ServerName with matching hostname and port.<a name="line.409"></a>
-<span class="sourceLineNo">410</span>   */<a name="line.410"></a>
-<span class="sourceLineNo">411</span>  private ServerName findServerWithSameHostnamePortWithLock(<a name="line.411"></a>
-<span class="sourceLineNo">412</span>      final ServerName serverName) {<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    ServerName end = ServerName.valueOf(serverName.getHostname(), serverName.getPort(),<a name="line.413"></a>
-<span class="sourceLineNo">414</span>        Long.MAX_VALUE);<a name="line.414"></a>
-<span class="sourceLineNo">415</span><a name="line.415"></a>
-<span class="sourceLineNo">416</span>    ServerName r = onlineServers.lowerKey(end);<a name="line.416"></a>
-<span class="sourceLineNo">417</span>    if (r != null) {<a name="line.417"></a>
-<span class="sourceLineNo">418</span>      if (ServerName.isSameAddress(r, serverName)) {<a name="line.418"></a>
-<span class="sourceLineNo">419</span>        return r;<a name="line.419"></a>
-<span class="sourceLineNo">420</span>      }<a name="line.420"></a>
-<span class="sourceLineNo">421</span>    }<a name="line.421"></a>
-<span class="sourceLineNo">422</span>    return null;<a name="line.422"></a>
-<span class="sourceLineNo">423</span>  }<a name="line.423"></a>
-<span class="sourceLineNo">424</span><a name="line.424"></a>
-<span class="sourceLineNo">425</span>  /**<a name="line.425"></a>
-<span class="sourceLineNo">426</span>   * Adds the onlineServers list. onlineServers should be locked.<a name="line.426"></a>
-<span class="sourceLineNo">427</span>   * @param serverName The remote servers name.<a name="line.427"></a>
-<span class="sourceLineNo">428</span>   */<a name="line.428"></a>
-<span class="sourceLineNo">429</span>  @VisibleForTesting<a name="line.429"></a>
-<span class="sourceLineNo">430</span>  void recordNewServerWithLock(final ServerName serverName, final ServerMetrics sl) {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>    LOG.info("Registering regionserver=" + serverName);<a name="line.431"></a>
-<span class="sourceLineNo">432</span>    this.onlineServers.put(serverName, sl);<a name="line.432"></a>
-<span class="sourceLineNo">433</span>  }<a name="line.433"></a>
-<span class="sourceLineNo">434</span><a name="line.434"></a>
-<span class="sourceLineNo">435</span>  @VisibleForTesting<a name="line.435"></a>
-<span class="sourceLineNo">436</span>  public ConcurrentNavigableMap&lt;byte[], Long&gt; getFlushedSequenceIdByRegion() {<a name="line.436"></a>
-<span class="sourceLineNo">437</span>    return flushedSequenceIdByRegion;<a name="line.437"></a>
-<span class="sourceLineNo">438</span>  }<a name="line.438"></a>
-<span class="sourceLineNo">439</span><a name="line.439"></a>
-<span class="sourceLineNo">440</span>  public RegionStoreSequenceIds getLastFlushedSequenceId(byte[] encodedRegionName) {<a name="line.440"></a>
-<span class="sourceLineNo">441</span>    RegionStoreSequenceIds.Builder builder = RegionStoreSequenceIds.newBuilder();<a name="line.441"></a>
-<span class="sourceLineNo">442</span>    Long seqId = flushedSequenceIdByRegion.get(encodedRegionName);<a name="line.442"></a>
-<span class="sourceLineNo">443</span>    builder.setLastFlushedSequenceId(seqId != null ? seqId.longValue() : HConstants.NO_SEQNUM);<a name="line.443"></a>
-<span class="sourceLineNo">444</span>    Map&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.444"></a>
-<span class="sourceLineNo">445</span>        storeFlushedSequenceIdsByRegion.get(encodedRegionName);<a name="line.445"></a>
-<span class="sourceLineNo">446</span>    if (storeFlushedSequenceId != null) {<a name="line.446"></a>
-<span class="sourceLineNo">447</span>      for (Map.Entry&lt;byte[], Long&gt; entry : storeFlushedSequenceId.entrySet()) {<a name="line.447"></a>
-<span class="sourceLineNo">448</span>        builder.addStoreSequenceId(StoreSequenceId.newBuilder()<a name="line.448"></a>
-<span class="sourceLineNo">449</span>            .setFamilyName(UnsafeByteOperations.unsafeWrap(entry.getKey()))<a name="line.449"></a>
-<span class="sourceLineNo">450</span>            .setSequenceId(entry.getValue().longValue()).build());<a name="line.450"></a>
-<span class="sourceLineNo">451</span>      }<a name="line.451"></a>
-<span class="sourceLineNo">452</span>    }<a name="line.452"></a>
-<span class="sourceLineNo">453</span>    return builder.build();<a name="line.453"></a>
-<span class="sourceLineNo">454</span>  }<a name="line.454"></a>
-<span class="sourceLineNo">455</span><a name="line.455"></a>
-<span class="sourceLineNo">456</span>  /**<a name="line.456"></a>
-<span class="sourceLineNo">457</span>   * @param serverName<a name="line.457"></a>
-<span class="sourceLineNo">458</span>   * @return ServerMetrics if serverName is known else null<a name="line.458"></a>
-<span class="sourceLineNo">459</span>   */<a name="line.459"></a>
-<span class="sourceLineNo">460</span>  public ServerMetrics getLoad(final ServerName serverName) {<a name="line.460"></a>
-<span class="sourceLineNo">461</span>    return this.onlineServers.get(serverName);<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  }<a name="line.462"></a>
-<span class="sourceLineNo">463</span><a name="line.463"></a>
-<span class="sourceLineNo">464</span>  /**<a name="line.464"></a>
-<span class="sourceLineNo">465</span>   * Compute the average load across all region servers.<a name="line.465"></a>
-<span class="sourceLineNo">466</span>   * Currently, this uses a very naive computation - just uses the number of<a name="line.466"></a>
-<span class="sourceLineNo">467</span>   * regions being served, ignoring stats about number of requests.<a name="line.467"></a>
-<span class="sourceLineNo">468</span>   * @return the average load<a name="line.468"></a>
-<span class="sourceLineNo">469</span>   */<a name="line.469"></a>
-<span class="sourceLineNo">470</span>  public double getAverageLoad() {<a name="line.470"></a>
-<span class="sourceLineNo">471</span>    int totalLoad = 0;<a name="line.471"></a>
-<span class="sourceLineNo">472</span>    int numServers = 0;<a name="line.472"></a>
-<span class="sourceLineNo">473</span>    for (ServerMetrics sl : this.onlineServers.values()) {<a name="line.473"></a>
-<span class="sourceLineNo">474</span>      numServers++;<a name="line.474"></a>
-<span class="sourceLineNo">475</span>      totalLoad += sl.getRegionMetrics().size();<a name="line.475"></a>
-<span class="sourceLineNo">476</span>    }<a name="line.476"></a>
-<span class="sourceLineNo">477</span>    return numServers == 0 ? 0 :<a name="line.477"></a>
-<span class="sourceLineNo">478</span>      (double)totalLoad / (double)numServers;<a name="line.478"></a>
-<span class="sourceLineNo">479</span>  }<a name="line.479"></a>
-<span class="sourceLineNo">480</span><a name="line.480"></a>
-<span class="sourceLineNo">481</span>  /** @return the count of active regionservers */<a name="line.481"></a>
-<span class="sourceLineNo">482</span>  public int countOfRegionServers() {<a name="line.482"></a>
-<span class="sourceLineNo">483</span>    // Presumes onlineServers is a concurrent map<a name="line.483"></a>
-<span class="sourceLineNo">484</span>    return this.onlineServers.size();<a name="line.484"></a>
-<span class="sourceLineNo">485</span>  }<a name="line.485"></a>
-<span class="sourceLineNo">486</span><a name="line.486"></a>
-<span class="sourceLineNo">487</span>  /**<a name="line.487"></a>
-<span class="sourceLineNo">488</span>   * @return Read-only map of servers to serverinfo<a name="line.488"></a>
-<span class="sourceLineNo">489</span>   */<a name="line.489"></a>
-<span class="sourceLineNo">490</span>  public Map&lt;ServerName, ServerMetrics&gt; getOnlineServers() {<a name="line.490"></a>
-<span class="sourceLineNo">491</span>    // Presumption is that iterating the returned Map is OK.<a name="line.491"></a>
-<span class="sourceLineNo">492</span>    synchronized (this.onlineServers) {<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      return Collections.unmodifiableMap(this.onlineServers);<a name="line.493"></a>
-<span class="sourceLineNo">494</span>    }<a name="line.494"></a>
-<span class="sourceLineNo">495</span>  }<a name="line.495"></a>
-<span class="sourceLineNo">496</span><a name="line.496"></a>
-<span class="sourceLineNo">497</span>  public DeadServer getDeadServers() {<a name="line.497"></a>
-<span class="sourceLineNo">498</span>    return this.deadservers;<a name="line.498"></a>
-<span class="sourceLineNo">499</span>  }<a name="line.499"></a>
-<span class="sourceLineNo">500</span><a name="line.500"></a>
-<span class="sourceLineNo">501</span>  /**<a name="line.501"></a>
-<span class="sourceLineNo">502</span>   * Checks if any dead servers are currently in progress.<a name="line.502"></a>
-<span class="sourceLineNo">503</span>   * @return true if any RS are being processed as dead, false if not<a name="line.503"></a>
-<span class="sourceLineNo">504</span>   */<a name="line.504"></a>
-<span class="sourceLineNo">505</span>  public boolean areDeadServersInProgress() {<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    return this.deadservers.areDeadServersInProgress();<a name="line.506"></a>
-<span class="sourceLineNo">507</span>  }<a name="line.507"></a>
-<span class="sourceLineNo">508</span><a name="line.508"></a>
-<span class="sourceLineNo">509</span>  void letRegionServersShutdown() {<a name="line.509"></a>
-<span class="sourceLineNo">510</span>    long previousLogTime = 0;<a name="line.510"></a>
-<span class="sourceLineNo">511</span>    ServerName sn = master.getServerName();<a name="line.511"></a>
-<span class="sourceLineNo">512</span>    ZKWatcher zkw = master.getZooKeeper();<a name="line.512"></a>
-<span class="sourceLineNo">513</span>    int onlineServersCt;<a name="line.513"></a>
-<span class="sourceLineNo">514</span>    while ((onlineServersCt = onlineServers.size()) &gt; 0){<a name="line.514"></a>
-<span class="sourceLineNo">515</span><a name="line.515"></a>
-<span class="sourceLineNo">516</span>      if (System.currentTimeMillis() &gt; (previousLogTime + 1000)) {<a name="line.516"></a>
-<span class="sourceLineNo">517</span>        Set&lt;ServerName&gt; remainingServers = onlineServers.keySet();<a name="line.517"></a>
-<span class="sourceLineNo">518</span>        synchronized (onlineServers) {<a name="line.518"></a>
-<span class="sourceLineNo">519</span>          if (remainingServers.size() == 1 &amp;&amp; remainingServers.contains(sn)) {<a name="line.519"></a>
-<span class="sourceLineNo">520</span>            // Master will delete itself later.<a name="line.520"></a>
-<span class="sourceLineNo">521</span>            return;<a name="line.521"></a>
-<span class="sourceLineNo">522</span>          }<a name="line.522"></a>
-<span class="sourceLineNo">523</span>        }<a name="line.523"></a>
-<span class="sourceLineNo">524</span>        StringBuilder sb = new StringBuilder();<a name="line.524"></a>
-<span class="sourceLineNo">525</span>        // It's ok here to not sync on onlineServers - merely logging<a name="line.525"></a>
-<span class="sourceLineNo">526</span>        for (ServerName key : remainingServers) {<a name="line.526"></a>
-<span class="sourceLineNo">527</span>          if (sb.length() &gt; 0) {<a name="line.527"></a>
-<span class="sourceLineNo">528</span>            sb.append(", ");<a name="line.528"></a>
-<span class="sourceLineNo">529</span>          }<a name="line.529"></a>
-<span class="sourceLineNo">530</span>          sb.append(key);<a name="line.530"></a>
-<span class="sourceLineNo">531</span>        }<a name="line.531"></a>
-<span class="sourceLineNo">532</span>        LOG.info("Waiting on regionserver(s) " + sb.toString());<a name="line.532"></a>
-<span class="sourceLineNo">533</span>        previousLogTime = System.currentTimeMillis();<a name="line.533"></a>
-<span class="sourceLineNo">534</span>      }<a name="line.534"></a>
-<span class="sourceLineNo">535</span><a name="line.535"></a>
-<span class="sourceLineNo">536</span>      try {<a name="line.536"></a>
-<span class="sourceLineNo">537</span>        List&lt;String&gt; servers = getRegionServersInZK(zkw);<a name="line.537"></a>
-<span class="sourceLineNo">538</span>        if (servers == null || servers.isEmpty() || (servers.size() == 1<a name="line.538"></a>
-<span class="sourceLineNo">539</span>            &amp;&amp; servers.contains(sn.toString()))) {<a name="line.539"></a>
-<span class="sourceLineNo">540</span>          LOG.info("ZK shows there is only the master self online, exiting now");<a name="line.540"></a>
-<span class="sourceLineNo">541</span>          // Master could have lost some ZK events, no need to wait more.<a name="line.541"></a>
-<span class="sourceLineNo">542</span>          break;<a name="line.542"></a>
-<span class="sourceLineNo">543</span>        }<a name="line.543"></a>
-<span class="sourceLineNo">544</span>      } catch (KeeperException ke) {<a name="line.544"></a>
-<span class="sourceLineNo">545</span>        LOG.warn("Failed to list regionservers", ke);<a name="line.545"></a>
-<span class="sourceLineNo">546</span>        // ZK is malfunctioning, don't hang here<a name="line.546"></a>
-<span class="sourceLineNo">547</span>        break;<a name="line.547"></a>
-<span class="sourceLineNo">548</span>      }<a name="line.548"></a>
-<span class="sourceLineNo">549</span>      synchronized (onlineServers) {<a name="line.549"></a>
-<span class="sourceLineNo">550</span>        try {<a name="line.550"></a>
-<span class="sourceLineNo">551</span>          if (onlineServersCt == onlineServers.size()) onlineServers.wait(100);<a name="line.551"></a>
-<span class="sourceLineNo">552</span>        } catch (InterruptedException ignored) {<a name="line.552"></a>
-<span class="sourceLineNo">553</span>          // continue<a name="line.553"></a>
-<span class="sourceLineNo">554</span>        }<a name="line.554"></a>
-<span class="sourceLineNo">555</span>      }<a name="line.555"></a>
-<span class="sourceLineNo">556</span>    }<a name="line.556"></a>
-<span class="sourceLineNo">557</span>  }<a name="line.557"></a>
-<span class="sourceLineNo">558</span><a name="line.558"></a>
-<span class="sourceLineNo">559</span>  private List&lt;String&gt; getRegionServersInZK(final ZKWatcher zkw)<a name="line.559"></a>
-<span class="sourceLineNo">560</span>  throws KeeperException {<a name="line.560"></a>
-<span class="sourceLineNo">561</span>    return ZKUtil.listChildrenNoWatch(zkw, zkw.getZNodePaths().rsZNode);<a name="line.561"></a>
-<span class="sourceLineNo">562</span>  }<a name="line.562"></a>
-<span class="sourceLineNo">563</span><a name="line.563"></a>
-<span class="sourceLineNo">564</span>  /**<a name="line.564"></a>
-<span class="sourceLineNo">565</span>   * Expire the passed server. Add it to list of dead servers and queue a shutdown processing.<a name="line.565"></a>
-<span class="sourceLineNo">566</span>   * @return pid if we queued a ServerCrashProcedure else {@link Procedure#NO_PROC_ID} if we did<a name="line.566"></a>
-<span class="sourceLineNo">567</span>   *         not (could happen for many reasons including the fact that its this server that is<a name="line.567"></a>
-<span class="sourceLineNo">568</span>   *         going down or we already have queued an SCP for this server or SCP processing is<a name="line.568"></a>
-<span class="sourceLineNo">569</span>   *         currently disabled because we are in startup phase).<a name="line.569"></a>
-<span class="sourceLineNo">570</span>   */<a name="line.570"></a>
-<span class="sourceLineNo">571</span>  @VisibleForTesting // Redo test so we can make this protected.<a name="line.571"></a>
-<span class="sourceLineNo">572</span>  public synchronized long expireServer(final ServerName serverName) {<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    return expireServer(serverName, false);<a name="line.573"></a>
-<span class="sourceLineNo">574</span><a name="line.574"></a>
-<span class="sourceLineNo">575</span>  }<a name="line.575"></a>
-<span class="sourceLineNo">576</span><a name="line.576"></a>
-<span class="sourceLineNo">577</span>  synchronized long expireServer(final ServerName serverName, boolean force) {<a name="line.577"></a>
-<span class="sourceLineNo">578</span>    // THIS server is going down... can't handle our own expiration.<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    if (serverName.equals(master.getServerName())) {<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      if (!(master.isAborted() || master.isStopped())) {<a name="line.580"></a>
-<span class="sourceLineNo">581</span>        master.stop("We lost our znode?");<a name="line.581"></a>
-<span class="sourceLineNo">582</span>      }<a name="line.582"></a>
-<span class="sourceLineNo">583</span>      return Procedure.NO_PROC_ID;<a name="line.583"></a>
-<span class="sourceLineNo">584</span>    }<a name="line.584"></a>
-<span class="sourceLineNo">585</span>    if (this.deadservers.isDeadServer(serverName)) {<a name="line.585"></a>
-<span class="sourceLineNo">586</span>      LOG.warn("Expiration called on {} but already in DeadServer", serverName);<a name="line.586"></a>
-<span class="sourceLineNo">587</span>      return Procedure.NO_PROC_ID;<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    }<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    moveFromOnlineToDeadServers(serverName);<a name="line.589"></a>
-<span class="sourceLineNo">590</span><a name="line.590"></a>
-<span class="sourceLineNo">591</span>    // If server is in draining mode, remove corresponding znode<a name="line.591"></a>
-<span class="sourceLineNo">592</span>    // In some tests, the mocked HM may not have ZK Instance, hence null check<a name="line.592"></a>
-<span class="sourceLineNo">593</span>    if (master.getZooKeeper() != null) {<a name="line.593"></a>
-<span class="sourceLineNo">594</span>      String drainingZnode = ZNodePaths<a name="line.594"></a>
-<span class="sourceLineNo">595</span>        .joinZNode(master.getZooKeeper().getZNodePaths().drainingZNode, serverName.getServerName());<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      try {<a name="line.596"></a>
-<span class="sourceLineNo">597</span>        ZKUtil.deleteNodeFailSilent(master.getZooKeeper(), drainingZnode);<a name="line.597"></a>
-<span class="sourceLineNo">598</span>      } catch (KeeperException e) {<a name="line.598"></a>
-<span class="sourceLineNo">599</span>        LOG.warn("Error deleting the draining znode for stopping server " + serverName.getServerName(), e);<a name="line.599"></a>
-<span class="sourceLineNo">600</span>      }<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    }<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    <a name="line.602"></a>
-<span class="sourceLineNo">603</span>    // If cluster is going down, yes, servers are going to be expiring; don't<a name="line.603"></a>
-<span class="sourceLineNo">604</span>    // process as a dead server<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    if (isClusterShutdown()) {<a name="line.605"></a>
-<span class="sourceLineNo">606</span>      LOG.info("Cluster shutdown set; " + serverName +<a name="line.606"></a>
-<span class="sourceLineNo">607</span>        " expired; onlineServers=" + this.onlineServers.size());<a name="line.607"></a>
-<span class="sourceLineNo">608</span>      if (this.onlineServers.isEmpty()) {<a name="line.608"></a>
-<span class="sourceLineNo">609</span>        master.stop("Cluster shutdown set; onlineServer=0");<a name="line.609"></a>
-<span class="sourceLineNo">610</span>      }<a name="line.610"></a>
-<span class="sourceLineNo">611</span>      return Procedure.NO_PROC_ID;<a name="line.611"></a>
-<span class="sourceLineNo">612</span>    }<a name="line.612"></a>
-<span class="sourceLineNo">613</span>    LOG.info("Processing expiration of " + serverName + " on " + this.master.getServerName());<a name="line.613"></a>
-<span class="sourceLineNo">614</span>    long pid = master.getAssignmentManager().submitServerCrash(serverName, true, force);<a name="line.614"></a>
-<span class="sourceLineNo">615</span>    // Tell our listeners that a server was removed<a name="line.615"></a>
-<span class="sourceLineNo">616</span>    if (!this.listeners.isEmpty()) {<a name="line.616"></a>
-<span class="sourceLineNo">617</span>      this.listeners.stream().forEach(l -&gt; l.serverRemoved(serverName));<a name="line.617"></a>
-<span class="sourceLineNo">618</span>    }<a name="line.618"></a>
-<span class="sourceLineNo">619</span>    // trigger a persist of flushedSeqId<a name="line.619"></a>
-<span class="sourceLineNo">620</span>    if (flushedSeqIdFlusher != null) {<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      flushedSeqIdFlusher.triggerNow();<a name="line.621"></a>
-<span class="sourceLineNo">622</span>    }<a name="line.622"></a>
-<span class="sourceLineNo">623</span>    return pid;<a name="line.623"></a>
-<span class="sourceLineNo">624</span>  }<a name="line.624"></a>
-<span class="sourceLineNo">625</span><a name="line.625"></a>
-<span class="sourceLineNo">626</span>  /**<a name="line.626"></a>
-<span class="sourceLineNo">627</span>   * Called when server has expired.<a name="line.627"></a>
-<span class="sourceLineNo">628</span>   */<a name="line.628"></a>
-<span class="sourceLineNo">629</span>  // Locking in this class needs cleanup.<a name="line.629"></a>
-<span class="sourceLineNo">630</span>  @VisibleForTesting<a name="line.630"></a>
-<span class="sourceLineNo">631</span>  public synchronized void moveFromOnlineToDeadServers(final ServerName sn) {<a name="line.631"></a>
-<span class="sourceLineNo">632</span>    synchronized (this.onlineServers) {<a name="line.632"></a>
-<span class="sourceLineNo">633</span>      boolean online = this.onlineServers.containsKey(sn);<a name="line.633"></a>
-<span class="sourceLineNo">634</span>      if (online) {<a name="line.634"></a>
-<span class="sourceLineNo">635</span>        // Remove the server from the known servers lists and update load info BUT<a name="line.635"></a>
-<span class="sourceLineNo">636</span>        // add to deadservers first; do this so it'll show in dead servers list if<a name="line.636"></a>
-<span class="sourceLineNo">637</span>        // not in online servers list.<a name="line.637"></a>
-<span class="sourceLineNo">638</span>        this.deadservers.putIfAbsent(sn);<a name="line.638"></a>
-<span class="sourceLineNo">639</span>        this.onlineServers.remove(sn);<a name="line.639"></a>
-<span class="sourceLineNo">640</span>        onlineServers.notifyAll();<a name="line.640"></a>
-<span class="sourceLineNo">641</span>      } else {<a name="line.641"></a>
-<span class="sourceLineNo">642</span>        // If not online, that is odd but may happen if 'Unknown Servers' -- where meta<a name="line.642"></a>
-<span class="sourceLineNo">643</span>        // has references to servers not online nor in dead servers list. If<a name="line.643"></a>
-<span class="sourceLineNo">644</span>        // 'Unknown Server', don't add to DeadServers else will be there for ever.<a name="line.644"></a>
-<span class="sourceLineNo">645</span>        LOG.trace("Expiration of {} but server not online", sn);<a name="line.645"></a>
-<span class="sourceLineNo">646</span>      }<a name="line.646"></a>
-<span class="sourceLineNo">647</span>    }<a name="line.647"></a>
-<span class="sourceLineNo">648</span>  }<a name="line.648"></a>
-<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span>  /*<a name="line.650"></a>
-<span class="sourceLineNo">651</span>   * Remove the server from the drain list.<a name="line.651"></a>
-<span class="sourceLineNo">652</span>   */<a name="line.652"></a>
-<span class="sourceLineNo">653</span>  public synchronized boolean removeServerFromDrainList(final ServerName sn) {<a name="line.653"></a>
-<span class="sourceLineNo">654</span>    // Warn if the server (sn) is not online.  ServerName is of the form:<a name="line.654"></a>
-<span class="sourceLineNo">655</span>    // &lt;hostname&gt; , &lt;port&gt; , &lt;startcode&gt;<a name="line.655"></a>
-<span class="sourceLineNo">656</span><a name="line.656"></a>
-<span class="sourceLineNo">657</span>    if (!this.isServerOnline(sn)) {<a name="line.657"></a>
-<span class="sourceLineNo">658</span>      LOG.warn("Server " + sn + " is not currently online. " +<a name="line.658"></a>
-<span class="sourceLineNo">659</span>               "Removing from draining list anyway, as requested.");<a name="line.659"></a>
-<span class="sourceLineNo">660</span>    }<a name="line.660"></a>
-<span class="sourceLineNo">661</span>    // Remove the server from the draining servers lists.<a name="line.661"></a>
-<span class="sourceLineNo">662</span>    return this.drainingServers.remove(sn);<a name="line.662"></a>
-<span class="sourceLineNo">663</span>  }<a name="line.663"></a>
-<span class="sourceLineNo">664</span><a name="line.664"></a>
-<span class="sourceLineNo">665</span>  /**<a name="line.665"></a>
-<span class="sourceLineNo">666</span>   * Add the server to the drain list.<a name="line.666"></a>
-<span class="sourceLineNo">667</span>   * @param sn<a name="line.667"></a>
-<span class="sourceLineNo">668</span>   * @return True if the server is added or the server is already on the drain list.<a name="line.668"></a>
-<span class="sourceLineNo">669</span>   */<a name="line.669"></a>
-<span class="sourceLineNo">670</span>  public synchronized boolean addServerToDrainList(final ServerName sn) {<a name="line.670"></a>
-<span class="sourceLineNo">671</span>    // Warn if the server (sn) is not online.  ServerName is of the form:<a name="line.671"></a>
-<span class="sourceLineNo">672</span>    // &lt;hostname&gt; , &lt;port&gt; , &lt;startcode&gt;<a name="line.672"></a>
-<span class="sourceLineNo">673</span><a name="line.673"></a>
-<span class="sourceLineNo">674</span>    if (!this.isServerOnline(sn)) {<a name="line.674"></a>
-<span class="sourceLineNo">675</span>      LOG.warn("Server " + sn + " is not currently online. " +<a name="line.675"></a>
-<span class="sourceLineNo">676</span>               "Ignoring request to add it to draining list.");<a name="line.676"></a>
-<span class="sourceLineNo">677</span>      return false;<a name="line.677"></a>
-<span class="sourceLineNo">678</span>    }<a name="line.678"></a>
-<span class="sourceLineNo">679</span>    // Add the server to the draining servers lists, if it's not already in<a name="line.679"></a>
-<span class="sourceLineNo">680</span>    // it.<a name="line.680"></a>
-<span class="sourceLineNo">681</span>    if (this.drainingServers.contains(sn)) {<a name="line.681"></a>
-<span class="sourceLineNo">682</span>      LOG.warn("Server " + sn + " is already in the draining server list." +<a name="line.682"></a>
-<span class="sourceLineNo">683</span>               "Ignoring request to add it again.");<a name="line.683"></a>
-<span class="sourceLineNo">684</span>      return true;<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    }<a name="line.685"></a>
-<span class="sourceLineNo">686</span>    LOG.info("Server " + sn + " added to draining server list.");<a name="line.686"></a>
-<span class="sourceLineNo">687</span>    return this.drainingServers.add(sn);<a name="line.687"></a>
-<span class="sourceLineNo">688</span>  }<a name="line.688"></a>
-<span class="sourceLineNo">689</span><a name="line.689"></a>
-<span class="sourceLineNo">690</span>  /**<a name="line.690"></a>
-<span class="sourceLineNo">691</span>   * Contacts a region server and waits up to timeout ms<a name="line.691"></a>
-<span class="sourceLineNo">692</span>   * to close the region.  This bypasses the active hmaster.<a name="line.692"></a>
-<span class="sourceLineNo">693</span>   * Pass -1 as timeout if you do not want to wait on result.<a name="line.693"></a>
-<span class="sourceLineNo">694</span>   */<a name="line.694"></a>
-<span class="sourceLineNo">695</span>  public static void closeRegionSilentlyAndWait(AsyncClusterConnection connection,<a name="line.695"></a>
-<span class="sourceLineNo">696</span>      ServerName server, RegionInfo region, long timeout) throws IOException, InterruptedException {<a name="line.696"></a>
-<span class="sourceLineNo">697</span>    AsyncRegionServerAdmin admin = connection.getRegionServerAdmin(server);<a name="line.697"></a>
-<span class="sourceLineNo">698</span>    try {<a name="line.698"></a>
-<span class="sourceLineNo">699</span>      FutureUtils.get(<a name="line.699"></a>
-<span class="sourceLineNo">700</span>        admin.closeRegion(ProtobufUtil.buildCloseRegionRequest(server, region.getRegionName())));<a name="line.700"></a>
-<span class="sourceLineNo">701</span>    } catch (IOException e) {<a name="line.701"></a>
-<span class="sourceLineNo">702</span>      LOG.warn("Exception when closing region: " + region.getRegionNameAsString(), e);<a name="line.702"></a>
-<span class="sourceLineNo">703</span>    }<a name="line.703"></a>
-<span class="sourceLineNo">704</span>    if (timeout &lt; 0) {<a name="line.704"></a>
-<span class="sourceLineNo">705</span>      return;<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    }<a name="line.706"></a>
-<span class="sourceLineNo">707</span>    long expiration = timeout + System.currentTimeMillis();<a name="line.707"></a>
-<span class="sourceLineNo">708</span>    while (System.currentTimeMillis() &lt; expiration) {<a name="line.708"></a>
-<span class="sourceLineNo">709</span>      try {<a name="line.709"></a>
-<span class="sourceLineNo">710</span>        RegionInfo rsRegion = ProtobufUtil.toRegionInfo(FutureUtils<a name="line.710"></a>
-<span class="sourceLineNo">711</span>          .get(<a name="line.711"></a>
-<span class="sourceLineNo">712</span>            admin.getRegionInfo(RequestConverter.buildGetRegionInfoRequest(region.getRegionName())))<a name="line.712"></a>
-<span class="sourceLineNo">713</span>          .getRegionInfo());<a name="line.713"></a>
-<span class="sourceLineNo">714</span>        if (rsRegion == null) {<a name="line.714"></a>
-<span class="sourceLineNo">715</span>          return;<a name="line.715"></a>
-<span class="sourceLineNo">716</span>        }<a name="line.716"></a>
-<span class="sourceLineNo">717</span>      } catch (IOException ioe) {<a name="line.717"></a>
-<span class="sourceLineNo">718</span>        if (ioe instanceof NotServingRegionException) {<a name="line.718"></a>
-<span class="sourceLineNo">719</span>          // no need to retry again<a name="line.719"></a>
-<span class="sourceLineNo">720</span>          return;<a name="line.720"></a>
-<span class="sourceLineNo">721</span>        }<a name="line.721"></a>
-<span class="sourceLineNo">722</span>        LOG.warn("Exception when retrieving regioninfo from: " + region.getRegionNameAsString(),<a name="line.722"></a>
-<span class="sourceLineNo">723</span>          ioe);<a name="line.723"></a>
-<span class="sourceLineNo">724</span>      }<a name="line.724"></a>
-<span class="sourceLineNo">725</span>      Thread.sleep(1000);<a name="line.725"></a>
-<span class="sourceLineNo">726</span>    }<a name="line.726"></a>
-<span class="sourceLineNo">727</span>    throw new IOException("Region " + region + " failed to close within" + " timeout " + timeout);<a name="line.727"></a>
-<span class="sourceLineNo">728</span>  }<a name="line.728"></a>
-<span class="sourceLineNo">729</span><a name="line.729"></a>
-<span class="sourceLineNo">730</span>  /**<a name="line.730"></a>
-<span class="sourceLineNo">731</span>   * Calculate min necessary to start. This is not an absolute. It is just<a name="line.731"></a>
-<span class="sourceLineNo">732</span>   * a friction that will cause us hang around a bit longer waiting on<a name="line.732"></a>
-<span class="sourceLineNo">733</span>   * RegionServers to check-in.<a name="line.733"></a>
-<span class="sourceLineNo">734</span>   */<a name="line.734"></a>
-<span class="sourceLineNo">735</span>  private int getMinToStart() {<a name="line.735"></a>
-<span class="sourceLineNo">736</span>    if (master.isInMaintenanceMode()) {<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      // If in maintenance mode, then master hosting meta will be the only server available<a name="line.737"></a>
-<span class="sourceLineNo">738</span>      return 1;<a name="line.738"></a>
-<span class="sourceLineNo">739</span>    }<a name="line.739"></a>
-<span class="sourceLineNo">740</span><a name="line.740"></a>
-<span class="sourceLineNo">741</span>    int minimumRequired = 1;<a name="line.741"></a>
-<span class="sourceLineNo">742</span>    if (LoadBalancer.isTablesOnMaster(master.getConfiguration()) &amp;&amp;<a name="line.742"></a>
-<span class="sourceLineNo">743</span>        LoadBalancer.isSystemTablesOnlyOnMaster(master.getConfiguration())) {<a name="line.743"></a>
-<span class="sourceLineNo">744</span>      // If Master is carrying regions it will show up as a 'server', but is not handling user-<a name="line.744"></a>
-<span class="sourceLineNo">745</span>      // space regions, so we need a second server.<a name="line.745"></a>
-<span class="sourceLineNo">746</span>      minimumRequired = 2;<a name="line.746"></a>
-<span class="sourceLineNo">747</span>    }<a name="line.747"></a>
-<span class="sourceLineNo">748</span><a name="line.748"></a>
-<span class="sourceLineNo">749</span>    int minToStart = this.master.getConfiguration().getInt(WAIT_ON_REGIONSERVERS_MINTOSTART, -1);<a name="line.749"></a>
-<span class="sourceLineNo">750</span>    // Ensure we are never less than minimumRequired else stuff won't work.<a name="line.750"></a>
-<span class="sourceLineNo">751</span>    return Math.max(minToStart, minimumRequired);<a name="line.751"></a>
-<span class="sourceLineNo">752</span>  }<a name="line.752"></a>
-<span class="sourceLineNo">753</span><a name="line.753"></a>
-<span class="sourceLineNo">754</span>  /**<a name="line.754"></a>
-<span class="sourceLineNo">755</span>   * Wait for the region servers to report in.<a name="line.755"></a>
-<span class="sourceLineNo">756</span>   * We will wait until one of this condition is met:<a name="line.756"></a>
-<span class="sourceLineNo">757</span>   *  - the master is stopped<a name="line.757"></a>
-<span class="sourceLineNo">758</span>   *  - the 'hbase.master.wait.on.regionservers.maxtostart' number of<a name="line.758"></a>
-<span class="sourceLineNo">759</span>   *    region servers is reached<a name="line.759"></a>
-<span class="sourceLineNo">760</span>   *  - the 'hbase.master.wait.on.regionservers.mintostart' is reached AND<a name="line.760"></a>
-<span class="sourceLineNo">761</span>   *   there have been no new region server in for<a name="line.761"></a>
-<span class="sourceLineNo">762</span>   *      'hbase.master.wait.on.regionservers.interval' time AND<a name="line.762"></a>
-<span class="sourceLineNo">763</span>   *   the 'hbase.master.wait.on.regionservers.timeout' is reached<a name="line.763"></a>
-<span class="sourceLineNo">764</span>   *<a name="line.764"></a>
-<span class="sourceLineNo">765</span>   * @throws InterruptedException<a name="line.765"></a>
-<span class="sourceLineNo">766</span>   */<a name="line.766"></a>
-<span class="sourceLineNo">767</span>  public void waitForRegionServers(MonitoredTask status) throws InterruptedException {<a name="line.767"></a>
-<span class="sourceLineNo">768</span>    final long interval = this.master.getConfiguration().<a name="line.768"></a>
-<span class="sourceLineNo">769</span>        getLong(WAIT_ON_REGIONSERVERS_INTERVAL, 1500);<a name="line.769"></a>
-<span class="sourceLineNo">770</span>    final long timeout = this.master.getConfiguration().<a name="line.770"></a>
-<span class="sourceLineNo">771</span>        getLong(WAIT_ON_REGIONSERVERS_TIMEOUT, 4500);<a name="line.771"></a>
-<span class="sourceLineNo">772</span>    // Min is not an absolute; just a friction making us wait longer on server checkin.<a name="line.772"></a>
-<span class="sourceLineNo">773</span>    int minToStart = getMinToStart();<a name="line.773"></a>
-<span class="sourceLineNo">774</span>    int maxToStart = this.master.getConfiguration().<a name="line.774"></a>
-<span class="sourceLineNo">775</span>        getInt(WAIT_ON_REGIONSERVERS_MAXTOSTART, Integer.MAX_VALUE);<a name="line.775"></a>
-<span class="sourceLineNo">776</span>    if (maxToStart &lt; minToStart) {<a name="line.776"></a>
-<span class="sourceLineNo">777</span>      LOG.warn(String.format("The value of '%s' (%d) is set less than '%s' (%d), ignoring.",<a name="line.777"></a>
-<span class="sourceLineNo">778</span>          WAIT_ON_REGIONSERVERS_MAXTOSTART, maxToStart,<a name="line.778"></a>
-<span class="sourceLineNo">779</span>          WAIT_ON_REGIONSERVERS_MINTOSTART, minToStart));<a name="line.779"></a>
-<span class="sourceLineNo">780</span>      maxToStart = Integer.MAX_VALUE;<a name="line.780"></a>
-<span class="sourceLineNo">781</span>    }<a name="line.781"></a>
-<span class="sourceLineNo">782</span><a name="line.782"></a>
-<span class="sourceLineNo">783</span>    long now =  System.currentTimeMillis();<a name="line.783"></a>
-<span class="sourceLineNo">784</span>    final long startTime = now;<a name="line.784"></a>
-<span class="sourceLineNo">785</span>    long slept = 0;<a name="line.785"></a>
-<span class="sourceLineNo">786</span>    long lastLogTime = 0;<a name="line.786"></a>
-<span class="sourceLineNo">787</span>    long lastCountChange = startTime;<a name="line.787"></a>
-<span class="sourceLineNo">788</span>    int count = countOfRegionServers();<a name="line.788"></a>
-<span class="sourceLineNo">789</span>    int oldCount = 0;<a name="line.789"></a>
-<span class="sourceLineNo">790</span>    // This while test is a little hard to read. We try to comment it in below but in essence:<a name="line.790"></a>
-<span class="sourceLineNo">791</span>    // Wait if Master is not stopped and the number of regionservers that have checked-in is<a name="line.791"></a>
-<span class="sourceLineNo">792</span>    // less than the maxToStart. Both of these conditions will be true near universally.<a name="line.792"></a>
-<span class="sourceLineNo">793</span>    // Next, we will keep cycling if ANY of the following three conditions are true:<a name="line.793"></a>
-<span class="sourceLineNo">794</span>    // 1. The time since a regionserver registered is &lt; interval (means servers are actively checking in).<a name="line.794"></a>
-<span class="sourceLineNo">795</span>    // 2. We are under the total timeout.<a name="line.795"></a>
-<span class="sourceLineNo">796</span>    // 3. The count of servers is &lt; minimum.<a name="line.796"></a>
-<span class="sourceLineNo">797</span>    for (ServerListener listener: this.listeners) {<a name="line.797"></a>
-<span class="sourceLineNo">798</span>      listener.waiting();<a name="line.798"></a>
-<span class="sourceLineNo">799</span>    }<a name="line.799"></a>
-<span class="sourceLineNo">800</span>    while (!this.master.isStopped() &amp;&amp; !isClusterShutdown() &amp;&amp; count &lt; maxToStart &amp;&amp;<a name="line.800"></a>
-<span class="sourceLineNo">801</span>        ((lastCountChange + interval) &gt; now || timeout &gt; slept || count &lt; minToStart)) {<a name="line.801"></a>
-<span class="sourceLineNo">802</span>      // Log some info at every interval time or if there is a change<a name="line.802"></a>
-<span class="sourceLineNo">803</span>      if (oldCount != count || lastLogTime + interval &lt; now) {<a name="line.803"></a>
-<span class="sourceLineNo">804</span>        lastLogTime = now;<a name="line.804"></a>
-<span class="sourceLineNo">805</span>        String msg =<a name="line.805"></a>
-<span class="sourceLineNo">806</span>            "Waiting on regionserver count=" + count + "; waited="+<a name="line.806"></a>
-<span class="sourceLineNo">807</span>                slept + "ms, expecting min=" + minToStart + " server(s), max="+ getStrForMax(maxToStart) +<a name="line.807"></a>
-<span class="sourceLineNo">808</span>                " server(s), " + "timeout=" + timeout + "ms, lastChange=" + (lastCountChange - now) + "ms";<a name="line.808"></a>
-<span class="sourceLineNo">809</span>        LOG.info(msg);<a name="line.809"></a>
-<span class="sourceLineNo">810</span>        status.setStatus(msg);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>      }<a name="line.811"></a>
-<span class="sourceLineNo">812</span><a name="line.812"></a>
-<span class="sourceLineNo">813</span>      // We sleep for some time<a name="line.813"></a>
-<span class="sourceLineNo">814</span>      final long sleepTime = 50;<a name="line.814"></a>
-<span class="sourceLineNo">815</span>      Thread.sleep(sleepTime);<a name="line.815"></a>
-<span class="sourceLineNo">816</span>      now =  System.currentTimeMillis();<a name="line.816"></a>
-<span class="sourceLineNo">817</span>      slept = now - startTime;<a name="line.817"></a>
-<span class="sourceLineNo">818</span><a name="line.818"></a>
-<span class="sourceLineNo">819</span>      oldCount = count;<a name="line.819"></a>
-<span class="sourceLineNo">820</span>      count = countOfRegionServers();<a name="line.820"></a>
-<span class="sourceLineNo">821</span>      if (count != oldCount) {<a name="line.821"></a>
-<span class="sourceLineNo">822</span>        lastCountChange = now;<a name="line.822"></a>
-<span class="sourceLineNo">823</span>      }<a name="line.823"></a>
-<span class="sourceLineNo">824</span>    }<a name="line.824"></a>
-<span class="sourceLineNo">825</span>    // Did we exit the loop because cluster is going down?<a name="line.825"></a>
-<span class="sourceLineNo">826</span>    if (isClusterShutdown()) {<a name="line.826"></a>
-<span class="sourceLineNo">827</span>      this.master.stop("Cluster shutdown");<a name="line.827"></a>
+<span class="sourceLineNo">154</span><a name="line.154"></a>
+<span class="sourceLineNo">155</span>  /**<a name="line.155"></a>
+<span class="sourceLineNo">156</span>   * The last flushed sequence id for a store in a region.<a name="line.156"></a>
+<span class="sourceLineNo">157</span>   */<a name="line.157"></a>
+<span class="sourceLineNo">158</span>  private final ConcurrentNavigableMap&lt;byte[], ConcurrentNavigableMap&lt;byte[], Long&gt;&gt;<a name="line.158"></a>
+<span class="sourceLineNo">159</span>    storeFlushedSequenceIdsByRegion = new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.159"></a>
+<span class="sourceLineNo">160</span><a name="line.160"></a>
+<span class="sourceLineNo">161</span>  /** Map of registered servers to their current load */<a name="line.161"></a>
+<span class="sourceLineNo">162</span>  private final ConcurrentNavigableMap&lt;ServerName, ServerMetrics&gt; onlineServers =<a name="line.162"></a>
+<span class="sourceLineNo">163</span>    new ConcurrentSkipListMap&lt;&gt;();<a name="line.163"></a>
+<span class="sourceLineNo">164</span><a name="line.164"></a>
+<span class="sourceLineNo">165</span>  /** List of region servers that should not get any more new regions. */<a name="line.165"></a>
+<span class="sourceLineNo">166</span>  private final ArrayList&lt;ServerName&gt; drainingServers = new ArrayList&lt;&gt;();<a name="line.166"></a>
+<span class="sourceLineNo">167</span><a name="line.167"></a>
+<span class="sourceLineNo">168</span>  private final MasterServices master;<a name="line.168"></a>
+<span class="sourceLineNo">169</span><a name="line.169"></a>
+<span class="sourceLineNo">170</span>  private final DeadServer deadservers = new DeadServer();<a name="line.170"></a>
+<span class="sourceLineNo">171</span><a name="line.171"></a>
+<span class="sourceLineNo">172</span>  private final long maxSkew;<a name="line.172"></a>
+<span class="sourceLineNo">173</span>  private final long warningSkew;<a name="line.173"></a>
+<span class="sourceLineNo">174</span><a name="line.174"></a>
+<span class="sourceLineNo">175</span>  /** Listeners that are called on server events. */<a name="line.175"></a>
+<span class="sourceLineNo">176</span>  private List&lt;ServerListener&gt; listeners = new CopyOnWriteArrayList&lt;&gt;();<a name="line.176"></a>
+<span class="sourceLineNo">177</span><a name="line.177"></a>
+<span class="sourceLineNo">178</span>  /**<a name="line.178"></a>
+<span class="sourceLineNo">179</span>   * Constructor.<a name="line.179"></a>
+<span class="sourceLineNo">180</span>   */<a name="line.180"></a>
+<span class="sourceLineNo">181</span>  public ServerManager(final MasterServices master) {<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    this.master = master;<a name="line.182"></a>
+<span class="sourceLineNo">183</span>    Configuration c = master.getConfiguration();<a name="line.183"></a>
+<span class="sourceLineNo">184</span>    maxSkew = c.getLong(MAX_CLOCK_SKEW_MS, 30000);<a name="line.184"></a>
+<span class="sourceLineNo">185</span>    warningSkew = c.getLong("hbase.master.warningclockskew", 10000);<a name="line.185"></a>
+<span class="sourceLineNo">186</span>    persistFlushedSequenceId = c.getBoolean(PERSIST_FLUSHEDSEQUENCEID,<a name="line.186"></a>
+<span class="sourceLineNo">187</span>        PERSIST_FLUSHEDSEQUENCEID_DEFAULT);<a name="line.187"></a>
+<span class="sourceLineNo">188</span>  }<a name="line.188"></a>
+<span class="sourceLineNo">189</span><a name="line.189"></a>
+<span class="sourceLineNo">190</span>  /**<a name="line.190"></a>
+<span class="sourceLineNo">191</span>   * Add the listener to the notification list.<a name="line.191"></a>
+<span class="sourceLineNo">192</span>   * @param listener The ServerListener to register<a name="line.192"></a>
+<span class="sourceLineNo">193</span>   */<a name="line.193"></a>
+<span class="sourceLineNo">194</span>  public void registerListener(final ServerListener listener) {<a name="line.194"></a>
+<span class="sourceLineNo">195</span>    this.listeners.add(listener);<a name="line.195"></a>
+<span class="sourceLineNo">196</span>  }<a name="line.196"></a>
+<span class="sourceLineNo">197</span><a name="line.197"></a>
+<span class="sourceLineNo">198</span>  /**<a name="line.198"></a>
+<span class="sourceLineNo">199</span>   * Remove the listener from the notification list.<a name="line.199"></a>
+<span class="sourceLineNo">200</span>   * @param listener The ServerListener to unregister<a name="line.200"></a>
+<span class="sourceLineNo">201</span>   */<a name="line.201"></a>
+<span class="sourceLineNo">202</span>  public boolean unregisterListener(final ServerListener listener) {<a name="line.202"></a>
+<span class="sourceLineNo">203</span>    return this.listeners.remove(listener);<a name="line.203"></a>
+<span class="sourceLineNo">204</span>  }<a name="line.204"></a>
+<span class="sourceLineNo">205</span><a name="line.205"></a>
+<span class="sourceLineNo">206</span>  /**<a name="line.206"></a>
+<span class="sourceLineNo">207</span>   * Let the server manager know a new regionserver has come online<a name="line.207"></a>
+<span class="sourceLineNo">208</span>   * @param request the startup request<a name="line.208"></a>
+<span class="sourceLineNo">209</span>   * @param versionNumber the version number of the new regionserver<a name="line.209"></a>
+<span class="sourceLineNo">210</span>   * @param version the version of the new regionserver, could contain strings like "SNAPSHOT"<a name="line.210"></a>
+<span class="sourceLineNo">211</span>   * @param ia the InetAddress from which request is received<a name="line.211"></a>
+<span class="sourceLineNo">212</span>   * @return The ServerName we know this server as.<a name="line.212"></a>
+<span class="sourceLineNo">213</span>   * @throws IOException<a name="line.213"></a>
+<span class="sourceLineNo">214</span>   */<a name="line.214"></a>
+<span class="sourceLineNo">215</span>  ServerName regionServerStartup(RegionServerStartupRequest request, int versionNumber,<a name="line.215"></a>
+<span class="sourceLineNo">216</span>      String version, InetAddress ia) throws IOException {<a name="line.216"></a>
+<span class="sourceLineNo">217</span>    // Test for case where we get a region startup message from a regionserver<a name="line.217"></a>
+<span class="sourceLineNo">218</span>    // that has been quickly restarted but whose znode expiration handler has<a name="line.218"></a>
+<span class="sourceLineNo">219</span>    // not yet run, or from a server whose fail we are currently processing.<a name="line.219"></a>
+<span class="sourceLineNo">220</span>    // Test its host+port combo is present in serverAddressToServerInfo. If it<a name="line.220"></a>
+<span class="sourceLineNo">221</span>    // is, reject the server and trigger its expiration. The next time it comes<a name="line.221"></a>
+<span class="sourceLineNo">222</span>    // in, it should have been removed from serverAddressToServerInfo and queued<a name="line.222"></a>
+<span class="sourceLineNo">223</span>    // for processing by ProcessServerShutdown.<a name="line.223"></a>
+<span class="sourceLineNo">224</span><a name="line.224"></a>
+<span class="sourceLineNo">225</span>    final String hostname =<a name="line.225"></a>
+<span class="sourceLineNo">226</span>      request.hasUseThisHostnameInstead() ? request.getUseThisHostnameInstead() : ia.getHostName();<a name="line.226"></a>
+<span class="sourceLineNo">227</span>    ServerName sn = ServerName.valueOf(hostname, request.getPort(), request.getServerStartCode());<a name="line.227"></a>
+<span class="sourceLineNo">228</span>    checkClockSkew(sn, request.getServerCurrentTime());<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    checkIsDead(sn, "STARTUP");<a name="line.229"></a>
+<span class="sourceLineNo">230</span>    if (!checkAndRecordNewServer(sn, ServerMetricsBuilder.of(sn, versionNumber, version))) {<a name="line.230"></a>
+<span class="sourceLineNo">231</span>      LOG.warn(<a name="line.231"></a>
+<span class="sourceLineNo">232</span>        "THIS SHOULD NOT HAPPEN, RegionServerStartup" + " could not record the server: " + sn);<a name="line.232"></a>
+<span class="sourceLineNo">233</span>    }<a name="line.233"></a>
+<span class="sourceLineNo">234</span>    return sn;<a name="line.234"></a>
+<span class="sourceLineNo">235</span>  }<a name="line.235"></a>
+<span class="sourceLineNo">236</span><a name="line.236"></a>
+<span class="sourceLineNo">237</span>  /**<a name="line.237"></a>
+<span class="sourceLineNo">238</span>   * Updates last flushed sequence Ids for the regions on server sn<a name="line.238"></a>
+<span class="sourceLineNo">239</span>   * @param sn<a name="line.239"></a>
+<span class="sourceLineNo">240</span>   * @param hsl<a name="line.240"></a>
+<span class="sourceLineNo">241</span>   */<a name="line.241"></a>
+<span class="sourceLineNo">242</span>  private void updateLastFlushedSequenceIds(ServerName sn, ServerMetrics hsl) {<a name="line.242"></a>
+<span class="sourceLineNo">243</span>    for (Entry&lt;byte[], RegionMetrics&gt; entry : hsl.getRegionMetrics().entrySet()) {<a name="line.243"></a>
+<span class="sourceLineNo">244</span>      byte[] encodedRegionName = Bytes.toBytes(RegionInfo.encodeRegionName(entry.getKey()));<a name="line.244"></a>
+<span class="sourceLineNo">245</span>      Long existingValue = flushedSequenceIdByRegion.get(encodedRegionName);<a name="line.245"></a>
+<span class="sourceLineNo">246</span>      long l = entry.getValue().getCompletedSequenceId();<a name="line.246"></a>
+<span class="sourceLineNo">247</span>      // Don't let smaller sequence ids override greater sequence ids.<a name="line.247"></a>
+<span class="sourceLineNo">248</span>      if (LOG.isTraceEnabled()) {<a name="line.248"></a>
+<span class="sourceLineNo">249</span>        LOG.trace(Bytes.toString(encodedRegionName) + ", existingValue=" + existingValue +<a name="line.249"></a>
+<span class="sourceLineNo">250</span>          ", completeSequenceId=" + l);<a name="line.250"></a>
+<span class="sourceLineNo">251</span>      }<a name="line.251"></a>
+<span class="sourceLineNo">252</span>      if (existingValue == null || (l != HConstants.NO_SEQNUM &amp;&amp; l &gt; existingValue)) {<a name="line.252"></a>
+<span class="sourceLineNo">253</span>        flushedSequenceIdByRegion.put(encodedRegionName, l);<a name="line.253"></a>
+<span class="sourceLineNo">254</span>      } else if (l != HConstants.NO_SEQNUM &amp;&amp; l &lt; existingValue) {<a name="line.254"></a>
+<span class="sourceLineNo">255</span>        LOG.warn("RegionServer " + sn + " indicates a last flushed sequence id ("<a name="line.255"></a>
+<span class="sourceLineNo">256</span>            + l + ") that is less than the previous last flushed sequence id ("<a name="line.256"></a>
+<span class="sourceLineNo">257</span>            + existingValue + ") for region " + Bytes.toString(entry.getKey()) + " Ignoring.");<a name="line.257"></a>
+<span class="sourceLineNo">258</span>      }<a name="line.258"></a>
+<span class="sourceLineNo">259</span>      ConcurrentNavigableMap&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.259"></a>
+<span class="sourceLineNo">260</span>          computeIfAbsent(storeFlushedSequenceIdsByRegion, encodedRegionName,<a name="line.260"></a>
+<span class="sourceLineNo">261</span>            () -&gt; new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR));<a name="line.261"></a>
+<span class="sourceLineNo">262</span>      for (Entry&lt;byte[], Long&gt; storeSeqId : entry.getValue().getStoreSequenceId().entrySet()) {<a name="line.262"></a>
+<span class="sourceLineNo">263</span>        byte[] family = storeSeqId.getKey();<a name="line.263"></a>
+<span class="sourceLineNo">264</span>        existingValue = storeFlushedSequenceId.get(family);<a name="line.264"></a>
+<span class="sourceLineNo">265</span>        l = storeSeqId.getValue();<a name="line.265"></a>
+<span class="sourceLineNo">266</span>        if (LOG.isTraceEnabled()) {<a name="line.266"></a>
+<span class="sourceLineNo">267</span>          LOG.trace(Bytes.toString(encodedRegionName) + ", family=" + Bytes.toString(family) +<a name="line.267"></a>
+<span class="sourceLineNo">268</span>            ", existingValue=" + existingValue + ", completeSequenceId=" + l);<a name="line.268"></a>
+<span class="sourceLineNo">269</span>        }<a name="line.269"></a>
+<span class="sourceLineNo">270</span>        // Don't let smaller sequence ids override greater sequence ids.<a name="line.270"></a>
+<span class="sourceLineNo">271</span>        if (existingValue == null || (l != HConstants.NO_SEQNUM &amp;&amp; l &gt; existingValue.longValue())) {<a name="line.271"></a>
+<span class="sourceLineNo">272</span>          storeFlushedSequenceId.put(family, l);<a name="line.272"></a>
+<span class="sourceLineNo">273</span>        }<a name="line.273"></a>
+<span class="sourceLineNo">274</span>      }<a name="line.274"></a>
+<span class="sourceLineNo">275</span>    }<a name="line.275"></a>
+<span class="sourceLineNo">276</span>  }<a name="line.276"></a>
+<span class="sourceLineNo">277</span><a name="line.277"></a>
+<span class="sourceLineNo">278</span>  @VisibleForTesting<a name="line.278"></a>
+<span class="sourceLineNo">279</span>  public void regionServerReport(ServerName sn,<a name="line.279"></a>
+<span class="sourceLineNo">280</span>    ServerMetrics sl) throws YouAreDeadException {<a name="line.280"></a>
+<span class="sourceLineNo">281</span>    checkIsDead(sn, "REPORT");<a name="line.281"></a>
+<span class="sourceLineNo">282</span>    if (null == this.onlineServers.replace(sn, sl)) {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>      // Already have this host+port combo and its just different start code?<a name="line.283"></a>
+<span class="sourceLineNo">284</span>      // Just let the server in. Presume master joining a running cluster.<a name="line.284"></a>
+<span class="sourceLineNo">285</span>      // recordNewServer is what happens at the end of reportServerStartup.<a name="line.285"></a>
+<span class="sourceLineNo">286</span>      // The only thing we are skipping is passing back to the regionserver<a name="line.286"></a>
+<span class="sourceLineNo">287</span>      // the ServerName to use. Here we presume a master has already done<a name="line.287"></a>
+<span class="sourceLineNo">288</span>      // that so we'll press on with whatever it gave us for ServerName.<a name="line.288"></a>
+<span class="sourceLineNo">289</span>      if (!checkAndRecordNewServer(sn, sl)) {<a name="line.289"></a>
+<span class="sourceLineNo">290</span>        LOG.info("RegionServerReport ignored, could not record the server: " + sn);<a name="line.290"></a>
+<span class="sourceLineNo">291</span>        return; // Not recorded, so no need to move on<a name="line.291"></a>
+<span class="sourceLineNo">292</span>      }<a name="line.292"></a>
+<span class="sourceLineNo">293</span>    }<a name="line.293"></a>
+<span class="sourceLineNo">294</span>    updateLastFlushedSequenceIds(sn, sl);<a name="line.294"></a>
+<span class="sourceLineNo">295</span>  }<a name="line.295"></a>
+<span class="sourceLineNo">296</span><a name="line.296"></a>
+<span class="sourceLineNo">297</span>  /**<a name="line.297"></a>
+<span class="sourceLineNo">298</span>   * Check is a server of same host and port already exists,<a name="line.298"></a>
+<span class="sourceLineNo">299</span>   * if not, or the existed one got a smaller start code, record it.<a name="line.299"></a>
+<span class="sourceLineNo">300</span>   *<a name="line.300"></a>
+<span class="sourceLineNo">301</span>   * @param serverName the server to check and record<a name="line.301"></a>
+<span class="sourceLineNo">302</span>   * @param sl the server load on the server<a name="line.302"></a>
+<span class="sourceLineNo">303</span>   * @return true if the server is recorded, otherwise, false<a name="line.303"></a>
+<span class="sourceLineNo">304</span>   */<a name="line.304"></a>
+<span class="sourceLineNo">305</span>  boolean checkAndRecordNewServer(final ServerName serverName, final ServerMetrics sl) {<a name="line.305"></a>
+<span class="sourceLineNo">306</span>    ServerName existingServer = null;<a name="line.306"></a>
+<span class="sourceLineNo">307</span>    synchronized (this.onlineServers) {<a name="line.307"></a>
+<span class="sourceLineNo">308</span>      existingServer = findServerWithSameHostnamePortWithLock(serverName);<a name="line.308"></a>
+<span class="sourceLineNo">309</span>      if (existingServer != null &amp;&amp; (existingServer.getStartcode() &gt; serverName.getStartcode())) {<a name="line.309"></a>
+<span class="sourceLineNo">310</span>        LOG.info("Server serverName=" + serverName + " rejected; we already have "<a name="line.310"></a>
+<span class="sourceLineNo">311</span>            + existingServer.toString() + " registered with same hostname and port");<a name="line.311"></a>
+<span class="sourceLineNo">312</span>        return false;<a name="line.312"></a>
+<span class="sourceLineNo">313</span>      }<a name="line.313"></a>
+<span class="sourceLineNo">314</span>      recordNewServerWithLock(serverName, sl);<a name="line.314"></a>
+<span class="sourceLineNo">315</span>    }<a name="line.315"></a>
+<span class="sourceLineNo">316</span><a name="line.316"></a>
+<span class="sourceLineNo">317</span>    // Tell our listeners that a server was added<a name="line.317"></a>
+<span class="sourceLineNo">318</span>    if (!this.listeners.isEmpty()) {<a name="line.318"></a>
+<span class="sourceLineNo">319</span>      for (ServerListener listener : this.listeners) {<a name="line.319"></a>
+<span class="sourceLineNo">320</span>        listener.serverAdded(serverName);<a name="line.320"></a>
+<span class="sourceLineNo">321</span>      }<a name="line.321"></a>
+<span class="sourceLineNo">322</span>    }<a name="line.322"></a>
+<span class="sourceLineNo">323</span><a name="line.323"></a>
+<span class="sourceLineNo">324</span>    // Note that we assume that same ts means same server, and don't expire in that case.<a name="line.324"></a>
+<span class="sourceLineNo">325</span>    //  TODO: ts can theoretically collide due to clock shifts, so this is a bit hacky.<a name="line.325"></a>
+<span class="sourceLineNo">326</span>    if (existingServer != null &amp;&amp;<a name="line.326"></a>
+<span class="sourceLineNo">327</span>        (existingServer.getStartcode() &lt; serverName.getStartcode())) {<a name="line.327"></a>
+<span class="sourceLineNo">328</span>      LOG.info("Triggering server recovery; existingServer " +<a name="line.328"></a>
+<span class="sourceLineNo">329</span>          existingServer + " looks stale, new server:" + serverName);<a name="line.329"></a>
+<span class="sourceLineNo">330</span>      expireServer(existingServer);<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    }<a name="line.331"></a>
+<span class="sourceLineNo">332</span>    return true;<a name="line.332"></a>
+<span class="sourceLineNo">333</span>  }<a name="line.333"></a>
+<span class="sourceLineNo">334</span><a name="line.334"></a>
+<span class="sourceLineNo">335</span>  /**<a name="line.335"></a>
+<span class="sourceLineNo">336</span>   * Find out the region servers crashed between the crash of the previous master instance and the<a name="line.336"></a>
+<span class="sourceLineNo">337</span>   * current master instance and schedule SCP for them.<a name="line.337"></a>
+<span class="sourceLineNo">338</span>   * &lt;p/&gt;<a name="line.338"></a>
+<span class="sourceLineNo">339</span>   * Since the {@code RegionServerTracker} has already helped us to construct the online servers set<a name="line.339"></a>
+<span class="sourceLineNo">340</span>   * by scanning zookeeper, now we can compare the online servers with {@code liveServersFromWALDir}<a name="line.340"></a>
+<span class="sourceLineNo">341</span>   * to find out whether there are servers which are already dead.<a name="line.341"></a>
+<span class="sourceLineNo">342</span>   * &lt;p/&gt;<a name="line.342"></a>
+<span class="sourceLineNo">343</span>   * Must be called inside the initialization method of {@code RegionServerTracker} to avoid<a name="line.343"></a>
+<span class="sourceLineNo">344</span>   * concurrency issue.<a name="line.344"></a>
+<span class="sourceLineNo">345</span>   * @param deadServersFromPE the region servers which already have a SCP associated.<a name="line.345"></a>
+<span class="sourceLineNo">346</span>   * @param liveServersFromWALDir the live region servers from wal directory.<a name="line.346"></a>
+<span class="sourceLineNo">347</span>   */<a name="line.347"></a>
+<span class="sourceLineNo">348</span>  void findDeadServersAndProcess(Set&lt;ServerName&gt; deadServersFromPE,<a name="line.348"></a>
+<span class="sourceLineNo">349</span>      Set&lt;ServerName&gt; liveServersFromWALDir) {<a name="line.349"></a>
+<span class="sourceLineNo">350</span>    deadServersFromPE.forEach(deadservers::putIfAbsent);<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    liveServersFromWALDir.stream().filter(sn -&gt; !onlineServers.containsKey(sn))<a name="line.351"></a>
+<span class="sourceLineNo">352</span>      .forEach(this::expireServer);<a name="line.352"></a>
+<span class="sourceLineNo">353</span>  }<a name="line.353"></a>
+<span class="sourceLineNo">354</span><a name="line.354"></a>
+<span class="sourceLineNo">355</span>  /**<a name="line.355"></a>
+<span class="sourceLineNo">356</span>   * Checks if the clock skew between the server and the master. If the clock skew exceeds the<a name="line.356"></a>
+<span class="sourceLineNo">357</span>   * configured max, it will throw an exception; if it exceeds the configured warning threshold,<a name="line.357"></a>
+<span class="sourceLineNo">358</span>   * it will log a warning but start normally.<a name="line.358"></a>
+<span class="sourceLineNo">359</span>   * @param serverName Incoming servers's name<a name="line.359"></a>
+<span class="sourceLineNo">360</span>   * @param serverCurrentTime<a name="line.360"></a>
+<span class="sourceLineNo">361</span>   * @throws ClockOutOfSyncException if the skew exceeds the configured max value<a name="line.361"></a>
+<span class="sourceLineNo">362</span>   */<a name="line.362"></a>
+<span class="sourceLineNo">363</span>  private void checkClockSkew(final ServerName serverName, final long serverCurrentTime)<a name="line.363"></a>
+<span class="sourceLineNo">364</span>      throws ClockOutOfSyncException {<a name="line.364"></a>
+<span class="sourceLineNo">365</span>    long skew = Math.abs(EnvironmentEdgeManager.currentTime() - serverCurrentTime);<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    if (skew &gt; maxSkew) {<a name="line.366"></a>
+<span class="sourceLineNo">367</span>      String message = "Server " + serverName + " has been " +<a name="line.367"></a>
+<span class="sourceLineNo">368</span>        "rejected; Reported time is too far out of sync with master.  " +<a name="line.368"></a>
+<span class="sourceLineNo">369</span>        "Time difference of " + skew + "ms &gt; max allowed of " + maxSkew + "ms";<a name="line.369"></a>
+<span class="sourceLineNo">370</span>      LOG.warn(message);<a name="line.370"></a>
+<span class="sourceLineNo">371</span>      throw new ClockOutOfSyncException(message);<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    } else if (skew &gt; warningSkew){<a name="line.372"></a>
+<span class="sourceLineNo">373</span>      String message = "Reported time for server " + serverName + " is out of sync with master " +<a name="line.373"></a>
+<span class="sourceLineNo">374</span>        "by " + skew + "ms. (Warning threshold is " + warningSkew + "ms; " +<a name="line.374"></a>
+<span class="sourceLineNo">375</span>        "error threshold is " + maxSkew + "ms)";<a name="line.375"></a>
+<span class="sourceLineNo">376</span>      LOG.warn(message);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    }<a name="line.377"></a>
+<span class="sourceLineNo">378</span>  }<a name="line.378"></a>
+<span class="sourceLineNo">379</span><a name="line.379"></a>
+<span class="sourceLineNo">380</span>  /**<a name="line.380"></a>
+<span class="sourceLineNo">381</span>   * Called when RegionServer first reports in for duty and thereafter each<a name="line.381"></a>
+<span class="sourceLineNo">382</span>   * time it heartbeats to make sure it is has not been figured for dead.<a name="line.382"></a>
+<span class="sourceLineNo">383</span>   * If this server is on the dead list, reject it with a YouAreDeadException.<a name="line.383"></a>
+<span class="sourceLineNo">384</span>   * If it was dead but came back with a new start code, remove the old entry<a name="line.384"></a>
+<span class="sourceLineNo">385</span>   * from the dead list.<a name="line.385"></a>
+<span class="sourceLineNo">386</span>   * @param what START or REPORT<a name="line.386"></a>
+<span class="sourceLineNo">387</span>   */<a name="line.387"></a>
+<span class="sourceLineNo">388</span>  private void checkIsDead(final ServerName serverName, final String what)<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      throws YouAreDeadException {<a name="line.389"></a>
+<span class="sourceLineNo">390</span>    if (this.deadservers.isDeadServer(serverName)) {<a name="line.390"></a>
+<span class="sourceLineNo">391</span>      // Exact match: host name, port and start code all match with existing one of the<a name="line.391"></a>
+<span class="sourceLineNo">392</span>      // dead servers. So, this server must be dead. Tell it to kill itself.<a name="line.392"></a>
+<span class="sourceLineNo">393</span>      String message = "Server " + what + " rejected; currently processing " +<a name="line.393"></a>
+<span class="sourceLineNo">394</span>          serverName + " as dead server";<a name="line.394"></a>
+<span class="sourceLineNo">395</span>      LOG.debug(message);<a name="line.395"></a>
+<span class="sourceLineNo">396</span>      throw new YouAreDeadException(message);<a name="line.396"></a>
+<span class="sourceLineNo">397</span>    }<a name="line.397"></a>
+<span class="sourceLineNo">398</span>    // Remove dead server with same hostname and port of newly checking in rs after master<a name="line.398"></a>
+<span class="sourceLineNo">399</span>    // initialization. See HBASE-5916 for more information.<a name="line.399"></a>
+<span class="sourceLineNo">400</span>    if ((this.master == null || this.master.isInitialized()) &amp;&amp;<a name="line.400"></a>
+<span class="sourceLineNo">401</span>        this.deadservers.cleanPreviousInstance(serverName)) {<a name="line.401"></a>
+<span class="sourceLineNo">402</span>      // This server has now become alive after we marked it as dead.<a name="line.402"></a>
+<span class="sourceLineNo">403</span>      // We removed it's previous entry from the dead list to reflect it.<a name="line.403"></a>
+<span class="sourceLineNo">404</span>      LOG.debug("{} {} came back up, removed it from the dead servers list", what, serverName);<a name="line.404"></a>
+<span class="sourceLineNo">405</span>    }<a name="line.405"></a>
+<span class="sourceLineNo">406</span>  }<a name="line.406"></a>
+<span class="sourceLineNo">407</span><a name="line.407"></a>
+<span class="sourceLineNo">408</span>  /**<a name="line.408"></a>
+<span class="sourceLineNo">409</span>   * Assumes onlineServers is locked.<a name="line.409"></a>
+<span class="sourceLineNo">410</span>   * @return ServerName with matching hostname and port.<a name="line.410"></a>
+<span class="sourceLineNo">411</span>   */<a name="line.411"></a>
+<span class="sourceLineNo">412</span>  private ServerName findServerWithSameHostnamePortWithLock(<a name="line.412"></a>
+<span class="sourceLineNo">413</span>      final ServerName serverName) {<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    ServerName end = ServerName.valueOf(serverName.getHostname(), serverName.getPort(),<a name="line.414"></a>
+<span class="sourceLineNo">415</span>        Long.MAX_VALUE);<a name="line.415"></a>
+<span class="sourceLineNo">416</span><a name="line.416"></a>
+<span class="sourceLineNo">417</span>    ServerName r = onlineServers.lowerKey(end);<a name="line.417"></a>
+<span class="sourceLineNo">418</span>    if (r != null) {<a name="line.418"></a>
+<span class="sourceLineNo">419</span>      if (ServerName.isSameAddress(r, serverName)) {<a name="line.419"></a>
+<span class="sourceLineNo">420</span>        return r;<a name="line.420"></a>
+<span class="sourceLineNo">421</span>      }<a name="line.421"></a>
+<span class="sourceLineNo">422</span>    }<a name="line.422"></a>
+<span class="sourceLineNo">423</span>    return null;<a name="line.423"></a>
+<span class="sourceLineNo">424</span>  }<a name="line.424"></a>
+<span class="sourceLineNo">425</span><a name="line.425"></a>
+<span class="sourceLineNo">426</span>  /**<a name="line.426"></a>
+<span class="sourceLineNo">427</span>   * Adds the onlineServers list. onlineServers should be locked.<a name="line.427"></a>
+<span class="sourceLineNo">428</span>   * @param serverName The remote servers name.<a name="line.428"></a>
+<span class="sourceLineNo">429</span>   */<a name="line.429"></a>
+<span class="sourceLineNo">430</span>  @VisibleForTesting<a name="line.430"></a>
+<span class="sourceLineNo">431</span>  void recordNewServerWithLock(final ServerName serverName, final ServerMetrics sl) {<a name="line.431"></a>
+<span class="sourceLineNo">432</span>    LOG.info("Registering regionserver=" + serverName);<a name="line.432"></a>
+<span class="sourceLineNo">433</span>    this.onlineServers.put(serverName, sl);<a name="line.433"></a>
+<span class="sourceLineNo">434</span>  }<a name="line.434"></a>
+<span class="sourceLineNo">435</span><a name="line.435"></a>
+<span class="sourceLineNo">436</span>  @VisibleForTesting<a name="line.436"></a>
+<span class="sourceLineNo">437</span>  public ConcurrentNavigableMap&lt;byte[], Long&gt; getFlushedSequenceIdByRegion() {<a name="line.437"></a>
+<span class="sourceLineNo">438</span>    return flushedSequenceIdByRegion;<a name="line.438"></a>
+<span class="sourceLineNo">439</span>  }<a name="line.439"></a>
+<span class="sourceLineNo">440</span><a name="line.440"></a>
+<span class="sourceLineNo">441</span>  public RegionStoreSequenceIds getLastFlushedSequenceId(byte[] encodedRegionName) {<a name="line.441"></a>
+<span class="sourceLineNo">442</span>    RegionStoreSequenceIds.Builder builder = RegionStoreSequenceIds.newBuilder();<a name="line.442"></a>
+<span class="sourceLineNo">443</span>    Long seqId = flushedSequenceIdByRegion.get(encodedRegionName);<a name="line.443"></a>
+<span class="sourceLineNo">444</span>    builder.setLastFlushedSequenceId(seqId != null ? seqId.longValue() : HConstants.NO_SEQNUM);<a name="line.444"></a>
+<span class="sourceLineNo">445</span>    Map&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.445"></a>
+<span class="sourceLineNo">446</span>        storeFlushedSequenceIdsByRegion.get(encodedRegionName);<a name="line.446"></a>
+<span class="sourceLineNo">447</span>    if (storeFlushedSequenceId != null) {<a name="line.447"></a>
+<span class="sourceLineNo">448</span>      for (Map.Entry&lt;byte[], Long&gt; entry : storeFlushedSequenceId.entrySet()) {<a name="line.448"></a>
+<span class="sourceLineNo">449</span>        builder.addStoreSequenceId(StoreSequenceId.newBuilder()<a name="line.449"></a>
+<span class="sourceLineNo">450</span>            .setFamilyName(UnsafeByteOperations.unsafeWrap(entry.getKey()))<a name="line.450"></a>
+<span class="sourceLineNo">451</span>            .setSequenceId(entry.getValue().longValue()).build());<a name="line.451"></a>
+<span class="sourceLineNo">452</span>      }<a name="line.452"></a>
+<span class="sourceLineNo">453</span>    }<a name="line.453"></a>
+<span class="sourceLineNo">454</span>    return builder.build();<a name="line.454"></a>
+<span class="sourceLineNo">455</span>  }<a name="line.455"></a>
+<span class="sourceLineNo">456</span><a name="line.456"></a>
+<span class="sourceLineNo">457</span>  /**<a name="line.457"></a>
+<span class="sourceLineNo">458</span>   * @param serverName<a name="line.458"></a>
+<span class="sourceLineNo">459</span>   * @return ServerMetrics if serverName is known else null<a name="line.459"></a>
+<span class="sourceLineNo">460</span>   */<a name="line.460"></a>
+<span class="sourceLineNo">461</span>  public ServerMetrics getLoad(final ServerName serverName) {<a name="line.461"></a>
+<span class="sourceLineNo">462</span>    return this.onlineServers.get(serverName);<a name="line.462"></a>
+<span class="sourceLineNo">463</span>  }<a name="line.463"></a>
+<span class="sourceLineNo">464</span><a name="line.464"></a>
+<span class="sourceLineNo">465</span>  /**<a name="line.465"></a>
+<span class="sourceLineNo">466</span>   * Compute the average load across all region servers.<a name="line.466"></a>
+<span class="sourceLineNo">467</span>   * Currently, this uses a very naive computation - just uses the number of<a name="line.467"></a>
+<span class="sourceLineNo">468</span>   * regions being served, ignoring stats about number of requests.<a name="line.468"></a>
+<span class="sourceLineNo">469</span>   * @return the average load<a name="line.469"></a>
+<span class="sourceLineNo">470</span>   */<a name="line.470"></a>
+<span class="sourceLineNo">471</span>  public double getAverageLoad() {<a name="line.471"></a>
+<span class="sourceLineNo">472</span>    int totalLoad = 0;<a name="line.472"></a>
+<span class="sourceLineNo">473</span>    int numServers = 0;<a name="line.473"></a>
+<span class="sourceLineNo">474</span>    for (ServerMetrics sl : this.onlineServers.values()) {<a name="line.474"></a>
+<span class="sourceLineNo">475</span>      numServers++;<a name="line.475"></a>
+<span class="sourceLineNo">476</span>      totalLoad += sl.getRegionMetrics().size();<a name="line.476"></a>
+<span class="sourceLineNo">477</span>    }<a name="line.477"></a>
+<span class="sourceLineNo">478</span>    return numServers == 0 ? 0 :<a name="line.478"></a>
+<span class="sourceLineNo">479</span>      (double)totalLoad / (double)numServers;<a name="line.479"></a>
+<span class="sourceLineNo">480</span>  }<a name="line.480"></a>
+<span class="sourceLineNo">481</span><a name="line.481"></a>
+<span class="sourceLineNo">482</span>  /** @return the count of active regionservers */<a name="line.482"></a>
+<span class="sourceLineNo">483</span>  public int countOfRegionServers() {<a name="line.483"></a>
+<span class="sourceLineNo">484</span>    // Presumes onlineServers is a concurrent map<a name="line.484"></a>
+<span class="sourceLineNo">485</span>    return this.onlineServers.size();<a name="line.485"></a>
+<span class="sourceLineNo">486</span>  }<a name="line.486"></a>
+<span class="sourceLineNo">487</span><a name="line.487"></a>
+<span class="sourceLineNo">488</span>  /**<a name="line.488"></a>
+<span class="sourceLineNo">489</span>   * @return Read-only map of servers to serverinfo<a name="line.489"></a>
+<span class="sourceLineNo">490</span>   */<a name="line.490"></a>
+<span class="sourceLineNo">491</span>  public Map&lt;ServerName, ServerMetrics&gt; getOnlineServers() {<a name="line.491"></a>
+<span class="sourceLineNo">492</span>    // Presumption is that iterating the returned Map is OK.<a name="line.492"></a>
+<span class="sourceLineNo">493</span>    synchronized (this.onlineServers) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      return Collections.unmodifiableMap(this.onlineServers);<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    }<a name="line.495"></a>
+<span class="sourceLineNo">496</span>  }<a name="line.496"></a>
+<span class="sourceLineNo">497</span><a name="line.497"></a>
+<span class="sourceLineNo">498</span>  public DeadServer getDeadServers() {<a name="line.498"></a>
+<span class="sourceLineNo">499</span>    return this.deadservers;<a name="line.499"></a>
+<span class="sourceLineNo">500</span>  }<a name="line.500"></a>
+<span class="sourceLineNo">501</span><a name="line.501"></a>
+<span class="sourceLineNo">502</span>  /**<a name="line.502"></a>
+<span class="sourceLineNo">503</span>   * Checks if any dead servers are currently in progress.<a name="line.503"></a>
+<span class="sourceLineNo">504</span>   * @return true if any RS are being processed as dead, false if not<a name="line.504"></a>
+<span class="sourceLineNo">505</span>   */<a name="line.505"></a>
+<span class="sourceLineNo">506</span>  public boolean areDeadServersInProgress() {<a name="line.506"></a>
+<span class="sourceLineNo">507</span>    return this.deadservers.areDeadServersInProgress();<a name="line.507"></a>
+<span class="sourceLineNo">508</span>  }<a name="line.508"></a>
+<span class="sourceLineNo">509</span><a name="line.509"></a>
+<span class="sourceLineNo">510</span>  void letRegionServersShutdown() {<a name="line.510"></a>
+<span class="sourceLineNo">511</span>    long previousLogTime = 0;<a name="line.511"></a>
+<span class="sourceLineNo">512</span>    ServerName sn = master.getServerName();<a name="line.512"></a>
+<span class="sourceLineNo">513</span>    ZKWatcher zkw = master.getZooKeeper();<a name="line.513"></a>
+<span class="sourceLineNo">514</span>    int onlineServersCt;<a name="line.514"></a>
+<span class="sourceLineNo">515</span>    while ((onlineServersCt = onlineServers.size()) &gt; 0){<a name="line.515"></a>
+<span class="sourceLineNo">516</span><a name="line.516"></a>
+<span class="sourceLineNo">517</span>      if (System.currentTimeMillis() &gt; (previousLogTime + 1000)) {<a name="line.517"></a>
+<span class="sourceLineNo">518</span>        Set&lt;ServerName&gt; remainingServers = onlineServers.keySet();<a name="line.518"></a>
+<span class="sourceLineNo">519</span>        synchronized (onlineServers) {<a name="line.519"></a>
+<span class="sourceLineNo">520</span>          if (remainingServers.size() == 1 &amp;&amp; remainingServers.contains(sn)) {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>            // Master will delete itself later.<a name="line.521"></a>
+<span class="sourceLineNo">522</span>            return;<a name="line.522"></a>
+<span class="sourceLineNo">523</span>          }<a name="line.523"></a>
+<span class="sourceLineNo">524</span>        }<a name="line.524"></a>
+<span class="sourceLineNo">525</span>        StringBuilder sb = new StringBuilder();<a name="line.525"></a>
+<span class="sourceLineNo">526</span>        // It's ok here to not sync on onlineServers - merely logging<a name="line.526"></a>
+<span class="sourceLineNo">527</span>        for (ServerName key : remainingServers) {<a name="line.527"></a>
+<span class="sourceLineNo">528</span>          if (sb.length() &gt; 0) {<a name="line.528"></a>
+<span class="sourceLineNo">529</span>            sb.append(", ");<a name="line.529"></a>
+<span class="sourceLineNo">530</span>          }<a name="line.530"></a>
+<span class="sourceLineNo">531</span>          sb.append(key);<a name="line.531"></a>
+<span class="sourceLineNo">532</span>        }<a name="line.532"></a>
+<span class="sourceLineNo">533</span>        LOG.info("Waiting on regionserver(s) " + sb.toString());<a name="line.533"></a>
+<span class="sourceLineNo">534</span>        previousLogTime = System.currentTimeMillis();<a name="line.534"></a>
+<span class="sourceLineNo">535</span>      }<a name="line.535"></a>
+<span class="sourceLineNo">536</span><a name="line.536"></a>
+<span class="sourceLineNo">537</span>      try {<a name="line.537"></a>
+<span class="sourceLineNo">538</span>        List&lt;String&gt; servers = getRegionServersInZK(zkw);<a name="line.538"></a>
+<span class="sourceLineNo">539</span>        if (servers == null || servers.isEmpty() || (servers.size() == 1<a name="line.539"></a>
+<span class="sourceLineNo">540</span>            &amp;&amp; servers.contains(sn.toString()))) {<a name="line.540"></a>
+<span class="sourceLineNo">541</span>          LOG.info("ZK shows there is only the master self online, exiting now");<a name="line.541"></a>
+<span class="sourceLineNo">542</span>          // Master could have lost some ZK events, no need to wait more.<a name="line.542"></a>
+<span class="sourceLineNo">543</span>          break;<a name="line.543"></a>
+<span class="sourceLineNo">544</span>        }<a name="line.544"></a>
+<span class="sourceLineNo">545</span>      } catch (KeeperException ke) {<a name="line.545"></a>
+<span class="sourceLineNo">546</span>        LOG.warn("Failed to list regionservers", ke);<a name="line.546"></a>
+<span class="sourceLineNo">547</span>        // ZK is malfunctioning, don't hang here<a name="line.547"></a>
+<span class="sourceLineNo">548</span>        break;<a name="line.548"></a>
+<span class="sourceLineNo">549</span>      }<a name="line.549"></a>
+<span class="sourceLineNo">550</span>      synchronized (onlineServers) {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>        try {<a name="line.551"></a>
+<span class="sourceLineNo">552</span>          if (onlineServersCt == onlineServers.size()) onlineServers.wait(100);<a name="line.552"></a>
+<span class="sourceLineNo">553</span>        } catch (InterruptedException ignored) {<a name="line.553"></a>
+<span class="sourceLineNo">554</span>          // continue<a name="line.554"></a>
+<span class="sourceLineNo">555</span>        }<a name="line.555"></a>
+<span class="sourceLineNo">556</span>      }<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    }<a name="line.557"></a>
+<span class="sourceLineNo">558</span>  }<a name="line.558"></a>
+<span class="sourceLineNo">559</span><a name="line.559"></a>
+<span class="sourceLineNo">560</span>  private List&lt;String&gt; getRegionServersInZK(final ZKWatcher zkw)<a name="line.560"></a>
+<span class="sourceLineNo">561</span>  throws KeeperException {<a name="line.561"></a>
+<span class="sourceLineNo">562</span>    return ZKUtil.listChildrenNoWatch(zkw, zkw.getZNodePaths().rsZNode);<a name="line.562"></a>
+<span class="sourceLineNo">563</span>  }<a name="line.563"></a>
+<span class="sourceLineNo">564</span><a name="line.564"></a>
+<span class="sourceLineNo">565</span>  /**<a name="line.565"></a>
+<span class="sourceLineNo">566</span>   * Expire the passed server. Add it to list of dead servers and queue a shutdown processing.<a name="line.566"></a>
+<span class="sourceLineNo">567</span>   * @return pid if we queued a ServerCrashProcedure else {@link Procedure#NO_PROC_ID} if we did<a name="line.567"></a>
+<span class="sourceLineNo">568</span>   *         not (could happen for many reasons including the fact that its this server that is<a name="line.568"></a>
+<span class="sourceLineNo">569</span>   *         going down or we already have queued an SCP for this server or SCP processing is<a name="line.569"></a>
+<span class="sourceLineNo">570</span>   *         currently disabled because we are in startup phase).<a name="line.570"></a>
+<span class="sourceLineNo">571</span>   */<a name="line.571"></a>
+<span class="sourceLineNo">572</span>  @VisibleForTesting // Redo test so we can make this protected.<a name="line.572"></a>
+<span class="sourceLineNo">573</span>  public synchronized long expireServer(final ServerName serverName) {<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    return expireServer(serverName, false);<a name="line.574"></a>
+<span class="sourceLineNo">575</span><a name="line.575"></a>
+<span class="sourceLineNo">576</span>  }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>  synchronized long expireServer(final ServerName serverName, boolean force) {<a name="line.578"></a>
+<span class="sourceLineNo">579</span>    // THIS server is going down... can't handle our own expiration.<a name="line.579"></a>
+<span class="sourceLineNo">580</span>    if (serverName.equals(master.getServerName())) {<a name="line.580"></a>
+<span class="sourceLineNo">581</span>      if (!(master.isAborted() || master.isStopped())) {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>        master.stop("We lost our znode?");<a name="line.582"></a>
+<span class="sourceLineNo">583</span>      }<a name="line.583"></a>
+<span class="sourceLineNo">584</span>      return Procedure.NO_PROC_ID;<a name="line.584"></a>
+<span class="sourceLineNo">585</span>    }<a name="line.585"></a>
+<span class="sourceLineNo">586</span>    if (this.deadservers.isDeadServer(serverName)) {<a name="line.586"></a>
+<span class="sourceLineNo">587</span>      LOG.warn("Expiration called on {} but already in DeadServer", serverName);<a name="line.587"></a>
+<span class="sourceLineNo">588</span>      return Procedure.NO_PROC_ID;<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    }<a name="line.589"></a>
+<span class="sourceLineNo">590</span>    moveFromOnlineToDeadServers(serverName);<a name="line.590"></a>
+<span class="sourceLineNo">591</span><a name="line.591"></a>
+<span class="sourceLineNo">592</span>    // If server is in draining mode, remove corresponding znode<a name="line.592"></a>
+<span class="sourceLineNo">593</span>    // In some tests, the mocked HM may not have ZK Instance, hence null check<a name="line.593"></a>
+<span class="sourceLineNo">594</span>    if (master.getZooKeeper() != null) {<a name="line.594"></a>
+<span class="sourceLineNo">595</span>      String drainingZnode = ZNodePaths<a name="line.595"></a>
+<span class="sourceLineNo">596</span>        .joinZNode(master.getZooKeeper().getZNodePaths().drainingZNode, serverName.getServerName());<a name="line.596"></a>
+<span class="sourceLineNo">597</span>      try {<a name="line.597"></a>
+<span class="sourceLineNo">598</span>        ZKUtil.deleteNodeFailSilent(master.getZooKeeper(), drainingZnode);<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      } catch (KeeperException e) {<a name="line.599"></a>
+<span class="sourceLineNo">600</span>        LOG.warn("Error deleting the draining znode for stopping server " + serverName.getServerName(), e);<a name="line.600"></a>
+<span class="sourceLineNo">601</span>      }<a name="line.601"></a>
+<span class="sourceLineNo">602</span>    }<a name="line.602"></a>
+<span class="sourceLineNo">603</span>    <a name="line.603"></a>
+<span class="sourceLineNo">604</span>    // If cluster is going down, yes, servers are going to be expiring; don't<a name="line.604"></a>
+<span class="sourceLineNo">605</span>    // process as a dead server<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    if (isClusterShutdown()) {<a name="line.606"></a>
+<span class="sourceLineNo">607</span>      LOG.info("Cluster shutdown set; " + serverName +<a name="line.607"></a>
+<span class="sourceLineNo">608</span>        " expired; onlineServers=" + this.onlineServers.size());<a name="line.608"></a>
+<span class="sourceLineNo">609</span>      if (this.onlineServers.isEmpty()) {<a name="line.609"></a>
+<span class="sourceLineNo">610</span>        master.stop("Cluster shutdown set; onlineServer=0");<a name="line.610"></a>
+<span class="sourceLineNo">611</span>      }<a name="line.611"></a>
+<span class="sourceLineNo">612</span>      return Procedure.NO_PROC_ID;<a name="line.612"></a>
+<span class="sourceLineNo">613</span>    }<a name="line.613"></a>
+<span class="sourceLineNo">614</span>    LOG.info("Processing expiration of " + serverName + " on " + this.master.getServerName());<a name="line.614"></a>
+<span class="sourceLineNo">615</span>    long pid = master.getAssignmentManager().submitServerCrash(serverName, true, force);<a name="line.615"></a>
+<span class="sourceLineNo">616</span>    // Tell our listeners that a server was removed<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    if (!this.listeners.isEmpty()) {<a name="line.617"></a>
+<span class="sourceLineNo">618</span>      this.listeners.stream().forEach(l -&gt; l.serverRemoved(serverName));<a name="line.618"></a>
+<span class="sourceLineNo">619</span>    }<a name="line.619"></a>
+<span class="sourceLineNo">620</span>    // trigger a persist of flushedSeqId<a name="line.620"></a>
+<span class="sourceLineNo">621</span>    if (flushedSeqIdFlusher != null) {<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      flushedSeqIdFlusher.triggerNow();<a name="line.622"></a>
+<span class="sourceLineNo">623</span>    }<a name="line.623"></a>
+<span class="sourceLineNo">624</span>    return pid;<a name="line.624"></a>
+<span class="sourceLineNo">625</span>  }<a name="line.625"></a>
+<span class="sourceLineNo">626</span><a name="line.626"></a>
+<span class="sourceLineNo">627</span>  /**<a name="line.627"></a>
+<span class="sourceLineNo">628</span>   * Called when server has expired.<a name="line.628"></a>
+<span class="sourceLineNo">629</span>   */<a name="line.629"></a>
+<span class="sourceLineNo">630</span>  // Locking in this class needs cleanup.<a name="line.630"></a>
+<span class="sourceLineNo">631</span>  @VisibleForTesting<a name="line.631"></a>
+<span class="sourceLineNo">632</span>  public synchronized void moveFromOnlineToDeadServers(final ServerName sn) {<a name="line.632"></a>
+<span class="sourceLineNo">633</span>    synchronized (this.onlineServers) {<a name="line.633"></a>
+<span class="sourceLineNo">634</span>      boolean online = this.onlineServers.containsKey(sn);<a name="line.634"></a>
+<span class="sourceLineNo">635</span>      if (online) {<a name="line.635"></a>
+<span class="sourceLineNo">636</span>        // Remove the server from the known servers lists and update load info BUT<a name="line.636"></a>
+<span class="sourceLineNo">637</span>        // add to deadservers first; do this so it'll show in dead servers list if<a name="line.637"></a>
+<span class="sourceLineNo">638</span>        // not in online servers list.<a name="line.638"></a>
+<span class="sourceLineNo">639</span>        this.deadservers.putIfAbsent(sn);<a name="line.639"></a>
+<span class="sourceLineNo">640</span>        this.onlineServers.remove(sn);<a name="line.640"></a>
+<span class="sourceLineNo">641</span>        onlineServers.notifyAll();<a name="line.641"></a>
+<span class="sourceLineNo">642</span>      } else {<a name="line.642"></a>
+<span class="sourceLineNo">643</span>        // If not online, that is odd but may happen if 'Unknown Servers' -- where meta<a name="line.643"></a>
+<span class="sourceLineNo">644</span>        // has references to servers not online nor in dead servers list. If<a name="line.644"></a>
+<span class="sourceLineNo">645</span>        // 'Unknown Server', don't add to DeadServers else will be there for ever.<a name="line.645"></a>
+<span class="sourceLineNo">646</span>        LOG.trace("Expiration of {} but server not online", sn);<a name="line.646"></a>
+<span class="sourceLineNo">647</span>      }<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    }<a name="line.648"></a>
+<span class="sourceLineNo">649</span>  }<a name="line.649"></a>
+<span class="sourceLineNo">650</span><a name="line.650"></a>
+<span class="sourceLineNo">651</span>  /*<a name="line.651"></a>
+<span class="sourceLineNo">652</span>   * Remove the server from the drain list.<a name="line.652"></a>
+<span class="sourceLineNo">653</span>   */<a name="line.653"></a>
+<span class="sourceLineNo">654</span>  public synchronized boolean removeServerFromDrainList(final ServerName sn) {<a name="line.654"></a>
+<span class="sourceLineNo">655</span>    // Warn if the server (sn) is not online.  ServerName is of the form:<a name="line.655"></a>
+<span class="sourceLineNo">656</span>    // &lt;hostname&gt; , &lt;port&gt; , &lt;startcode&gt;<a name="line.656"></a>
+<span class="sourceLineNo">657</span><a name="line.657"></a>
+<span class="sourceLineNo">658</span>    if (!this.isServerOnline(sn)) {<a name="line.658"></a>
+<span class="sourceLineNo">659</span>      LOG.warn("Server " + sn + " is not currently online. " +<a name="line.659"></a>
+<span class="sourceLineNo">660</span>               "Removing from draining list anyway, as requested.");<a name="line.660"></a>
+<span class="sourceLineNo">661</span>    }<a name="line.661"></a>
+<span class="sourceLineNo">662</span>    // Remove the server from the draining servers lists.<a name="line.662"></a>
+<span class="sourceLineNo">663</span>    return this.drainingServers.remove(sn);<a name="line.663"></a>
+<span class="sourceLineNo">664</span>  }<a name="line.664"></a>
+<span class="sourceLineNo">665</span><a name="line.665"></a>
+<span class="sourceLineNo">666</span>  /**<a name="line.666"></a>
+<span class="sourceLineNo">667</span>   * Add the server to the drain list.<a name="line.667"></a>
+<span class="sourceLineNo">668</span>   * @param sn<a name="line.668"></a>
+<span class="sourceLineNo">669</span>   * @return True if the server is added or the server is already on the drain list.<a name="line.669"></a>
+<span class="sourceLineNo">670</span>   */<a name="line.670"></a>
+<span class="sourceLineNo">671</span>  public synchronized boolean addServerToDrainList(final ServerName sn) {<a name="line.671"></a>
+<span class="sourceLineNo">672</span>    // Warn if the server (sn) is not online.  ServerName is of the form:<a name="line.672"></a>
+<span class="sourceLineNo">673</span>    // &lt;hostname&gt; , &lt;port&gt; , &lt;startcode&gt;<a name="line.673"></a>
+<span class="sourceLineNo">674</span><a name="line.674"></a>
+<span class="sourceLineNo">675</span>    if (!this.isServerOnline(sn)) {<a name="line.675"></a>
+<span class="sourceLineNo">676</span>      LOG.warn("Server " + sn + " is not currently online. " +<a name="line.676"></a>
+<span class="sourceLineNo">677</span>               "Ignoring request to add it to draining list.");<a name="line.677"></a>
+<span class="sourceLineNo">678</span>      return false;<a name="line.678"></a>
+<span class="sourceLineNo">679</span>    }<a name="line.679"></a>
+<span class="sourceLineNo">680</span>    // Add the server to the draining servers lists, if it's not already in<a name="line.680"></a>
+<span class="sourceLineNo">681</span>    // it.<a name="line.681"></a>
+<span class="sourceLineNo">682</span>    if (this.drainingServers.contains(sn)) {<a name="line.682"></a>
+<span class="sourceLineNo">683</span>      LOG.warn("Server " + sn + " is already in the draining server list." +<a name="line.683"></a>
+<span class="sourceLineNo">684</span>               "Ignoring request to add it again.");<a name="line.684"></a>
+<span class="sourceLineNo">685</span>      return true;<a name="line.685"></a>
+<span class="sourceLineNo">686</span>    }<a name="line.686"></a>
+<span class="sourceLineNo">687</span>    LOG.info("Server " + sn + " added to draining server list.");<a name="line.687"></a>
+<span class="sourceLineNo">688</span>    return this.drainingServers.add(sn);<a name="line.688"></a>
+<span class="sourceLineNo">689</span>  }<a name="line.689"></a>
+<span class="sourceLineNo">690</span><a name="line.690"></a>
+<span class="sourceLineNo">691</span>  /**<a name="line.691"></a>
+<span class="sourceLineNo">692</span>   * Contacts a region server and waits up to timeout ms<a name="line.692"></a>
+<span class="sourceLineNo">693</span>   * to close the region.  This bypasses the active hmaster.<a name="line.693"></a>
+<span class="sourceLineNo">694</span>   * Pass -1 as timeout if you do not want to wait on result.<a name="line.694"></a>
+<span class="sourceLineNo">695</span>   */<a name="line.695"></a>
+<span class="sourceLineNo">696</span>  public static void closeRegionSilentlyAndWait(AsyncClusterConnection connection,<a name="line.696"></a>
+<span class="sourceLineNo">697</span>      ServerName server, RegionInfo region, long timeout) throws IOException, InterruptedException {<a name="line.697"></a>
+<span class="sourceLineNo">698</span>    AsyncRegionServerAdmin admin = connection.getRegionServerAdmin(server);<a name="line.698"></a>
+<span class="sourceLineNo">699</span>    try {<a name="line.699"></a>
+<span class="sourceLineNo">700</span>      FutureUtils.get(<a name="line.700"></a>
+<span class="sourceLineNo">701</span>        admin.closeRegion(ProtobufUtil.buildCloseRegionRequest(server, region.getRegionName())));<a name="line.701"></a>
+<span class="sourceLineNo">702</span>    } catch (IOException e) {<a name="line.702"></a>
+<span class="sourceLineNo">703</span>      LOG.warn("Exception when closing region: " + region.getRegionNameAsString(), e);<a name="line.703"></a>
+<span class="sourceLineNo">704</span>    }<a name="line.704"></a>
+<span class="sourceLineNo">705</span>    if (timeout &lt; 0) {<a name="line.705"></a>
+<span class="sourceLineNo">706</span>      return;<a name="line.706"></a>
+<span class="sourceLineNo">707</span>    }<a name="line.707"></a>
+<span class="sourceLineNo">708</span>    long expiration = timeout + System.currentTimeMillis();<a name="line.708"></a>
+<span class="sourceLineNo">709</span>    while (System.currentTimeMillis() &lt; expiration) {<a name="line.709"></a>
+<span class="sourceLineNo">710</span>      try {<a name="line.710"></a>
+<span class="sourceLineNo">711</span>        RegionInfo rsRegion = ProtobufUtil.toRegionInfo(FutureUtils<a name="line.711"></a>
+<span class="sourceLineNo">712</span>          .get(<a name="line.712"></a>
+<span class="sourceLineNo">713</span>            admin.getRegionInfo(RequestConverter.buildGetRegionInfoRequest(region.getRegionName())))<a name="line.713"></a>
+<span class="sourceLineNo">714</span>          .getRegionInfo());<a name="line.714"></a>
+<span class="sourceLineNo">715</span>        if (rsRegion == null) {<a name="line.715"></a>
+<span class="sourceLineNo">716</span>          return;<a name="line.716"></a>
+<span class="sourceLineNo">717</span>        }<a name="line.717"></a>
+<span class="sourceLineNo">718</span>      } catch (IOException ioe) {<a name="line.718"></a>
+<span class="sourceLineNo">719</span>        if (ioe instanceof NotServingRegionException ||<a name="line.719"></a>
+<span class="sourceLineNo">720</span>          (ioe instanceof RemoteWithExtrasException &amp;&amp;<a name="line.720"></a>
+<span class="sourceLineNo">721</span>            ((RemoteWithExtrasException)ioe).unwrapRemoteException()<a name="line.721"></a>
+<span class="sourceLineNo">722</span>              instanceof NotServingRegionException)) {<a name="line.722"></a>
+<span class="sourceLineNo">723</span>          // no need to retry again<a name="line.723"></a>
+<span class="sourceLineNo">724</span>          return;<a name="line.724"></a>
+<span class="sourceLineNo">725</span>        }<a name="line.725"></a>
+<span class="sourceLineNo">726</span>        LOG.warn("Exception when retrieving regioninfo from: " + region.getRegionNameAsString(),<a name="line.726"></a>
+<span class="sourceLineNo">727</span>          ioe);<a name="line.727"></a>
+<span class="sourceLineNo">728</span>      }<a name="line.728"></a>
+<span class="sourceLineNo">729</span>      Thread.sleep(1000);<a name="line.729"></a>
+<span class="sourceLineNo">730</span>    }<a name="line.730"></a>
+<span class="sourceLineNo">731</span>    throw new IOException("Region " + region + " failed to close within" + " timeout " + timeout);<a name="line.731"></a>
+<span class="sourceLineNo">732</span>  }<a name="line.732"></a>
+<span class="sourceLineNo">733</span><a name="line.733"></a>
+<span class="sourceLineNo">734</span>  /**<a name="line.734"></a>
+<span class="sourceLineNo">735</span>   * Calculate min necessary to start. This is not an absolute. It is just<a name="line.735"></a>
+<span class="sourceLineNo">736</span>   * a friction that will cause us hang around a bit longer waiting on<a name="line.736"></a>
+<span class="sourceLineNo">737</span>   * RegionServers to check-in.<a name="line.737"></a>
+<span class="sourceLineNo">738</span>   */<a name="line.738"></a>
+<span class="sourceLineNo">739</span>  private int getMinToStart() {<a name="line.739"></a>
+<span class="sourceLineNo">740</span>    if (master.isInMaintenanceMode()) {<a name="line.740"></a>
+<span class="sourceLineNo">741</span>      // If in maintenance mode, then master hosting meta will be the only server available<a name="line.741"></a>
+<span class="sourceLineNo">742</span>      return 1;<a name="line.742"></a>
+<span class="sourceLineNo">743</span>    }<a name="line.743"></a>
+<span class="sourceLineNo">744</span><a name="line.744"></a>
+<span class="sourceLineNo">745</span>    int minimumRequired = 1;<a name="line.745"></a>
+<span class="sourceLineNo">746</span>    if (LoadBalancer.isTablesOnMaster(master.getConfiguration()) &amp;&amp;<a name="line.746"></a>
+<span class="sourceLineNo">747</span>        LoadBalancer.isSystemTablesOnlyOnMaster(master.getConfiguration())) {<a name="line.747"></a>
+<span class="sourceLineNo">748</span>      // If Master is carrying regions it will show up as a 'server', but is not handling user-<a name="line.748"></a>
+<span class="sourceLineNo">749</span>      // space regions, so we need a second server.<a name="line.749"></a>
+<span class="sourceLineNo">750</span>      minimumRequired = 2;<a name="line.750"></a>
+<span class="sourceLineNo">751</span>    }<a name="line.751"></a>
+<span class="sourceLineNo">752</span><a name="line.752"></a>
+<span class="sourceLineNo">753</span>    int minToStart = this.master.getConfiguration().getInt(WAIT_ON_REGIONSERVERS_MINTOSTART, -1);<a name="line.753"></a>
+<span class="sourceLineNo">754</span>    // Ensure we are never less than minimumRequired else stuff won't work.<a name="line.754"></a>
+<span class="sourceLineNo">755</span>    return Math.max(minToStart, minimumRequired);<a name="line.755"></a>
+<span class="sourceLineNo">756</span>  }<a name="line.756"></a>
+<span class="sourceLineNo">757</span><a name="line.757"></a>
+<span class="sourceLineNo">758</span>  /**<a name="line.758"></a>
+<span class="sourceLineNo">759</span>   * Wait for the region servers to report in.<a name="line.759"></a>
+<span class="sourceLineNo">760</span>   * We will wait until one of this condition is met:<a name="line.760"></a>
+<span class="sourceLineNo">761</span>   *  - the master is stopped<a name="line.761"></a>
+<span class="sourceLineNo">762</span>   *  - the 'hbase.master.wait.on.regionservers.maxtostart' number of<a name="line.762"></a>
+<span class="sourceLineNo">763</span>   *    region servers is reached<a name="line.763"></a>
+<span class="sourceLineNo">764</span>   *  - the 'hbase.master.wait.on.regionservers.mintostart' is reached AND<a name="line.764"></a>
+<span class="sourceLineNo">765</span>   *   there have been no new region server in for<a name="line.765"></a>
+<span class="sourceLineNo">766</span>   *      'hbase.master.wait.on.regionservers.interval' time AND<a name="line.766"></a>
+<span class="sourceLineNo">767</span>   *   the 'hbase.master.wait.on.regionservers.timeout' is reached<a name="line.767"></a>
+<span class="sourceLineNo">768</span>   *<a name="line.768"></a>
+<span class="sourceLineNo">769</span>   * @throws InterruptedException<a name="line.769"></a>
+<span class="sourceLineNo">770</span>   */<a name="line.770"></a>
+<span class="sourceLineNo">771</span>  public void waitForRegionServers(MonitoredTask status) throws InterruptedException {<a name="line.771"></a>
+<span class="sourceLineNo">772</span>    final long interval = this.master.getConfiguration().<a name="line.772"></a>
+<span class="sourceLineNo">773</span>        getLong(WAIT_ON_REGIONSERVERS_INTERVAL, 1500);<a name="line.773"></a>
+<span class="sourceLineNo">774</span>    final long timeout = this.master.getConfiguration().<a name="line.774"></a>
+<span class="sourceLineNo">775</span>        getLong(WAIT_ON_REGIONSERVERS_TIMEOUT, 4500);<a name="line.775"></a>
+<span class="sourceLineNo">776</span>    // Min is not an absolute; just a friction making us wait longer on server checkin.<a name="line.776"></a>
+<span class="sourceLineNo">777</span>    int minToStart = getMinToStart();<a name="line.777"></a>
+<span class="sourceLineNo">778</span>    int maxToStart = this.master.getConfiguration().<a name="line.778"></a>
+<span class="sourceLineNo">779</span>        getInt(WAIT_ON_REGIONSERVERS_MAXTOSTART, Integer.MAX_VALUE);<a name="line.779"></a>
+<span class="sourceLineNo">780</span>    if (maxToStart &lt; minToStart) {<a name="line.780"></a>
+<span class="sourceLineNo">781</span>      LOG.warn(String.format("The value of '%s' (%d) is set less than '%s' (%d), ignoring.",<a name="line.781"></a>
+<span class="sourceLineNo">782</span>          WAIT_ON_REGIONSERVERS_MAXTOSTART, maxToStart,<a name="line.782"></a>
+<span class="sourceLineNo">783</span>          WAIT_ON_REGIONSERVERS_MINTOSTART, minToStart));<a name="line.783"></a>
+<span class="sourceLineNo">784</span>      maxToStart = Integer.MAX_VALUE;<a name="line.784"></a>
+<span class="sourceLineNo">785</span>    }<a name="line.785"></a>
+<span class="sourceLineNo">786</span><a name="line.786"></a>
+<span class="sourceLineNo">787</span>    long now =  System.currentTimeMillis();<a name="line.787"></a>
+<span class="sourceLineNo">788</span>    final long startTime = now;<a name="line.788"></a>
+<span class="sourceLineNo">789</span>    long slept = 0;<a name="line.789"></a>
+<span class="sourceLineNo">790</span>    long lastLogTime = 0;<a name="line.790"></a>
+<span class="sourceLineNo">791</span>    long lastCountChange = startTime;<a name="line.791"></a>
+<span class="sourceLineNo">792</span>    int count = countOfRegionServers();<a name="line.792"></a>
+<span class="sourceLineNo">793</span>    int oldCount = 0;<a name="line.793"></a>
+<span class="sourceLineNo">794</span>    // This while test is a little hard to read. We try to comment it in below but in essence:<a name="line.794"></a>
+<span class="sourceLineNo">795</span>    // Wait if Master is not stopped and the number of regionservers that have checked-in is<a name="line.795"></a>
+<span class="sourceLineNo">796</span>    // less than the maxToStart. Both of these conditions will be true near universally.<a name="line.796"></a>
+<span class="sourceLineNo">797</span>    // Next, we will keep cycling if ANY of the following three conditions are true:<a name="line.797"></a>
+<span class="sourceLineNo">798</span>    // 1. The time since a regionserver registered is &lt; interval (means servers are actively checking in).<a name="line.798"></a>
+<span class="sourceLineNo">799</span>    // 2. We are under the total timeout.<a name="line.799"></a>
+<span class="sourceLineNo">800</span>    // 3. The count of servers is &lt; minimum.<a name="line.800"></a>
+<span class="sourceLineNo">801</span>    for (ServerListener listener: this.listeners) {<a name="line.801"></a>
+<span class="sourceLineNo">802</span>      listener.waiting();<a name="line.802"></a>
+<span class="sourceLineNo">803</span>    }<a name="line.803"></a>
+<span class="sourceLineNo">804</span>    while (!this.master.isStopped() &amp;&amp; !isClusterShutdown() &amp;&amp; count &lt; maxToStart &amp;&amp;<a name="line.804"></a>
+<span class="sourceLineNo">805</span>        ((lastCountChange + interval) &gt; now || timeout &gt; slept || count &lt; minToStart)) {<a name="line.805"></a>
+<span class="sourceLineNo">806</span>      // Log some info at every interval time or if there is a change<a name="line.806"></a>
+<span class="sourceLineNo">807</span>      if (oldCount != count || lastLogTime + interval &lt; now) {<a name="line.807"></a>
+<span class="sourceLineNo">808</span>        lastLogTime = now;<a name="line.808"></a>
+<span class="sourceLineNo">809</span>        String msg =<a name="line.809"></a>
+<span class="sourceLineNo">810</span>            "Waiting on regionserver count=" + count + "; waited="+<a name="line.810"></a>
+<span class="sourceLineNo">811</span>                slept + "ms, expecting min=" + minToStart + " server(s), max="+ getStrForMax(maxToStart) +<a name="line.811"></a>
+<span class="sourceLineNo">812</span>                " server(s), " + "timeout=" + timeout + "ms, lastChange=" + (lastCountChange - now) + "ms";<a name="line.812"></a>
+<span class="sourceLineNo">813</span>        LOG.info(msg);<a name="line.813"></a>
+<span class="sourceLineNo">814</span>        status.setStatus(msg);<a name="line.814"></a>
+<span class="sourceLineNo">815</span>      }<a name="line.815"></a>
+<span class="sourceLineNo">816</span><a name="line.816"></a>
+<span class="sourceLineNo">817</span>      // We sleep for some time<a name="line.817"></a>
+<span class="sourceLineNo">818</span>      final long sleepTime = 50;<a name="line.818"></a>
+<span class="sourceLineNo">819</span>      Thread.sleep(sleepTime);<a name="line.819"></a>
+<span class="sourceLineNo">820</span>      now =  System.currentTimeMillis();<a name="line.820"></a>
+<span class="sourceLineNo">821</span>      slept = now - startTime;<a name="line.821"></a>
+<span class="sourceLineNo">822</span><a name="line.822"></a>
+<span class="sourceLineNo">823</span>      oldCount = count;<a name="line.823"></a>
+<span class="sourceLineNo">824</span>      count = countOfRegionServers();<a name="line.824"></a>
+<span class="sourceLineNo">825</span>      if (count != oldCount) {<a name="line.825"></a>
+<span class="sourceLineNo">826</span>        lastCountChange = now;<a name="line.826"></a>
+<span class="sourceLineNo">827</span>      }<a name="line.827"></a>
 <span class="sourceLineNo">828</span>    }<a name="line.828"></a>
-<span class="sourceLineNo">829</span>    LOG.info("Finished waiting on RegionServer count=" + count + "; waited=" + slept + "ms," +<a name="line.829"></a>
-<span class="sourceLineNo">830</span>        " expected min=" + minToStart + " server(s), max=" +  getStrForMax(maxToStart) + " server(s),"+<a name="line.830"></a>
-<span class="sourceLineNo">831</span>        " master is "+ (this.master.isStopped() ? "stopped.": "running"));<a name="line.831"></a>
-<span class="sourceLineNo">832</span>  }<a name="line.832"></a>
-<span class="sourceLineNo">833</span><a name="line.833"></a>
-<span class="sourceLineNo">834</span>  private String getStrForMax(final int max) {<a name="line.834"></a>
-<span class="sourceLineNo">835</span>    return max == Integer.MAX_VALUE? "NO_LIMIT": Integer.toString(max);<a name="line.835"></a>
+<span class="sourceLineNo">829</span>    // Did we exit the loop because cluster is going down?<a name="line.829"></a>
+<span class="sourceLineNo">830</span>    if (isClusterShutdown()) {<a name="line.830"></a>
+<span class="sourceLineNo">831</span>      this.master.stop("Cluster shutdown");<a name="line.831"></a>
+<span class="sourceLineNo">832</span>    }<a name="line.832"></a>
+<span class="sourceLineNo">833</span>    LOG.info("Finished waiting on RegionServer count=" + count + "; waited=" + slept + "ms," +<a name="line.833"></a>
+<span class="sourceLineNo">834</span>        " expected min=" + minToStart + " server(s), max=" +  getStrForMax(maxToStart) + " server(s),"+<a name="line.834"></a>
+<span class="sourceLineNo">835</span>        " master is "+ (this.master.isStopped() ? "stopped.": "running"));<a name="line.835"></a>
 <span class="sourceLineNo">836</span>  }<a name="line.836"></a>
 <span class="sourceLineNo">837</span><a name="line.837"></a>
-<span class="sourceLineNo">838</span>  /**<a name="line.838"></a>
-<span class="sourceLineNo">839</span>   * @return A copy of the internal list of online servers.<a name="line.839"></a>
-<span class="sourceLineNo">840</span>   */<a name="line.840"></a>
-<span class="sourceLineNo">841</span>  public List&lt;ServerName&gt; getOnlineServersList() {<a name="line.841"></a>
-<span class="sourceLineNo">842</span>    // TODO: optimize the load balancer call so we don't need to make a new list<a name="line.842"></a>
-<span class="sourceLineNo">843</span>    // TODO: FIX. THIS IS POPULAR CALL.<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    return new ArrayList&lt;&gt;(this.onlineServers.keySet());<a name="line.844"></a>
-<span class="sourceLineNo">845</span>  }<a name="line.845"></a>
-<span class="sourceLineNo">846</span><a name="line.846"></a>
-<span class="sourceLineNo">847</span>  /**<a name="line.847"></a>
-<span class="sourceLineNo">848</span>   * @param keys The target server name<a name="line.848"></a>
-<span class="sourceLineNo">849</span>   * @param idleServerPredicator Evaluates the server on the given load<a name="line.849"></a>
-<span class="sourceLineNo">850</span>   * @return A copy of the internal list of online servers matched by the predicator<a name="line.850"></a>
-<span class="sourceLineNo">851</span>   */<a name="line.851"></a>
-<span class="sourceLineNo">852</span>  public List&lt;ServerName&gt; getOnlineServersListWithPredicator(List&lt;ServerName&gt; keys,<a name="line.852"></a>
-<span class="sourceLineNo">853</span>    Predicate&lt;ServerMetrics&gt; idleServerPredicator) {<a name="line.853"></a>
-<span class="sourceLineNo">854</span>    List&lt;ServerName&gt; names = new ArrayList&lt;&gt;();<a name="line.854"></a>
-<span class="sourceLineNo">855</span>    if (keys != null &amp;&amp; idleServerPredicator != null) {<a name="line.855"></a>
-<span class="sourceLineNo">856</span>      keys.forEach(name -&gt; {<a name="line.856"></a>
-<span class="sourceLineNo">857</span>        ServerMetrics load = onlineServers.get(name);<a name="line.857"></a>
-<span class="sourceLineNo">858</span>        if (load != null) {<a name="line.858"></a>
-<span class="sourceLineNo">859</span>          if (idleServerPredicator.test(load)) {<a name="line.859"></a>
-<span class="sourceLineNo">860</span>            names.add(name);<a name="line.860"></a>
-<span class="sourceLineNo">861</span>          }<a name="line.861"></a>
-<span class="sourceLineNo">862</span>        }<a name="line.862"></a>
-<span class="sourceLineNo">863</span>      });<a name="line.863"></a>
-<span class="sourceLineNo">864</span>    }<a name="line.864"></a>
-<span class="sourceLineNo">865</span>    return names;<a name="line.865"></a>
-<span class="sourceLineNo">866</span>  }<a name="line.866"></a>
-<span class="sourceLineNo">867</span><a name="line.867"></a>
-<span class="sourceLineNo">868</span>  /**<a name="line.868"></a>
-<span class="sourceLineNo">869</span>   * @return A copy of the internal list of draining servers.<a name="line.869"></a>
-<span class="sourceLineNo">870</span>   */<a name="line.870"></a>
-<span class="sourceLineNo">871</span>  public List&lt;ServerName&gt; getDrainingServersList() {<a name="line.871"></a>
-<span class="sourceLineNo">872</span>    return new ArrayList&lt;&gt;(this.drainingServers);<a name="line.872"></a>
-<span class="sourceLineNo">873</span>  }<a name="line.873"></a>
-<span class="sourceLineNo">874</span><a name="line.874"></a>
-<span class="sourceLineNo">875</span>  public boolean isServerOnline(ServerName serverName) {<a name="line.875"></a>
-<span class="sourceLineNo">876</span>    return serverName != null &amp;&amp; onlineServers.containsKey(serverName);<a name="line.876"></a>
+<span class="sourceLineNo">838</span>  private String getStrForMax(final int max) {<a name="line.838"></a>
+<span class="sourceLineNo">839</span>    return max == Integer.MAX_VALUE? "NO_LIMIT": Integer.toString(max);<a name="line.839"></a>
+<span class="sourceLineNo">840</span>  }<a name="line.840"></a>
+<span class="sourceLineNo">841</span><a name="line.841"></a>
+<span class="sourceLineNo">842</span>  /**<a name="line.842"></a>
+<span class="sourceLineNo">843</span>   * @return A copy of the internal list of online servers.<a name="line.843"></a>
+<span class="sourceLineNo">844</span>   */<a name="line.844"></a>
+<span class="sourceLineNo">845</span>  public List&lt;ServerName&gt; getOnlineServersList() {<a name="line.845"></a>
+<span class="sourceLineNo">846</span>    // TODO: optimize the load balancer call so we don't need to make a new list<a name="line.846"></a>
+<span class="sourceLineNo">847</span>    // TODO: FIX. THIS IS POPULAR CALL.<a name="line.847"></a>
+<span class="sourceLineNo">848</span>    return new ArrayList&lt;&gt;(this.onlineServers.keySet());<a name="line.848"></a>
+<span class="sourceLineNo">849</span>  }<a name="line.849"></a>
+<span class="sourceLineNo">850</span><a name="line.850"></a>
+<span class="sourceLineNo">851</span>  /**<a name="line.851"></a>
+<span class="sourceLineNo">852</span>   * @param keys The target server name<a name="line.852"></a>
+<span class="sourceLineNo">853</span>   * @param idleServerPredicator Evaluates the server on the given load<a name="line.853"></a>
+<span class="sourceLineNo">854</span>   * @return A copy of the internal list of online servers matched by the predicator<a name="line.854"></a>
+<span class="sourceLineNo">855</span>   */<a name="line.855"></a>
+<span class="sourceLineNo">856</span>  public List&lt;ServerName&gt; getOnlineServersListWithPredicator(List&lt;ServerName&gt; keys,<a name="line.856"></a>
+<span class="sourceLineNo">857</span>    Predicate&lt;ServerMetrics&gt; idleServerPredicator) {<a name="line.857"></a>
+<span class="sourceLineNo">858</span>    List&lt;ServerName&gt; names = new ArrayList&lt;&gt;();<a name="line.858"></a>
+<span class="sourceLineNo">859</span>    if (keys != null &amp;&amp; idleServerPredicator != null) {<a name="line.859"></a>
+<span class="sourceLineNo">860</span>      keys.forEach(name -&gt; {<a name="line.860"></a>
+<span class="sourceLineNo">861</span>        ServerMetrics load = onlineServers.get(name);<a name="line.861"></a>
+<span class="sourceLineNo">862</span>        if (load != null) {<a name="line.862"></a>
+<span class="sourceLineNo">863</span>          if (idleServerPredicator.test(load)) {<a name="line.863"></a>
+<span class="sourceLineNo">864</span>            names.add(name);<a name="line.864"></a>
+<span class="sourceLineNo">865</span>          }<a name="line.865"></a>
+<span class="sourceLineNo">866</span>        }<a name="line.866"></a>
+<span class="sourceLineNo">867</span>      });<a name="line.867"></a>
+<span class="sourceLineNo">868</span>    }<a name="line.868"></a>
+<span class="sourceLineNo">869</span>    return names;<a name="line.869"></a>
+<span class="sourceLineNo">870</span>  }<a name="line.870"></a>
+<span class="sourceLineNo">871</span><a name="line.871"></a>
+<span class="sourceLineNo">872</span>  /**<a name="line.872"></a>
+<span class="sourceLineNo">873</span>   * @return A copy of the internal list of draining servers.<a name="line.873"></a>
+<span class="sourceLineNo">874</span>   */<a name="line.874"></a>
+<span class="sourceLineNo">875</span>  public List&lt;ServerName&gt; getDrainingServersList() {<a name="line.875"></a>
+<span class="sourceLineNo">876</span>    return new ArrayList&lt;&gt;(this.drainingServers);<a name="line.876"></a>
 <span class="sourceLineNo">877</span>  }<a name="line.877"></a>
 <span class="sourceLineNo">878</span><a name="line.878"></a>
-<span class="sourceLineNo">879</span>  public enum ServerLiveState {<a name="line.879"></a>
-<span class="sourceLineNo">880</span>    LIVE,<a name="line.880"></a>
-<span class="sourceLineNo">881</span>    DEAD,<a name="line.881"></a>
-<span class="sourceLineNo">882</span>    UNKNOWN<a name="line.882"></a>
-<span class="sourceLineNo">883</span>  }<a name="line.883"></a>
-<span class="sourceLineNo">884</span><a name="line.884"></a>
-<span class="sourceLineNo">885</span>  /**<a name="line.885"></a>
-<span class="sourceLineNo">886</span>   * @return whether the server is online, dead, or unknown.<a name="line.886"></a>
-<span class="sourceLineNo">887</span>   */<a name="line.887"></a>
-<span class="sourceLineNo">888</span>  public synchronized ServerLiveState isServerKnownAndOnline(ServerName serverName) {<a name="line.888"></a>
-<span class="sourceLineNo">889</span>    return onlineServers.containsKey(serverName) ? ServerLiveState.LIVE<a name="line.889"></a>
-<span class="sourceLineNo">890</span>      : (deadservers.isDeadServer(serverName) ? ServerLiveState.DEAD : ServerLiveState.UNKNOWN);<a name="line.890"></a>
-<span class="sourceLineNo">891</span>  }<a name="line.891"></a>
-<span class="sourceLineNo">892</span><a name="line.892"></a>
-<span class="sourceLineNo">893</span>  /**<a name="line.893"></a>
-<span class="sourceLineNo">894</span>   * Check if a server is known to be dead.  A server can be online,<a name="line.894"></a>
-<span class="sourceLineNo">895</span>   * or known to be dead, or unknown to this manager (i.e, not online,<a name="line.895"></a>
-<span class="sourceLineNo">896</span>   * not known to be dead either; it is simply not tracked by the<a name="line.896"></a>
-<span class="sourceLineNo">897</span>   * master any more, for example, a very old previous instance).<a name="line.897"></a>
-<span class="sourceLineNo">898</span>   */<a name="line.898"></a>
-<span class="sourceLineNo">899</span>  public synchronized boolean isServerDead(ServerName serverName) {<a name="line.899"></a>
-<span class="sourceLineNo">900</span>    return serverName == null || deadservers.isDeadServer(serverName);<a name="line.900"></a>
-<span class="sourceLineNo">901</span>  }<a name="line.901"></a>
-<span class="sourceLineNo">902</span><a name="line.902"></a>
-<span class="sourceLineNo">903</span>  public void shutdownCluster() {<a name="line.903"></a>
-<span class="sourceLineNo">904</span>    String statusStr = "Cluster shutdown requested of master=" + this.master.getServerName();<a name="line.904"></a>
-<span class="sourceLineNo">905</span>    LOG.info(statusStr);<a name="line.905"></a>
-<span class="sourceLineNo">906</span>    this.clusterShutdown.set(true);<a name="line.906"></a>
-<span class="sourceLineNo">907</span>    if (onlineServers.isEmpty()) {<a name="line.907"></a>
-<span class="sourceLineNo">908</span>      // we do not synchronize here so this may cause a double stop, but not a big deal<a name="line.908"></a>
-<span class="sourceLineNo">909</span>      master.stop("OnlineServer=0 right after cluster shutdown set");<a name="line.909"></a>
-<span class="sourceLineNo">910</span>    }<a name="line.910"></a>
-<span class="sourceLineNo">911</span>  }<a name="line.911"></a>
-<span class="sourceLineNo">912</span><a name="line.912"></a>
-<span class="sourceLineNo">913</span>  public boolean isClusterShutdown() {<a name="line.913"></a>
-<span class="sourceLineNo">914</span>    return this.clusterShutdown.get();<a name="line.914"></a>
+<span class="sourceLineNo">879</span>  public boolean isServerOnline(ServerName serverName) {<a name="line.879"></a>
+<span class="sourceLineNo">880</span>    return serverName != null &amp;&amp; onlineServers.containsKey(serverName);<a name="line.880"></a>
+<span class="sourceLineNo">881</span>  }<a name="line.881"></a>
+<span class="sourceLineNo">882</span><a name="line.882"></a>
+<span class="sourceLineNo">883</span>  public enum ServerLiveState {<a name="line.883"></a>
+<span class="sourceLineNo">884</span>    LIVE,<a name="line.884"></a>
+<span class="sourceLineNo">885</span>    DEAD,<a name="line.885"></a>
+<span class="sourceLineNo">886</span>    UNKNOWN<a name="line.886"></a>
+<span class="sourceLineNo">887</span>  }<a name="line.887"></a>
+<span class="sourceLineNo">888</span><a name="line.888"></a>
+<span class="sourceLineNo">889</span>  /**<a name="line.889"></a>
+<span class="sourceLineNo">890</span>   * @return whether the server is online, dead, or unknown.<a name="line.890"></a>
+<span class="sourceLineNo">891</span>   */<a name="line.891"></a>
+<span class="sourceLineNo">892</span>  public synchronized ServerLiveState isServerKnownAndOnline(ServerName serverName) {<a name="line.892"></a>
+<span class="sourceLineNo">893</span>    return onlineServers.containsKey(serverName) ? ServerLiveState.LIVE<a name="line.893"></a>
+<span class="sourceLineNo">894</span>      : (deadservers.isDeadServer(serverName) ? ServerLiveState.DEAD : ServerLiveState.UNKNOWN);<a name="line.894"></a>
+<span class="sourceLineNo">895</span>  }<a name="line.895"></a>
+<span class="sourceLineNo">896</span><a name="line.896"></a>
+<span class="sourceLineNo">897</span>  /**<a name="line.897"></a>
+<span class="sourceLineNo">898</span>   * Check if a server is known to be dead.  A server can be online,<a name="line.898"></a>
+<span class="sourceLineNo">899</span>   * or known to be dead, or unknown to this manager (i.e, not online,<a name="line.899"></a>
+<span class="sourceLineNo">900</span>   * not known to be dead either; it is simply not tracked by the<a name="line.900"></a>
+<span class="sourceLineNo">901</span>   * master any more, for example, a very old previous instance).<a name="line.901"></a>
+<span class="sourceLineNo">902</span>   */<a name="line.902"></a>
+<span class="sourceLineNo">903</span>  public synchronized boolean isServerDead(ServerName serverName) {<a name="line.903"></a>
+<span class="sourceLineNo">904</span>    return serverName == null || deadservers.isDeadServer(serverName);<a name="line.904"></a>
+<span class="sourceLineNo">905</span>  }<a name="line.905"></a>
+<span class="sourceLineNo">906</span><a name="line.906"></a>
+<span class="sourceLineNo">907</span>  public void shutdownCluster() {<a name="line.907"></a>
+<span class="sourceLineNo">908</span>    String statusStr = "Cluster shutdown requested of master=" + this.master.getServerName();<a name="line.908"></a>
+<span class="sourceLineNo">909</span>    LOG.info(statusStr);<a name="line.909"></a>
+<span class="sourceLineNo">910</span>    this.clusterShutdown.set(true);<a name="line.910"></a>
+<span class="sourceLineNo">911</span>    if (onlineServers.isEmpty()) {<a name="line.911"></a>
+<span class="sourceLineNo">912</span>      // we do not synchronize here so this may cause a double stop, but not a big deal<a name="line.912"></a>
+<span class="sourceLineNo">913</span>      master.stop("OnlineServer=0 right after cluster shutdown set");<a name="line.913"></a>
+<span class="sourceLineNo">914</span>    }<a name="line.914"></a>
 <span class="sourceLineNo">915</span>  }<a name="line.915"></a>
 <span class="sourceLineNo">916</span><a name="line.916"></a>
-<span class="sourceLineNo">917</span>  /**<a name="line.917"></a>
-<span class="sourceLineNo">918</span>   * start chore in ServerManager<a name="line.918"></a>
-<span class="sourceLineNo">919</span>   */<a name="line.919"></a>
-<span class="sourceLineNo">920</span>  public void startChore() {<a name="line.920"></a>
-<span class="sourceLineNo">921</span>    Configuration c = master.getConfiguration();<a name="line.921"></a>
-<span class="sourceLineNo">922</span>    if (persistFlushedSequenceId) {<a name="line.922"></a>
-<span class="sourceLineNo">923</span>      // when reach here, RegionStates should loaded, firstly, we call remove deleted regions<a name="line.923"></a>
-<span class="sourceLineNo">924</span>      removeDeletedRegionFromLoadedFlushedSequenceIds();<a name="line.924"></a>
-<span class="sourceLineNo">925</span>      int flushPeriod = c.getInt(FLUSHEDSEQUENCEID_FLUSHER_INTERVAL,<a name="line.925"></a>
-<span class="sourceLineNo">926</span>          FLUSHEDSEQUENCEID_FLUSHER_INTERVAL_DEFAULT);<a name="line.926"></a>
-<span class="sourceLineNo">927</span>      flushedSeqIdFlusher = new FlushedSequenceIdFlusher(<a name="line.927"></a>
-<span class="sourceLineNo">928</span>          "FlushedSequenceIdFlusher", flushPeriod);<a name="line.928"></a>
-<span class="sourceLineNo">929</span>      master.getChoreService().scheduleChore(flushedSeqIdFlusher);<a name="line.929"></a>
-<span class="sourceLineNo">930</span>    }<a name="line.930"></a>
-<span class="sourceLineNo">931</span>  }<a name="line.931"></a>
-<span class="sourceLineNo">932</span><a name="line.932"></a>
-<span class="sourceLineNo">933</span>  /**<a name="line.933"></a>
-<span class="sourceLineNo">934</span>   * Stop the ServerManager.<a name="line.934"></a>
-<span class="sourceLineNo">935</span>   */<a name="line.935"></a>
-<span class="sourceLineNo">936</span>  public void stop() {<a name="line.936"></a>
-<span class="sourceLineNo">937</span>    if (flushedSeqIdFlusher != null) {<a name="line.937"></a>
-<span class="sourceLineNo">938</span>      flushedSeqIdFlusher.cancel();<a name="line.938"></a>
-<span class="sourceLineNo">939</span>    }<a name="line.939"></a>
-<span class="sourceLineNo">940</span>    if (persistFlushedSequenceId) {<a name="line.940"></a>
-<span class="sourceLineNo">941</span>      try {<a name="line.941"></a>
-<span class="sourceLineNo">942</span>        persistRegionLastFlushedSequenceIds();<a name="line.942"></a>
-<span class="sourceLineNo">943</span>      } catch (IOException e) {<a name="line.943"></a>
-<span class="sourceLineNo">944</span>        LOG.warn("Failed to persist last flushed sequence id of regions"<a name="line.944"></a>
-<span class="sourceLineNo">945</span>            + " to file system", e);<a name="line.945"></a>
-<span class="sourceLineNo">946</span>      }<a name="line.946"></a>
-<span class="sourceLineNo">947</span>    }<a name="line.947"></a>
-<span class="sourceLineNo">948</span>  }<a name="line.948"></a>
-<span class="sourceLineNo">949</span><a name="line.949"></a>
-<span class="sourceLineNo">950</span>  /**<a name="line.950"></a>
-<span class="sourceLineNo">951</span>   * Creates a list of possible destinations for a region. It contains the online servers, but not<a name="line.951"></a>
-<span class="sourceLineNo">952</span>   *  the draining or dying servers.<a name="line.952"></a>
-<span class="sourceLineNo">953</span>   *  @param serversToExclude can be null if there is no server to exclude<a name="line.953"></a>
-<span class="sourceLineNo">954</span>   */<a name="line.954"></a>
-<span class="sourceLineNo">955</span>  public List&lt;ServerName&gt; createDestinationServersList(final List&lt;ServerName&gt; serversToExclude){<a name="line.955"></a>
-<span class="sourceLineNo">956</span>    final List&lt;ServerName&gt; destServers = getOnlineServersList();<a name="line.956"></a>
-<span class="sourceLineNo">957</span><a name="line.957"></a>
-<span class="sourceLineNo">958</span>    if (serversToExclude != null) {<a name="line.958"></a>
-<span class="sourceLineNo">959</span>      destServers.removeAll(serversToExclude);<a name="line.959"></a>
-<span class="sourceLineNo">960</span>    }<a name="line.960"></a>
+<span class="sourceLineNo">917</span>  public boolean isClusterShutdown() {<a name="line.917"></a>
+<span class="sourceLineNo">918</span>    return this.clusterShutdown.get();<a name="line.918"></a>
+<span class="sourceLineNo">919</span>  }<a name="line.919"></a>
+<span class="sourceLineNo">920</span><a name="line.920"></a>
+<span class="sourceLineNo">921</span>  /**<a name="line.921"></a>
+<span class="sourceLineNo">922</span>   * start chore in ServerManager<a name="line.922"></a>
+<span class="sourceLineNo">923</span>   */<a name="line.923"></a>
+<span class="sourceLineNo">924</span>  public void startChore() {<a name="line.924"></a>
+<span class="sourceLineNo">925</span>    Configuration c = master.getConfiguration();<a name="line.925"></a>
+<span class="sourceLineNo">926</span>    if (persistFlushedSequenceId) {<a name="line.926"></a>
+<span class="sourceLineNo">927</span>      // when reach here, RegionStates should loaded, firstly, we call remove deleted regions<a name="line.927"></a>
+<span class="sourceLineNo">928</span>      removeDeletedRegionFromLoadedFlushedSequenceIds();<a name="line.928"></a>
+<span class="sourceLineNo">929</span>      int flushPeriod = c.getInt(FLUSHEDSEQUENCEID_FLUSHER_INTERVAL,<a name="line.929"></a>
+<span class="sourceLineNo">930</span>          FLUSHEDSEQUENCEID_FLUSHER_INTERVAL_DEFAULT);<a name="line.930"></a>
+<span class="sourceLineNo">931</span>      flushedSeqIdFlusher = new FlushedSequenceIdFlusher(<a name="line.931"></a>
+<span class="sourceLineNo">932</span>          "FlushedSequenceIdFlusher", flushPeriod);<a name="line.932"></a>
+<span class="sourceLineNo">933</span>      master.getChoreService().scheduleChore(flushedSeqIdFlusher);<a name="line.933"></a>
+<span class="sourceLineNo">934</span>    }<a name="line.934"></a>
+<span class="sourceLineNo">935</span>  }<a name="line.935"></a>
+<span class="sourceLineNo">936</span><a name="line.936"></a>
+<span class="sourceLineNo">937</span>  /**<a name="line.937"></a>
+<span class="sourceLineNo">938</span>   * Stop the ServerManager.<a name="line.938"></a>
+<span class="sourceLineNo">939</span>   */<a name="line.939"></a>
+<span class="sourceLineNo">940</span>  public void stop() {<a name="line.940"></a>
+<span class="sourceLineNo">941</span>    if (flushedSeqIdFlusher != null) {<a name="line.941"></a>
+<span class="sourceLineNo">942</span>      flushedSeqIdFlusher.cancel();<a name="line.942"></a>
+<span class="sourceLineNo">943</span>    }<a name="line.943"></a>
+<span class="sourceLineNo">944</span>    if (persistFlushedSequenceId) {<a name="line.944"></a>
+<span class="sourceLineNo">945</span>      try {<a name="line.945"></a>
+<span class="sourceLineNo">946</span>        persistRegionLastFlushedSequenceIds();<a name="line.946"></a>
+<span class="sourceLineNo">947</span>      } catch (IOException e) {<a name="line.947"></a>
+<span class="sourceLineNo">948</span>        LOG.warn("Failed to persist last flushed sequence id of regions"<a name="line.948"></a>
+<span class="sourceLineNo">949</span>            + " to file system", e);<a name="line.949"></a>
+<span class="sourceLineNo">950</span>      }<a name="line.950"></a>
+<span class="sourceLineNo">951</span>    }<a name="line.951"></a>
+<span class="sourceLineNo">952</span>  }<a name="line.952"></a>
+<span class="sourceLineNo">953</span><a name="line.953"></a>
+<span class="sourceLineNo">954</span>  /**<a name="line.954"></a>
+<span class="sourceLineNo">955</span>   * Creates a list of possible destinations for a region. It contains the online servers, but not<a name="line.955"></a>
+<span class="sourceLineNo">956</span>   *  the draining or dying servers.<a name="line.956"></a>
+<span class="sourceLineNo">957</span>   *  @param serversToExclude can be null if there is no server to exclude<a name="line.957"></a>
+<span class="sourceLineNo">958</span>   */<a name="line.958"></a>
+<span class="sourceLineNo">959</span>  public List&lt;ServerName&gt; createDestinationServersList(final List&lt;ServerName&gt; serversToExclude){<a name="line.959"></a>
+<span class="sourceLineNo">960</span>    final List&lt;ServerName&gt; destServers = getOnlineServersList();<a name="line.960"></a>
 <span class="sourceLineNo">961</span><a name="line.961"></a>
-<span class="sourceLineNo">962</span>    // Loop through the draining server list and remove them from the server list<a name="line.962"></a>
-<span class="sourceLineNo">963</span>    final List&lt;ServerName&gt; drainingServersCopy = getDrainingServersList();<a name="line.963"></a>
-<span class="sourceLineNo">964</span>    destServers.removeAll(drainingServersCopy);<a name="line.964"></a>
+<span class="sourceLineNo">962</span>    if (serversToExclude != null) {<a name="line.962"></a>
+<span class="sourceLineNo">963</span>      destServers.removeAll(serversToExclude);<a name="line.963"></a>
+<span class="sourceLineNo">964</span>    }<a name="line.964"></a>
 <span class="sourceLineNo">965</span><a name="line.965"></a>
-<span class="sourceLineNo">966</span>    return destServers;<a name="line.966"></a>
-<span class="sourceLineNo">967</span>  }<a name="line.967"></a>
-<span class="sourceLineNo">968</span><a name="line.968"></a>
-<span class="sourceLineNo">969</span>  /**<a name="line.969"></a>
-<span class="sourceLineNo">970</span>   * Calls {@link #createDestinationServersList} without server to exclude.<a name="line.970"></a>
-<span class="sourceLineNo">971</span>   */<a name="line.971"></a>
-<span class="sourceLineNo">972</span>  public List&lt;ServerName&gt; createDestinationServersList(){<a name="line.972"></a>
-<span class="sourceLineNo">973</span>    return createDestinationServersList(null);<a name="line.973"></a>
-<span class="sourceLineNo">974</span>  }<a name="line.974"></a>
-<span class="sourceLineNo">975</span><a name="line.975"></a>
-<span class="sourceLineNo">976</span>  /**<a name="line.976"></a>
-<span class="sourceLineNo">977</span>   * To clear any dead server with same host name and port of any online server<a name="line.977"></a>
-<span class="sourceLineNo">978</span>   */<a name="line.978"></a>
-<span class="sourceLineNo">979</span>  void clearDeadServersWithSameHostNameAndPortOfOnlineServer() {<a name="line.979"></a>
-<span class="sourceLineNo">980</span>    for (ServerName serverName : getOnlineServersList()) {<a name="line.980"></a>
-<span class="sourceLineNo">981</span>      deadservers.cleanAllPreviousInstances(serverName);<a name="line.981"></a>
-<span class="sourceLineNo">982</span>    }<a name="line.982"></a>
-<span class="sourceLineNo">983</span>  }<a name="line.983"></a>
-<span class="sourceLineNo">984</span><a name="line.984"></a>
-<span class="sourceLineNo">985</span>  /**<a name="line.985"></a>
-<span class="sourceLineNo">986</span>   * Called by delete table and similar to notify the ServerManager that a region was removed.<a name="line.986"></a>
-<span class="sourceLineNo">987</span>   */<a name="line.987"></a>
-<span class="sourceLineNo">988</span>  public void removeRegion(final RegionInfo regionInfo) {<a name="line.988"></a>
-<span class="sourceLineNo">989</span>    final byte[] encodedName = regionInfo.getEncodedNameAsBytes();<a name="line.989"></a>
-<span class="sourceLineNo">990</span>    storeFlushedSequenceIdsByRegion.remove(encodedName);<a name="line.990"></a>
-<span class="sourceLineNo">991</span>    flushedSequenceIdByRegion.remove(encodedName);<a name="line.991"></a>
-<span class="sourceLineNo">992</span>  }<a name="line.992"></a>
-<span class="sourceLineNo">993</span><a name="line.993"></a>
-<span class="sourceLineNo">994</span>  @VisibleForTesting<a name="line.994"></a>
-<span class="sourceLineNo">995</span>  public boolean isRegionInServerManagerStates(final RegionInfo hri) {<a name="line.995"></a>
-<span class="sourceLineNo">996</span>    final byte[] encodedName = hri.getEncodedNameAsBytes();<a name="line.996"></a>
-<span class="sourceLineNo">997</span>    return (storeFlushedSequenceIdsByRegion.containsKey(encodedName)<a name="line.997"></a>
-<span class="sourceLineNo">998</span>        || flushedSequenceIdByRegion.containsKey(encodedName));<a name="line.998"></a>
-<span class="sourceLineNo">999</span>  }<a name="line.999"></a>
-<span class="sourceLineNo">1000</span><a name="line.1000"></a>
-<span class="sourceLineNo">1001</span>  /**<a name="line.1001"></a>
-<span class="sourceLineNo">1002</span>   * Called by delete table and similar to notify the ServerManager that a region was removed.<a name="line.1002"></a>
-<span class="sourceLineNo">1003</span>   */<a name="line.1003"></a>
-<span class="sourceLineNo">1004</span>  public void removeRegions(final List&lt;RegionInfo&gt; regions) {<a name="line.1004"></a>
-<span class="sourceLineNo">1005</span>    for (RegionInfo hri: regions) {<a name="line.1005"></a>
-<span class="sourceLineNo">1006</span>      removeRegion(hri);<a name="line.1006"></a>
-<span class="sourceLineNo">1007</span>    }<a name="line.1007"></a>
-<span class="sourceLineNo">1008</span>  }<a name="line.1008"></a>
-<span class="sourceLineNo">1009</span><a name="line.1009"></a>
-<span class="sourceLineNo">1010</span>  /**<a name="line.1010"></a>
-<span class="sourceLineNo">1011</span>   * May return 0 when server is not online.<a name="line.1011"></a>
-<span class="sourceLineNo">1012</span>   */<a name="line.1012"></a>
-<span class="sourceLineNo">1013</span>  public int getVersionNumber(ServerName serverName) {<a name="line.1013"></a>
-<span class="sourceLineNo">1014</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1014"></a>
-<span class="sourceLineNo">1015</span>    return serverMetrics != null ? serverMetrics.getVersionNumber() : 0;<a name="line.1015"></a>
-<span class="sourceLineNo">1016</span>  }<a name="line.1016"></a>
-<span class="sourceLineNo">1017</span><a name="line.1017"></a>
-<span class="sourceLineNo">1018</span>  /**<a name="line.1018"></a>
-<span class="sourceLineNo">1019</span>   * May return "0.0.0" when server is not online<a name="line.1019"></a>
-<span class="sourceLineNo">1020</span>   */<a name="line.1020"></a>
-<span class="sourceLineNo">1021</span>  public String getVersion(ServerName serverName) {<a name="line.1021"></a>
-<span class="sourceLineNo">1022</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1022"></a>
-<span class="sourceLineNo">1023</span>    return serverMetrics != null ? serverMetrics.getVersion() : "0.0.0";<a name="line.1023"></a>
-<span class="sourceLineNo">1024</span>  }<a name="line.1024"></a>
-<span class="sourceLineNo">1025</span><a name="line.1025"></a>
-<span class="sourceLineNo">1026</span>  public int getInfoPort(ServerName serverName) {<a name="line.1026"></a>
-<span class="sourceLineNo">1027</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1027"></a>
-<span class="sourceLineNo">1028</span>    return serverMetrics != null ? serverMetrics.getInfoServerPort() : 0;<a name="line.1028"></a>
-<span class="sourceLineNo">1029</span>  }<a name="line.1029"></a>
-<span class="sourceLineNo">1030</span><a name="line.1030"></a>
-<span class="sourceLineNo">1031</span>  /**<a name="line.1031"></a>
-<span class="sourceLineNo">1032</span>   * Persist last flushed sequence id of each region to HDFS<a name="line.1032"></a>
-<span class="sourceLineNo">1033</span>   * @throws IOException if persit to HDFS fails<a name="line.1033"></a>
-<span class="sourceLineNo">1034</span>   */<a name="line.1034"></a>
-<span class="sourceLineNo">1035</span>  private void persistRegionLastFlushedSequenceIds() throws IOException {<a name="line.1035"></a>
-<span class="sourceLineNo">1036</span>    if (isFlushSeqIdPersistInProgress) {<a name="line.1036"></a>
-<span class="sourceLineNo">1037</span>      return;<a name="line.1037"></a>
-<span class="sourceLineNo">1038</span>    }<a name="line.1038"></a>
-<span class="sourceLineNo">1039</span>    isFlushSeqIdPersistInProgress = true;<a name="line.1039"></a>
-<span class="sourceLineNo">1040</span>    try {<a name="line.1040"></a>
-<span class="sourceLineNo">1041</span>      Configuration conf = master.getConfiguration();<a name="line.1041"></a>
-<span class="sourceLineNo">1042</span>      Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.1042"></a>
-<span class="sourceLineNo">1043</span>      Path lastFlushedSeqIdPath = new Path(rootDir, LAST_FLUSHED_SEQ_ID_FILE);<a name="line.1043"></a>
-<span class="sourceLineNo">1044</span>      FileSystem fs = FileSystem.get(conf);<a name="line.1044"></a>
-<span class="sourceLineNo">1045</span>      if (fs.exists(lastFlushedSeqIdPath)) {<a name="line.1045"></a>
-<span class="sourceLineNo">1046</span>        LOG.info("Rewriting .lastflushedseqids file at: "<a name="line.1046"></a>
-<span class="sourceLineNo">1047</span>            + lastFlushedSeqIdPath);<a name="line.1047"></a>
-<span class="sourceLineNo">1048</span>        if (!fs.delete(lastFlushedSeqIdPath, false)) {<a name="line.1048"></a>
-<span class="sourceLineNo">1049</span>          throw new IOException("Unable to remove existing "<a name="line.1049"></a>
-<span class="sourceLineNo">1050</span>              + lastFlushedSeqIdPath);<a name="line.1050"></a>
-<span class="sourceLineNo">1051</span>        }<a name="line.1051"></a>
-<span class="sourceLineNo">1052</span>      } else {<a name="line.1052"></a>
-<span class="sourceLineNo">1053</span>        LOG.info("Writing .lastflushedseqids file at: " + lastFlushedSeqIdPath);<a name="line.1053"></a>
-<span class="sourceLineNo">1054</span>      }<a name="line.1054"></a>
-<span class="sourceLineNo">1055</span>      FSDataOutputStream out = fs.create(lastFlushedSeqIdPath);<a name="line.1055"></a>
-<span class="sourceLineNo">1056</span>      FlushedSequenceId.Builder flushedSequenceIdBuilder =<a name="line.1056"></a>
-<span class="sourceLineNo">1057</span>          FlushedSequenceId.newBuilder();<a name="line.1057"></a>
-<span class="sourceLineNo">1058</span>      try {<a name="line.1058"></a>
-<span class="sourceLineNo">1059</span>        for (Entry&lt;byte[], Long&gt; entry : flushedSequenceIdByRegion.entrySet()) {<a name="line.1059"></a>
-<span class="sourceLineNo">1060</span>          FlushedRegionSequenceId.Builder flushedRegionSequenceIdBuilder =<a name="line.1060"></a>
-<span class="sourceLineNo">1061</span>              FlushedRegionSequenceId.newBuilder();<a name="line.1061"></a>
-<span class="sourceLineNo">1062</span>          flushedRegionSequenceIdBuilder.setRegionEncodedName(<a name="line.1062"></a>
-<span class="sourceLineNo">1063</span>              ByteString.copyFrom(entry.getKey()));<a name="line.1063"></a>
-<span class="sourceLineNo">1064</span>          flushedRegionSequenceIdBuilder.setSeqId(entry.getValue());<a name="line.1064"></a>
-<span class="sourceLineNo">1065</span>          ConcurrentNavigableMap&lt;byte[], Long&gt; storeSeqIds =<a name="line.1065"></a>
-<span class="sourceLineNo">1066</span>              storeFlushedSequenceIdsByRegion.get(entry.getKey());<a name="line.1066"></a>
-<span class="sourceLineNo">1067</span>          if (storeSeqIds != null) {<a name="line.1067"></a>
-<span class="sourceLineNo">1068</span>            for (Entry&lt;byte[], Long&gt; store : storeSeqIds.entrySet()) {<a name="line.1068"></a>
-<span class="sourceLineNo">1069</span>              FlushedStoreSequenceId.Builder flushedStoreSequenceIdBuilder =<a name="line.1069"></a>
-<span class="sourceLineNo">1070</span>                  FlushedStoreSequenceId.newBuilder();<a name="line.1070"></a>
-<span class="sourceLineNo">1071</span>              flushedStoreSequenceIdBuilder.setFamily(ByteString.copyFrom(store.getKey()));<a name="line.1071"></a>
-<span class="sourceLineNo">1072</span>              flushedStoreSequenceIdBuilder.setSeqId(store.getValue());<a name="line.1072"></a>
-<span class="sourceLineNo">1073</span>              flushedRegionSequenceIdBuilder.addStores(flushedStoreSequenceIdBuilder);<a name="line.1073"></a>
-<span class="sourceLineNo">1074</span>            }<a name="line.1074"></a>
-<span class="sourceLineNo">1075</span>          }<a name="line.1075"></a>
-<span class="sourceLineNo">1076</span>          flushedSequenceIdBuilder.addRegionSequenceId(flushedRegionSequenceIdBuilder);<a name="line.1076"></a>
-<span class="sourceLineNo">1077</span>        }<a name="line.1077"></a>
-<span class="sourceLineNo">1078</span>        flushedSequenceIdBuilder.build().writeDelimitedTo(out);<a name="line.1078"></a>
-<span class="sourceLineNo">1079</span>      } finally {<a name="line.1079"></a>
-<span class="sourceLineNo">1080</span>        if (out != null) {<a name="line.1080"></a>
-<span class="sourceLineNo">1081</span>          out.close();<a name="line.1081"></a>
-<span class="sourceLineNo">1082</span>        }<a name="line.1082"></a>
-<span class="sourceLineNo">1083</span>      }<a name="line.1083"></a>
-<span class="sourceLineNo">1084</span>    } finally {<a name="line.1084"></a>
-<span class="sourceLineNo">1085</span>      isFlushSeqIdPersistInProgress = false;<a name="line.1085"></a>
-<span class="sourceLineNo">1086</span>    }<a name="line.1086"></a>
-<span class="sourceLineNo">1087</span>  }<a name="line.1087"></a>
-<span class="sourceLineNo">1088</span><a name="line.1088"></a>
-<span class="sourceLineNo">1089</span>  /**<a name="line.1089"></a>
-<span class="sourceLineNo">1090</span>   * Load last flushed sequence id of each region from HDFS, if persisted<a name="line.1090"></a>
-<span class="sourceLineNo">1091</span>   */<a name="line.1091"></a>
-<span class="sourceLineNo">1092</span>  public void loadLastFlushedSequenceIds() throws IOException {<a name="line.1092"></a>
-<span class="sourceLineNo">1093</span>    if (!persistFlushedSequenceId) {<a name="line.1093"></a>
-<span class="sourceLineNo">1094</span>      return;<a name="line.1094"></a>
-<span class="sourceLineNo">1095</span>    }<a name="line.1095"></a>
-<span class="sourceLineNo">1096</span>    Configuration conf = master.getConfiguration();<a name="line.1096"></a>
-<span class="sourceLineNo">1097</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.1097"></a>
-<span class="sourceLineNo">1098</span>    Path lastFlushedSeqIdPath = new Path(rootDir, LAST_FLUSHED_SEQ_ID_FILE);<a name="line.1098"></a>
-<span class="sourceLineNo">1099</span>    FileSystem fs = FileSystem.get(conf);<a name="line.1099"></a>
-<span class="sourceLineNo">1100</span>    if (!fs.exists(lastFlushedSeqIdPath)) {<a name="line.1100"></a>
-<span class="sourceLineNo">1101</span>      LOG.info("No .lastflushedseqids found at" + lastFlushedSeqIdPath<a name="line.1101"></a>
-<span class="sourceLineNo">1102</span>          + " will record last flushed sequence id"<a name="line.1102"></a>
-<span class="sourceLineNo">1103</span>          + " for regions by regionserver report all over again");<a name="line.1103"></a>
-<span class="sourceLineNo">1104</span>      return;<a name="line.1104"></a>
-<span class="sourceLineNo">1105</span>    } else {<a name="line.1105"></a>
-<span class="sourceLineNo">1106</span>      LOG.info("begin to load .lastflushedseqids at " + lastFlushedSeqIdPath);<a name="line.1106"></a>
-<span class="sourceLineNo">1107</span>    }<a name="line.1107"></a>
-<span class="sourceLineNo">1108</span>    FSDataInputStream in = fs.open(lastFlushedSeqIdPath);<a name="line.1108"></a>
-<span class="sourceLineNo">1109</span>    try {<a name="line.1109"></a>
-<span class="sourceLineNo">1110</span>      FlushedSequenceId flushedSequenceId =<a name="line.1110"></a>
-<span class="sourceLineNo">1111</span>          FlushedSequenceId.parseDelimitedFrom(in);<a name="line.1111"></a>
-<span class="sourceLineNo">1112</span>      if (flushedSequenceId == null) {<a name="line.1112"></a>
-<span class="sourceLineNo">1113</span>        LOG.info(".lastflushedseqids found at {} is empty", lastFlushedSeqIdPath);<a name="line.1113"></a>
-<span class="sourceLineNo">1114</span>        return;<a name="line.1114"></a>
-<span class="sourceLineNo">1115</span>      }<a name="line.1115"></a>
-<span class="sourceLineNo">1116</span>      for (FlushedRegionSequenceId flushedRegionSequenceId : flushedSequenceId<a name="line.1116"></a>
-<span class="sourceLineNo">1117</span>          .getRegionSequenceIdList()) {<a name="line.1117"></a>
-<span class="sourceLineNo">1118</span>        byte[] encodedRegionName = flushedRegionSequenceId<a name="line.1118"></a>
-<span class="sourceLineNo">1119</span>            .getRegionEncodedName().toByteArray();<a name="line.1119"></a>
-<span class="sourceLineNo">1120</span>        flushedSequenceIdByRegion<a name="line.1120"></a>
-<span class="sourceLineNo">1121</span>            .putIfAbsent(encodedRegionName, flushedRegionSequenceId.getSeqId());<a name="line.1121"></a>
-<span class="sourceLineNo">1122</span>        if (flushedRegionSequenceId.getStoresList() != null<a name="line.1122"></a>
-<span class="sourceLineNo">1123</span>            &amp;&amp; flushedRegionSequenceId.getStoresList().size() != 0) {<a name="line.1123"></a>
-<span class="sourceLineNo">1124</span>          ConcurrentNavigableMap&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.1124"></a>
-<span class="sourceLineNo">1125</span>              computeIfAbsent(storeFlushedSequenceIdsByRegion, encodedRegionName,<a name="line.1125"></a>
-<span class="sourceLineNo">1126</span>                () -&gt; new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR));<a name="line.1126"></a>
-<span class="sourceLineNo">1127</span>          for (FlushedStoreSequenceId flushedStoreSequenceId : flushedRegionSequenceId<a name="line.1127"></a>
-<span class="sourceLineNo">1128</span>              .getStoresList()) {<a name="line.1128"></a>
-<span class="sourceLineNo">1129</span>            storeFlushedSequenceId<a name="line.1129"></a>
-<span class="sourceLineNo">1130</span>                .put(flushedStoreSequenceId.getFamily().toByteArray(),<a name="line.1130"></a>
-<span class="sourceLineNo">1131</span>                    flushedStoreSequenceId.getSeqId());<a name="line.1131"></a>
-<span class="sourceLineNo">1132</span>          }<a name="line.1132"></a>
-<span class="sourceLineNo">1133</span>        }<a name="line.1133"></a>
-<span class="sourceLineNo">1134</span>      }<a name="line.1134"></a>
-<span class="sourceLineNo">1135</span>    } finally {<a name="line.1135"></a>
-<span class="sourceLineNo">1136</span>      in.close();<a name="line.1136"></a>
-<span class="sourceLineNo">1137</span>    }<a name="line.1137"></a>
-<span class="sourceLineNo">1138</span>  }<a name="line.1138"></a>
-<span class="sourceLineNo">1139</span><a name="line.1139"></a>
-<span class="sourceLineNo">1140</span>  /**<a name="line.1140"></a>
-<span class="sourceLineNo">1141</span>   * Regions may have been removed between latest persist of FlushedSequenceIds<a name="line.1141"></a>
-<span class="sourceLineNo">1142</span>   * and master abort. So after loading FlushedSequenceIds from file, and after<a name="line.1142"></a>
-<span class="sourceLineNo">1143</span>   * meta loaded, we need to remove the deleted region according to RegionStates.<a name="line.1143"></a>
-<span class="sourceLineNo">1144</span>   */<a name="line.1144"></a>
-<span class="sourceLineNo">1145</span>  public void removeDeletedRegionFromLoadedFlushedSequenceIds() {<a name="line.1145"></a>
-<span class="sourceLineNo">1146</span>    RegionStates regionStates = master.getAssignmentManager().getRegionStates();<a name="line.1146"></a>
-<span class="sourceLineNo">1147</span>    Iterator&lt;byte[]&gt; it = flushedSequenceIdByRegion.keySet().iterator();<a name="line.1147"></a>
-<span class="sourceLineNo">1148</span>    while(it.hasNext()) {<a name="line.1148"></a>
-<span class="sourceLineNo">1149</span>      byte[] regionEncodedName = it.next();<a name="line.1149"></a>
-<span class="sourceLineNo">1150</span>      if (regionStates.getRegionState(Bytes.toStringBinary(regionEncodedName)) == null) {<a name="line.1150"></a>
-<span class="sourceLineNo">1151</span>        it.remove();<a name="line.1151"></a>
-<span class="sourceLineNo">1152</span>        storeFlushedSequenceIdsByRegion.remove(regionEncodedName);<a name="line.1152"></a>
-<span class="sourceLineNo">1153</span>      }<a name="line.1153"></a>
-<span class="sourceLineNo">1154</span>    }<a name="line.1154"></a>
-<span class="sourceLineNo">1155</span>  }<a name="line.1155"></a>
-<span class="sourceLineNo">1156</span><a name="line.1156"></a>
-<span class="sourceLineNo">1157</span>  private class FlushedSequenceIdFlusher extends ScheduledChore {<a name="line.1157"></a>
-<span class="sourceLineNo">1158</span><a name="line.1158"></a>
-<span class="sourceLineNo">1159</span>    public FlushedSequenceIdFlusher(String name, int p) {<a name="line.1159"></a>
-<span class="sourceLineNo">1160</span>      super(name, master, p, 60 * 1000); //delay one minute before first execute<a name="line.1160"></a>
-<span class="sourceLineNo">1161</span>    }<a name="line.1161"></a>
+<span class="sourceLineNo">966</span>    // Loop through the draining server list and remove them from the server list<a name="line.966"></a>
+<span class="sourceLineNo">967</span>    final List&lt;ServerName&gt; drainingServersCopy = getDrainingServersList();<a name="line.967"></a>
+<span class="sourceLineNo">968</span>    destServers.removeAll(drainingServersCopy);<a name="line.968"></a>
+<span class="sourceLineNo">969</span><a name="line.969"></a>
+<span class="sourceLineNo">970</span>    return destServers;<a name="line.970"></a>
+<span class="sourceLineNo">971</span>  }<a name="line.971"></a>
+<span class="sourceLineNo">972</span><a name="line.972"></a>
+<span class="sourceLineNo">973</span>  /**<a name="line.973"></a>
+<span class="sourceLineNo">974</span>   * Calls {@link #createDestinationServersList} without server to exclude.<a name="line.974"></a>
+<span class="sourceLineNo">975</span>   */<a name="line.975"></a>
+<span class="sourceLineNo">976</span>  public List&lt;ServerName&gt; createDestinationServersList(){<a name="line.976"></a>
+<span class="sourceLineNo">977</span>    return createDestinationServersList(null);<a name="line.977"></a>
+<span class="sourceLineNo">978</span>  }<a name="line.978"></a>
+<span class="sourceLineNo">979</span><a name="line.979"></a>
+<span class="sourceLineNo">980</span>  /**<a name="line.980"></a>
+<span class="sourceLineNo">981</span>   * To clear any dead server with same host name and port of any online server<a name="line.981"></a>
+<span class="sourceLineNo">982</span>   */<a name="line.982"></a>
+<span class="sourceLineNo">983</span>  void clearDeadServersWithSameHostNameAndPortOfOnlineServer() {<a name="line.983"></a>
+<span class="sourceLineNo">984</span>    for (ServerName serverName : getOnlineServersList()) {<a name="line.984"></a>
+<span class="sourceLineNo">985</span>      deadservers.cleanAllPreviousInstances(serverName);<a name="line.985"></a>
+<span class="sourceLineNo">986</span>    }<a name="line.986"></a>
+<span class="sourceLineNo">987</span>  }<a name="line.987"></a>
+<span class="sourceLineNo">988</span><a name="line.988"></a>
+<span class="sourceLineNo">989</span>  /**<a name="line.989"></a>
+<span class="sourceLineNo">990</span>   * Called by delete table and similar to notify the ServerManager that a region was removed.<a name="line.990"></a>
+<span class="sourceLineNo">991</span>   */<a name="line.991"></a>
+<span class="sourceLineNo">992</span>  public void removeRegion(final RegionInfo regionInfo) {<a name="line.992"></a>
+<span class="sourceLineNo">993</span>    final byte[] encodedName = regionInfo.getEncodedNameAsBytes();<a name="line.993"></a>
+<span class="sourceLineNo">994</span>    storeFlushedSequenceIdsByRegion.remove(encodedName);<a name="line.994"></a>
+<span class="sourceLineNo">995</span>    flushedSequenceIdByRegion.remove(encodedName);<a name="line.995"></a>
+<span class="sourceLineNo">996</span>  }<a name="line.996"></a>
+<span class="sourceLineNo">997</span><a name="line.997"></a>
+<span class="sourceLineNo">998</span>  @VisibleForTesting<a name="line.998"></a>
+<span class="sourceLineNo">999</span>  public boolean isRegionInServerManagerStates(final RegionInfo hri) {<a name="line.999"></a>
+<span class="sourceLineNo">1000</span>    final byte[] encodedName = hri.getEncodedNameAsBytes();<a name="line.1000"></a>
+<span class="sourceLineNo">1001</span>    return (storeFlushedSequenceIdsByRegion.containsKey(encodedName)<a name="line.1001"></a>
+<span class="sourceLineNo">1002</span>        || flushedSequenceIdByRegion.containsKey(encodedName));<a name="line.1002"></a>
+<span class="sourceLineNo">1003</span>  }<a name="line.1003"></a>
+<span class="sourceLineNo">1004</span><a name="line.1004"></a>
+<span class="sourceLineNo">1005</span>  /**<a name="line.1005"></a>
+<span class="sourceLineNo">1006</span>   * Called by delete table and similar to notify the ServerManager that a region was removed.<a name="line.1006"></a>
+<span class="sourceLineNo">1007</span>   */<a name="line.1007"></a>
+<span class="sourceLineNo">1008</span>  public void removeRegions(final List&lt;RegionInfo&gt; regions) {<a name="line.1008"></a>
+<span class="sourceLineNo">1009</span>    for (RegionInfo hri: regions) {<a name="line.1009"></a>
+<span class="sourceLineNo">1010</span>      removeRegion(hri);<a name="line.1010"></a>
+<span class="sourceLineNo">1011</span>    }<a name="line.1011"></a>
+<span class="sourceLineNo">1012</span>  }<a name="line.1012"></a>
+<span class="sourceLineNo">1013</span><a name="line.1013"></a>
+<span class="sourceLineNo">1014</span>  /**<a name="line.1014"></a>
+<span class="sourceLineNo">1015</span>   * May return 0 when server is not online.<a name="line.1015"></a>
+<span class="sourceLineNo">1016</span>   */<a name="line.1016"></a>
+<span class="sourceLineNo">1017</span>  public int getVersionNumber(ServerName serverName) {<a name="line.1017"></a>
+<span class="sourceLineNo">1018</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1018"></a>
+<span class="sourceLineNo">1019</span>    return serverMetrics != null ? serverMetrics.getVersionNumber() : 0;<a name="line.1019"></a>
+<span class="sourceLineNo">1020</span>  }<a name="line.1020"></a>
+<span class="sourceLineNo">1021</span><a name="line.1021"></a>
+<span class="sourceLineNo">1022</span>  /**<a name="line.1022"></a>
+<span class="sourceLineNo">1023</span>   * May return "0.0.0" when server is not online<a name="line.1023"></a>
+<span class="sourceLineNo">1024</span>   */<a name="line.1024"></a>
+<span class="sourceLineNo">1025</span>  public String getVersion(ServerName serverName) {<a name="line.1025"></a>
+<span class="sourceLineNo">1026</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1026"></a>
+<span class="sourceLineNo">1027</span>    return serverMetrics != null ? serverMetrics.getVersion() : "0.0.0";<a name="line.1027"></a>
+<span class="sourceLineNo">1028</span>  }<a name="line.1028"></a>
+<span class="sourceLineNo">1029</span><a name="line.1029"></a>
+<span class="sourceLineNo">1030</span>  public int getInfoPort(ServerName serverName) {<a name="line.1030"></a>
+<span class="sourceLineNo">1031</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1031"></a>
+<span class="sourceLineNo">1032</span>    return serverMetrics != null ? serverMetrics.getInfoServerPort() : 0;<a name="line.1032"></a>
+<span class="sourceLineNo">1033</span>  }<a name="line.1033"></a>
+<span class="sourceLineNo">1034</span><a name="line.1034"></a>
+<span class="sourceLineNo">1035</span>  /**<a name="line.1035"></a>
+<span class="sourceLineNo">1036</span>   * Persist last flushed sequence id of each region to HDFS<a name="line.1036"></a>
+<span class="sourceLineNo">1037</span>   * @throws IOException if persit to HDFS fails<a name="line.1037"></a>
+<span class="sourceLineNo">1038</span>   */<a name="line.1038"></a>
+<span class="sourceLineNo">1039</span>  private void persistRegionLastFlushedSequenceIds() throws IOException {<a name="line.1039"></a>
+<span class="sourceLineNo">1040</span>    if (isFlushSeqIdPersistInProgress) {<a name="line.1040"></a>
+<span class="sourceLineNo">1041</span>      return;<a name="line.1041"></a>
+<span class="sourceLineNo">1042</span>    }<a name="line.1042"></a>
+<span class="sourceLineNo">1043</span>    isFlushSeqIdPersistInProgress = true;<a name="line.1043"></a>
+<span class="sourceLineNo">1044</span>    try {<a name="line.1044"></a>
+<span class="sourceLineNo">1045</span>      Configuration conf = master.getConfiguration();<a name="line.1045"></a>
+<span class="sourceLineNo">1046</span>      Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.1046"></a>
+<span class="sourceLineNo">1047</span>      Path lastFlushedSeqIdPath = new Path(rootDir, LAST_FLUSHED_SEQ_ID_FILE);<a name="line.1047"></a>
+<span class="sourceLineNo">1048</span>      FileSystem fs = FileSystem.get(conf);<a name="line.1048"></a>
+<span class="sourceLineNo">1049</span>      if (fs.exists(lastFlushedSeqIdPath)) {<a name="line.1049"></a>
+<span class="sourceLineNo">1050</span>        LOG.info("Rewriting .lastflushedseqids file at: "<a name="line.1050"></a>
+<span class="sourceLineNo">1051</span>            + lastFlushedSeqIdPath);<a name="line.1051"></a>
+<span class="sourceLineNo">1052</span>        if (!fs.delete(lastFlushedSeqIdPath, false)) {<a name="line.1052"></a>
+<span class="sourceLineNo">1053</span>          throw new IOException("Unable to remove existing "<a name="line.1053"></a>
+<span class="sourceLineNo">1054</span>              + lastFlushedSeqIdPath);<a name="line.1054"></a>
+<span class="sourceLineNo">1055</span>        }<a name="line.1055"></a>
+<span class="sourceLineNo">1056</span>      } else {<a name="line.1056"></a>
+<span class="sourceLineNo">1057</span>        LOG.info("Writing .lastflushedseqids file at: " + lastFlushedSeqIdPath);<a name="line.1057"></a>
+<span class="sourceLineNo">1058</span>      }<a name="line.1058"></a>
+<span class="sourceLineNo">1059</span>      FSDataOutputStream out = fs.create(lastFlushedSeqIdPath);<a name="line.1059"></a>
+<span class="sourceLineNo">1060</span>      FlushedSequenceId.Builder flushedSequenceIdBuilder =<a name="line.1060"></a>
+<span class="sourceLineNo">1061</span>          FlushedSequenceId.newBuilder();<a name="line.1061"></a>
+<span class="sourceLineNo">1062</span>      try {<a name="line.1062"></a>
+<span class="sourceLineNo">1063</span>        for (Entry&lt;byte[], Long&gt; entry : flushedSequenceIdByRegion.entrySet()) {<a name="line.1063"></a>
+<span class="sourceLineNo">1064</span>          FlushedRegionSequenceId.Builder flushedRegionSequenceIdBuilder =<a name="line.1064"></a>
+<span class="sourceLineNo">1065</span>              FlushedRegionSequenceId.newBuilder();<a name="line.1065"></a>
+<span class="sourceLineNo">1066</span>          flushedRegionSequenceIdBuilder.setRegionEncodedName(<a name="line.1066"></a>
+<span class="sourceLineNo">1067</span>              ByteString.copyFrom(entry.getKey()));<a name="line.1067"></a>
+<span class="sourceLineNo">1068</span>          flushedRegionSequenceIdBuilder.setSeqId(entry.getValue());<a name="line.1068"></a>
+<span class="sourceLineNo">1069</span>          ConcurrentNavigableMap&lt;byte[], Long&gt; storeSeqIds =<a name="line.1069"></a>
+<span class="sourceLineNo">1070</span>              storeFlushedSequenceIdsByRegion.get(entry.getKey());<a name="line.1070"></a>
+<span class="sourceLineNo">1071</span>          if (storeSeqIds != null) {<a name="line.1071"></a>
+<span class="sourceLineNo">1072</span>            for (Entry&lt;byte[], Long&gt; store : storeSeqIds.entrySet()) {<a name="line.1072"></a>
+<span class="sourceLineNo">1073</span>              FlushedStoreSequenceId.Builder flushedStoreSequenceIdBuilder =<a name="line.1073"></a>
+<span class="sourceLineNo">1074</span>                  FlushedStoreSequenceId.newBuilder();<a name="line.1074"></a>
+<span class="sourceLineNo">1075</span>              flushedStoreSequenceIdBuilder.setFamily(ByteString.copyFrom(store.getKey()));<a name="line.1075"></a>
+<span class="sourceLineNo">1076</span>              flushedStoreSequenceIdBuilder.setSeqId(store.getValue());<a name="line.1076"></a>
+<span class="sourceLineNo">1077</span>              flushedRegionSequenceIdBuilder.addStores(flushedStoreSequenceIdBuilder);<a name="line.1077"></a>
+<span class="sourceLineNo">1078</span>            }<a name="line.1078"></a>
+<span class="sourceLineNo">1079</span>          }<a name="line.1079"></a>
+<span class="sourceLineNo">1080</span>          flushedSequenceIdBuilder.addRegionSequenceId(flushedRegionSequenceIdBuilder);<a name="line.1080"></a>
+<span class="sourceLineNo">1081</span>        }<a name="line.1081"></a>
+<span class="sourceLineNo">1082</span>        flushedSequenceIdBuilder.build().writeDelimitedTo(out);<a name="line.1082"></a>
+<span class="sourceLineNo">1083</span>      } finally {<a name="line.1083"></a>
+<span class="sourceLineNo">1084</span>        if (out != null) {<a name="line.1084"></a>
+<span class="sourceLineNo">1085</span>          out.close();<a name="line.1085"></a>
+<span class="sourceLineNo">1086</span>        }<a name="line.1086"></a>
+<span class="sourceLineNo">1087</span>      }<a name="line.1087"></a>
+<span class="sourceLineNo">1088</span>    } finally {<a name="line.1088"></a>
+<span class="sourceLineNo">1089</span>      isFlushSeqIdPersistInProgress = false;<a name="line.1089"></a>
+<span class="sourceLineNo">1090</span>    }<a name="line.1090"></a>
+<span class="sourceLineNo">1091</span>  }<a name="line.1091"></a>
+<span class="sourceLineNo">1092</span><a name="line.1092"></a>
+<span class="sourceLineNo">1093</span>  /**<a name="line.1093"></a>
+<span class="sourceLineNo">1094</span>   * Load last flushed sequence id of each region from HDFS, if persisted<a name="line.1094"></a>
+<span class="sourceLineNo">1095</span>   */<a name="line.1095"></a>
+<span class="sourceLineNo">1096</span>  public void loadLastFlushedSequenceIds() throws IOException {<a name="line.1096"></a>
+<span class="sourceLineNo">1097</span>    if (!persistFlushedSequenceId) {<a name="line.1097"></a>
+<span class="sourceLineNo">1098</span>      return;<a name="line.1098"></a>
+<span class="sourceLineNo">1099</span>    }<a name="line.1099"></a>
+<span class="sourceLineNo">1100</span>    Configuration conf = master.getConfiguration();<a name="line.1100"></a>
+<span class="sourceLineNo">1101</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.1101"></a>
+<span class="sourceLineNo">1102</span>    Path lastFlushedSeqIdPath = new Path(rootDir, LAST_FLUSHED_SEQ_ID_FILE);<a name="line.1102"></a>
+<span class="sourceLineNo">1103</span>    FileSystem fs = FileSystem.get(conf);<a name="line.1103"></a>
+<span class="sourceLineNo">1104</span>    if (!fs.exists(lastFlushedSeqIdPath)) {<a name="line.1104"></a>
+<span class="sourceLineNo">1105</span>      LOG.info("No .lastflushedseqids found at" + lastFlushedSeqIdPath<a name="line.1105"></a>
+<span class="sourceLineNo">1106</span>          + " will record last flushed sequence id"<a name="line.1106"></a>
+<span class="sourceLineNo">1107</span>          + " for regions by regionserver report all over again");<a name="line.1107"></a>
+<span class="sourceLineNo">1108</span>      return;<a name="line.1108"></a>
+<span class="sourceLineNo">1109</span>    } else {<a name="line.1109"></a>
+<span class="sourceLineNo">1110</span>      LOG.info("begin to load .lastflushedseqids at " + lastFlushedSeqIdPath);<a name="line.1110"></a>
+<span class="sourceLineNo">1111</span>    }<a name="line.1111"></a>
+<span class="sourceLineNo">1112</span>    FSDataInputStream in = fs.open(lastFlushedSeqIdPath);<a name="line.1112"></a>
+<span class="sourceLineNo">1113</span>    try {<a name="line.1113"></a>
+<span class="sourceLineNo">1114</span>      FlushedSequenceId flushedSequenceId =<a name="line.1114"></a>
+<span class="sourceLineNo">1115</span>          FlushedSequenceId.parseDelimitedFrom(in);<a name="line.1115"></a>
+<span class="sourceLineNo">1116</span>      if (flushedSequenceId == null) {<a name="line.1116"></a>
+<span class="sourceLineNo">1117</span>        LOG.info(".lastflushedseqids found at {} is empty", lastFlushedSeqIdPath);<a name="line.1117"></a>
+<span class="sourceLineNo">1118</span>        return;<a name="line.1118"></a>
+<span class="sourceLineNo">1119</span>      }<a name="line.1119"></a>
+<span class="sourceLineNo">1120</span>      for (FlushedRegionSequenceId flushedRegionSequenceId : flushedSequenceId<a name="line.1120"></a>
+<span class="sourceLineNo">1121</span>          .getRegionSequenceIdList()) {<a name="line.1121"></a>
+<span class="sourceLineNo">1122</span>        byte[] encodedRegionName = flushedRegionSequenceId<a name="line.1122"></a>
+<span class="sourceLineNo">1123</span>            .getRegionEncodedName().toByteArray();<a name="line.1123"></a>
+<span class="sourceLineNo">1124</span>        flushedSequenceIdByRegion<a name="line.1124"></a>
+<span class="sourceLineNo">1125</span>            .putIfAbsent(encodedRegionName, flushedRegionSequenceId.getSeqId());<a name="line.1125"></a>
+<span class="sourceLineNo">1126</span>        if (flushedRegionSequenceId.getStoresList() != null<a name="line.1126"></a>
+<span class="sourceLineNo">1127</span>            &amp;&amp; flushedRegionSequenceId.getStoresList().size() != 0) {<a name="line.1127"></a>
+<span class="sourceLineNo">1128</span>          ConcurrentNavigableMap&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.1128"></a>
+<span class="sourceLineNo">1129</span>              computeIfAbsent(storeFlushedSequenceIdsByRegion, encodedRegionName,<a name="line.1129"></a>
+<span class="sourceLineNo">1130</span>                () -&gt; new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR));<a name="line.1130"></a>
+<span class="sourceLineNo">1131</span>          for (FlushedStoreSequenceId flushedStoreSequenceId : flushedRegionSequenceId<a name="line.1131"></a>
+<span class="sourceLineNo">1132</span>              .getStoresList()) {<a name="line.1132"></a>
+<span class="sourceLineNo">1133</span>            storeFlushedSequenceId<a name="line.1133"></a>
+<span class="sourceLineNo">1134</span>                .put(flushedStoreSequenceId.getFamily().toByteArray(),<a name="line.1134"></a>
+<span class="sourceLineNo">1135</span>                    flushedStoreSequenceId.getSeqId());<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>      }<a name="line.1138"></a>
+<span class="sourceLineNo">1139</span>    } finally {<a name="line.1139"></a>
+<span class="sourceLineNo">1140</span>      in.close();<a name="line.1140"></a>
+<span class="sourceLineNo">1141</span>    }<a name="line.1141"></a>
+<span class="sourceLineNo">1142</span>  }<a name="line.1142"></a>
+<span class="sourceLineNo">1143</span><a name="line.1143"></a>
+<span class="sourceLineNo">1144</span>  /**<a name="line.1144"></a>
+<span class="sourceLineNo">1145</span>   * Regions may have been removed between latest persist of FlushedSequenceIds<a name="line.1145"></a>
+<span class="sourceLineNo">1146</span>   * and master abort. So after loading FlushedSequenceIds from file, and after<a name="line.1146"></a>
+<span class="sourceLineNo">1147</span>   * meta loaded, we need to remove the deleted region according to RegionStates.<a name="line.1147"></a>
+<span class="sourceLineNo">1148</span>   */<a name="line.1148"></a>
+<span class="sourceLineNo">1149</span>  public void removeDeletedRegionFromLoadedFlushedSequenceIds() {<a name="line.1149"></a>
+<span class="sourceLineNo">1150</span>    RegionStates regionStates = master.getAssignmentManager().getRegionStates();<a name="line.1150"></a>
+<span class="sourceLineNo">1151</span>    Iterator&lt;byte[]&gt; it = flushedSequenceIdByRegion.keySet().iterator();<a name="line.1151"></a>
+<span class="sourceLineNo">1152</span>    while(it.hasNext()) {<a name="line.1152"></a>
+<span class="sourceLineNo">1153</span>      byte[] regionEncodedName = it.next();<a name="line.1153"></a>
+<span class="sourceLineNo">1154</span>      if (regionStates.getRegionState(Bytes.toStringBinary(regionEncodedName)) == null) {<a name="line.1154"></a>
+<span class="sourceLineNo">1155</span>        it.remove();<a name="line.1155"></a>
+<span class="sourceLineNo">1156</span>        storeFlushedSequenceIdsByRegion.remove(regionEncodedName);<a name="line.1156"></a>
+<span class="sourceLineNo">1157</span>      }<a name="line.1157"></a>
+<span class="sourceLineNo">1158</span>    }<a name="line.1158"></a>
+<span class="sourceLineNo">1159</span>  }<a name="line.1159"></a>
+<span class="sourceLineNo">1160</span><a name="line.1160"></a>
+<span class="sourceLineNo">1161</span>  private class FlushedSequenceIdFlusher extends ScheduledChore {<a name="line.1161"></a>
 <span class="sourceLineNo">1162</span><a name="line.1162"></a>
-<span class="sourceLineNo">1163</span>    @Override<a name="line.1163"></a>
-<span class="sourceLineNo">1164</span>    protected void chore() {<a name="line.1164"></a>
-<span class="sourceLineNo">1165</span>      try {<a name="line.1165"></a>
-<span class="sourceLineNo">1166</span>        persistRegionLastFlushedSequenceIds();<a name="line.1166"></a>
-<span class="sourceLineNo">1167</span>      } catch (IOException e) {<a name="line.1167"></a>
-<span class="sourceLineNo">1168</span>        LOG.debug("Failed to persist last flushed sequence id of regions"<a name="line.1168"></a>
-<span class="sourceLineNo">1169</span>            + " to file system", e);<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>  }<a name="line.1172"></a>
-<span class="sourceLineNo">1173</span>}<a name="line.1173"></a>
+<span class="sourceLineNo">1163</span>    public FlushedSequenceIdFlusher(String name, int p) {<a name="line.1163"></a>
+<span class="sourceLineNo">1164</span>      super(name, master, p, 60 * 1000); //delay one minute before first execute<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>    @Override<a name="line.1167"></a>
+<span class="sourceLineNo">1168</span>    protected void chore() {<a name="line.1168"></a>
+<span class="sourceLineNo">1169</span>      try {<a name="line.1169"></a>
+<span class="sourceLineNo">1170</span>        persistRegionLastFlushedSequenceIds();<a name="line.1170"></a>
+<span class="sourceLineNo">1171</span>      } catch (IOException e) {<a name="line.1171"></a>
+<span class="sourceLineNo">1172</span>        LOG.debug("Failed to persist last flushed sequence id of regions"<a name="line.1172"></a>
+<span class="sourceLineNo">1173</span>            + " to file system", e);<a name="line.1173"></a>
+<span class="sourceLineNo">1174</span>      }<a name="line.1174"></a>
+<span class="sourceLineNo">1175</span>    }<a name="line.1175"></a>
+<span class="sourceLineNo">1176</span>  }<a name="line.1176"></a>
+<span class="sourceLineNo">1177</span>}<a name="line.1177"></a>
 
 
 
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html b/devapidocs/src-html/org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html
index 7f98dd8..99dd552 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html
@@ -59,1126 +59,1130 @@
 <span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.client.AsyncClusterConnection;<a name="line.51"></a>
 <span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.client.AsyncRegionServerAdmin;<a name="line.52"></a>
 <span class="sourceLineNo">053</span>import org.apache.hadoop.hbase.client.RegionInfo;<a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.apache.hadoop.hbase.master.assignment.RegionStates;<a name="line.54"></a>
-<span class="sourceLineNo">055</span>import org.apache.hadoop.hbase.monitoring.MonitoredTask;<a name="line.55"></a>
-<span class="sourceLineNo">056</span>import org.apache.hadoop.hbase.procedure2.Procedure;<a name="line.56"></a>
-<span class="sourceLineNo">057</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.57"></a>
-<span class="sourceLineNo">058</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.58"></a>
-<span class="sourceLineNo">059</span>import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;<a name="line.59"></a>
-<span class="sourceLineNo">060</span>import org.apache.hadoop.hbase.util.FutureUtils;<a name="line.60"></a>
-<span class="sourceLineNo">061</span>import org.apache.hadoop.hbase.zookeeper.ZKUtil;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>import org.apache.hadoop.hbase.zookeeper.ZKWatcher;<a name="line.62"></a>
-<span class="sourceLineNo">063</span>import org.apache.hadoop.hbase.zookeeper.ZNodePaths;<a name="line.63"></a>
-<span class="sourceLineNo">064</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.64"></a>
-<span class="sourceLineNo">065</span>import org.apache.zookeeper.KeeperException;<a name="line.65"></a>
-<span class="sourceLineNo">066</span>import org.slf4j.Logger;<a name="line.66"></a>
-<span class="sourceLineNo">067</span>import org.slf4j.LoggerFactory;<a name="line.67"></a>
-<span class="sourceLineNo">068</span><a name="line.68"></a>
-<span class="sourceLineNo">069</span>import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;<a name="line.69"></a>
-<span class="sourceLineNo">070</span>import org.apache.hbase.thirdparty.com.google.protobuf.ByteString;<a name="line.70"></a>
-<span class="sourceLineNo">071</span>import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations;<a name="line.71"></a>
-<span class="sourceLineNo">072</span><a name="line.72"></a>
-<span class="sourceLineNo">073</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.73"></a>
-<span class="sourceLineNo">074</span>import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter;<a name="line.74"></a>
-<span class="sourceLineNo">075</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.RegionStoreSequenceIds;<a name="line.75"></a>
-<span class="sourceLineNo">076</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.StoreSequenceId;<a name="line.76"></a>
-<span class="sourceLineNo">077</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedRegionSequenceId;<a name="line.77"></a>
-<span class="sourceLineNo">078</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedSequenceId;<a name="line.78"></a>
-<span class="sourceLineNo">079</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedStoreSequenceId;<a name="line.79"></a>
-<span class="sourceLineNo">080</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest;<a name="line.80"></a>
-<span class="sourceLineNo">081</span><a name="line.81"></a>
-<span class="sourceLineNo">082</span>/**<a name="line.82"></a>
-<span class="sourceLineNo">083</span> * The ServerManager class manages info about region servers.<a name="line.83"></a>
-<span class="sourceLineNo">084</span> * &lt;p&gt;<a name="line.84"></a>
-<span class="sourceLineNo">085</span> * Maintains lists of online and dead servers.  Processes the startups,<a name="line.85"></a>
-<span class="sourceLineNo">086</span> * shutdowns, and deaths of region servers.<a name="line.86"></a>
-<span class="sourceLineNo">087</span> * &lt;p&gt;<a name="line.87"></a>
-<span class="sourceLineNo">088</span> * Servers are distinguished in two different ways.  A given server has a<a name="line.88"></a>
-<span class="sourceLineNo">089</span> * location, specified by hostname and port, and of which there can only be one<a name="line.89"></a>
-<span class="sourceLineNo">090</span> * online at any given time.  A server instance is specified by the location<a name="line.90"></a>
-<span class="sourceLineNo">091</span> * (hostname and port) as well as the startcode (timestamp from when the server<a name="line.91"></a>
-<span class="sourceLineNo">092</span> * was started).  This is used to differentiate a restarted instance of a given<a name="line.92"></a>
-<span class="sourceLineNo">093</span> * server from the original instance.<a name="line.93"></a>
-<span class="sourceLineNo">094</span> * &lt;p&gt;<a name="line.94"></a>
-<span class="sourceLineNo">095</span> * If a sever is known not to be running any more, it is called dead. The dead<a name="line.95"></a>
-<span class="sourceLineNo">096</span> * server needs to be handled by a ServerShutdownHandler.  If the handler is not<a name="line.96"></a>
-<span class="sourceLineNo">097</span> * enabled yet, the server can't be handled right away so it is queued up.<a name="line.97"></a>
-<span class="sourceLineNo">098</span> * After the handler is enabled, the server will be submitted to a handler to handle.<a name="line.98"></a>
-<span class="sourceLineNo">099</span> * However, the handler may be just partially enabled.  If so,<a name="line.99"></a>
-<span class="sourceLineNo">100</span> * the server cannot be fully processed, and be queued up for further processing.<a name="line.100"></a>
-<span class="sourceLineNo">101</span> * A server is fully processed only after the handler is fully enabled<a name="line.101"></a>
-<span class="sourceLineNo">102</span> * and has completed the handling.<a name="line.102"></a>
-<span class="sourceLineNo">103</span> */<a name="line.103"></a>
-<span class="sourceLineNo">104</span>@InterfaceAudience.Private<a name="line.104"></a>
-<span class="sourceLineNo">105</span>public class ServerManager {<a name="line.105"></a>
-<span class="sourceLineNo">106</span>  public static final String WAIT_ON_REGIONSERVERS_MAXTOSTART =<a name="line.106"></a>
-<span class="sourceLineNo">107</span>      "hbase.master.wait.on.regionservers.maxtostart";<a name="line.107"></a>
-<span class="sourceLineNo">108</span><a name="line.108"></a>
-<span class="sourceLineNo">109</span>  public static final String WAIT_ON_REGIONSERVERS_MINTOSTART =<a name="line.109"></a>
-<span class="sourceLineNo">110</span>      "hbase.master.wait.on.regionservers.mintostart";<a name="line.110"></a>
-<span class="sourceLineNo">111</span><a name="line.111"></a>
-<span class="sourceLineNo">112</span>  public static final String WAIT_ON_REGIONSERVERS_TIMEOUT =<a name="line.112"></a>
-<span class="sourceLineNo">113</span>      "hbase.master.wait.on.regionservers.timeout";<a name="line.113"></a>
-<span class="sourceLineNo">114</span><a name="line.114"></a>
-<span class="sourceLineNo">115</span>  public static final String WAIT_ON_REGIONSERVERS_INTERVAL =<a name="line.115"></a>
-<span class="sourceLineNo">116</span>      "hbase.master.wait.on.regionservers.interval";<a name="line.116"></a>
-<span class="sourceLineNo">117</span><a name="line.117"></a>
-<span class="sourceLineNo">118</span>  /**<a name="line.118"></a>
-<span class="sourceLineNo">119</span>   * see HBASE-20727<a name="line.119"></a>
-<span class="sourceLineNo">120</span>   * if set to true, flushedSequenceIdByRegion and storeFlushedSequenceIdsByRegion<a name="line.120"></a>
-<span class="sourceLineNo">121</span>   * will be persisted to HDFS and loaded when master restart to speed up log split<a name="line.121"></a>
-<span class="sourceLineNo">122</span>   */<a name="line.122"></a>
-<span class="sourceLineNo">123</span>  public static final String PERSIST_FLUSHEDSEQUENCEID =<a name="line.123"></a>
-<span class="sourceLineNo">124</span>      "hbase.master.persist.flushedsequenceid.enabled";<a name="line.124"></a>
-<span class="sourceLineNo">125</span><a name="line.125"></a>
-<span class="sourceLineNo">126</span>  public static final boolean PERSIST_FLUSHEDSEQUENCEID_DEFAULT = true;<a name="line.126"></a>
-<span class="sourceLineNo">127</span><a name="line.127"></a>
-<span class="sourceLineNo">128</span>  public static final String FLUSHEDSEQUENCEID_FLUSHER_INTERVAL =<a name="line.128"></a>
-<span class="sourceLineNo">129</span>      "hbase.master.flushedsequenceid.flusher.interval";<a name="line.129"></a>
-<span class="sourceLineNo">130</span><a name="line.130"></a>
-<span class="sourceLineNo">131</span>  public static final int FLUSHEDSEQUENCEID_FLUSHER_INTERVAL_DEFAULT =<a name="line.131"></a>
-<span class="sourceLineNo">132</span>      3 * 60 * 60 * 1000; // 3 hours<a name="line.132"></a>
-<span class="sourceLineNo">133</span><a name="line.133"></a>
-<span class="sourceLineNo">134</span>  public static final String MAX_CLOCK_SKEW_MS = "hbase.master.maxclockskew";<a name="line.134"></a>
-<span class="sourceLineNo">135</span><a name="line.135"></a>
-<span class="sourceLineNo">136</span>  private static final Logger LOG = LoggerFactory.getLogger(ServerManager.class);<a name="line.136"></a>
-<span class="sourceLineNo">137</span><a name="line.137"></a>
-<span class="sourceLineNo">138</span>  // Set if we are to shutdown the cluster.<a name="line.138"></a>
-<span class="sourceLineNo">139</span>  private AtomicBoolean clusterShutdown = new AtomicBoolean(false);<a name="line.139"></a>
-<span class="sourceLineNo">140</span><a name="line.140"></a>
-<span class="sourceLineNo">141</span>  /**<a name="line.141"></a>
-<span class="sourceLineNo">142</span>   * The last flushed sequence id for a region.<a name="line.142"></a>
-<span class="sourceLineNo">143</span>   */<a name="line.143"></a>
-<span class="sourceLineNo">144</span>  private final ConcurrentNavigableMap&lt;byte[], Long&gt; flushedSequenceIdByRegion =<a name="line.144"></a>
-<span class="sourceLineNo">145</span>    new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.145"></a>
-<span class="sourceLineNo">146</span><a name="line.146"></a>
-<span class="sourceLineNo">147</span>  private boolean persistFlushedSequenceId = true;<a name="line.147"></a>
-<span class="sourceLineNo">148</span>  private volatile boolean isFlushSeqIdPersistInProgress = false;<a name="line.148"></a>
-<span class="sourceLineNo">149</span>  /** File on hdfs to store last flushed sequence id of regions */<a name="line.149"></a>
-<span class="sourceLineNo">150</span>  private static final String LAST_FLUSHED_SEQ_ID_FILE = ".lastflushedseqids";<a name="line.150"></a>
-<span class="sourceLineNo">151</span>  private  FlushedSequenceIdFlusher flushedSeqIdFlusher;<a name="line.151"></a>
-<span class="sourceLineNo">152</span><a name="line.152"></a>
+<span class="sourceLineNo">054</span>import org.apache.hadoop.hbase.ipc.RemoteWithExtrasException;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>import org.apache.hadoop.hbase.master.assignment.RegionStates;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>import org.apache.hadoop.hbase.monitoring.MonitoredTask;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>import org.apache.hadoop.hbase.procedure2.Procedure;<a name="line.57"></a>
+<span class="sourceLineNo">058</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.58"></a>
+<span class="sourceLineNo">059</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.59"></a>
+<span class="sourceLineNo">060</span>import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;<a name="line.60"></a>
+<span class="sourceLineNo">061</span>import org.apache.hadoop.hbase.util.FutureUtils;<a name="line.61"></a>
+<span class="sourceLineNo">062</span>import org.apache.hadoop.hbase.zookeeper.ZKUtil;<a name="line.62"></a>
+<span class="sourceLineNo">063</span>import org.apache.hadoop.hbase.zookeeper.ZKWatcher;<a name="line.63"></a>
+<span class="sourceLineNo">064</span>import org.apache.hadoop.hbase.zookeeper.ZNodePaths;<a name="line.64"></a>
+<span class="sourceLineNo">065</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.65"></a>
+<span class="sourceLineNo">066</span>import org.apache.zookeeper.KeeperException;<a name="line.66"></a>
+<span class="sourceLineNo">067</span>import org.slf4j.Logger;<a name="line.67"></a>
+<span class="sourceLineNo">068</span>import org.slf4j.LoggerFactory;<a name="line.68"></a>
+<span class="sourceLineNo">069</span><a name="line.69"></a>
+<span class="sourceLineNo">070</span>import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;<a name="line.70"></a>
+<span class="sourceLineNo">071</span>import org.apache.hbase.thirdparty.com.google.protobuf.ByteString;<a name="line.71"></a>
+<span class="sourceLineNo">072</span>import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations;<a name="line.72"></a>
+<span class="sourceLineNo">073</span><a name="line.73"></a>
+<span class="sourceLineNo">074</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.74"></a>
+<span class="sourceLineNo">075</span>import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter;<a name="line.75"></a>
+<span class="sourceLineNo">076</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.RegionStoreSequenceIds;<a name="line.76"></a>
+<span class="sourceLineNo">077</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.StoreSequenceId;<a name="line.77"></a>
+<span class="sourceLineNo">078</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedRegionSequenceId;<a name="line.78"></a>
+<span class="sourceLineNo">079</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedSequenceId;<a name="line.79"></a>
+<span class="sourceLineNo">080</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedStoreSequenceId;<a name="line.80"></a>
+<span class="sourceLineNo">081</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest;<a name="line.81"></a>
+<span class="sourceLineNo">082</span><a name="line.82"></a>
+<span class="sourceLineNo">083</span>/**<a name="line.83"></a>
+<span class="sourceLineNo">084</span> * The ServerManager class manages info about region servers.<a name="line.84"></a>
+<span class="sourceLineNo">085</span> * &lt;p&gt;<a name="line.85"></a>
+<span class="sourceLineNo">086</span> * Maintains lists of online and dead servers.  Processes the startups,<a name="line.86"></a>
+<span class="sourceLineNo">087</span> * shutdowns, and deaths of region servers.<a name="line.87"></a>
+<span class="sourceLineNo">088</span> * &lt;p&gt;<a name="line.88"></a>
+<span class="sourceLineNo">089</span> * Servers are distinguished in two different ways.  A given server has a<a name="line.89"></a>
+<span class="sourceLineNo">090</span> * location, specified by hostname and port, and of which there can only be one<a name="line.90"></a>
+<span class="sourceLineNo">091</span> * online at any given time.  A server instance is specified by the location<a name="line.91"></a>
+<span class="sourceLineNo">092</span> * (hostname and port) as well as the startcode (timestamp from when the server<a name="line.92"></a>
+<span class="sourceLineNo">093</span> * was started).  This is used to differentiate a restarted instance of a given<a name="line.93"></a>
+<span class="sourceLineNo">094</span> * server from the original instance.<a name="line.94"></a>
+<span class="sourceLineNo">095</span> * &lt;p&gt;<a name="line.95"></a>
+<span class="sourceLineNo">096</span> * If a sever is known not to be running any more, it is called dead. The dead<a name="line.96"></a>
+<span class="sourceLineNo">097</span> * server needs to be handled by a ServerShutdownHandler.  If the handler is not<a name="line.97"></a>
+<span class="sourceLineNo">098</span> * enabled yet, the server can't be handled right away so it is queued up.<a name="line.98"></a>
+<span class="sourceLineNo">099</span> * After the handler is enabled, the server will be submitted to a handler to handle.<a name="line.99"></a>
+<span class="sourceLineNo">100</span> * However, the handler may be just partially enabled.  If so,<a name="line.100"></a>
+<span class="sourceLineNo">101</span> * the server cannot be fully processed, and be queued up for further processing.<a name="line.101"></a>
+<span class="sourceLineNo">102</span> * A server is fully processed only after the handler is fully enabled<a name="line.102"></a>
+<span class="sourceLineNo">103</span> * and has completed the handling.<a name="line.103"></a>
+<span class="sourceLineNo">104</span> */<a name="line.104"></a>
+<span class="sourceLineNo">105</span>@InterfaceAudience.Private<a name="line.105"></a>
+<span class="sourceLineNo">106</span>public class ServerManager {<a name="line.106"></a>
+<span class="sourceLineNo">107</span>  public static final String WAIT_ON_REGIONSERVERS_MAXTOSTART =<a name="line.107"></a>
+<span class="sourceLineNo">108</span>      "hbase.master.wait.on.regionservers.maxtostart";<a name="line.108"></a>
+<span class="sourceLineNo">109</span><a name="line.109"></a>
+<span class="sourceLineNo">110</span>  public static final String WAIT_ON_REGIONSERVERS_MINTOSTART =<a name="line.110"></a>
+<span class="sourceLineNo">111</span>      "hbase.master.wait.on.regionservers.mintostart";<a name="line.111"></a>
+<span class="sourceLineNo">112</span><a name="line.112"></a>
+<span class="sourceLineNo">113</span>  public static final String WAIT_ON_REGIONSERVERS_TIMEOUT =<a name="line.113"></a>
+<span class="sourceLineNo">114</span>      "hbase.master.wait.on.regionservers.timeout";<a name="line.114"></a>
+<span class="sourceLineNo">115</span><a name="line.115"></a>
+<span class="sourceLineNo">116</span>  public static final String WAIT_ON_REGIONSERVERS_INTERVAL =<a name="line.116"></a>
+<span class="sourceLineNo">117</span>      "hbase.master.wait.on.regionservers.interval";<a name="line.117"></a>
+<span class="sourceLineNo">118</span><a name="line.118"></a>
+<span class="sourceLineNo">119</span>  /**<a name="line.119"></a>
+<span class="sourceLineNo">120</span>   * see HBASE-20727<a name="line.120"></a>
+<span class="sourceLineNo">121</span>   * if set to true, flushedSequenceIdByRegion and storeFlushedSequenceIdsByRegion<a name="line.121"></a>
+<span class="sourceLineNo">122</span>   * will be persisted to HDFS and loaded when master restart to speed up log split<a name="line.122"></a>
+<span class="sourceLineNo">123</span>   */<a name="line.123"></a>
+<span class="sourceLineNo">124</span>  public static final String PERSIST_FLUSHEDSEQUENCEID =<a name="line.124"></a>
+<span class="sourceLineNo">125</span>      "hbase.master.persist.flushedsequenceid.enabled";<a name="line.125"></a>
+<span class="sourceLineNo">126</span><a name="line.126"></a>
+<span class="sourceLineNo">127</span>  public static final boolean PERSIST_FLUSHEDSEQUENCEID_DEFAULT = true;<a name="line.127"></a>
+<span class="sourceLineNo">128</span><a name="line.128"></a>
+<span class="sourceLineNo">129</span>  public static final String FLUSHEDSEQUENCEID_FLUSHER_INTERVAL =<a name="line.129"></a>
+<span class="sourceLineNo">130</span>      "hbase.master.flushedsequenceid.flusher.interval";<a name="line.130"></a>
+<span class="sourceLineNo">131</span><a name="line.131"></a>
+<span class="sourceLineNo">132</span>  public static final int FLUSHEDSEQUENCEID_FLUSHER_INTERVAL_DEFAULT =<a name="line.132"></a>
+<span class="sourceLineNo">133</span>      3 * 60 * 60 * 1000; // 3 hours<a name="line.133"></a>
+<span class="sourceLineNo">134</span><a name="line.134"></a>
+<span class="sourceLineNo">135</span>  public static final String MAX_CLOCK_SKEW_MS = "hbase.master.maxclockskew";<a name="line.135"></a>
+<span class="sourceLineNo">136</span><a name="line.136"></a>
+<span class="sourceLineNo">137</span>  private static final Logger LOG = LoggerFactory.getLogger(ServerManager.class);<a name="line.137"></a>
+<span class="sourceLineNo">138</span><a name="line.138"></a>
+<span class="sourceLineNo">139</span>  // Set if we are to shutdown the cluster.<a name="line.139"></a>
+<span class="sourceLineNo">140</span>  private AtomicBoolean clusterShutdown = new AtomicBoolean(false);<a name="line.140"></a>
+<span class="sourceLineNo">141</span><a name="line.141"></a>
+<span class="sourceLineNo">142</span>  /**<a name="line.142"></a>
+<span class="sourceLineNo">143</span>   * The last flushed sequence id for a region.<a name="line.143"></a>
+<span class="sourceLineNo">144</span>   */<a name="line.144"></a>
+<span class="sourceLineNo">145</span>  private final ConcurrentNavigableMap&lt;byte[], Long&gt; flushedSequenceIdByRegion =<a name="line.145"></a>
+<span class="sourceLineNo">146</span>    new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.146"></a>
+<span class="sourceLineNo">147</span><a name="line.147"></a>
+<span class="sourceLineNo">148</span>  private boolean persistFlushedSequenceId = true;<a name="line.148"></a>
+<span class="sourceLineNo">149</span>  private volatile boolean isFlushSeqIdPersistInProgress = false;<a name="line.149"></a>
+<span class="sourceLineNo">150</span>  /** File on hdfs to store last flushed sequence id of regions */<a name="line.150"></a>
+<span class="sourceLineNo">151</span>  private static final String LAST_FLUSHED_SEQ_ID_FILE = ".lastflushedseqids";<a name="line.151"></a>
+<span class="sourceLineNo">152</span>  private  FlushedSequenceIdFlusher flushedSeqIdFlusher;<a name="line.152"></a>
 <span class="sourceLineNo">153</span><a name="line.153"></a>
-<span class="sourceLineNo">154</span>  /**<a name="line.154"></a>
-<span class="sourceLineNo">155</span>   * The last flushed sequence id for a store in a region.<a name="line.155"></a>
-<span class="sourceLineNo">156</span>   */<a name="line.156"></a>
-<span class="sourceLineNo">157</span>  private final ConcurrentNavigableMap&lt;byte[], ConcurrentNavigableMap&lt;byte[], Long&gt;&gt;<a name="line.157"></a>
-<span class="sourceLineNo">158</span>    storeFlushedSequenceIdsByRegion = new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.158"></a>
-<span class="sourceLineNo">159</span><a name="line.159"></a>
-<span class="sourceLineNo">160</span>  /** Map of registered servers to their current load */<a name="line.160"></a>
-<span class="sourceLineNo">161</span>  private final ConcurrentNavigableMap&lt;ServerName, ServerMetrics&gt; onlineServers =<a name="line.161"></a>
-<span class="sourceLineNo">162</span>    new ConcurrentSkipListMap&lt;&gt;();<a name="line.162"></a>
-<span class="sourceLineNo">163</span><a name="line.163"></a>
-<span class="sourceLineNo">164</span>  /** List of region servers that should not get any more new regions. */<a name="line.164"></a>
-<span class="sourceLineNo">165</span>  private final ArrayList&lt;ServerName&gt; drainingServers = new ArrayList&lt;&gt;();<a name="line.165"></a>
-<span class="sourceLineNo">166</span><a name="line.166"></a>
-<span class="sourceLineNo">167</span>  private final MasterServices master;<a name="line.167"></a>
-<span class="sourceLineNo">168</span><a name="line.168"></a>
-<span class="sourceLineNo">169</span>  private final DeadServer deadservers = new DeadServer();<a name="line.169"></a>
-<span class="sourceLineNo">170</span><a name="line.170"></a>
-<span class="sourceLineNo">171</span>  private final long maxSkew;<a name="line.171"></a>
-<span class="sourceLineNo">172</span>  private final long warningSkew;<a name="line.172"></a>
-<span class="sourceLineNo">173</span><a name="line.173"></a>
-<span class="sourceLineNo">174</span>  /** Listeners that are called on server events. */<a name="line.174"></a>
-<span class="sourceLineNo">175</span>  private List&lt;ServerListener&gt; listeners = new CopyOnWriteArrayList&lt;&gt;();<a name="line.175"></a>
-<span class="sourceLineNo">176</span><a name="line.176"></a>
-<span class="sourceLineNo">177</span>  /**<a name="line.177"></a>
-<span class="sourceLineNo">178</span>   * Constructor.<a name="line.178"></a>
-<span class="sourceLineNo">179</span>   */<a name="line.179"></a>
-<span class="sourceLineNo">180</span>  public ServerManager(final MasterServices master) {<a name="line.180"></a>
-<span class="sourceLineNo">181</span>    this.master = master;<a name="line.181"></a>
-<span class="sourceLineNo">182</span>    Configuration c = master.getConfiguration();<a name="line.182"></a>
-<span class="sourceLineNo">183</span>    maxSkew = c.getLong(MAX_CLOCK_SKEW_MS, 30000);<a name="line.183"></a>
-<span class="sourceLineNo">184</span>    warningSkew = c.getLong("hbase.master.warningclockskew", 10000);<a name="line.184"></a>
-<span class="sourceLineNo">185</span>    persistFlushedSequenceId = c.getBoolean(PERSIST_FLUSHEDSEQUENCEID,<a name="line.185"></a>
-<span class="sourceLineNo">186</span>        PERSIST_FLUSHEDSEQUENCEID_DEFAULT);<a name="line.186"></a>
-<span class="sourceLineNo">187</span>  }<a name="line.187"></a>
-<span class="sourceLineNo">188</span><a name="line.188"></a>
-<span class="sourceLineNo">189</span>  /**<a name="line.189"></a>
-<span class="sourceLineNo">190</span>   * Add the listener to the notification list.<a name="line.190"></a>
-<span class="sourceLineNo">191</span>   * @param listener The ServerListener to register<a name="line.191"></a>
-<span class="sourceLineNo">192</span>   */<a name="line.192"></a>
-<span class="sourceLineNo">193</span>  public void registerListener(final ServerListener listener) {<a name="line.193"></a>
-<span class="sourceLineNo">194</span>    this.listeners.add(listener);<a name="line.194"></a>
-<span class="sourceLineNo">195</span>  }<a name="line.195"></a>
-<span class="sourceLineNo">196</span><a name="line.196"></a>
-<span class="sourceLineNo">197</span>  /**<a name="line.197"></a>
-<span class="sourceLineNo">198</span>   * Remove the listener from the notification list.<a name="line.198"></a>
-<span class="sourceLineNo">199</span>   * @param listener The ServerListener to unregister<a name="line.199"></a>
-<span class="sourceLineNo">200</span>   */<a name="line.200"></a>
-<span class="sourceLineNo">201</span>  public boolean unregisterListener(final ServerListener listener) {<a name="line.201"></a>
-<span class="sourceLineNo">202</span>    return this.listeners.remove(listener);<a name="line.202"></a>
-<span class="sourceLineNo">203</span>  }<a name="line.203"></a>
-<span class="sourceLineNo">204</span><a name="line.204"></a>
-<span class="sourceLineNo">205</span>  /**<a name="line.205"></a>
-<span class="sourceLineNo">206</span>   * Let the server manager know a new regionserver has come online<a name="line.206"></a>
-<span class="sourceLineNo">207</span>   * @param request the startup request<a name="line.207"></a>
-<span class="sourceLineNo">208</span>   * @param versionNumber the version number of the new regionserver<a name="line.208"></a>
-<span class="sourceLineNo">209</span>   * @param version the version of the new regionserver, could contain strings like "SNAPSHOT"<a name="line.209"></a>
-<span class="sourceLineNo">210</span>   * @param ia the InetAddress from which request is received<a name="line.210"></a>
-<span class="sourceLineNo">211</span>   * @return The ServerName we know this server as.<a name="line.211"></a>
-<span class="sourceLineNo">212</span>   * @throws IOException<a name="line.212"></a>
-<span class="sourceLineNo">213</span>   */<a name="line.213"></a>
-<span class="sourceLineNo">214</span>  ServerName regionServerStartup(RegionServerStartupRequest request, int versionNumber,<a name="line.214"></a>
-<span class="sourceLineNo">215</span>      String version, InetAddress ia) throws IOException {<a name="line.215"></a>
-<span class="sourceLineNo">216</span>    // Test for case where we get a region startup message from a regionserver<a name="line.216"></a>
-<span class="sourceLineNo">217</span>    // that has been quickly restarted but whose znode expiration handler has<a name="line.217"></a>
-<span class="sourceLineNo">218</span>    // not yet run, or from a server whose fail we are currently processing.<a name="line.218"></a>
-<span class="sourceLineNo">219</span>    // Test its host+port combo is present in serverAddressToServerInfo. If it<a name="line.219"></a>
-<span class="sourceLineNo">220</span>    // is, reject the server and trigger its expiration. The next time it comes<a name="line.220"></a>
-<span class="sourceLineNo">221</span>    // in, it should have been removed from serverAddressToServerInfo and queued<a name="line.221"></a>
-<span class="sourceLineNo">222</span>    // for processing by ProcessServerShutdown.<a name="line.222"></a>
-<span class="sourceLineNo">223</span><a name="line.223"></a>
-<span class="sourceLineNo">224</span>    final String hostname =<a name="line.224"></a>
-<span class="sourceLineNo">225</span>      request.hasUseThisHostnameInstead() ? request.getUseThisHostnameInstead() : ia.getHostName();<a name="line.225"></a>
-<span class="sourceLineNo">226</span>    ServerName sn = ServerName.valueOf(hostname, request.getPort(), request.getServerStartCode());<a name="line.226"></a>
-<span class="sourceLineNo">227</span>    checkClockSkew(sn, request.getServerCurrentTime());<a name="line.227"></a>
-<span class="sourceLineNo">228</span>    checkIsDead(sn, "STARTUP");<a name="line.228"></a>
-<span class="sourceLineNo">229</span>    if (!checkAndRecordNewServer(sn, ServerMetricsBuilder.of(sn, versionNumber, version))) {<a name="line.229"></a>
-<span class="sourceLineNo">230</span>      LOG.warn(<a name="line.230"></a>
-<span class="sourceLineNo">231</span>        "THIS SHOULD NOT HAPPEN, RegionServerStartup" + " could not record the server: " + sn);<a name="line.231"></a>
-<span class="sourceLineNo">232</span>    }<a name="line.232"></a>
-<span class="sourceLineNo">233</span>    return sn;<a name="line.233"></a>
-<span class="sourceLineNo">234</span>  }<a name="line.234"></a>
-<span class="sourceLineNo">235</span><a name="line.235"></a>
-<span class="sourceLineNo">236</span>  /**<a name="line.236"></a>
-<span class="sourceLineNo">237</span>   * Updates last flushed sequence Ids for the regions on server sn<a name="line.237"></a>
-<span class="sourceLineNo">238</span>   * @param sn<a name="line.238"></a>
-<span class="sourceLineNo">239</span>   * @param hsl<a name="line.239"></a>
-<span class="sourceLineNo">240</span>   */<a name="line.240"></a>
-<span class="sourceLineNo">241</span>  private void updateLastFlushedSequenceIds(ServerName sn, ServerMetrics hsl) {<a name="line.241"></a>
-<span class="sourceLineNo">242</span>    for (Entry&lt;byte[], RegionMetrics&gt; entry : hsl.getRegionMetrics().entrySet()) {<a name="line.242"></a>
-<span class="sourceLineNo">243</span>      byte[] encodedRegionName = Bytes.toBytes(RegionInfo.encodeRegionName(entry.getKey()));<a name="line.243"></a>
-<span class="sourceLineNo">244</span>      Long existingValue = flushedSequenceIdByRegion.get(encodedRegionName);<a name="line.244"></a>
-<span class="sourceLineNo">245</span>      long l = entry.getValue().getCompletedSequenceId();<a name="line.245"></a>
-<span class="sourceLineNo">246</span>      // Don't let smaller sequence ids override greater sequence ids.<a name="line.246"></a>
-<span class="sourceLineNo">247</span>      if (LOG.isTraceEnabled()) {<a name="line.247"></a>
-<span class="sourceLineNo">248</span>        LOG.trace(Bytes.toString(encodedRegionName) + ", existingValue=" + existingValue +<a name="line.248"></a>
-<span class="sourceLineNo">249</span>          ", completeSequenceId=" + l);<a name="line.249"></a>
-<span class="sourceLineNo">250</span>      }<a name="line.250"></a>
-<span class="sourceLineNo">251</span>      if (existingValue == null || (l != HConstants.NO_SEQNUM &amp;&amp; l &gt; existingValue)) {<a name="line.251"></a>
-<span class="sourceLineNo">252</span>        flushedSequenceIdByRegion.put(encodedRegionName, l);<a name="line.252"></a>
-<span class="sourceLineNo">253</span>      } else if (l != HConstants.NO_SEQNUM &amp;&amp; l &lt; existingValue) {<a name="line.253"></a>
-<span class="sourceLineNo">254</span>        LOG.warn("RegionServer " + sn + " indicates a last flushed sequence id ("<a name="line.254"></a>
-<span class="sourceLineNo">255</span>            + l + ") that is less than the previous last flushed sequence id ("<a name="line.255"></a>
-<span class="sourceLineNo">256</span>            + existingValue + ") for region " + Bytes.toString(entry.getKey()) + " Ignoring.");<a name="line.256"></a>
-<span class="sourceLineNo">257</span>      }<a name="line.257"></a>
-<span class="sourceLineNo">258</span>      ConcurrentNavigableMap&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.258"></a>
-<span class="sourceLineNo">259</span>          computeIfAbsent(storeFlushedSequenceIdsByRegion, encodedRegionName,<a name="line.259"></a>
-<span class="sourceLineNo">260</span>            () -&gt; new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR));<a name="line.260"></a>
-<span class="sourceLineNo">261</span>      for (Entry&lt;byte[], Long&gt; storeSeqId : entry.getValue().getStoreSequenceId().entrySet()) {<a name="line.261"></a>
-<span class="sourceLineNo">262</span>        byte[] family = storeSeqId.getKey();<a name="line.262"></a>
-<span class="sourceLineNo">263</span>        existingValue = storeFlushedSequenceId.get(family);<a name="line.263"></a>
-<span class="sourceLineNo">264</span>        l = storeSeqId.getValue();<a name="line.264"></a>
-<span class="sourceLineNo">265</span>        if (LOG.isTraceEnabled()) {<a name="line.265"></a>
-<span class="sourceLineNo">266</span>          LOG.trace(Bytes.toString(encodedRegionName) + ", family=" + Bytes.toString(family) +<a name="line.266"></a>
-<span class="sourceLineNo">267</span>            ", existingValue=" + existingValue + ", completeSequenceId=" + l);<a name="line.267"></a>
-<span class="sourceLineNo">268</span>        }<a name="line.268"></a>
-<span class="sourceLineNo">269</span>        // Don't let smaller sequence ids override greater sequence ids.<a name="line.269"></a>
-<span class="sourceLineNo">270</span>        if (existingValue == null || (l != HConstants.NO_SEQNUM &amp;&amp; l &gt; existingValue.longValue())) {<a name="line.270"></a>
-<span class="sourceLineNo">271</span>          storeFlushedSequenceId.put(family, l);<a name="line.271"></a>
-<span class="sourceLineNo">272</span>        }<a name="line.272"></a>
-<span class="sourceLineNo">273</span>      }<a name="line.273"></a>
-<span class="sourceLineNo">274</span>    }<a name="line.274"></a>
-<span class="sourceLineNo">275</span>  }<a name="line.275"></a>
-<span class="sourceLineNo">276</span><a name="line.276"></a>
-<span class="sourceLineNo">277</span>  @VisibleForTesting<a name="line.277"></a>
-<span class="sourceLineNo">278</span>  public void regionServerReport(ServerName sn,<a name="line.278"></a>
-<span class="sourceLineNo">279</span>    ServerMetrics sl) throws YouAreDeadException {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>    checkIsDead(sn, "REPORT");<a name="line.280"></a>
-<span class="sourceLineNo">281</span>    if (null == this.onlineServers.replace(sn, sl)) {<a name="line.281"></a>
-<span class="sourceLineNo">282</span>      // Already have this host+port combo and its just different start code?<a name="line.282"></a>
-<span class="sourceLineNo">283</span>      // Just let the server in. Presume master joining a running cluster.<a name="line.283"></a>
-<span class="sourceLineNo">284</span>      // recordNewServer is what happens at the end of reportServerStartup.<a name="line.284"></a>
-<span class="sourceLineNo">285</span>      // The only thing we are skipping is passing back to the regionserver<a name="line.285"></a>
-<span class="sourceLineNo">286</span>      // the ServerName to use. Here we presume a master has already done<a name="line.286"></a>
-<span class="sourceLineNo">287</span>      // that so we'll press on with whatever it gave us for ServerName.<a name="line.287"></a>
-<span class="sourceLineNo">288</span>      if (!checkAndRecordNewServer(sn, sl)) {<a name="line.288"></a>
-<span class="sourceLineNo">289</span>        LOG.info("RegionServerReport ignored, could not record the server: " + sn);<a name="line.289"></a>
-<span class="sourceLineNo">290</span>        return; // Not recorded, so no need to move on<a name="line.290"></a>
-<span class="sourceLineNo">291</span>      }<a name="line.291"></a>
-<span class="sourceLineNo">292</span>    }<a name="line.292"></a>
-<span class="sourceLineNo">293</span>    updateLastFlushedSequenceIds(sn, sl);<a name="line.293"></a>
-<span class="sourceLineNo">294</span>  }<a name="line.294"></a>
-<span class="sourceLineNo">295</span><a name="line.295"></a>
-<span class="sourceLineNo">296</span>  /**<a name="line.296"></a>
-<span class="sourceLineNo">297</span>   * Check is a server of same host and port already exists,<a name="line.297"></a>
-<span class="sourceLineNo">298</span>   * if not, or the existed one got a smaller start code, record it.<a name="line.298"></a>
-<span class="sourceLineNo">299</span>   *<a name="line.299"></a>
-<span class="sourceLineNo">300</span>   * @param serverName the server to check and record<a name="line.300"></a>
-<span class="sourceLineNo">301</span>   * @param sl the server load on the server<a name="line.301"></a>
-<span class="sourceLineNo">302</span>   * @return true if the server is recorded, otherwise, false<a name="line.302"></a>
-<span class="sourceLineNo">303</span>   */<a name="line.303"></a>
-<span class="sourceLineNo">304</span>  boolean checkAndRecordNewServer(final ServerName serverName, final ServerMetrics sl) {<a name="line.304"></a>
-<span class="sourceLineNo">305</span>    ServerName existingServer = null;<a name="line.305"></a>
-<span class="sourceLineNo">306</span>    synchronized (this.onlineServers) {<a name="line.306"></a>
-<span class="sourceLineNo">307</span>      existingServer = findServerWithSameHostnamePortWithLock(serverName);<a name="line.307"></a>
-<span class="sourceLineNo">308</span>      if (existingServer != null &amp;&amp; (existingServer.getStartcode() &gt; serverName.getStartcode())) {<a name="line.308"></a>
-<span class="sourceLineNo">309</span>        LOG.info("Server serverName=" + serverName + " rejected; we already have "<a name="line.309"></a>
-<span class="sourceLineNo">310</span>            + existingServer.toString() + " registered with same hostname and port");<a name="line.310"></a>
-<span class="sourceLineNo">311</span>        return false;<a name="line.311"></a>
-<span class="sourceLineNo">312</span>      }<a name="line.312"></a>
-<span class="sourceLineNo">313</span>      recordNewServerWithLock(serverName, sl);<a name="line.313"></a>
-<span class="sourceLineNo">314</span>    }<a name="line.314"></a>
-<span class="sourceLineNo">315</span><a name="line.315"></a>
-<span class="sourceLineNo">316</span>    // Tell our listeners that a server was added<a name="line.316"></a>
-<span class="sourceLineNo">317</span>    if (!this.listeners.isEmpty()) {<a name="line.317"></a>
-<span class="sourceLineNo">318</span>      for (ServerListener listener : this.listeners) {<a name="line.318"></a>
-<span class="sourceLineNo">319</span>        listener.serverAdded(serverName);<a name="line.319"></a>
-<span class="sourceLineNo">320</span>      }<a name="line.320"></a>
-<span class="sourceLineNo">321</span>    }<a name="line.321"></a>
-<span class="sourceLineNo">322</span><a name="line.322"></a>
-<span class="sourceLineNo">323</span>    // Note that we assume that same ts means same server, and don't expire in that case.<a name="line.323"></a>
-<span class="sourceLineNo">324</span>    //  TODO: ts can theoretically collide due to clock shifts, so this is a bit hacky.<a name="line.324"></a>
-<span class="sourceLineNo">325</span>    if (existingServer != null &amp;&amp;<a name="line.325"></a>
-<span class="sourceLineNo">326</span>        (existingServer.getStartcode() &lt; serverName.getStartcode())) {<a name="line.326"></a>
-<span class="sourceLineNo">327</span>      LOG.info("Triggering server recovery; existingServer " +<a name="line.327"></a>
-<span class="sourceLineNo">328</span>          existingServer + " looks stale, new server:" + serverName);<a name="line.328"></a>
-<span class="sourceLineNo">329</span>      expireServer(existingServer);<a name="line.329"></a>
-<span class="sourceLineNo">330</span>    }<a name="line.330"></a>
-<span class="sourceLineNo">331</span>    return true;<a name="line.331"></a>
-<span class="sourceLineNo">332</span>  }<a name="line.332"></a>
-<span class="sourceLineNo">333</span><a name="line.333"></a>
-<span class="sourceLineNo">334</span>  /**<a name="line.334"></a>
-<span class="sourceLineNo">335</span>   * Find out the region servers crashed between the crash of the previous master instance and the<a name="line.335"></a>
-<span class="sourceLineNo">336</span>   * current master instance and schedule SCP for them.<a name="line.336"></a>
-<span class="sourceLineNo">337</span>   * &lt;p/&gt;<a name="line.337"></a>
-<span class="sourceLineNo">338</span>   * Since the {@code RegionServerTracker} has already helped us to construct the online servers set<a name="line.338"></a>
-<span class="sourceLineNo">339</span>   * by scanning zookeeper, now we can compare the online servers with {@code liveServersFromWALDir}<a name="line.339"></a>
-<span class="sourceLineNo">340</span>   * to find out whether there are servers which are already dead.<a name="line.340"></a>
-<span class="sourceLineNo">341</span>   * &lt;p/&gt;<a name="line.341"></a>
-<span class="sourceLineNo">342</span>   * Must be called inside the initialization method of {@code RegionServerTracker} to avoid<a name="line.342"></a>
-<span class="sourceLineNo">343</span>   * concurrency issue.<a name="line.343"></a>
-<span class="sourceLineNo">344</span>   * @param deadServersFromPE the region servers which already have a SCP associated.<a name="line.344"></a>
-<span class="sourceLineNo">345</span>   * @param liveServersFromWALDir the live region servers from wal directory.<a name="line.345"></a>
-<span class="sourceLineNo">346</span>   */<a name="line.346"></a>
-<span class="sourceLineNo">347</span>  void findDeadServersAndProcess(Set&lt;ServerName&gt; deadServersFromPE,<a name="line.347"></a>
-<span class="sourceLineNo">348</span>      Set&lt;ServerName&gt; liveServersFromWALDir) {<a name="line.348"></a>
-<span class="sourceLineNo">349</span>    deadServersFromPE.forEach(deadservers::putIfAbsent);<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    liveServersFromWALDir.stream().filter(sn -&gt; !onlineServers.containsKey(sn))<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      .forEach(this::expireServer);<a name="line.351"></a>
-<span class="sourceLineNo">352</span>  }<a name="line.352"></a>
-<span class="sourceLineNo">353</span><a name="line.353"></a>
-<span class="sourceLineNo">354</span>  /**<a name="line.354"></a>
-<span class="sourceLineNo">355</span>   * Checks if the clock skew between the server and the master. If the clock skew exceeds the<a name="line.355"></a>
-<span class="sourceLineNo">356</span>   * configured max, it will throw an exception; if it exceeds the configured warning threshold,<a name="line.356"></a>
-<span class="sourceLineNo">357</span>   * it will log a warning but start normally.<a name="line.357"></a>
-<span class="sourceLineNo">358</span>   * @param serverName Incoming servers's name<a name="line.358"></a>
-<span class="sourceLineNo">359</span>   * @param serverCurrentTime<a name="line.359"></a>
-<span class="sourceLineNo">360</span>   * @throws ClockOutOfSyncException if the skew exceeds the configured max value<a name="line.360"></a>
-<span class="sourceLineNo">361</span>   */<a name="line.361"></a>
-<span class="sourceLineNo">362</span>  private void checkClockSkew(final ServerName serverName, final long serverCurrentTime)<a name="line.362"></a>
-<span class="sourceLineNo">363</span>      throws ClockOutOfSyncException {<a name="line.363"></a>
-<span class="sourceLineNo">364</span>    long skew = Math.abs(EnvironmentEdgeManager.currentTime() - serverCurrentTime);<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    if (skew &gt; maxSkew) {<a name="line.365"></a>
-<span class="sourceLineNo">366</span>      String message = "Server " + serverName + " has been " +<a name="line.366"></a>
-<span class="sourceLineNo">367</span>        "rejected; Reported time is too far out of sync with master.  " +<a name="line.367"></a>
-<span class="sourceLineNo">368</span>        "Time difference of " + skew + "ms &gt; max allowed of " + maxSkew + "ms";<a name="line.368"></a>
-<span class="sourceLineNo">369</span>      LOG.warn(message);<a name="line.369"></a>
-<span class="sourceLineNo">370</span>      throw new ClockOutOfSyncException(message);<a name="line.370"></a>
-<span class="sourceLineNo">371</span>    } else if (skew &gt; warningSkew){<a name="line.371"></a>
-<span class="sourceLineNo">372</span>      String message = "Reported time for server " + serverName + " is out of sync with master " +<a name="line.372"></a>
-<span class="sourceLineNo">373</span>        "by " + skew + "ms. (Warning threshold is " + warningSkew + "ms; " +<a name="line.373"></a>
-<span class="sourceLineNo">374</span>        "error threshold is " + maxSkew + "ms)";<a name="line.374"></a>
-<span class="sourceLineNo">375</span>      LOG.warn(message);<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    }<a name="line.376"></a>
-<span class="sourceLineNo">377</span>  }<a name="line.377"></a>
-<span class="sourceLineNo">378</span><a name="line.378"></a>
-<span class="sourceLineNo">379</span>  /**<a name="line.379"></a>
-<span class="sourceLineNo">380</span>   * Called when RegionServer first reports in for duty and thereafter each<a name="line.380"></a>
-<span class="sourceLineNo">381</span>   * time it heartbeats to make sure it is has not been figured for dead.<a name="line.381"></a>
-<span class="sourceLineNo">382</span>   * If this server is on the dead list, reject it with a YouAreDeadException.<a name="line.382"></a>
-<span class="sourceLineNo">383</span>   * If it was dead but came back with a new start code, remove the old entry<a name="line.383"></a>
-<span class="sourceLineNo">384</span>   * from the dead list.<a name="line.384"></a>
-<span class="sourceLineNo">385</span>   * @param what START or REPORT<a name="line.385"></a>
-<span class="sourceLineNo">386</span>   */<a name="line.386"></a>
-<span class="sourceLineNo">387</span>  private void checkIsDead(final ServerName serverName, final String what)<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      throws YouAreDeadException {<a name="line.388"></a>
-<span class="sourceLineNo">389</span>    if (this.deadservers.isDeadServer(serverName)) {<a name="line.389"></a>
-<span class="sourceLineNo">390</span>      // Exact match: host name, port and start code all match with existing one of the<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      // dead servers. So, this server must be dead. Tell it to kill itself.<a name="line.391"></a>
-<span class="sourceLineNo">392</span>      String message = "Server " + what + " rejected; currently processing " +<a name="line.392"></a>
-<span class="sourceLineNo">393</span>          serverName + " as dead server";<a name="line.393"></a>
-<span class="sourceLineNo">394</span>      LOG.debug(message);<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      throw new YouAreDeadException(message);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    }<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    // Remove dead server with same hostname and port of newly checking in rs after master<a name="line.397"></a>
-<span class="sourceLineNo">398</span>    // initialization. See HBASE-5916 for more information.<a name="line.398"></a>
-<span class="sourceLineNo">399</span>    if ((this.master == null || this.master.isInitialized()) &amp;&amp;<a name="line.399"></a>
-<span class="sourceLineNo">400</span>        this.deadservers.cleanPreviousInstance(serverName)) {<a name="line.400"></a>
-<span class="sourceLineNo">401</span>      // This server has now become alive after we marked it as dead.<a name="line.401"></a>
-<span class="sourceLineNo">402</span>      // We removed it's previous entry from the dead list to reflect it.<a name="line.402"></a>
-<span class="sourceLineNo">403</span>      LOG.debug("{} {} came back up, removed it from the dead servers list", what, serverName);<a name="line.403"></a>
-<span class="sourceLineNo">404</span>    }<a name="line.404"></a>
-<span class="sourceLineNo">405</span>  }<a name="line.405"></a>
-<span class="sourceLineNo">406</span><a name="line.406"></a>
-<span class="sourceLineNo">407</span>  /**<a name="line.407"></a>
-<span class="sourceLineNo">408</span>   * Assumes onlineServers is locked.<a name="line.408"></a>
-<span class="sourceLineNo">409</span>   * @return ServerName with matching hostname and port.<a name="line.409"></a>
-<span class="sourceLineNo">410</span>   */<a name="line.410"></a>
-<span class="sourceLineNo">411</span>  private ServerName findServerWithSameHostnamePortWithLock(<a name="line.411"></a>
-<span class="sourceLineNo">412</span>      final ServerName serverName) {<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    ServerName end = ServerName.valueOf(serverName.getHostname(), serverName.getPort(),<a name="line.413"></a>
-<span class="sourceLineNo">414</span>        Long.MAX_VALUE);<a name="line.414"></a>
-<span class="sourceLineNo">415</span><a name="line.415"></a>
-<span class="sourceLineNo">416</span>    ServerName r = onlineServers.lowerKey(end);<a name="line.416"></a>
-<span class="sourceLineNo">417</span>    if (r != null) {<a name="line.417"></a>
-<span class="sourceLineNo">418</span>      if (ServerName.isSameAddress(r, serverName)) {<a name="line.418"></a>
-<span class="sourceLineNo">419</span>        return r;<a name="line.419"></a>
-<span class="sourceLineNo">420</span>      }<a name="line.420"></a>
-<span class="sourceLineNo">421</span>    }<a name="line.421"></a>
-<span class="sourceLineNo">422</span>    return null;<a name="line.422"></a>
-<span class="sourceLineNo">423</span>  }<a name="line.423"></a>
-<span class="sourceLineNo">424</span><a name="line.424"></a>
-<span class="sourceLineNo">425</span>  /**<a name="line.425"></a>
-<span class="sourceLineNo">426</span>   * Adds the onlineServers list. onlineServers should be locked.<a name="line.426"></a>
-<span class="sourceLineNo">427</span>   * @param serverName The remote servers name.<a name="line.427"></a>
-<span class="sourceLineNo">428</span>   */<a name="line.428"></a>
-<span class="sourceLineNo">429</span>  @VisibleForTesting<a name="line.429"></a>
-<span class="sourceLineNo">430</span>  void recordNewServerWithLock(final ServerName serverName, final ServerMetrics sl) {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>    LOG.info("Registering regionserver=" + serverName);<a name="line.431"></a>
-<span class="sourceLineNo">432</span>    this.onlineServers.put(serverName, sl);<a name="line.432"></a>
-<span class="sourceLineNo">433</span>  }<a name="line.433"></a>
-<span class="sourceLineNo">434</span><a name="line.434"></a>
-<span class="sourceLineNo">435</span>  @VisibleForTesting<a name="line.435"></a>
-<span class="sourceLineNo">436</span>  public ConcurrentNavigableMap&lt;byte[], Long&gt; getFlushedSequenceIdByRegion() {<a name="line.436"></a>
-<span class="sourceLineNo">437</span>    return flushedSequenceIdByRegion;<a name="line.437"></a>
-<span class="sourceLineNo">438</span>  }<a name="line.438"></a>
-<span class="sourceLineNo">439</span><a name="line.439"></a>
-<span class="sourceLineNo">440</span>  public RegionStoreSequenceIds getLastFlushedSequenceId(byte[] encodedRegionName) {<a name="line.440"></a>
-<span class="sourceLineNo">441</span>    RegionStoreSequenceIds.Builder builder = RegionStoreSequenceIds.newBuilder();<a name="line.441"></a>
-<span class="sourceLineNo">442</span>    Long seqId = flushedSequenceIdByRegion.get(encodedRegionName);<a name="line.442"></a>
-<span class="sourceLineNo">443</span>    builder.setLastFlushedSequenceId(seqId != null ? seqId.longValue() : HConstants.NO_SEQNUM);<a name="line.443"></a>
-<span class="sourceLineNo">444</span>    Map&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.444"></a>
-<span class="sourceLineNo">445</span>        storeFlushedSequenceIdsByRegion.get(encodedRegionName);<a name="line.445"></a>
-<span class="sourceLineNo">446</span>    if (storeFlushedSequenceId != null) {<a name="line.446"></a>
-<span class="sourceLineNo">447</span>      for (Map.Entry&lt;byte[], Long&gt; entry : storeFlushedSequenceId.entrySet()) {<a name="line.447"></a>
-<span class="sourceLineNo">448</span>        builder.addStoreSequenceId(StoreSequenceId.newBuilder()<a name="line.448"></a>
-<span class="sourceLineNo">449</span>            .setFamilyName(UnsafeByteOperations.unsafeWrap(entry.getKey()))<a name="line.449"></a>
-<span class="sourceLineNo">450</span>            .setSequenceId(entry.getValue().longValue()).build());<a name="line.450"></a>
-<span class="sourceLineNo">451</span>      }<a name="line.451"></a>
-<span class="sourceLineNo">452</span>    }<a name="line.452"></a>
-<span class="sourceLineNo">453</span>    return builder.build();<a name="line.453"></a>
-<span class="sourceLineNo">454</span>  }<a name="line.454"></a>
-<span class="sourceLineNo">455</span><a name="line.455"></a>
-<span class="sourceLineNo">456</span>  /**<a name="line.456"></a>
-<span class="sourceLineNo">457</span>   * @param serverName<a name="line.457"></a>
-<span class="sourceLineNo">458</span>   * @return ServerMetrics if serverName is known else null<a name="line.458"></a>
-<span class="sourceLineNo">459</span>   */<a name="line.459"></a>
-<span class="sourceLineNo">460</span>  public ServerMetrics getLoad(final ServerName serverName) {<a name="line.460"></a>
-<span class="sourceLineNo">461</span>    return this.onlineServers.get(serverName);<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  }<a name="line.462"></a>
-<span class="sourceLineNo">463</span><a name="line.463"></a>
-<span class="sourceLineNo">464</span>  /**<a name="line.464"></a>
-<span class="sourceLineNo">465</span>   * Compute the average load across all region servers.<a name="line.465"></a>
-<span class="sourceLineNo">466</span>   * Currently, this uses a very naive computation - just uses the number of<a name="line.466"></a>
-<span class="sourceLineNo">467</span>   * regions being served, ignoring stats about number of requests.<a name="line.467"></a>
-<span class="sourceLineNo">468</span>   * @return the average load<a name="line.468"></a>
-<span class="sourceLineNo">469</span>   */<a name="line.469"></a>
-<span class="sourceLineNo">470</span>  public double getAverageLoad() {<a name="line.470"></a>
-<span class="sourceLineNo">471</span>    int totalLoad = 0;<a name="line.471"></a>
-<span class="sourceLineNo">472</span>    int numServers = 0;<a name="line.472"></a>
-<span class="sourceLineNo">473</span>    for (ServerMetrics sl : this.onlineServers.values()) {<a name="line.473"></a>
-<span class="sourceLineNo">474</span>      numServers++;<a name="line.474"></a>
-<span class="sourceLineNo">475</span>      totalLoad += sl.getRegionMetrics().size();<a name="line.475"></a>
-<span class="sourceLineNo">476</span>    }<a name="line.476"></a>
-<span class="sourceLineNo">477</span>    return numServers == 0 ? 0 :<a name="line.477"></a>
-<span class="sourceLineNo">478</span>      (double)totalLoad / (double)numServers;<a name="line.478"></a>
-<span class="sourceLineNo">479</span>  }<a name="line.479"></a>
-<span class="sourceLineNo">480</span><a name="line.480"></a>
-<span class="sourceLineNo">481</span>  /** @return the count of active regionservers */<a name="line.481"></a>
-<span class="sourceLineNo">482</span>  public int countOfRegionServers() {<a name="line.482"></a>
-<span class="sourceLineNo">483</span>    // Presumes onlineServers is a concurrent map<a name="line.483"></a>
-<span class="sourceLineNo">484</span>    return this.onlineServers.size();<a name="line.484"></a>
-<span class="sourceLineNo">485</span>  }<a name="line.485"></a>
-<span class="sourceLineNo">486</span><a name="line.486"></a>
-<span class="sourceLineNo">487</span>  /**<a name="line.487"></a>
-<span class="sourceLineNo">488</span>   * @return Read-only map of servers to serverinfo<a name="line.488"></a>
-<span class="sourceLineNo">489</span>   */<a name="line.489"></a>
-<span class="sourceLineNo">490</span>  public Map&lt;ServerName, ServerMetrics&gt; getOnlineServers() {<a name="line.490"></a>
-<span class="sourceLineNo">491</span>    // Presumption is that iterating the returned Map is OK.<a name="line.491"></a>
-<span class="sourceLineNo">492</span>    synchronized (this.onlineServers) {<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      return Collections.unmodifiableMap(this.onlineServers);<a name="line.493"></a>
-<span class="sourceLineNo">494</span>    }<a name="line.494"></a>
-<span class="sourceLineNo">495</span>  }<a name="line.495"></a>
-<span class="sourceLineNo">496</span><a name="line.496"></a>
-<span class="sourceLineNo">497</span>  public DeadServer getDeadServers() {<a name="line.497"></a>
-<span class="sourceLineNo">498</span>    return this.deadservers;<a name="line.498"></a>
-<span class="sourceLineNo">499</span>  }<a name="line.499"></a>
-<span class="sourceLineNo">500</span><a name="line.500"></a>
-<span class="sourceLineNo">501</span>  /**<a name="line.501"></a>
-<span class="sourceLineNo">502</span>   * Checks if any dead servers are currently in progress.<a name="line.502"></a>
-<span class="sourceLineNo">503</span>   * @return true if any RS are being processed as dead, false if not<a name="line.503"></a>
-<span class="sourceLineNo">504</span>   */<a name="line.504"></a>
-<span class="sourceLineNo">505</span>  public boolean areDeadServersInProgress() {<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    return this.deadservers.areDeadServersInProgress();<a name="line.506"></a>
-<span class="sourceLineNo">507</span>  }<a name="line.507"></a>
-<span class="sourceLineNo">508</span><a name="line.508"></a>
-<span class="sourceLineNo">509</span>  void letRegionServersShutdown() {<a name="line.509"></a>
-<span class="sourceLineNo">510</span>    long previousLogTime = 0;<a name="line.510"></a>
-<span class="sourceLineNo">511</span>    ServerName sn = master.getServerName();<a name="line.511"></a>
-<span class="sourceLineNo">512</span>    ZKWatcher zkw = master.getZooKeeper();<a name="line.512"></a>
-<span class="sourceLineNo">513</span>    int onlineServersCt;<a name="line.513"></a>
-<span class="sourceLineNo">514</span>    while ((onlineServersCt = onlineServers.size()) &gt; 0){<a name="line.514"></a>
-<span class="sourceLineNo">515</span><a name="line.515"></a>
-<span class="sourceLineNo">516</span>      if (System.currentTimeMillis() &gt; (previousLogTime + 1000)) {<a name="line.516"></a>
-<span class="sourceLineNo">517</span>        Set&lt;ServerName&gt; remainingServers = onlineServers.keySet();<a name="line.517"></a>
-<span class="sourceLineNo">518</span>        synchronized (onlineServers) {<a name="line.518"></a>
-<span class="sourceLineNo">519</span>          if (remainingServers.size() == 1 &amp;&amp; remainingServers.contains(sn)) {<a name="line.519"></a>
-<span class="sourceLineNo">520</span>            // Master will delete itself later.<a name="line.520"></a>
-<span class="sourceLineNo">521</span>            return;<a name="line.521"></a>
-<span class="sourceLineNo">522</span>          }<a name="line.522"></a>
-<span class="sourceLineNo">523</span>        }<a name="line.523"></a>
-<span class="sourceLineNo">524</span>        StringBuilder sb = new StringBuilder();<a name="line.524"></a>
-<span class="sourceLineNo">525</span>        // It's ok here to not sync on onlineServers - merely logging<a name="line.525"></a>
-<span class="sourceLineNo">526</span>        for (ServerName key : remainingServers) {<a name="line.526"></a>
-<span class="sourceLineNo">527</span>          if (sb.length() &gt; 0) {<a name="line.527"></a>
-<span class="sourceLineNo">528</span>            sb.append(", ");<a name="line.528"></a>
-<span class="sourceLineNo">529</span>          }<a name="line.529"></a>
-<span class="sourceLineNo">530</span>          sb.append(key);<a name="line.530"></a>
-<span class="sourceLineNo">531</span>        }<a name="line.531"></a>
-<span class="sourceLineNo">532</span>        LOG.info("Waiting on regionserver(s) " + sb.toString());<a name="line.532"></a>
-<span class="sourceLineNo">533</span>        previousLogTime = System.currentTimeMillis();<a name="line.533"></a>
-<span class="sourceLineNo">534</span>      }<a name="line.534"></a>
-<span class="sourceLineNo">535</span><a name="line.535"></a>
-<span class="sourceLineNo">536</span>      try {<a name="line.536"></a>
-<span class="sourceLineNo">537</span>        List&lt;String&gt; servers = getRegionServersInZK(zkw);<a name="line.537"></a>
-<span class="sourceLineNo">538</span>        if (servers == null || servers.isEmpty() || (servers.size() == 1<a name="line.538"></a>
-<span class="sourceLineNo">539</span>            &amp;&amp; servers.contains(sn.toString()))) {<a name="line.539"></a>
-<span class="sourceLineNo">540</span>          LOG.info("ZK shows there is only the master self online, exiting now");<a name="line.540"></a>
-<span class="sourceLineNo">541</span>          // Master could have lost some ZK events, no need to wait more.<a name="line.541"></a>
-<span class="sourceLineNo">542</span>          break;<a name="line.542"></a>
-<span class="sourceLineNo">543</span>        }<a name="line.543"></a>
-<span class="sourceLineNo">544</span>      } catch (KeeperException ke) {<a name="line.544"></a>
-<span class="sourceLineNo">545</span>        LOG.warn("Failed to list regionservers", ke);<a name="line.545"></a>
-<span class="sourceLineNo">546</span>        // ZK is malfunctioning, don't hang here<a name="line.546"></a>
-<span class="sourceLineNo">547</span>        break;<a name="line.547"></a>
-<span class="sourceLineNo">548</span>      }<a name="line.548"></a>
-<span class="sourceLineNo">549</span>      synchronized (onlineServers) {<a name="line.549"></a>
-<span class="sourceLineNo">550</span>        try {<a name="line.550"></a>
-<span class="sourceLineNo">551</span>          if (onlineServersCt == onlineServers.size()) onlineServers.wait(100);<a name="line.551"></a>
-<span class="sourceLineNo">552</span>        } catch (InterruptedException ignored) {<a name="line.552"></a>
-<span class="sourceLineNo">553</span>          // continue<a name="line.553"></a>
-<span class="sourceLineNo">554</span>        }<a name="line.554"></a>
-<span class="sourceLineNo">555</span>      }<a name="line.555"></a>
-<span class="sourceLineNo">556</span>    }<a name="line.556"></a>
-<span class="sourceLineNo">557</span>  }<a name="line.557"></a>
-<span class="sourceLineNo">558</span><a name="line.558"></a>
-<span class="sourceLineNo">559</span>  private List&lt;String&gt; getRegionServersInZK(final ZKWatcher zkw)<a name="line.559"></a>
-<span class="sourceLineNo">560</span>  throws KeeperException {<a name="line.560"></a>
-<span class="sourceLineNo">561</span>    return ZKUtil.listChildrenNoWatch(zkw, zkw.getZNodePaths().rsZNode);<a name="line.561"></a>
-<span class="sourceLineNo">562</span>  }<a name="line.562"></a>
-<span class="sourceLineNo">563</span><a name="line.563"></a>
-<span class="sourceLineNo">564</span>  /**<a name="line.564"></a>
-<span class="sourceLineNo">565</span>   * Expire the passed server. Add it to list of dead servers and queue a shutdown processing.<a name="line.565"></a>
-<span class="sourceLineNo">566</span>   * @return pid if we queued a ServerCrashProcedure else {@link Procedure#NO_PROC_ID} if we did<a name="line.566"></a>
-<span class="sourceLineNo">567</span>   *         not (could happen for many reasons including the fact that its this server that is<a name="line.567"></a>
-<span class="sourceLineNo">568</span>   *         going down or we already have queued an SCP for this server or SCP processing is<a name="line.568"></a>
-<span class="sourceLineNo">569</span>   *         currently disabled because we are in startup phase).<a name="line.569"></a>
-<span class="sourceLineNo">570</span>   */<a name="line.570"></a>
-<span class="sourceLineNo">571</span>  @VisibleForTesting // Redo test so we can make this protected.<a name="line.571"></a>
-<span class="sourceLineNo">572</span>  public synchronized long expireServer(final ServerName serverName) {<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    return expireServer(serverName, false);<a name="line.573"></a>
-<span class="sourceLineNo">574</span><a name="line.574"></a>
-<span class="sourceLineNo">575</span>  }<a name="line.575"></a>
-<span class="sourceLineNo">576</span><a name="line.576"></a>
-<span class="sourceLineNo">577</span>  synchronized long expireServer(final ServerName serverName, boolean force) {<a name="line.577"></a>
-<span class="sourceLineNo">578</span>    // THIS server is going down... can't handle our own expiration.<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    if (serverName.equals(master.getServerName())) {<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      if (!(master.isAborted() || master.isStopped())) {<a name="line.580"></a>
-<span class="sourceLineNo">581</span>        master.stop("We lost our znode?");<a name="line.581"></a>
-<span class="sourceLineNo">582</span>      }<a name="line.582"></a>
-<span class="sourceLineNo">583</span>      return Procedure.NO_PROC_ID;<a name="line.583"></a>
-<span class="sourceLineNo">584</span>    }<a name="line.584"></a>
-<span class="sourceLineNo">585</span>    if (this.deadservers.isDeadServer(serverName)) {<a name="line.585"></a>
-<span class="sourceLineNo">586</span>      LOG.warn("Expiration called on {} but already in DeadServer", serverName);<a name="line.586"></a>
-<span class="sourceLineNo">587</span>      return Procedure.NO_PROC_ID;<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    }<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    moveFromOnlineToDeadServers(serverName);<a name="line.589"></a>
-<span class="sourceLineNo">590</span><a name="line.590"></a>
-<span class="sourceLineNo">591</span>    // If server is in draining mode, remove corresponding znode<a name="line.591"></a>
-<span class="sourceLineNo">592</span>    // In some tests, the mocked HM may not have ZK Instance, hence null check<a name="line.592"></a>
-<span class="sourceLineNo">593</span>    if (master.getZooKeeper() != null) {<a name="line.593"></a>
-<span class="sourceLineNo">594</span>      String drainingZnode = ZNodePaths<a name="line.594"></a>
-<span class="sourceLineNo">595</span>        .joinZNode(master.getZooKeeper().getZNodePaths().drainingZNode, serverName.getServerName());<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      try {<a name="line.596"></a>
-<span class="sourceLineNo">597</span>        ZKUtil.deleteNodeFailSilent(master.getZooKeeper(), drainingZnode);<a name="line.597"></a>
-<span class="sourceLineNo">598</span>      } catch (KeeperException e) {<a name="line.598"></a>
-<span class="sourceLineNo">599</span>        LOG.warn("Error deleting the draining znode for stopping server " + serverName.getServerName(), e);<a name="line.599"></a>
-<span class="sourceLineNo">600</span>      }<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    }<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    <a name="line.602"></a>
-<span class="sourceLineNo">603</span>    // If cluster is going down, yes, servers are going to be expiring; don't<a name="line.603"></a>
-<span class="sourceLineNo">604</span>    // process as a dead server<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    if (isClusterShutdown()) {<a name="line.605"></a>
-<span class="sourceLineNo">606</span>      LOG.info("Cluster shutdown set; " + serverName +<a name="line.606"></a>
-<span class="sourceLineNo">607</span>        " expired; onlineServers=" + this.onlineServers.size());<a name="line.607"></a>
-<span class="sourceLineNo">608</span>      if (this.onlineServers.isEmpty()) {<a name="line.608"></a>
-<span class="sourceLineNo">609</span>        master.stop("Cluster shutdown set; onlineServer=0");<a name="line.609"></a>
-<span class="sourceLineNo">610</span>      }<a name="line.610"></a>
-<span class="sourceLineNo">611</span>      return Procedure.NO_PROC_ID;<a name="line.611"></a>
-<span class="sourceLineNo">612</span>    }<a name="line.612"></a>
-<span class="sourceLineNo">613</span>    LOG.info("Processing expiration of " + serverName + " on " + this.master.getServerName());<a name="line.613"></a>
-<span class="sourceLineNo">614</span>    long pid = master.getAssignmentManager().submitServerCrash(serverName, true, force);<a name="line.614"></a>
-<span class="sourceLineNo">615</span>    // Tell our listeners that a server was removed<a name="line.615"></a>
-<span class="sourceLineNo">616</span>    if (!this.listeners.isEmpty()) {<a name="line.616"></a>
-<span class="sourceLineNo">617</span>      this.listeners.stream().forEach(l -&gt; l.serverRemoved(serverName));<a name="line.617"></a>
-<span class="sourceLineNo">618</span>    }<a name="line.618"></a>
-<span class="sourceLineNo">619</span>    // trigger a persist of flushedSeqId<a name="line.619"></a>
-<span class="sourceLineNo">620</span>    if (flushedSeqIdFlusher != null) {<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      flushedSeqIdFlusher.triggerNow();<a name="line.621"></a>
-<span class="sourceLineNo">622</span>    }<a name="line.622"></a>
-<span class="sourceLineNo">623</span>    return pid;<a name="line.623"></a>
-<span class="sourceLineNo">624</span>  }<a name="line.624"></a>
-<span class="sourceLineNo">625</span><a name="line.625"></a>
-<span class="sourceLineNo">626</span>  /**<a name="line.626"></a>
-<span class="sourceLineNo">627</span>   * Called when server has expired.<a name="line.627"></a>
-<span class="sourceLineNo">628</span>   */<a name="line.628"></a>
-<span class="sourceLineNo">629</span>  // Locking in this class needs cleanup.<a name="line.629"></a>
-<span class="sourceLineNo">630</span>  @VisibleForTesting<a name="line.630"></a>
-<span class="sourceLineNo">631</span>  public synchronized void moveFromOnlineToDeadServers(final ServerName sn) {<a name="line.631"></a>
-<span class="sourceLineNo">632</span>    synchronized (this.onlineServers) {<a name="line.632"></a>
-<span class="sourceLineNo">633</span>      boolean online = this.onlineServers.containsKey(sn);<a name="line.633"></a>
-<span class="sourceLineNo">634</span>      if (online) {<a name="line.634"></a>
-<span class="sourceLineNo">635</span>        // Remove the server from the known servers lists and update load info BUT<a name="line.635"></a>
-<span class="sourceLineNo">636</span>        // add to deadservers first; do this so it'll show in dead servers list if<a name="line.636"></a>
-<span class="sourceLineNo">637</span>        // not in online servers list.<a name="line.637"></a>
-<span class="sourceLineNo">638</span>        this.deadservers.putIfAbsent(sn);<a name="line.638"></a>
-<span class="sourceLineNo">639</span>        this.onlineServers.remove(sn);<a name="line.639"></a>
-<span class="sourceLineNo">640</span>        onlineServers.notifyAll();<a name="line.640"></a>
-<span class="sourceLineNo">641</span>      } else {<a name="line.641"></a>
-<span class="sourceLineNo">642</span>        // If not online, that is odd but may happen if 'Unknown Servers' -- where meta<a name="line.642"></a>
-<span class="sourceLineNo">643</span>        // has references to servers not online nor in dead servers list. If<a name="line.643"></a>
-<span class="sourceLineNo">644</span>        // 'Unknown Server', don't add to DeadServers else will be there for ever.<a name="line.644"></a>
-<span class="sourceLineNo">645</span>        LOG.trace("Expiration of {} but server not online", sn);<a name="line.645"></a>
-<span class="sourceLineNo">646</span>      }<a name="line.646"></a>
-<span class="sourceLineNo">647</span>    }<a name="line.647"></a>
-<span class="sourceLineNo">648</span>  }<a name="line.648"></a>
-<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span>  /*<a name="line.650"></a>
-<span class="sourceLineNo">651</span>   * Remove the server from the drain list.<a name="line.651"></a>
-<span class="sourceLineNo">652</span>   */<a name="line.652"></a>
-<span class="sourceLineNo">653</span>  public synchronized boolean removeServerFromDrainList(final ServerName sn) {<a name="line.653"></a>
-<span class="sourceLineNo">654</span>    // Warn if the server (sn) is not online.  ServerName is of the form:<a name="line.654"></a>
-<span class="sourceLineNo">655</span>    // &lt;hostname&gt; , &lt;port&gt; , &lt;startcode&gt;<a name="line.655"></a>
-<span class="sourceLineNo">656</span><a name="line.656"></a>
-<span class="sourceLineNo">657</span>    if (!this.isServerOnline(sn)) {<a name="line.657"></a>
-<span class="sourceLineNo">658</span>      LOG.warn("Server " + sn + " is not currently online. " +<a name="line.658"></a>
-<span class="sourceLineNo">659</span>               "Removing from draining list anyway, as requested.");<a name="line.659"></a>
-<span class="sourceLineNo">660</span>    }<a name="line.660"></a>
-<span class="sourceLineNo">661</span>    // Remove the server from the draining servers lists.<a name="line.661"></a>
-<span class="sourceLineNo">662</span>    return this.drainingServers.remove(sn);<a name="line.662"></a>
-<span class="sourceLineNo">663</span>  }<a name="line.663"></a>
-<span class="sourceLineNo">664</span><a name="line.664"></a>
-<span class="sourceLineNo">665</span>  /**<a name="line.665"></a>
-<span class="sourceLineNo">666</span>   * Add the server to the drain list.<a name="line.666"></a>
-<span class="sourceLineNo">667</span>   * @param sn<a name="line.667"></a>
-<span class="sourceLineNo">668</span>   * @return True if the server is added or the server is already on the drain list.<a name="line.668"></a>
-<span class="sourceLineNo">669</span>   */<a name="line.669"></a>
-<span class="sourceLineNo">670</span>  public synchronized boolean addServerToDrainList(final ServerName sn) {<a name="line.670"></a>
-<span class="sourceLineNo">671</span>    // Warn if the server (sn) is not online.  ServerName is of the form:<a name="line.671"></a>
-<span class="sourceLineNo">672</span>    // &lt;hostname&gt; , &lt;port&gt; , &lt;startcode&gt;<a name="line.672"></a>
-<span class="sourceLineNo">673</span><a name="line.673"></a>
-<span class="sourceLineNo">674</span>    if (!this.isServerOnline(sn)) {<a name="line.674"></a>
-<span class="sourceLineNo">675</span>      LOG.warn("Server " + sn + " is not currently online. " +<a name="line.675"></a>
-<span class="sourceLineNo">676</span>               "Ignoring request to add it to draining list.");<a name="line.676"></a>
-<span class="sourceLineNo">677</span>      return false;<a name="line.677"></a>
-<span class="sourceLineNo">678</span>    }<a name="line.678"></a>
-<span class="sourceLineNo">679</span>    // Add the server to the draining servers lists, if it's not already in<a name="line.679"></a>
-<span class="sourceLineNo">680</span>    // it.<a name="line.680"></a>
-<span class="sourceLineNo">681</span>    if (this.drainingServers.contains(sn)) {<a name="line.681"></a>
-<span class="sourceLineNo">682</span>      LOG.warn("Server " + sn + " is already in the draining server list." +<a name="line.682"></a>
-<span class="sourceLineNo">683</span>               "Ignoring request to add it again.");<a name="line.683"></a>
-<span class="sourceLineNo">684</span>      return true;<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    }<a name="line.685"></a>
-<span class="sourceLineNo">686</span>    LOG.info("Server " + sn + " added to draining server list.");<a name="line.686"></a>
-<span class="sourceLineNo">687</span>    return this.drainingServers.add(sn);<a name="line.687"></a>
-<span class="sourceLineNo">688</span>  }<a name="line.688"></a>
-<span class="sourceLineNo">689</span><a name="line.689"></a>
-<span class="sourceLineNo">690</span>  /**<a name="line.690"></a>
-<span class="sourceLineNo">691</span>   * Contacts a region server and waits up to timeout ms<a name="line.691"></a>
-<span class="sourceLineNo">692</span>   * to close the region.  This bypasses the active hmaster.<a name="line.692"></a>
-<span class="sourceLineNo">693</span>   * Pass -1 as timeout if you do not want to wait on result.<a name="line.693"></a>
-<span class="sourceLineNo">694</span>   */<a name="line.694"></a>
-<span class="sourceLineNo">695</span>  public static void closeRegionSilentlyAndWait(AsyncClusterConnection connection,<a name="line.695"></a>
-<span class="sourceLineNo">696</span>      ServerName server, RegionInfo region, long timeout) throws IOException, InterruptedException {<a name="line.696"></a>
-<span class="sourceLineNo">697</span>    AsyncRegionServerAdmin admin = connection.getRegionServerAdmin(server);<a name="line.697"></a>
-<span class="sourceLineNo">698</span>    try {<a name="line.698"></a>
-<span class="sourceLineNo">699</span>      FutureUtils.get(<a name="line.699"></a>
-<span class="sourceLineNo">700</span>        admin.closeRegion(ProtobufUtil.buildCloseRegionRequest(server, region.getRegionName())));<a name="line.700"></a>
-<span class="sourceLineNo">701</span>    } catch (IOException e) {<a name="line.701"></a>
-<span class="sourceLineNo">702</span>      LOG.warn("Exception when closing region: " + region.getRegionNameAsString(), e);<a name="line.702"></a>
-<span class="sourceLineNo">703</span>    }<a name="line.703"></a>
-<span class="sourceLineNo">704</span>    if (timeout &lt; 0) {<a name="line.704"></a>
-<span class="sourceLineNo">705</span>      return;<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    }<a name="line.706"></a>
-<span class="sourceLineNo">707</span>    long expiration = timeout + System.currentTimeMillis();<a name="line.707"></a>
-<span class="sourceLineNo">708</span>    while (System.currentTimeMillis() &lt; expiration) {<a name="line.708"></a>
-<span class="sourceLineNo">709</span>      try {<a name="line.709"></a>
-<span class="sourceLineNo">710</span>        RegionInfo rsRegion = ProtobufUtil.toRegionInfo(FutureUtils<a name="line.710"></a>
-<span class="sourceLineNo">711</span>          .get(<a name="line.711"></a>
-<span class="sourceLineNo">712</span>            admin.getRegionInfo(RequestConverter.buildGetRegionInfoRequest(region.getRegionName())))<a name="line.712"></a>
-<span class="sourceLineNo">713</span>          .getRegionInfo());<a name="line.713"></a>
-<span class="sourceLineNo">714</span>        if (rsRegion == null) {<a name="line.714"></a>
-<span class="sourceLineNo">715</span>          return;<a name="line.715"></a>
-<span class="sourceLineNo">716</span>        }<a name="line.716"></a>
-<span class="sourceLineNo">717</span>      } catch (IOException ioe) {<a name="line.717"></a>
-<span class="sourceLineNo">718</span>        if (ioe instanceof NotServingRegionException) {<a name="line.718"></a>
-<span class="sourceLineNo">719</span>          // no need to retry again<a name="line.719"></a>
-<span class="sourceLineNo">720</span>          return;<a name="line.720"></a>
-<span class="sourceLineNo">721</span>        }<a name="line.721"></a>
-<span class="sourceLineNo">722</span>        LOG.warn("Exception when retrieving regioninfo from: " + region.getRegionNameAsString(),<a name="line.722"></a>
-<span class="sourceLineNo">723</span>          ioe);<a name="line.723"></a>
-<span class="sourceLineNo">724</span>      }<a name="line.724"></a>
-<span class="sourceLineNo">725</span>      Thread.sleep(1000);<a name="line.725"></a>
-<span class="sourceLineNo">726</span>    }<a name="line.726"></a>
-<span class="sourceLineNo">727</span>    throw new IOException("Region " + region + " failed to close within" + " timeout " + timeout);<a name="line.727"></a>
-<span class="sourceLineNo">728</span>  }<a name="line.728"></a>
-<span class="sourceLineNo">729</span><a name="line.729"></a>
-<span class="sourceLineNo">730</span>  /**<a name="line.730"></a>
-<span class="sourceLineNo">731</span>   * Calculate min necessary to start. This is not an absolute. It is just<a name="line.731"></a>
-<span class="sourceLineNo">732</span>   * a friction that will cause us hang around a bit longer waiting on<a name="line.732"></a>
-<span class="sourceLineNo">733</span>   * RegionServers to check-in.<a name="line.733"></a>
-<span class="sourceLineNo">734</span>   */<a name="line.734"></a>
-<span class="sourceLineNo">735</span>  private int getMinToStart() {<a name="line.735"></a>
-<span class="sourceLineNo">736</span>    if (master.isInMaintenanceMode()) {<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      // If in maintenance mode, then master hosting meta will be the only server available<a name="line.737"></a>
-<span class="sourceLineNo">738</span>      return 1;<a name="line.738"></a>
-<span class="sourceLineNo">739</span>    }<a name="line.739"></a>
-<span class="sourceLineNo">740</span><a name="line.740"></a>
-<span class="sourceLineNo">741</span>    int minimumRequired = 1;<a name="line.741"></a>
-<span class="sourceLineNo">742</span>    if (LoadBalancer.isTablesOnMaster(master.getConfiguration()) &amp;&amp;<a name="line.742"></a>
-<span class="sourceLineNo">743</span>        LoadBalancer.isSystemTablesOnlyOnMaster(master.getConfiguration())) {<a name="line.743"></a>
-<span class="sourceLineNo">744</span>      // If Master is carrying regions it will show up as a 'server', but is not handling user-<a name="line.744"></a>
-<span class="sourceLineNo">745</span>      // space regions, so we need a second server.<a name="line.745"></a>
-<span class="sourceLineNo">746</span>      minimumRequired = 2;<a name="line.746"></a>
-<span class="sourceLineNo">747</span>    }<a name="line.747"></a>
-<span class="sourceLineNo">748</span><a name="line.748"></a>
-<span class="sourceLineNo">749</span>    int minToStart = this.master.getConfiguration().getInt(WAIT_ON_REGIONSERVERS_MINTOSTART, -1);<a name="line.749"></a>
-<span class="sourceLineNo">750</span>    // Ensure we are never less than minimumRequired else stuff won't work.<a name="line.750"></a>
-<span class="sourceLineNo">751</span>    return Math.max(minToStart, minimumRequired);<a name="line.751"></a>
-<span class="sourceLineNo">752</span>  }<a name="line.752"></a>
-<span class="sourceLineNo">753</span><a name="line.753"></a>
-<span class="sourceLineNo">754</span>  /**<a name="line.754"></a>
-<span class="sourceLineNo">755</span>   * Wait for the region servers to report in.<a name="line.755"></a>
-<span class="sourceLineNo">756</span>   * We will wait until one of this condition is met:<a name="line.756"></a>
-<span class="sourceLineNo">757</span>   *  - the master is stopped<a name="line.757"></a>
-<span class="sourceLineNo">758</span>   *  - the 'hbase.master.wait.on.regionservers.maxtostart' number of<a name="line.758"></a>
-<span class="sourceLineNo">759</span>   *    region servers is reached<a name="line.759"></a>
-<span class="sourceLineNo">760</span>   *  - the 'hbase.master.wait.on.regionservers.mintostart' is reached AND<a name="line.760"></a>
-<span class="sourceLineNo">761</span>   *   there have been no new region server in for<a name="line.761"></a>
-<span class="sourceLineNo">762</span>   *      'hbase.master.wait.on.regionservers.interval' time AND<a name="line.762"></a>
-<span class="sourceLineNo">763</span>   *   the 'hbase.master.wait.on.regionservers.timeout' is reached<a name="line.763"></a>
-<span class="sourceLineNo">764</span>   *<a name="line.764"></a>
-<span class="sourceLineNo">765</span>   * @throws InterruptedException<a name="line.765"></a>
-<span class="sourceLineNo">766</span>   */<a name="line.766"></a>
-<span class="sourceLineNo">767</span>  public void waitForRegionServers(MonitoredTask status) throws InterruptedException {<a name="line.767"></a>
-<span class="sourceLineNo">768</span>    final long interval = this.master.getConfiguration().<a name="line.768"></a>
-<span class="sourceLineNo">769</span>        getLong(WAIT_ON_REGIONSERVERS_INTERVAL, 1500);<a name="line.769"></a>
-<span class="sourceLineNo">770</span>    final long timeout = this.master.getConfiguration().<a name="line.770"></a>
-<span class="sourceLineNo">771</span>        getLong(WAIT_ON_REGIONSERVERS_TIMEOUT, 4500);<a name="line.771"></a>
-<span class="sourceLineNo">772</span>    // Min is not an absolute; just a friction making us wait longer on server checkin.<a name="line.772"></a>
-<span class="sourceLineNo">773</span>    int minToStart = getMinToStart();<a name="line.773"></a>
-<span class="sourceLineNo">774</span>    int maxToStart = this.master.getConfiguration().<a name="line.774"></a>
-<span class="sourceLineNo">775</span>        getInt(WAIT_ON_REGIONSERVERS_MAXTOSTART, Integer.MAX_VALUE);<a name="line.775"></a>
-<span class="sourceLineNo">776</span>    if (maxToStart &lt; minToStart) {<a name="line.776"></a>
-<span class="sourceLineNo">777</span>      LOG.warn(String.format("The value of '%s' (%d) is set less than '%s' (%d), ignoring.",<a name="line.777"></a>
-<span class="sourceLineNo">778</span>          WAIT_ON_REGIONSERVERS_MAXTOSTART, maxToStart,<a name="line.778"></a>
-<span class="sourceLineNo">779</span>          WAIT_ON_REGIONSERVERS_MINTOSTART, minToStart));<a name="line.779"></a>
-<span class="sourceLineNo">780</span>      maxToStart = Integer.MAX_VALUE;<a name="line.780"></a>
-<span class="sourceLineNo">781</span>    }<a name="line.781"></a>
-<span class="sourceLineNo">782</span><a name="line.782"></a>
-<span class="sourceLineNo">783</span>    long now =  System.currentTimeMillis();<a name="line.783"></a>
-<span class="sourceLineNo">784</span>    final long startTime = now;<a name="line.784"></a>
-<span class="sourceLineNo">785</span>    long slept = 0;<a name="line.785"></a>
-<span class="sourceLineNo">786</span>    long lastLogTime = 0;<a name="line.786"></a>
-<span class="sourceLineNo">787</span>    long lastCountChange = startTime;<a name="line.787"></a>
-<span class="sourceLineNo">788</span>    int count = countOfRegionServers();<a name="line.788"></a>
-<span class="sourceLineNo">789</span>    int oldCount = 0;<a name="line.789"></a>
-<span class="sourceLineNo">790</span>    // This while test is a little hard to read. We try to comment it in below but in essence:<a name="line.790"></a>
-<span class="sourceLineNo">791</span>    // Wait if Master is not stopped and the number of regionservers that have checked-in is<a name="line.791"></a>
-<span class="sourceLineNo">792</span>    // less than the maxToStart. Both of these conditions will be true near universally.<a name="line.792"></a>
-<span class="sourceLineNo">793</span>    // Next, we will keep cycling if ANY of the following three conditions are true:<a name="line.793"></a>
-<span class="sourceLineNo">794</span>    // 1. The time since a regionserver registered is &lt; interval (means servers are actively checking in).<a name="line.794"></a>
-<span class="sourceLineNo">795</span>    // 2. We are under the total timeout.<a name="line.795"></a>
-<span class="sourceLineNo">796</span>    // 3. The count of servers is &lt; minimum.<a name="line.796"></a>
-<span class="sourceLineNo">797</span>    for (ServerListener listener: this.listeners) {<a name="line.797"></a>
-<span class="sourceLineNo">798</span>      listener.waiting();<a name="line.798"></a>
-<span class="sourceLineNo">799</span>    }<a name="line.799"></a>
-<span class="sourceLineNo">800</span>    while (!this.master.isStopped() &amp;&amp; !isClusterShutdown() &amp;&amp; count &lt; maxToStart &amp;&amp;<a name="line.800"></a>
-<span class="sourceLineNo">801</span>        ((lastCountChange + interval) &gt; now || timeout &gt; slept || count &lt; minToStart)) {<a name="line.801"></a>
-<span class="sourceLineNo">802</span>      // Log some info at every interval time or if there is a change<a name="line.802"></a>
-<span class="sourceLineNo">803</span>      if (oldCount != count || lastLogTime + interval &lt; now) {<a name="line.803"></a>
-<span class="sourceLineNo">804</span>        lastLogTime = now;<a name="line.804"></a>
-<span class="sourceLineNo">805</span>        String msg =<a name="line.805"></a>
-<span class="sourceLineNo">806</span>            "Waiting on regionserver count=" + count + "; waited="+<a name="line.806"></a>
-<span class="sourceLineNo">807</span>                slept + "ms, expecting min=" + minToStart + " server(s), max="+ getStrForMax(maxToStart) +<a name="line.807"></a>
-<span class="sourceLineNo">808</span>                " server(s), " + "timeout=" + timeout + "ms, lastChange=" + (lastCountChange - now) + "ms";<a name="line.808"></a>
-<span class="sourceLineNo">809</span>        LOG.info(msg);<a name="line.809"></a>
-<span class="sourceLineNo">810</span>        status.setStatus(msg);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>      }<a name="line.811"></a>
-<span class="sourceLineNo">812</span><a name="line.812"></a>
-<span class="sourceLineNo">813</span>      // We sleep for some time<a name="line.813"></a>
-<span class="sourceLineNo">814</span>      final long sleepTime = 50;<a name="line.814"></a>
-<span class="sourceLineNo">815</span>      Thread.sleep(sleepTime);<a name="line.815"></a>
-<span class="sourceLineNo">816</span>      now =  System.currentTimeMillis();<a name="line.816"></a>
-<span class="sourceLineNo">817</span>      slept = now - startTime;<a name="line.817"></a>
-<span class="sourceLineNo">818</span><a name="line.818"></a>
-<span class="sourceLineNo">819</span>      oldCount = count;<a name="line.819"></a>
-<span class="sourceLineNo">820</span>      count = countOfRegionServers();<a name="line.820"></a>
-<span class="sourceLineNo">821</span>      if (count != oldCount) {<a name="line.821"></a>
-<span class="sourceLineNo">822</span>        lastCountChange = now;<a name="line.822"></a>
-<span class="sourceLineNo">823</span>      }<a name="line.823"></a>
-<span class="sourceLineNo">824</span>    }<a name="line.824"></a>
-<span class="sourceLineNo">825</span>    // Did we exit the loop because cluster is going down?<a name="line.825"></a>
-<span class="sourceLineNo">826</span>    if (isClusterShutdown()) {<a name="line.826"></a>
-<span class="sourceLineNo">827</span>      this.master.stop("Cluster shutdown");<a name="line.827"></a>
+<span class="sourceLineNo">154</span><a name="line.154"></a>
+<span class="sourceLineNo">155</span>  /**<a name="line.155"></a>
+<span class="sourceLineNo">156</span>   * The last flushed sequence id for a store in a region.<a name="line.156"></a>
+<span class="sourceLineNo">157</span>   */<a name="line.157"></a>
+<span class="sourceLineNo">158</span>  private final ConcurrentNavigableMap&lt;byte[], ConcurrentNavigableMap&lt;byte[], Long&gt;&gt;<a name="line.158"></a>
+<span class="sourceLineNo">159</span>    storeFlushedSequenceIdsByRegion = new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.159"></a>
+<span class="sourceLineNo">160</span><a name="line.160"></a>
+<span class="sourceLineNo">161</span>  /** Map of registered servers to their current load */<a name="line.161"></a>
+<span class="sourceLineNo">162</span>  private final ConcurrentNavigableMap&lt;ServerName, ServerMetrics&gt; onlineServers =<a name="line.162"></a>
+<span class="sourceLineNo">163</span>    new ConcurrentSkipListMap&lt;&gt;();<a name="line.163"></a>
+<span class="sourceLineNo">164</span><a name="line.164"></a>
+<span class="sourceLineNo">165</span>  /** List of region servers that should not get any more new regions. */<a name="line.165"></a>
+<span class="sourceLineNo">166</span>  private final ArrayList&lt;ServerName&gt; drainingServers = new ArrayList&lt;&gt;();<a name="line.166"></a>
+<span class="sourceLineNo">167</span><a name="line.167"></a>
+<span class="sourceLineNo">168</span>  private final MasterServices master;<a name="line.168"></a>
+<span class="sourceLineNo">169</span><a name="line.169"></a>
+<span class="sourceLineNo">170</span>  private final DeadServer deadservers = new DeadServer();<a name="line.170"></a>
+<span class="sourceLineNo">171</span><a name="line.171"></a>
+<span class="sourceLineNo">172</span>  private final long maxSkew;<a name="line.172"></a>
+<span class="sourceLineNo">173</span>  private final long warningSkew;<a name="line.173"></a>
+<span class="sourceLineNo">174</span><a name="line.174"></a>
+<span class="sourceLineNo">175</span>  /** Listeners that are called on server events. */<a name="line.175"></a>
+<span class="sourceLineNo">176</span>  private List&lt;ServerListener&gt; listeners = new CopyOnWriteArrayList&lt;&gt;();<a name="line.176"></a>
+<span class="sourceLineNo">177</span><a name="line.177"></a>
+<span class="sourceLineNo">178</span>  /**<a name="line.178"></a>
+<span class="sourceLineNo">179</span>   * Constructor.<a name="line.179"></a>
+<span class="sourceLineNo">180</span>   */<a name="line.180"></a>
+<span class="sourceLineNo">181</span>  public ServerManager(final MasterServices master) {<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    this.master = master;<a name="line.182"></a>
+<span class="sourceLineNo">183</span>    Configuration c = master.getConfiguration();<a name="line.183"></a>
+<span class="sourceLineNo">184</span>    maxSkew = c.getLong(MAX_CLOCK_SKEW_MS, 30000);<a name="line.184"></a>
+<span class="sourceLineNo">185</span>    warningSkew = c.getLong("hbase.master.warningclockskew", 10000);<a name="line.185"></a>
+<span class="sourceLineNo">186</span>    persistFlushedSequenceId = c.getBoolean(PERSIST_FLUSHEDSEQUENCEID,<a name="line.186"></a>
+<span class="sourceLineNo">187</span>        PERSIST_FLUSHEDSEQUENCEID_DEFAULT);<a name="line.187"></a>
+<span class="sourceLineNo">188</span>  }<a name="line.188"></a>
+<span class="sourceLineNo">189</span><a name="line.189"></a>
+<span class="sourceLineNo">190</span>  /**<a name="line.190"></a>
+<span class="sourceLineNo">191</span>   * Add the listener to the notification list.<a name="line.191"></a>
+<span class="sourceLineNo">192</span>   * @param listener The ServerListener to register<a name="line.192"></a>
+<span class="sourceLineNo">193</span>   */<a name="line.193"></a>
+<span class="sourceLineNo">194</span>  public void registerListener(final ServerListener listener) {<a name="line.194"></a>
+<span class="sourceLineNo">195</span>    this.listeners.add(listener);<a name="line.195"></a>
+<span class="sourceLineNo">196</span>  }<a name="line.196"></a>
+<span class="sourceLineNo">197</span><a name="line.197"></a>
+<span class="sourceLineNo">198</span>  /**<a name="line.198"></a>
+<span class="sourceLineNo">199</span>   * Remove the listener from the notification list.<a name="line.199"></a>
+<span class="sourceLineNo">200</span>   * @param listener The ServerListener to unregister<a name="line.200"></a>
+<span class="sourceLineNo">201</span>   */<a name="line.201"></a>
+<span class="sourceLineNo">202</span>  public boolean unregisterListener(final ServerListener listener) {<a name="line.202"></a>
+<span class="sourceLineNo">203</span>    return this.listeners.remove(listener);<a name="line.203"></a>
+<span class="sourceLineNo">204</span>  }<a name="line.204"></a>
+<span class="sourceLineNo">205</span><a name="line.205"></a>
+<span class="sourceLineNo">206</span>  /**<a name="line.206"></a>
+<span class="sourceLineNo">207</span>   * Let the server manager know a new regionserver has come online<a name="line.207"></a>
+<span class="sourceLineNo">208</span>   * @param request the startup request<a name="line.208"></a>
+<span class="sourceLineNo">209</span>   * @param versionNumber the version number of the new regionserver<a name="line.209"></a>
+<span class="sourceLineNo">210</span>   * @param version the version of the new regionserver, could contain strings like "SNAPSHOT"<a name="line.210"></a>
+<span class="sourceLineNo">211</span>   * @param ia the InetAddress from which request is received<a name="line.211"></a>
+<span class="sourceLineNo">212</span>   * @return The ServerName we know this server as.<a name="line.212"></a>
+<span class="sourceLineNo">213</span>   * @throws IOException<a name="line.213"></a>
+<span class="sourceLineNo">214</span>   */<a name="line.214"></a>
+<span class="sourceLineNo">215</span>  ServerName regionServerStartup(RegionServerStartupRequest request, int versionNumber,<a name="line.215"></a>
+<span class="sourceLineNo">216</span>      String version, InetAddress ia) throws IOException {<a name="line.216"></a>
+<span class="sourceLineNo">217</span>    // Test for case where we get a region startup message from a regionserver<a name="line.217"></a>
+<span class="sourceLineNo">218</span>    // that has been quickly restarted but whose znode expiration handler has<a name="line.218"></a>
+<span class="sourceLineNo">219</span>    // not yet run, or from a server whose fail we are currently processing.<a name="line.219"></a>
+<span class="sourceLineNo">220</span>    // Test its host+port combo is present in serverAddressToServerInfo. If it<a name="line.220"></a>
+<span class="sourceLineNo">221</span>    // is, reject the server and trigger its expiration. The next time it comes<a name="line.221"></a>
+<span class="sourceLineNo">222</span>    // in, it should have been removed from serverAddressToServerInfo and queued<a name="line.222"></a>
+<span class="sourceLineNo">223</span>    // for processing by ProcessServerShutdown.<a name="line.223"></a>
+<span class="sourceLineNo">224</span><a name="line.224"></a>
+<span class="sourceLineNo">225</span>    final String hostname =<a name="line.225"></a>
+<span class="sourceLineNo">226</span>      request.hasUseThisHostnameInstead() ? request.getUseThisHostnameInstead() : ia.getHostName();<a name="line.226"></a>
+<span class="sourceLineNo">227</span>    ServerName sn = ServerName.valueOf(hostname, request.getPort(), request.getServerStartCode());<a name="line.227"></a>
+<span class="sourceLineNo">228</span>    checkClockSkew(sn, request.getServerCurrentTime());<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    checkIsDead(sn, "STARTUP");<a name="line.229"></a>
+<span class="sourceLineNo">230</span>    if (!checkAndRecordNewServer(sn, ServerMetricsBuilder.of(sn, versionNumber, version))) {<a name="line.230"></a>
+<span class="sourceLineNo">231</span>      LOG.warn(<a name="line.231"></a>
+<span class="sourceLineNo">232</span>        "THIS SHOULD NOT HAPPEN, RegionServerStartup" + " could not record the server: " + sn);<a name="line.232"></a>
+<span class="sourceLineNo">233</span>    }<a name="line.233"></a>
+<span class="sourceLineNo">234</span>    return sn;<a name="line.234"></a>
+<span class="sourceLineNo">235</span>  }<a name="line.235"></a>
+<span class="sourceLineNo">236</span><a name="line.236"></a>
+<span class="sourceLineNo">237</span>  /**<a name="line.237"></a>
+<span class="sourceLineNo">238</span>   * Updates last flushed sequence Ids for the regions on server sn<a name="line.238"></a>
+<span class="sourceLineNo">239</span>   * @param sn<a name="line.239"></a>
+<span class="sourceLineNo">240</span>   * @param hsl<a name="line.240"></a>
+<span class="sourceLineNo">241</span>   */<a name="line.241"></a>
+<span class="sourceLineNo">242</span>  private void updateLastFlushedSequenceIds(ServerName sn, ServerMetrics hsl) {<a name="line.242"></a>
+<span class="sourceLineNo">243</span>    for (Entry&lt;byte[], RegionMetrics&gt; entry : hsl.getRegionMetrics().entrySet()) {<a name="line.243"></a>
+<span class="sourceLineNo">244</span>      byte[] encodedRegionName = Bytes.toBytes(RegionInfo.encodeRegionName(entry.getKey()));<a name="line.244"></a>
+<span class="sourceLineNo">245</span>      Long existingValue = flushedSequenceIdByRegion.get(encodedRegionName);<a name="line.245"></a>
+<span class="sourceLineNo">246</span>      long l = entry.getValue().getCompletedSequenceId();<a name="line.246"></a>
+<span class="sourceLineNo">247</span>      // Don't let smaller sequence ids override greater sequence ids.<a name="line.247"></a>
+<span class="sourceLineNo">248</span>      if (LOG.isTraceEnabled()) {<a name="line.248"></a>
+<span class="sourceLineNo">249</span>        LOG.trace(Bytes.toString(encodedRegionName) + ", existingValue=" + existingValue +<a name="line.249"></a>
+<span class="sourceLineNo">250</span>          ", completeSequenceId=" + l);<a name="line.250"></a>
+<span class="sourceLineNo">251</span>      }<a name="line.251"></a>
+<span class="sourceLineNo">252</span>      if (existingValue == null || (l != HConstants.NO_SEQNUM &amp;&amp; l &gt; existingValue)) {<a name="line.252"></a>
+<span class="sourceLineNo">253</span>        flushedSequenceIdByRegion.put(encodedRegionName, l);<a name="line.253"></a>
+<span class="sourceLineNo">254</span>      } else if (l != HConstants.NO_SEQNUM &amp;&amp; l &lt; existingValue) {<a name="line.254"></a>
+<span class="sourceLineNo">255</span>        LOG.warn("RegionServer " + sn + " indicates a last flushed sequence id ("<a name="line.255"></a>
+<span class="sourceLineNo">256</span>            + l + ") that is less than the previous last flushed sequence id ("<a name="line.256"></a>
+<span class="sourceLineNo">257</span>            + existingValue + ") for region " + Bytes.toString(entry.getKey()) + " Ignoring.");<a name="line.257"></a>
+<span class="sourceLineNo">258</span>      }<a name="line.258"></a>
+<span class="sourceLineNo">259</span>      ConcurrentNavigableMap&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.259"></a>
+<span class="sourceLineNo">260</span>          computeIfAbsent(storeFlushedSequenceIdsByRegion, encodedRegionName,<a name="line.260"></a>
+<span class="sourceLineNo">261</span>            () -&gt; new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR));<a name="line.261"></a>
+<span class="sourceLineNo">262</span>      for (Entry&lt;byte[], Long&gt; storeSeqId : entry.getValue().getStoreSequenceId().entrySet()) {<a name="line.262"></a>
+<span class="sourceLineNo">263</span>        byte[] family = storeSeqId.getKey();<a name="line.263"></a>
+<span class="sourceLineNo">264</span>        existingValue = storeFlushedSequenceId.get(family);<a name="line.264"></a>
+<span class="sourceLineNo">265</span>        l = storeSeqId.getValue();<a name="line.265"></a>
+<span class="sourceLineNo">266</span>        if (LOG.isTraceEnabled()) {<a name="line.266"></a>
+<span class="sourceLineNo">267</span>          LOG.trace(Bytes.toString(encodedRegionName) + ", family=" + Bytes.toString(family) +<a name="line.267"></a>
+<span class="sourceLineNo">268</span>            ", existingValue=" + existingValue + ", completeSequenceId=" + l);<a name="line.268"></a>
+<span class="sourceLineNo">269</span>        }<a name="line.269"></a>
+<span class="sourceLineNo">270</span>        // Don't let smaller sequence ids override greater sequence ids.<a name="line.270"></a>
+<span class="sourceLineNo">271</span>        if (existingValue == null || (l != HConstants.NO_SEQNUM &amp;&amp; l &gt; existingValue.longValue())) {<a name="line.271"></a>
+<span class="sourceLineNo">272</span>          storeFlushedSequenceId.put(family, l);<a name="line.272"></a>
+<span class="sourceLineNo">273</span>        }<a name="line.273"></a>
+<span class="sourceLineNo">274</span>      }<a name="line.274"></a>
+<span class="sourceLineNo">275</span>    }<a name="line.275"></a>
+<span class="sourceLineNo">276</span>  }<a name="line.276"></a>
+<span class="sourceLineNo">277</span><a name="line.277"></a>
+<span class="sourceLineNo">278</span>  @VisibleForTesting<a name="line.278"></a>
+<span class="sourceLineNo">279</span>  public void regionServerReport(ServerName sn,<a name="line.279"></a>
+<span class="sourceLineNo">280</span>    ServerMetrics sl) throws YouAreDeadException {<a name="line.280"></a>
+<span class="sourceLineNo">281</span>    checkIsDead(sn, "REPORT");<a name="line.281"></a>
+<span class="sourceLineNo">282</span>    if (null == this.onlineServers.replace(sn, sl)) {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>      // Already have this host+port combo and its just different start code?<a name="line.283"></a>
+<span class="sourceLineNo">284</span>      // Just let the server in. Presume master joining a running cluster.<a name="line.284"></a>
+<span class="sourceLineNo">285</span>      // recordNewServer is what happens at the end of reportServerStartup.<a name="line.285"></a>
+<span class="sourceLineNo">286</span>      // The only thing we are skipping is passing back to the regionserver<a name="line.286"></a>
+<span class="sourceLineNo">287</span>      // the ServerName to use. Here we presume a master has already done<a name="line.287"></a>
+<span class="sourceLineNo">288</span>      // that so we'll press on with whatever it gave us for ServerName.<a name="line.288"></a>
+<span class="sourceLineNo">289</span>      if (!checkAndRecordNewServer(sn, sl)) {<a name="line.289"></a>
+<span class="sourceLineNo">290</span>        LOG.info("RegionServerReport ignored, could not record the server: " + sn);<a name="line.290"></a>
+<span class="sourceLineNo">291</span>        return; // Not recorded, so no need to move on<a name="line.291"></a>
+<span class="sourceLineNo">292</span>      }<a name="line.292"></a>
+<span class="sourceLineNo">293</span>    }<a name="line.293"></a>
+<span class="sourceLineNo">294</span>    updateLastFlushedSequenceIds(sn, sl);<a name="line.294"></a>
+<span class="sourceLineNo">295</span>  }<a name="line.295"></a>
+<span class="sourceLineNo">296</span><a name="line.296"></a>
+<span class="sourceLineNo">297</span>  /**<a name="line.297"></a>
+<span class="sourceLineNo">298</span>   * Check is a server of same host and port already exists,<a name="line.298"></a>
+<span class="sourceLineNo">299</span>   * if not, or the existed one got a smaller start code, record it.<a name="line.299"></a>
+<span class="sourceLineNo">300</span>   *<a name="line.300"></a>
+<span class="sourceLineNo">301</span>   * @param serverName the server to check and record<a name="line.301"></a>
+<span class="sourceLineNo">302</span>   * @param sl the server load on the server<a name="line.302"></a>
+<span class="sourceLineNo">303</span>   * @return true if the server is recorded, otherwise, false<a name="line.303"></a>
+<span class="sourceLineNo">304</span>   */<a name="line.304"></a>
+<span class="sourceLineNo">305</span>  boolean checkAndRecordNewServer(final ServerName serverName, final ServerMetrics sl) {<a name="line.305"></a>
+<span class="sourceLineNo">306</span>    ServerName existingServer = null;<a name="line.306"></a>
+<span class="sourceLineNo">307</span>    synchronized (this.onlineServers) {<a name="line.307"></a>
+<span class="sourceLineNo">308</span>      existingServer = findServerWithSameHostnamePortWithLock(serverName);<a name="line.308"></a>
+<span class="sourceLineNo">309</span>      if (existingServer != null &amp;&amp; (existingServer.getStartcode() &gt; serverName.getStartcode())) {<a name="line.309"></a>
+<span class="sourceLineNo">310</span>        LOG.info("Server serverName=" + serverName + " rejected; we already have "<a name="line.310"></a>
+<span class="sourceLineNo">311</span>            + existingServer.toString() + " registered with same hostname and port");<a name="line.311"></a>
+<span class="sourceLineNo">312</span>        return false;<a name="line.312"></a>
+<span class="sourceLineNo">313</span>      }<a name="line.313"></a>
+<span class="sourceLineNo">314</span>      recordNewServerWithLock(serverName, sl);<a name="line.314"></a>
+<span class="sourceLineNo">315</span>    }<a name="line.315"></a>
+<span class="sourceLineNo">316</span><a name="line.316"></a>
+<span class="sourceLineNo">317</span>    // Tell our listeners that a server was added<a name="line.317"></a>
+<span class="sourceLineNo">318</span>    if (!this.listeners.isEmpty()) {<a name="line.318"></a>
+<span class="sourceLineNo">319</span>      for (ServerListener listener : this.listeners) {<a name="line.319"></a>
+<span class="sourceLineNo">320</span>        listener.serverAdded(serverName);<a name="line.320"></a>
+<span class="sourceLineNo">321</span>      }<a name="line.321"></a>
+<span class="sourceLineNo">322</span>    }<a name="line.322"></a>
+<span class="sourceLineNo">323</span><a name="line.323"></a>
+<span class="sourceLineNo">324</span>    // Note that we assume that same ts means same server, and don't expire in that case.<a name="line.324"></a>
+<span class="sourceLineNo">325</span>    //  TODO: ts can theoretically collide due to clock shifts, so this is a bit hacky.<a name="line.325"></a>
+<span class="sourceLineNo">326</span>    if (existingServer != null &amp;&amp;<a name="line.326"></a>
+<span class="sourceLineNo">327</span>        (existingServer.getStartcode() &lt; serverName.getStartcode())) {<a name="line.327"></a>
+<span class="sourceLineNo">328</span>      LOG.info("Triggering server recovery; existingServer " +<a name="line.328"></a>
+<span class="sourceLineNo">329</span>          existingServer + " looks stale, new server:" + serverName);<a name="line.329"></a>
+<span class="sourceLineNo">330</span>      expireServer(existingServer);<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    }<a name="line.331"></a>
+<span class="sourceLineNo">332</span>    return true;<a name="line.332"></a>
+<span class="sourceLineNo">333</span>  }<a name="line.333"></a>
+<span class="sourceLineNo">334</span><a name="line.334"></a>
+<span class="sourceLineNo">335</span>  /**<a name="line.335"></a>
+<span class="sourceLineNo">336</span>   * Find out the region servers crashed between the crash of the previous master instance and the<a name="line.336"></a>
+<span class="sourceLineNo">337</span>   * current master instance and schedule SCP for them.<a name="line.337"></a>
+<span class="sourceLineNo">338</span>   * &lt;p/&gt;<a name="line.338"></a>
+<span class="sourceLineNo">339</span>   * Since the {@code RegionServerTracker} has already helped us to construct the online servers set<a name="line.339"></a>
+<span class="sourceLineNo">340</span>   * by scanning zookeeper, now we can compare the online servers with {@code liveServersFromWALDir}<a name="line.340"></a>
+<span class="sourceLineNo">341</span>   * to find out whether there are servers which are already dead.<a name="line.341"></a>
+<span class="sourceLineNo">342</span>   * &lt;p/&gt;<a name="line.342"></a>
+<span class="sourceLineNo">343</span>   * Must be called inside the initialization method of {@code RegionServerTracker} to avoid<a name="line.343"></a>
+<span class="sourceLineNo">344</span>   * concurrency issue.<a name="line.344"></a>
+<span class="sourceLineNo">345</span>   * @param deadServersFromPE the region servers which already have a SCP associated.<a name="line.345"></a>
+<span class="sourceLineNo">346</span>   * @param liveServersFromWALDir the live region servers from wal directory.<a name="line.346"></a>
+<span class="sourceLineNo">347</span>   */<a name="line.347"></a>
+<span class="sourceLineNo">348</span>  void findDeadServersAndProcess(Set&lt;ServerName&gt; deadServersFromPE,<a name="line.348"></a>
+<span class="sourceLineNo">349</span>      Set&lt;ServerName&gt; liveServersFromWALDir) {<a name="line.349"></a>
+<span class="sourceLineNo">350</span>    deadServersFromPE.forEach(deadservers::putIfAbsent);<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    liveServersFromWALDir.stream().filter(sn -&gt; !onlineServers.containsKey(sn))<a name="line.351"></a>
+<span class="sourceLineNo">352</span>      .forEach(this::expireServer);<a name="line.352"></a>
+<span class="sourceLineNo">353</span>  }<a name="line.353"></a>
+<span class="sourceLineNo">354</span><a name="line.354"></a>
+<span class="sourceLineNo">355</span>  /**<a name="line.355"></a>
+<span class="sourceLineNo">356</span>   * Checks if the clock skew between the server and the master. If the clock skew exceeds the<a name="line.356"></a>
+<span class="sourceLineNo">357</span>   * configured max, it will throw an exception; if it exceeds the configured warning threshold,<a name="line.357"></a>
+<span class="sourceLineNo">358</span>   * it will log a warning but start normally.<a name="line.358"></a>
+<span class="sourceLineNo">359</span>   * @param serverName Incoming servers's name<a name="line.359"></a>
+<span class="sourceLineNo">360</span>   * @param serverCurrentTime<a name="line.360"></a>
+<span class="sourceLineNo">361</span>   * @throws ClockOutOfSyncException if the skew exceeds the configured max value<a name="line.361"></a>
+<span class="sourceLineNo">362</span>   */<a name="line.362"></a>
+<span class="sourceLineNo">363</span>  private void checkClockSkew(final ServerName serverName, final long serverCurrentTime)<a name="line.363"></a>
+<span class="sourceLineNo">364</span>      throws ClockOutOfSyncException {<a name="line.364"></a>
+<span class="sourceLineNo">365</span>    long skew = Math.abs(EnvironmentEdgeManager.currentTime() - serverCurrentTime);<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    if (skew &gt; maxSkew) {<a name="line.366"></a>
+<span class="sourceLineNo">367</span>      String message = "Server " + serverName + " has been " +<a name="line.367"></a>
+<span class="sourceLineNo">368</span>        "rejected; Reported time is too far out of sync with master.  " +<a name="line.368"></a>
+<span class="sourceLineNo">369</span>        "Time difference of " + skew + "ms &gt; max allowed of " + maxSkew + "ms";<a name="line.369"></a>
+<span class="sourceLineNo">370</span>      LOG.warn(message);<a name="line.370"></a>
+<span class="sourceLineNo">371</span>      throw new ClockOutOfSyncException(message);<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    } else if (skew &gt; warningSkew){<a name="line.372"></a>
+<span class="sourceLineNo">373</span>      String message = "Reported time for server " + serverName + " is out of sync with master " +<a name="line.373"></a>
+<span class="sourceLineNo">374</span>        "by " + skew + "ms. (Warning threshold is " + warningSkew + "ms; " +<a name="line.374"></a>
+<span class="sourceLineNo">375</span>        "error threshold is " + maxSkew + "ms)";<a name="line.375"></a>
+<span class="sourceLineNo">376</span>      LOG.warn(message);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    }<a name="line.377"></a>
+<span class="sourceLineNo">378</span>  }<a name="line.378"></a>
+<span class="sourceLineNo">379</span><a name="line.379"></a>
+<span class="sourceLineNo">380</span>  /**<a name="line.380"></a>
+<span class="sourceLineNo">381</span>   * Called when RegionServer first reports in for duty and thereafter each<a name="line.381"></a>
+<span class="sourceLineNo">382</span>   * time it heartbeats to make sure it is has not been figured for dead.<a name="line.382"></a>
+<span class="sourceLineNo">383</span>   * If this server is on the dead list, reject it with a YouAreDeadException.<a name="line.383"></a>
+<span class="sourceLineNo">384</span>   * If it was dead but came back with a new start code, remove the old entry<a name="line.384"></a>
+<span class="sourceLineNo">385</span>   * from the dead list.<a name="line.385"></a>
+<span class="sourceLineNo">386</span>   * @param what START or REPORT<a name="line.386"></a>
+<span class="sourceLineNo">387</span>   */<a name="line.387"></a>
+<span class="sourceLineNo">388</span>  private void checkIsDead(final ServerName serverName, final String what)<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      throws YouAreDeadException {<a name="line.389"></a>
+<span class="sourceLineNo">390</span>    if (this.deadservers.isDeadServer(serverName)) {<a name="line.390"></a>
+<span class="sourceLineNo">391</span>      // Exact match: host name, port and start code all match with existing one of the<a name="line.391"></a>
+<span class="sourceLineNo">392</span>      // dead servers. So, this server must be dead. Tell it to kill itself.<a name="line.392"></a>
+<span class="sourceLineNo">393</span>      String message = "Server " + what + " rejected; currently processing " +<a name="line.393"></a>
+<span class="sourceLineNo">394</span>          serverName + " as dead server";<a name="line.394"></a>
+<span class="sourceLineNo">395</span>      LOG.debug(message);<a name="line.395"></a>
+<span class="sourceLineNo">396</span>      throw new YouAreDeadException(message);<a name="line.396"></a>
+<span class="sourceLineNo">397</span>    }<a name="line.397"></a>
+<span class="sourceLineNo">398</span>    // Remove dead server with same hostname and port of newly checking in rs after master<a name="line.398"></a>
+<span class="sourceLineNo">399</span>    // initialization. See HBASE-5916 for more information.<a name="line.399"></a>
+<span class="sourceLineNo">400</span>    if ((this.master == null || this.master.isInitialized()) &amp;&amp;<a name="line.400"></a>
+<span class="sourceLineNo">401</span>        this.deadservers.cleanPreviousInstance(serverName)) {<a name="line.401"></a>
+<span class="sourceLineNo">402</span>      // This server has now become alive after we marked it as dead.<a name="line.402"></a>
+<span class="sourceLineNo">403</span>      // We removed it's previous entry from the dead list to reflect it.<a name="line.403"></a>
+<span class="sourceLineNo">404</span>      LOG.debug("{} {} came back up, removed it from the dead servers list", what, serverName);<a name="line.404"></a>
+<span class="sourceLineNo">405</span>    }<a name="line.405"></a>
+<span class="sourceLineNo">406</span>  }<a name="line.406"></a>
+<span class="sourceLineNo">407</span><a name="line.407"></a>
+<span class="sourceLineNo">408</span>  /**<a name="line.408"></a>
+<span class="sourceLineNo">409</span>   * Assumes onlineServers is locked.<a name="line.409"></a>
+<span class="sourceLineNo">410</span>   * @return ServerName with matching hostname and port.<a name="line.410"></a>
+<span class="sourceLineNo">411</span>   */<a name="line.411"></a>
+<span class="sourceLineNo">412</span>  private ServerName findServerWithSameHostnamePortWithLock(<a name="line.412"></a>
+<span class="sourceLineNo">413</span>      final ServerName serverName) {<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    ServerName end = ServerName.valueOf(serverName.getHostname(), serverName.getPort(),<a name="line.414"></a>
+<span class="sourceLineNo">415</span>        Long.MAX_VALUE);<a name="line.415"></a>
+<span class="sourceLineNo">416</span><a name="line.416"></a>
+<span class="sourceLineNo">417</span>    ServerName r = onlineServers.lowerKey(end);<a name="line.417"></a>
+<span class="sourceLineNo">418</span>    if (r != null) {<a name="line.418"></a>
+<span class="sourceLineNo">419</span>      if (ServerName.isSameAddress(r, serverName)) {<a name="line.419"></a>
+<span class="sourceLineNo">420</span>        return r;<a name="line.420"></a>
+<span class="sourceLineNo">421</span>      }<a name="line.421"></a>
+<span class="sourceLineNo">422</span>    }<a name="line.422"></a>
+<span class="sourceLineNo">423</span>    return null;<a name="line.423"></a>
+<span class="sourceLineNo">424</span>  }<a name="line.424"></a>
+<span class="sourceLineNo">425</span><a name="line.425"></a>
+<span class="sourceLineNo">426</span>  /**<a name="line.426"></a>
+<span class="sourceLineNo">427</span>   * Adds the onlineServers list. onlineServers should be locked.<a name="line.427"></a>
+<span class="sourceLineNo">428</span>   * @param serverName The remote servers name.<a name="line.428"></a>
+<span class="sourceLineNo">429</span>   */<a name="line.429"></a>
+<span class="sourceLineNo">430</span>  @VisibleForTesting<a name="line.430"></a>
+<span class="sourceLineNo">431</span>  void recordNewServerWithLock(final ServerName serverName, final ServerMetrics sl) {<a name="line.431"></a>
+<span class="sourceLineNo">432</span>    LOG.info("Registering regionserver=" + serverName);<a name="line.432"></a>
+<span class="sourceLineNo">433</span>    this.onlineServers.put(serverName, sl);<a name="line.433"></a>
+<span class="sourceLineNo">434</span>  }<a name="line.434"></a>
+<span class="sourceLineNo">435</span><a name="line.435"></a>
+<span class="sourceLineNo">436</span>  @VisibleForTesting<a name="line.436"></a>
+<span class="sourceLineNo">437</span>  public ConcurrentNavigableMap&lt;byte[], Long&gt; getFlushedSequenceIdByRegion() {<a name="line.437"></a>
+<span class="sourceLineNo">438</span>    return flushedSequenceIdByRegion;<a name="line.438"></a>
+<span class="sourceLineNo">439</span>  }<a name="line.439"></a>
+<span class="sourceLineNo">440</span><a name="line.440"></a>
+<span class="sourceLineNo">441</span>  public RegionStoreSequenceIds getLastFlushedSequenceId(byte[] encodedRegionName) {<a name="line.441"></a>
+<span class="sourceLineNo">442</span>    RegionStoreSequenceIds.Builder builder = RegionStoreSequenceIds.newBuilder();<a name="line.442"></a>
+<span class="sourceLineNo">443</span>    Long seqId = flushedSequenceIdByRegion.get(encodedRegionName);<a name="line.443"></a>
+<span class="sourceLineNo">444</span>    builder.setLastFlushedSequenceId(seqId != null ? seqId.longValue() : HConstants.NO_SEQNUM);<a name="line.444"></a>
+<span class="sourceLineNo">445</span>    Map&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.445"></a>
+<span class="sourceLineNo">446</span>        storeFlushedSequenceIdsByRegion.get(encodedRegionName);<a name="line.446"></a>
+<span class="sourceLineNo">447</span>    if (storeFlushedSequenceId != null) {<a name="line.447"></a>
+<span class="sourceLineNo">448</span>      for (Map.Entry&lt;byte[], Long&gt; entry : storeFlushedSequenceId.entrySet()) {<a name="line.448"></a>
+<span class="sourceLineNo">449</span>        builder.addStoreSequenceId(StoreSequenceId.newBuilder()<a name="line.449"></a>
+<span class="sourceLineNo">450</span>            .setFamilyName(UnsafeByteOperations.unsafeWrap(entry.getKey()))<a name="line.450"></a>
+<span class="sourceLineNo">451</span>            .setSequenceId(entry.getValue().longValue()).build());<a name="line.451"></a>
+<span class="sourceLineNo">452</span>      }<a name="line.452"></a>
+<span class="sourceLineNo">453</span>    }<a name="line.453"></a>
+<span class="sourceLineNo">454</span>    return builder.build();<a name="line.454"></a>
+<span class="sourceLineNo">455</span>  }<a name="line.455"></a>
+<span class="sourceLineNo">456</span><a name="line.456"></a>
+<span class="sourceLineNo">457</span>  /**<a name="line.457"></a>
+<span class="sourceLineNo">458</span>   * @param serverName<a name="line.458"></a>
+<span class="sourceLineNo">459</span>   * @return ServerMetrics if serverName is known else null<a name="line.459"></a>
+<span class="sourceLineNo">460</span>   */<a name="line.460"></a>
+<span class="sourceLineNo">461</span>  public ServerMetrics getLoad(final ServerName serverName) {<a name="line.461"></a>
+<span class="sourceLineNo">462</span>    return this.onlineServers.get(serverName);<a name="line.462"></a>
+<span class="sourceLineNo">463</span>  }<a name="line.463"></a>
+<span class="sourceLineNo">464</span><a name="line.464"></a>
+<span class="sourceLineNo">465</span>  /**<a name="line.465"></a>
+<span class="sourceLineNo">466</span>   * Compute the average load across all region servers.<a name="line.466"></a>
+<span class="sourceLineNo">467</span>   * Currently, this uses a very naive computation - just uses the number of<a name="line.467"></a>
+<span class="sourceLineNo">468</span>   * regions being served, ignoring stats about number of requests.<a name="line.468"></a>
+<span class="sourceLineNo">469</span>   * @return the average load<a name="line.469"></a>
+<span class="sourceLineNo">470</span>   */<a name="line.470"></a>
+<span class="sourceLineNo">471</span>  public double getAverageLoad() {<a name="line.471"></a>
+<span class="sourceLineNo">472</span>    int totalLoad = 0;<a name="line.472"></a>
+<span class="sourceLineNo">473</span>    int numServers = 0;<a name="line.473"></a>
+<span class="sourceLineNo">474</span>    for (ServerMetrics sl : this.onlineServers.values()) {<a name="line.474"></a>
+<span class="sourceLineNo">475</span>      numServers++;<a name="line.475"></a>
+<span class="sourceLineNo">476</span>      totalLoad += sl.getRegionMetrics().size();<a name="line.476"></a>
+<span class="sourceLineNo">477</span>    }<a name="line.477"></a>
+<span class="sourceLineNo">478</span>    return numServers == 0 ? 0 :<a name="line.478"></a>
+<span class="sourceLineNo">479</span>      (double)totalLoad / (double)numServers;<a name="line.479"></a>
+<span class="sourceLineNo">480</span>  }<a name="line.480"></a>
+<span class="sourceLineNo">481</span><a name="line.481"></a>
+<span class="sourceLineNo">482</span>  /** @return the count of active regionservers */<a name="line.482"></a>
+<span class="sourceLineNo">483</span>  public int countOfRegionServers() {<a name="line.483"></a>
+<span class="sourceLineNo">484</span>    // Presumes onlineServers is a concurrent map<a name="line.484"></a>
+<span class="sourceLineNo">485</span>    return this.onlineServers.size();<a name="line.485"></a>
+<span class="sourceLineNo">486</span>  }<a name="line.486"></a>
+<span class="sourceLineNo">487</span><a name="line.487"></a>
+<span class="sourceLineNo">488</span>  /**<a name="line.488"></a>
+<span class="sourceLineNo">489</span>   * @return Read-only map of servers to serverinfo<a name="line.489"></a>
+<span class="sourceLineNo">490</span>   */<a name="line.490"></a>
+<span class="sourceLineNo">491</span>  public Map&lt;ServerName, ServerMetrics&gt; getOnlineServers() {<a name="line.491"></a>
+<span class="sourceLineNo">492</span>    // Presumption is that iterating the returned Map is OK.<a name="line.492"></a>
+<span class="sourceLineNo">493</span>    synchronized (this.onlineServers) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      return Collections.unmodifiableMap(this.onlineServers);<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    }<a name="line.495"></a>
+<span class="sourceLineNo">496</span>  }<a name="line.496"></a>
+<span class="sourceLineNo">497</span><a name="line.497"></a>
+<span class="sourceLineNo">498</span>  public DeadServer getDeadServers() {<a name="line.498"></a>
+<span class="sourceLineNo">499</span>    return this.deadservers;<a name="line.499"></a>
+<span class="sourceLineNo">500</span>  }<a name="line.500"></a>
+<span class="sourceLineNo">501</span><a name="line.501"></a>
+<span class="sourceLineNo">502</span>  /**<a name="line.502"></a>
+<span class="sourceLineNo">503</span>   * Checks if any dead servers are currently in progress.<a name="line.503"></a>
+<span class="sourceLineNo">504</span>   * @return true if any RS are being processed as dead, false if not<a name="line.504"></a>
+<span class="sourceLineNo">505</span>   */<a name="line.505"></a>
+<span class="sourceLineNo">506</span>  public boolean areDeadServersInProgress() {<a name="line.506"></a>
+<span class="sourceLineNo">507</span>    return this.deadservers.areDeadServersInProgress();<a name="line.507"></a>
+<span class="sourceLineNo">508</span>  }<a name="line.508"></a>
+<span class="sourceLineNo">509</span><a name="line.509"></a>
+<span class="sourceLineNo">510</span>  void letRegionServersShutdown() {<a name="line.510"></a>
+<span class="sourceLineNo">511</span>    long previousLogTime = 0;<a name="line.511"></a>
+<span class="sourceLineNo">512</span>    ServerName sn = master.getServerName();<a name="line.512"></a>
+<span class="sourceLineNo">513</span>    ZKWatcher zkw = master.getZooKeeper();<a name="line.513"></a>
+<span class="sourceLineNo">514</span>    int onlineServersCt;<a name="line.514"></a>
+<span class="sourceLineNo">515</span>    while ((onlineServersCt = onlineServers.size()) &gt; 0){<a name="line.515"></a>
+<span class="sourceLineNo">516</span><a name="line.516"></a>
+<span class="sourceLineNo">517</span>      if (System.currentTimeMillis() &gt; (previousLogTime + 1000)) {<a name="line.517"></a>
+<span class="sourceLineNo">518</span>        Set&lt;ServerName&gt; remainingServers = onlineServers.keySet();<a name="line.518"></a>
+<span class="sourceLineNo">519</span>        synchronized (onlineServers) {<a name="line.519"></a>
+<span class="sourceLineNo">520</span>          if (remainingServers.size() == 1 &amp;&amp; remainingServers.contains(sn)) {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>            // Master will delete itself later.<a name="line.521"></a>
+<span class="sourceLineNo">522</span>            return;<a name="line.522"></a>
+<span class="sourceLineNo">523</span>          }<a name="line.523"></a>
+<span class="sourceLineNo">524</span>        }<a name="line.524"></a>
+<span class="sourceLineNo">525</span>        StringBuilder sb = new StringBuilder();<a name="line.525"></a>
+<span class="sourceLineNo">526</span>        // It's ok here to not sync on onlineServers - merely logging<a name="line.526"></a>
+<span class="sourceLineNo">527</span>        for (ServerName key : remainingServers) {<a name="line.527"></a>
+<span class="sourceLineNo">528</span>          if (sb.length() &gt; 0) {<a name="line.528"></a>
+<span class="sourceLineNo">529</span>            sb.append(", ");<a name="line.529"></a>
+<span class="sourceLineNo">530</span>          }<a name="line.530"></a>
+<span class="sourceLineNo">531</span>          sb.append(key);<a name="line.531"></a>
+<span class="sourceLineNo">532</span>        }<a name="line.532"></a>
+<span class="sourceLineNo">533</span>        LOG.info("Waiting on regionserver(s) " + sb.toString());<a name="line.533"></a>
+<span class="sourceLineNo">534</span>        previousLogTime = System.currentTimeMillis();<a name="line.534"></a>
+<span class="sourceLineNo">535</span>      }<a name="line.535"></a>
+<span class="sourceLineNo">536</span><a name="line.536"></a>
+<span class="sourceLineNo">537</span>      try {<a name="line.537"></a>
+<span class="sourceLineNo">538</span>        List&lt;String&gt; servers = getRegionServersInZK(zkw);<a name="line.538"></a>
+<span class="sourceLineNo">539</span>        if (servers == null || servers.isEmpty() || (servers.size() == 1<a name="line.539"></a>
+<span class="sourceLineNo">540</span>            &amp;&amp; servers.contains(sn.toString()))) {<a name="line.540"></a>
+<span class="sourceLineNo">541</span>          LOG.info("ZK shows there is only the master self online, exiting now");<a name="line.541"></a>
+<span class="sourceLineNo">542</span>          // Master could have lost some ZK events, no need to wait more.<a name="line.542"></a>
+<span class="sourceLineNo">543</span>          break;<a name="line.543"></a>
+<span class="sourceLineNo">544</span>        }<a name="line.544"></a>
+<span class="sourceLineNo">545</span>      } catch (KeeperException ke) {<a name="line.545"></a>
+<span class="sourceLineNo">546</span>        LOG.warn("Failed to list regionservers", ke);<a name="line.546"></a>
+<span class="sourceLineNo">547</span>        // ZK is malfunctioning, don't hang here<a name="line.547"></a>
+<span class="sourceLineNo">548</span>        break;<a name="line.548"></a>
+<span class="sourceLineNo">549</span>      }<a name="line.549"></a>
+<span class="sourceLineNo">550</span>      synchronized (onlineServers) {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>        try {<a name="line.551"></a>
+<span class="sourceLineNo">552</span>          if (onlineServersCt == onlineServers.size()) onlineServers.wait(100);<a name="line.552"></a>
+<span class="sourceLineNo">553</span>        } catch (InterruptedException ignored) {<a name="line.553"></a>
+<span class="sourceLineNo">554</span>          // continue<a name="line.554"></a>
+<span class="sourceLineNo">555</span>        }<a name="line.555"></a>
+<span class="sourceLineNo">556</span>      }<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    }<a name="line.557"></a>
+<span class="sourceLineNo">558</span>  }<a name="line.558"></a>
+<span class="sourceLineNo">559</span><a name="line.559"></a>
+<span class="sourceLineNo">560</span>  private List&lt;String&gt; getRegionServersInZK(final ZKWatcher zkw)<a name="line.560"></a>
+<span class="sourceLineNo">561</span>  throws KeeperException {<a name="line.561"></a>
+<span class="sourceLineNo">562</span>    return ZKUtil.listChildrenNoWatch(zkw, zkw.getZNodePaths().rsZNode);<a name="line.562"></a>
+<span class="sourceLineNo">563</span>  }<a name="line.563"></a>
+<span class="sourceLineNo">564</span><a name="line.564"></a>
+<span class="sourceLineNo">565</span>  /**<a name="line.565"></a>
+<span class="sourceLineNo">566</span>   * Expire the passed server. Add it to list of dead servers and queue a shutdown processing.<a name="line.566"></a>
+<span class="sourceLineNo">567</span>   * @return pid if we queued a ServerCrashProcedure else {@link Procedure#NO_PROC_ID} if we did<a name="line.567"></a>
+<span class="sourceLineNo">568</span>   *         not (could happen for many reasons including the fact that its this server that is<a name="line.568"></a>
+<span class="sourceLineNo">569</span>   *         going down or we already have queued an SCP for this server or SCP processing is<a name="line.569"></a>
+<span class="sourceLineNo">570</span>   *         currently disabled because we are in startup phase).<a name="line.570"></a>
+<span class="sourceLineNo">571</span>   */<a name="line.571"></a>
+<span class="sourceLineNo">572</span>  @VisibleForTesting // Redo test so we can make this protected.<a name="line.572"></a>
+<span class="sourceLineNo">573</span>  public synchronized long expireServer(final ServerName serverName) {<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    return expireServer(serverName, false);<a name="line.574"></a>
+<span class="sourceLineNo">575</span><a name="line.575"></a>
+<span class="sourceLineNo">576</span>  }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>  synchronized long expireServer(final ServerName serverName, boolean force) {<a name="line.578"></a>
+<span class="sourceLineNo">579</span>    // THIS server is going down... can't handle our own expiration.<a name="line.579"></a>
+<span class="sourceLineNo">580</span>    if (serverName.equals(master.getServerName())) {<a name="line.580"></a>
+<span class="sourceLineNo">581</span>      if (!(master.isAborted() || master.isStopped())) {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>        master.stop("We lost our znode?");<a name="line.582"></a>
+<span class="sourceLineNo">583</span>      }<a name="line.583"></a>
+<span class="sourceLineNo">584</span>      return Procedure.NO_PROC_ID;<a name="line.584"></a>
+<span class="sourceLineNo">585</span>    }<a name="line.585"></a>
+<span class="sourceLineNo">586</span>    if (this.deadservers.isDeadServer(serverName)) {<a name="line.586"></a>
+<span class="sourceLineNo">587</span>      LOG.warn("Expiration called on {} but already in DeadServer", serverName);<a name="line.587"></a>
+<span class="sourceLineNo">588</span>      return Procedure.NO_PROC_ID;<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    }<a name="line.589"></a>
+<span class="sourceLineNo">590</span>    moveFromOnlineToDeadServers(serverName);<a name="line.590"></a>
+<span class="sourceLineNo">591</span><a name="line.591"></a>
+<span class="sourceLineNo">592</span>    // If server is in draining mode, remove corresponding znode<a name="line.592"></a>
+<span class="sourceLineNo">593</span>    // In some tests, the mocked HM may not have ZK Instance, hence null check<a name="line.593"></a>
+<span class="sourceLineNo">594</span>    if (master.getZooKeeper() != null) {<a name="line.594"></a>
+<span class="sourceLineNo">595</span>      String drainingZnode = ZNodePaths<a name="line.595"></a>
+<span class="sourceLineNo">596</span>        .joinZNode(master.getZooKeeper().getZNodePaths().drainingZNode, serverName.getServerName());<a name="line.596"></a>
+<span class="sourceLineNo">597</span>      try {<a name="line.597"></a>
+<span class="sourceLineNo">598</span>        ZKUtil.deleteNodeFailSilent(master.getZooKeeper(), drainingZnode);<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      } catch (KeeperException e) {<a name="line.599"></a>
+<span class="sourceLineNo">600</span>        LOG.warn("Error deleting the draining znode for stopping server " + serverName.getServerName(), e);<a name="line.600"></a>
+<span class="sourceLineNo">601</span>      }<a name="line.601"></a>
+<span class="sourceLineNo">602</span>    }<a name="line.602"></a>
+<span class="sourceLineNo">603</span>    <a name="line.603"></a>
+<span class="sourceLineNo">604</span>    // If cluster is going down, yes, servers are going to be expiring; don't<a name="line.604"></a>
+<span class="sourceLineNo">605</span>    // process as a dead server<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    if (isClusterShutdown()) {<a name="line.606"></a>
+<span class="sourceLineNo">607</span>      LOG.info("Cluster shutdown set; " + serverName +<a name="line.607"></a>
+<span class="sourceLineNo">608</span>        " expired; onlineServers=" + this.onlineServers.size());<a name="line.608"></a>
+<span class="sourceLineNo">609</span>      if (this.onlineServers.isEmpty()) {<a name="line.609"></a>
+<span class="sourceLineNo">610</span>        master.stop("Cluster shutdown set; onlineServer=0");<a name="line.610"></a>
+<span class="sourceLineNo">611</span>      }<a name="line.611"></a>
+<span class="sourceLineNo">612</span>      return Procedure.NO_PROC_ID;<a name="line.612"></a>
+<span class="sourceLineNo">613</span>    }<a name="line.613"></a>
+<span class="sourceLineNo">614</span>    LOG.info("Processing expiration of " + serverName + " on " + this.master.getServerName());<a name="line.614"></a>
+<span class="sourceLineNo">615</span>    long pid = master.getAssignmentManager().submitServerCrash(serverName, true, force);<a name="line.615"></a>
+<span class="sourceLineNo">616</span>    // Tell our listeners that a server was removed<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    if (!this.listeners.isEmpty()) {<a name="line.617"></a>
+<span class="sourceLineNo">618</span>      this.listeners.stream().forEach(l -&gt; l.serverRemoved(serverName));<a name="line.618"></a>
+<span class="sourceLineNo">619</span>    }<a name="line.619"></a>
+<span class="sourceLineNo">620</span>    // trigger a persist of flushedSeqId<a name="line.620"></a>
+<span class="sourceLineNo">621</span>    if (flushedSeqIdFlusher != null) {<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      flushedSeqIdFlusher.triggerNow();<a name="line.622"></a>
+<span class="sourceLineNo">623</span>    }<a name="line.623"></a>
+<span class="sourceLineNo">624</span>    return pid;<a name="line.624"></a>
+<span class="sourceLineNo">625</span>  }<a name="line.625"></a>
+<span class="sourceLineNo">626</span><a name="line.626"></a>
+<span class="sourceLineNo">627</span>  /**<a name="line.627"></a>
+<span class="sourceLineNo">628</span>   * Called when server has expired.<a name="line.628"></a>
+<span class="sourceLineNo">629</span>   */<a name="line.629"></a>
+<span class="sourceLineNo">630</span>  // Locking in this class needs cleanup.<a name="line.630"></a>
+<span class="sourceLineNo">631</span>  @VisibleForTesting<a name="line.631"></a>
+<span class="sourceLineNo">632</span>  public synchronized void moveFromOnlineToDeadServers(final ServerName sn) {<a name="line.632"></a>
+<span class="sourceLineNo">633</span>    synchronized (this.onlineServers) {<a name="line.633"></a>
+<span class="sourceLineNo">634</span>      boolean online = this.onlineServers.containsKey(sn);<a name="line.634"></a>
+<span class="sourceLineNo">635</span>      if (online) {<a name="line.635"></a>
+<span class="sourceLineNo">636</span>        // Remove the server from the known servers lists and update load info BUT<a name="line.636"></a>
+<span class="sourceLineNo">637</span>        // add to deadservers first; do this so it'll show in dead servers list if<a name="line.637"></a>
+<span class="sourceLineNo">638</span>        // not in online servers list.<a name="line.638"></a>
+<span class="sourceLineNo">639</span>        this.deadservers.putIfAbsent(sn);<a name="line.639"></a>
+<span class="sourceLineNo">640</span>        this.onlineServers.remove(sn);<a name="line.640"></a>
+<span class="sourceLineNo">641</span>        onlineServers.notifyAll();<a name="line.641"></a>
+<span class="sourceLineNo">642</span>      } else {<a name="line.642"></a>
+<span class="sourceLineNo">643</span>        // If not online, that is odd but may happen if 'Unknown Servers' -- where meta<a name="line.643"></a>
+<span class="sourceLineNo">644</span>        // has references to servers not online nor in dead servers list. If<a name="line.644"></a>
+<span class="sourceLineNo">645</span>        // 'Unknown Server', don't add to DeadServers else will be there for ever.<a name="line.645"></a>
+<span class="sourceLineNo">646</span>        LOG.trace("Expiration of {} but server not online", sn);<a name="line.646"></a>
+<span class="sourceLineNo">647</span>      }<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    }<a name="line.648"></a>
+<span class="sourceLineNo">649</span>  }<a name="line.649"></a>
+<span class="sourceLineNo">650</span><a name="line.650"></a>
+<span class="sourceLineNo">651</span>  /*<a name="line.651"></a>
+<span class="sourceLineNo">652</span>   * Remove the server from the drain list.<a name="line.652"></a>
+<span class="sourceLineNo">653</span>   */<a name="line.653"></a>
+<span class="sourceLineNo">654</span>  public synchronized boolean removeServerFromDrainList(final ServerName sn) {<a name="line.654"></a>
+<span class="sourceLineNo">655</span>    // Warn if the server (sn) is not online.  ServerName is of the form:<a name="line.655"></a>
+<span class="sourceLineNo">656</span>    // &lt;hostname&gt; , &lt;port&gt; , &lt;startcode&gt;<a name="line.656"></a>
+<span class="sourceLineNo">657</span><a name="line.657"></a>
+<span class="sourceLineNo">658</span>    if (!this.isServerOnline(sn)) {<a name="line.658"></a>
+<span class="sourceLineNo">659</span>      LOG.warn("Server " + sn + " is not currently online. " +<a name="line.659"></a>
+<span class="sourceLineNo">660</span>               "Removing from draining list anyway, as requested.");<a name="line.660"></a>
+<span class="sourceLineNo">661</span>    }<a name="line.661"></a>
+<span class="sourceLineNo">662</span>    // Remove the server from the draining servers lists.<a name="line.662"></a>
+<span class="sourceLineNo">663</span>    return this.drainingServers.remove(sn);<a name="line.663"></a>
+<span class="sourceLineNo">664</span>  }<a name="line.664"></a>
+<span class="sourceLineNo">665</span><a name="line.665"></a>
+<span class="sourceLineNo">666</span>  /**<a name="line.666"></a>
+<span class="sourceLineNo">667</span>   * Add the server to the drain list.<a name="line.667"></a>
+<span class="sourceLineNo">668</span>   * @param sn<a name="line.668"></a>
+<span class="sourceLineNo">669</span>   * @return True if the server is added or the server is already on the drain list.<a name="line.669"></a>
+<span class="sourceLineNo">670</span>   */<a name="line.670"></a>
+<span class="sourceLineNo">671</span>  public synchronized boolean addServerToDrainList(final ServerName sn) {<a name="line.671"></a>
+<span class="sourceLineNo">672</span>    // Warn if the server (sn) is not online.  ServerName is of the form:<a name="line.672"></a>
+<span class="sourceLineNo">673</span>    // &lt;hostname&gt; , &lt;port&gt; , &lt;startcode&gt;<a name="line.673"></a>
+<span class="sourceLineNo">674</span><a name="line.674"></a>
+<span class="sourceLineNo">675</span>    if (!this.isServerOnline(sn)) {<a name="line.675"></a>
+<span class="sourceLineNo">676</span>      LOG.warn("Server " + sn + " is not currently online. " +<a name="line.676"></a>
+<span class="sourceLineNo">677</span>               "Ignoring request to add it to draining list.");<a name="line.677"></a>
+<span class="sourceLineNo">678</span>      return false;<a name="line.678"></a>
+<span class="sourceLineNo">679</span>    }<a name="line.679"></a>
+<span class="sourceLineNo">680</span>    // Add the server to the draining servers lists, if it's not already in<a name="line.680"></a>
+<span class="sourceLineNo">681</span>    // it.<a name="line.681"></a>
+<span class="sourceLineNo">682</span>    if (this.drainingServers.contains(sn)) {<a name="line.682"></a>
+<span class="sourceLineNo">683</span>      LOG.warn("Server " + sn + " is already in the draining server list." +<a name="line.683"></a>
+<span class="sourceLineNo">684</span>               "Ignoring request to add it again.");<a name="line.684"></a>
+<span class="sourceLineNo">685</span>      return true;<a name="line.685"></a>
+<span class="sourceLineNo">686</span>    }<a name="line.686"></a>
+<span class="sourceLineNo">687</span>    LOG.info("Server " + sn + " added to draining server list.");<a name="line.687"></a>
+<span class="sourceLineNo">688</span>    return this.drainingServers.add(sn);<a name="line.688"></a>
+<span class="sourceLineNo">689</span>  }<a name="line.689"></a>
+<span class="sourceLineNo">690</span><a name="line.690"></a>
+<span class="sourceLineNo">691</span>  /**<a name="line.691"></a>
+<span class="sourceLineNo">692</span>   * Contacts a region server and waits up to timeout ms<a name="line.692"></a>
+<span class="sourceLineNo">693</span>   * to close the region.  This bypasses the active hmaster.<a name="line.693"></a>
+<span class="sourceLineNo">694</span>   * Pass -1 as timeout if you do not want to wait on result.<a name="line.694"></a>
+<span class="sourceLineNo">695</span>   */<a name="line.695"></a>
+<span class="sourceLineNo">696</span>  public static void closeRegionSilentlyAndWait(AsyncClusterConnection connection,<a name="line.696"></a>
+<span class="sourceLineNo">697</span>      ServerName server, RegionInfo region, long timeout) throws IOException, InterruptedException {<a name="line.697"></a>
+<span class="sourceLineNo">698</span>    AsyncRegionServerAdmin admin = connection.getRegionServerAdmin(server);<a name="line.698"></a>
+<span class="sourceLineNo">699</span>    try {<a name="line.699"></a>
+<span class="sourceLineNo">700</span>      FutureUtils.get(<a name="line.700"></a>
+<span class="sourceLineNo">701</span>        admin.closeRegion(ProtobufUtil.buildCloseRegionRequest(server, region.getRegionName())));<a name="line.701"></a>
+<span class="sourceLineNo">702</span>    } catch (IOException e) {<a name="line.702"></a>
+<span class="sourceLineNo">703</span>      LOG.warn("Exception when closing region: " + region.getRegionNameAsString(), e);<a name="line.703"></a>
+<span class="sourceLineNo">704</span>    }<a name="line.704"></a>
+<span class="sourceLineNo">705</span>    if (timeout &lt; 0) {<a name="line.705"></a>
+<span class="sourceLineNo">706</span>      return;<a name="line.706"></a>
+<span class="sourceLineNo">707</span>    }<a name="line.707"></a>
+<span class="sourceLineNo">708</span>    long expiration = timeout + System.currentTimeMillis();<a name="line.708"></a>
+<span class="sourceLineNo">709</span>    while (System.currentTimeMillis() &lt; expiration) {<a name="line.709"></a>
+<span class="sourceLineNo">710</span>      try {<a name="line.710"></a>
+<span class="sourceLineNo">711</span>        RegionInfo rsRegion = ProtobufUtil.toRegionInfo(FutureUtils<a name="line.711"></a>
+<span class="sourceLineNo">712</span>          .get(<a name="line.712"></a>
+<span class="sourceLineNo">713</span>            admin.getRegionInfo(RequestConverter.buildGetRegionInfoRequest(region.getRegionName())))<a name="line.713"></a>
+<span class="sourceLineNo">714</span>          .getRegionInfo());<a name="line.714"></a>
+<span class="sourceLineNo">715</span>        if (rsRegion == null) {<a name="line.715"></a>
+<span class="sourceLineNo">716</span>          return;<a name="line.716"></a>
+<span class="sourceLineNo">717</span>        }<a name="line.717"></a>
+<span class="sourceLineNo">718</span>      } catch (IOException ioe) {<a name="line.718"></a>
+<span class="sourceLineNo">719</span>        if (ioe instanceof NotServingRegionException ||<a name="line.719"></a>
+<span class="sourceLineNo">720</span>          (ioe instanceof RemoteWithExtrasException &amp;&amp;<a name="line.720"></a>
+<span class="sourceLineNo">721</span>            ((RemoteWithExtrasException)ioe).unwrapRemoteException()<a name="line.721"></a>
+<span class="sourceLineNo">722</span>              instanceof NotServingRegionException)) {<a name="line.722"></a>
+<span class="sourceLineNo">723</span>          // no need to retry again<a name="line.723"></a>
+<span class="sourceLineNo">724</span>          return;<a name="line.724"></a>
+<span class="sourceLineNo">725</span>        }<a name="line.725"></a>
+<span class="sourceLineNo">726</span>        LOG.warn("Exception when retrieving regioninfo from: " + region.getRegionNameAsString(),<a name="line.726"></a>
+<span class="sourceLineNo">727</span>          ioe);<a name="line.727"></a>
+<span class="sourceLineNo">728</span>      }<a name="line.728"></a>
+<span class="sourceLineNo">729</span>      Thread.sleep(1000);<a name="line.729"></a>
+<span class="sourceLineNo">730</span>    }<a name="line.730"></a>
+<span class="sourceLineNo">731</span>    throw new IOException("Region " + region + " failed to close within" + " timeout " + timeout);<a name="line.731"></a>
+<span class="sourceLineNo">732</span>  }<a name="line.732"></a>
+<span class="sourceLineNo">733</span><a name="line.733"></a>
+<span class="sourceLineNo">734</span>  /**<a name="line.734"></a>
+<span class="sourceLineNo">735</span>   * Calculate min necessary to start. This is not an absolute. It is just<a name="line.735"></a>
+<span class="sourceLineNo">736</span>   * a friction that will cause us hang around a bit longer waiting on<a name="line.736"></a>
+<span class="sourceLineNo">737</span>   * RegionServers to check-in.<a name="line.737"></a>
+<span class="sourceLineNo">738</span>   */<a name="line.738"></a>
+<span class="sourceLineNo">739</span>  private int getMinToStart() {<a name="line.739"></a>
+<span class="sourceLineNo">740</span>    if (master.isInMaintenanceMode()) {<a name="line.740"></a>
+<span class="sourceLineNo">741</span>      // If in maintenance mode, then master hosting meta will be the only server available<a name="line.741"></a>
+<span class="sourceLineNo">742</span>      return 1;<a name="line.742"></a>
+<span class="sourceLineNo">743</span>    }<a name="line.743"></a>
+<span class="sourceLineNo">744</span><a name="line.744"></a>
+<span class="sourceLineNo">745</span>    int minimumRequired = 1;<a name="line.745"></a>
+<span class="sourceLineNo">746</span>    if (LoadBalancer.isTablesOnMaster(master.getConfiguration()) &amp;&amp;<a name="line.746"></a>
+<span class="sourceLineNo">747</span>        LoadBalancer.isSystemTablesOnlyOnMaster(master.getConfiguration())) {<a name="line.747"></a>
+<span class="sourceLineNo">748</span>      // If Master is carrying regions it will show up as a 'server', but is not handling user-<a name="line.748"></a>
+<span class="sourceLineNo">749</span>      // space regions, so we need a second server.<a name="line.749"></a>
+<span class="sourceLineNo">750</span>      minimumRequired = 2;<a name="line.750"></a>
+<span class="sourceLineNo">751</span>    }<a name="line.751"></a>
+<span class="sourceLineNo">752</span><a name="line.752"></a>
+<span class="sourceLineNo">753</span>    int minToStart = this.master.getConfiguration().getInt(WAIT_ON_REGIONSERVERS_MINTOSTART, -1);<a name="line.753"></a>
+<span class="sourceLineNo">754</span>    // Ensure we are never less than minimumRequired else stuff won't work.<a name="line.754"></a>
+<span class="sourceLineNo">755</span>    return Math.max(minToStart, minimumRequired);<a name="line.755"></a>
+<span class="sourceLineNo">756</span>  }<a name="line.756"></a>
+<span class="sourceLineNo">757</span><a name="line.757"></a>
+<span class="sourceLineNo">758</span>  /**<a name="line.758"></a>
+<span class="sourceLineNo">759</span>   * Wait for the region servers to report in.<a name="line.759"></a>
+<span class="sourceLineNo">760</span>   * We will wait until one of this condition is met:<a name="line.760"></a>
+<span class="sourceLineNo">761</span>   *  - the master is stopped<a name="line.761"></a>
+<span class="sourceLineNo">762</span>   *  - the 'hbase.master.wait.on.regionservers.maxtostart' number of<a name="line.762"></a>
+<span class="sourceLineNo">763</span>   *    region servers is reached<a name="line.763"></a>
+<span class="sourceLineNo">764</span>   *  - the 'hbase.master.wait.on.regionservers.mintostart' is reached AND<a name="line.764"></a>
+<span class="sourceLineNo">765</span>   *   there have been no new region server in for<a name="line.765"></a>
+<span class="sourceLineNo">766</span>   *      'hbase.master.wait.on.regionservers.interval' time AND<a name="line.766"></a>
+<span class="sourceLineNo">767</span>   *   the 'hbase.master.wait.on.regionservers.timeout' is reached<a name="line.767"></a>
+<span class="sourceLineNo">768</span>   *<a name="line.768"></a>
+<span class="sourceLineNo">769</span>   * @throws InterruptedException<a name="line.769"></a>
+<span class="sourceLineNo">770</span>   */<a name="line.770"></a>
+<span class="sourceLineNo">771</span>  public void waitForRegionServers(MonitoredTask status) throws InterruptedException {<a name="line.771"></a>
+<span class="sourceLineNo">772</span>    final long interval = this.master.getConfiguration().<a name="line.772"></a>
+<span class="sourceLineNo">773</span>        getLong(WAIT_ON_REGIONSERVERS_INTERVAL, 1500);<a name="line.773"></a>
+<span class="sourceLineNo">774</span>    final long timeout = this.master.getConfiguration().<a name="line.774"></a>
+<span class="sourceLineNo">775</span>        getLong(WAIT_ON_REGIONSERVERS_TIMEOUT, 4500);<a name="line.775"></a>
+<span class="sourceLineNo">776</span>    // Min is not an absolute; just a friction making us wait longer on server checkin.<a name="line.776"></a>
+<span class="sourceLineNo">777</span>    int minToStart = getMinToStart();<a name="line.777"></a>
+<span class="sourceLineNo">778</span>    int maxToStart = this.master.getConfiguration().<a name="line.778"></a>
+<span class="sourceLineNo">779</span>        getInt(WAIT_ON_REGIONSERVERS_MAXTOSTART, Integer.MAX_VALUE);<a name="line.779"></a>
+<span class="sourceLineNo">780</span>    if (maxToStart &lt; minToStart) {<a name="line.780"></a>
+<span class="sourceLineNo">781</span>      LOG.warn(String.format("The value of '%s' (%d) is set less than '%s' (%d), ignoring.",<a name="line.781"></a>
+<span class="sourceLineNo">782</span>          WAIT_ON_REGIONSERVERS_MAXTOSTART, maxToStart,<a name="line.782"></a>
+<span class="sourceLineNo">783</span>          WAIT_ON_REGIONSERVERS_MINTOSTART, minToStart));<a name="line.783"></a>
+<span class="sourceLineNo">784</span>      maxToStart = Integer.MAX_VALUE;<a name="line.784"></a>
+<span class="sourceLineNo">785</span>    }<a name="line.785"></a>
+<span class="sourceLineNo">786</span><a name="line.786"></a>
+<span class="sourceLineNo">787</span>    long now =  System.currentTimeMillis();<a name="line.787"></a>
+<span class="sourceLineNo">788</span>    final long startTime = now;<a name="line.788"></a>
+<span class="sourceLineNo">789</span>    long slept = 0;<a name="line.789"></a>
+<span class="sourceLineNo">790</span>    long lastLogTime = 0;<a name="line.790"></a>
+<span class="sourceLineNo">791</span>    long lastCountChange = startTime;<a name="line.791"></a>
+<span class="sourceLineNo">792</span>    int count = countOfRegionServers();<a name="line.792"></a>
+<span class="sourceLineNo">793</span>    int oldCount = 0;<a name="line.793"></a>
+<span class="sourceLineNo">794</span>    // This while test is a little hard to read. We try to comment it in below but in essence:<a name="line.794"></a>
+<span class="sourceLineNo">795</span>    // Wait if Master is not stopped and the number of regionservers that have checked-in is<a name="line.795"></a>
+<span class="sourceLineNo">796</span>    // less than the maxToStart. Both of these conditions will be true near universally.<a name="line.796"></a>
+<span class="sourceLineNo">797</span>    // Next, we will keep cycling if ANY of the following three conditions are true:<a name="line.797"></a>
+<span class="sourceLineNo">798</span>    // 1. The time since a regionserver registered is &lt; interval (means servers are actively checking in).<a name="line.798"></a>
+<span class="sourceLineNo">799</span>    // 2. We are under the total timeout.<a name="line.799"></a>
+<span class="sourceLineNo">800</span>    // 3. The count of servers is &lt; minimum.<a name="line.800"></a>
+<span class="sourceLineNo">801</span>    for (ServerListener listener: this.listeners) {<a name="line.801"></a>
+<span class="sourceLineNo">802</span>      listener.waiting();<a name="line.802"></a>
+<span class="sourceLineNo">803</span>    }<a name="line.803"></a>
+<span class="sourceLineNo">804</span>    while (!this.master.isStopped() &amp;&amp; !isClusterShutdown() &amp;&amp; count &lt; maxToStart &amp;&amp;<a name="line.804"></a>
+<span class="sourceLineNo">805</span>        ((lastCountChange + interval) &gt; now || timeout &gt; slept || count &lt; minToStart)) {<a name="line.805"></a>
+<span class="sourceLineNo">806</span>      // Log some info at every interval time or if there is a change<a name="line.806"></a>
+<span class="sourceLineNo">807</span>      if (oldCount != count || lastLogTime + interval &lt; now) {<a name="line.807"></a>
+<span class="sourceLineNo">808</span>        lastLogTime = now;<a name="line.808"></a>
+<span class="sourceLineNo">809</span>        String msg =<a name="line.809"></a>
+<span class="sourceLineNo">810</span>            "Waiting on regionserver count=" + count + "; waited="+<a name="line.810"></a>
+<span class="sourceLineNo">811</span>                slept + "ms, expecting min=" + minToStart + " server(s), max="+ getStrForMax(maxToStart) +<a name="line.811"></a>
+<span class="sourceLineNo">812</span>                " server(s), " + "timeout=" + timeout + "ms, lastChange=" + (lastCountChange - now) + "ms";<a name="line.812"></a>
+<span class="sourceLineNo">813</span>        LOG.info(msg);<a name="line.813"></a>
+<span class="sourceLineNo">814</span>        status.setStatus(msg);<a name="line.814"></a>
+<span class="sourceLineNo">815</span>      }<a name="line.815"></a>
+<span class="sourceLineNo">816</span><a name="line.816"></a>
+<span class="sourceLineNo">817</span>      // We sleep for some time<a name="line.817"></a>
+<span class="sourceLineNo">818</span>      final long sleepTime = 50;<a name="line.818"></a>
+<span class="sourceLineNo">819</span>      Thread.sleep(sleepTime);<a name="line.819"></a>
+<span class="sourceLineNo">820</span>      now =  System.currentTimeMillis();<a name="line.820"></a>
+<span class="sourceLineNo">821</span>      slept = now - startTime;<a name="line.821"></a>
+<span class="sourceLineNo">822</span><a name="line.822"></a>
+<span class="sourceLineNo">823</span>      oldCount = count;<a name="line.823"></a>
+<span class="sourceLineNo">824</span>      count = countOfRegionServers();<a name="line.824"></a>
+<span class="sourceLineNo">825</span>      if (count != oldCount) {<a name="line.825"></a>
+<span class="sourceLineNo">826</span>        lastCountChange = now;<a name="line.826"></a>
+<span class="sourceLineNo">827</span>      }<a name="line.827"></a>
 <span class="sourceLineNo">828</span>    }<a name="line.828"></a>
-<span class="sourceLineNo">829</span>    LOG.info("Finished waiting on RegionServer count=" + count + "; waited=" + slept + "ms," +<a name="line.829"></a>
-<span class="sourceLineNo">830</span>        " expected min=" + minToStart + " server(s), max=" +  getStrForMax(maxToStart) + " server(s),"+<a name="line.830"></a>
-<span class="sourceLineNo">831</span>        " master is "+ (this.master.isStopped() ? "stopped.": "running"));<a name="line.831"></a>
-<span class="sourceLineNo">832</span>  }<a name="line.832"></a>
-<span class="sourceLineNo">833</span><a name="line.833"></a>
-<span class="sourceLineNo">834</span>  private String getStrForMax(final int max) {<a name="line.834"></a>
-<span class="sourceLineNo">835</span>    return max == Integer.MAX_VALUE? "NO_LIMIT": Integer.toString(max);<a name="line.835"></a>
+<span class="sourceLineNo">829</span>    // Did we exit the loop because cluster is going down?<a name="line.829"></a>
+<span class="sourceLineNo">830</span>    if (isClusterShutdown()) {<a name="line.830"></a>
+<span class="sourceLineNo">831</span>      this.master.stop("Cluster shutdown");<a name="line.831"></a>
+<span class="sourceLineNo">832</span>    }<a name="line.832"></a>
+<span class="sourceLineNo">833</span>    LOG.info("Finished waiting on RegionServer count=" + count + "; waited=" + slept + "ms," +<a name="line.833"></a>
+<span class="sourceLineNo">834</span>        " expected min=" + minToStart + " server(s), max=" +  getStrForMax(maxToStart) + " server(s),"+<a name="line.834"></a>
+<span class="sourceLineNo">835</span>        " master is "+ (this.master.isStopped() ? "stopped.": "running"));<a name="line.835"></a>
 <span class="sourceLineNo">836</span>  }<a name="line.836"></a>
 <span class="sourceLineNo">837</span><a name="line.837"></a>
-<span class="sourceLineNo">838</span>  /**<a name="line.838"></a>
-<span class="sourceLineNo">839</span>   * @return A copy of the internal list of online servers.<a name="line.839"></a>
-<span class="sourceLineNo">840</span>   */<a name="line.840"></a>
-<span class="sourceLineNo">841</span>  public List&lt;ServerName&gt; getOnlineServersList() {<a name="line.841"></a>
-<span class="sourceLineNo">842</span>    // TODO: optimize the load balancer call so we don't need to make a new list<a name="line.842"></a>
-<span class="sourceLineNo">843</span>    // TODO: FIX. THIS IS POPULAR CALL.<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    return new ArrayList&lt;&gt;(this.onlineServers.keySet());<a name="line.844"></a>
-<span class="sourceLineNo">845</span>  }<a name="line.845"></a>
-<span class="sourceLineNo">846</span><a name="line.846"></a>
-<span class="sourceLineNo">847</span>  /**<a name="line.847"></a>
-<span class="sourceLineNo">848</span>   * @param keys The target server name<a name="line.848"></a>
-<span class="sourceLineNo">849</span>   * @param idleServerPredicator Evaluates the server on the given load<a name="line.849"></a>
-<span class="sourceLineNo">850</span>   * @return A copy of the internal list of online servers matched by the predicator<a name="line.850"></a>
-<span class="sourceLineNo">851</span>   */<a name="line.851"></a>
-<span class="sourceLineNo">852</span>  public List&lt;ServerName&gt; getOnlineServersListWithPredicator(List&lt;ServerName&gt; keys,<a name="line.852"></a>
-<span class="sourceLineNo">853</span>    Predicate&lt;ServerMetrics&gt; idleServerPredicator) {<a name="line.853"></a>
-<span class="sourceLineNo">854</span>    List&lt;ServerName&gt; names = new ArrayList&lt;&gt;();<a name="line.854"></a>
-<span class="sourceLineNo">855</span>    if (keys != null &amp;&amp; idleServerPredicator != null) {<a name="line.855"></a>
-<span class="sourceLineNo">856</span>      keys.forEach(name -&gt; {<a name="line.856"></a>
-<span class="sourceLineNo">857</span>        ServerMetrics load = onlineServers.get(name);<a name="line.857"></a>
-<span class="sourceLineNo">858</span>        if (load != null) {<a name="line.858"></a>
-<span class="sourceLineNo">859</span>          if (idleServerPredicator.test(load)) {<a name="line.859"></a>
-<span class="sourceLineNo">860</span>            names.add(name);<a name="line.860"></a>
-<span class="sourceLineNo">861</span>          }<a name="line.861"></a>
-<span class="sourceLineNo">862</span>        }<a name="line.862"></a>
-<span class="sourceLineNo">863</span>      });<a name="line.863"></a>
-<span class="sourceLineNo">864</span>    }<a name="line.864"></a>
-<span class="sourceLineNo">865</span>    return names;<a name="line.865"></a>
-<span class="sourceLineNo">866</span>  }<a name="line.866"></a>
-<span class="sourceLineNo">867</span><a name="line.867"></a>
-<span class="sourceLineNo">868</span>  /**<a name="line.868"></a>
-<span class="sourceLineNo">869</span>   * @return A copy of the internal list of draining servers.<a name="line.869"></a>
-<span class="sourceLineNo">870</span>   */<a name="line.870"></a>
-<span class="sourceLineNo">871</span>  public List&lt;ServerName&gt; getDrainingServersList() {<a name="line.871"></a>
-<span class="sourceLineNo">872</span>    return new ArrayList&lt;&gt;(this.drainingServers);<a name="line.872"></a>
-<span class="sourceLineNo">873</span>  }<a name="line.873"></a>
-<span class="sourceLineNo">874</span><a name="line.874"></a>
-<span class="sourceLineNo">875</span>  public boolean isServerOnline(ServerName serverName) {<a name="line.875"></a>
-<span class="sourceLineNo">876</span>    return serverName != null &amp;&amp; onlineServers.containsKey(serverName);<a name="line.876"></a>
+<span class="sourceLineNo">838</span>  private String getStrForMax(final int max) {<a name="line.838"></a>
+<span class="sourceLineNo">839</span>    return max == Integer.MAX_VALUE? "NO_LIMIT": Integer.toString(max);<a name="line.839"></a>
+<span class="sourceLineNo">840</span>  }<a name="line.840"></a>
+<span class="sourceLineNo">841</span><a name="line.841"></a>
+<span class="sourceLineNo">842</span>  /**<a name="line.842"></a>
+<span class="sourceLineNo">843</span>   * @return A copy of the internal list of online servers.<a name="line.843"></a>
+<span class="sourceLineNo">844</span>   */<a name="line.844"></a>
+<span class="sourceLineNo">845</span>  public List&lt;ServerName&gt; getOnlineServersList() {<a name="line.845"></a>
+<span class="sourceLineNo">846</span>    // TODO: optimize the load balancer call so we don't need to make a new list<a name="line.846"></a>
+<span class="sourceLineNo">847</span>    // TODO: FIX. THIS IS POPULAR CALL.<a name="line.847"></a>
+<span class="sourceLineNo">848</span>    return new ArrayList&lt;&gt;(this.onlineServers.keySet());<a name="line.848"></a>
+<span class="sourceLineNo">849</span>  }<a name="line.849"></a>
+<span class="sourceLineNo">850</span><a name="line.850"></a>
+<span class="sourceLineNo">851</span>  /**<a name="line.851"></a>
+<span class="sourceLineNo">852</span>   * @param keys The target server name<a name="line.852"></a>
+<span class="sourceLineNo">853</span>   * @param idleServerPredicator Evaluates the server on the given load<a name="line.853"></a>
+<span class="sourceLineNo">854</span>   * @return A copy of the internal list of online servers matched by the predicator<a name="line.854"></a>
+<span class="sourceLineNo">855</span>   */<a name="line.855"></a>
+<span class="sourceLineNo">856</span>  public List&lt;ServerName&gt; getOnlineServersListWithPredicator(List&lt;ServerName&gt; keys,<a name="line.856"></a>
+<span class="sourceLineNo">857</span>    Predicate&lt;ServerMetrics&gt; idleServerPredicator) {<a name="line.857"></a>
+<span class="sourceLineNo">858</span>    List&lt;ServerName&gt; names = new ArrayList&lt;&gt;();<a name="line.858"></a>
+<span class="sourceLineNo">859</span>    if (keys != null &amp;&amp; idleServerPredicator != null) {<a name="line.859"></a>
+<span class="sourceLineNo">860</span>      keys.forEach(name -&gt; {<a name="line.860"></a>
+<span class="sourceLineNo">861</span>        ServerMetrics load = onlineServers.get(name);<a name="line.861"></a>
+<span class="sourceLineNo">862</span>        if (load != null) {<a name="line.862"></a>
+<span class="sourceLineNo">863</span>          if (idleServerPredicator.test(load)) {<a name="line.863"></a>
+<span class="sourceLineNo">864</span>            names.add(name);<a name="line.864"></a>
+<span class="sourceLineNo">865</span>          }<a name="line.865"></a>
+<span class="sourceLineNo">866</span>        }<a name="line.866"></a>
+<span class="sourceLineNo">867</span>      });<a name="line.867"></a>
+<span class="sourceLineNo">868</span>    }<a name="line.868"></a>
+<span class="sourceLineNo">869</span>    return names;<a name="line.869"></a>
+<span class="sourceLineNo">870</span>  }<a name="line.870"></a>
+<span class="sourceLineNo">871</span><a name="line.871"></a>
+<span class="sourceLineNo">872</span>  /**<a name="line.872"></a>
+<span class="sourceLineNo">873</span>   * @return A copy of the internal list of draining servers.<a name="line.873"></a>
+<span class="sourceLineNo">874</span>   */<a name="line.874"></a>
+<span class="sourceLineNo">875</span>  public List&lt;ServerName&gt; getDrainingServersList() {<a name="line.875"></a>
+<span class="sourceLineNo">876</span>    return new ArrayList&lt;&gt;(this.drainingServers);<a name="line.876"></a>
 <span class="sourceLineNo">877</span>  }<a name="line.877"></a>
 <span class="sourceLineNo">878</span><a name="line.878"></a>
-<span class="sourceLineNo">879</span>  public enum ServerLiveState {<a name="line.879"></a>
-<span class="sourceLineNo">880</span>    LIVE,<a name="line.880"></a>
-<span class="sourceLineNo">881</span>    DEAD,<a name="line.881"></a>
-<span class="sourceLineNo">882</span>    UNKNOWN<a name="line.882"></a>
-<span class="sourceLineNo">883</span>  }<a name="line.883"></a>
-<span class="sourceLineNo">884</span><a name="line.884"></a>
-<span class="sourceLineNo">885</span>  /**<a name="line.885"></a>
-<span class="sourceLineNo">886</span>   * @return whether the server is online, dead, or unknown.<a name="line.886"></a>
-<span class="sourceLineNo">887</span>   */<a name="line.887"></a>
-<span class="sourceLineNo">888</span>  public synchronized ServerLiveState isServerKnownAndOnline(ServerName serverName) {<a name="line.888"></a>
-<span class="sourceLineNo">889</span>    return onlineServers.containsKey(serverName) ? ServerLiveState.LIVE<a name="line.889"></a>
-<span class="sourceLineNo">890</span>      : (deadservers.isDeadServer(serverName) ? ServerLiveState.DEAD : ServerLiveState.UNKNOWN);<a name="line.890"></a>
-<span class="sourceLineNo">891</span>  }<a name="line.891"></a>
-<span class="sourceLineNo">892</span><a name="line.892"></a>
-<span class="sourceLineNo">893</span>  /**<a name="line.893"></a>
-<span class="sourceLineNo">894</span>   * Check if a server is known to be dead.  A server can be online,<a name="line.894"></a>
-<span class="sourceLineNo">895</span>   * or known to be dead, or unknown to this manager (i.e, not online,<a name="line.895"></a>
-<span class="sourceLineNo">896</span>   * not known to be dead either; it is simply not tracked by the<a name="line.896"></a>
-<span class="sourceLineNo">897</span>   * master any more, for example, a very old previous instance).<a name="line.897"></a>
-<span class="sourceLineNo">898</span>   */<a name="line.898"></a>
-<span class="sourceLineNo">899</span>  public synchronized boolean isServerDead(ServerName serverName) {<a name="line.899"></a>
-<span class="sourceLineNo">900</span>    return serverName == null || deadservers.isDeadServer(serverName);<a name="line.900"></a>
-<span class="sourceLineNo">901</span>  }<a name="line.901"></a>
-<span class="sourceLineNo">902</span><a name="line.902"></a>
-<span class="sourceLineNo">903</span>  public void shutdownCluster() {<a name="line.903"></a>
-<span class="sourceLineNo">904</span>    String statusStr = "Cluster shutdown requested of master=" + this.master.getServerName();<a name="line.904"></a>
-<span class="sourceLineNo">905</span>    LOG.info(statusStr);<a name="line.905"></a>
-<span class="sourceLineNo">906</span>    this.clusterShutdown.set(true);<a name="line.906"></a>
-<span class="sourceLineNo">907</span>    if (onlineServers.isEmpty()) {<a name="line.907"></a>
-<span class="sourceLineNo">908</span>      // we do not synchronize here so this may cause a double stop, but not a big deal<a name="line.908"></a>
-<span class="sourceLineNo">909</span>      master.stop("OnlineServer=0 right after cluster shutdown set");<a name="line.909"></a>
-<span class="sourceLineNo">910</span>    }<a name="line.910"></a>
-<span class="sourceLineNo">911</span>  }<a name="line.911"></a>
-<span class="sourceLineNo">912</span><a name="line.912"></a>
-<span class="sourceLineNo">913</span>  public boolean isClusterShutdown() {<a name="line.913"></a>
-<span class="sourceLineNo">914</span>    return this.clusterShutdown.get();<a name="line.914"></a>
+<span class="sourceLineNo">879</span>  public boolean isServerOnline(ServerName serverName) {<a name="line.879"></a>
+<span class="sourceLineNo">880</span>    return serverName != null &amp;&amp; onlineServers.containsKey(serverName);<a name="line.880"></a>
+<span class="sourceLineNo">881</span>  }<a name="line.881"></a>
+<span class="sourceLineNo">882</span><a name="line.882"></a>
+<span class="sourceLineNo">883</span>  public enum ServerLiveState {<a name="line.883"></a>
+<span class="sourceLineNo">884</span>    LIVE,<a name="line.884"></a>
+<span class="sourceLineNo">885</span>    DEAD,<a name="line.885"></a>
+<span class="sourceLineNo">886</span>    UNKNOWN<a name="line.886"></a>
+<span class="sourceLineNo">887</span>  }<a name="line.887"></a>
+<span class="sourceLineNo">888</span><a name="line.888"></a>
+<span class="sourceLineNo">889</span>  /**<a name="line.889"></a>
+<span class="sourceLineNo">890</span>   * @return whether the server is online, dead, or unknown.<a name="line.890"></a>
+<span class="sourceLineNo">891</span>   */<a name="line.891"></a>
+<span class="sourceLineNo">892</span>  public synchronized ServerLiveState isServerKnownAndOnline(ServerName serverName) {<a name="line.892"></a>
+<span class="sourceLineNo">893</span>    return onlineServers.containsKey(serverName) ? ServerLiveState.LIVE<a name="line.893"></a>
+<span class="sourceLineNo">894</span>      : (deadservers.isDeadServer(serverName) ? ServerLiveState.DEAD : ServerLiveState.UNKNOWN);<a name="line.894"></a>
+<span class="sourceLineNo">895</span>  }<a name="line.895"></a>
+<span class="sourceLineNo">896</span><a name="line.896"></a>
+<span class="sourceLineNo">897</span>  /**<a name="line.897"></a>
+<span class="sourceLineNo">898</span>   * Check if a server is known to be dead.  A server can be online,<a name="line.898"></a>
+<span class="sourceLineNo">899</span>   * or known to be dead, or unknown to this manager (i.e, not online,<a name="line.899"></a>
+<span class="sourceLineNo">900</span>   * not known to be dead either; it is simply not tracked by the<a name="line.900"></a>
+<span class="sourceLineNo">901</span>   * master any more, for example, a very old previous instance).<a name="line.901"></a>
+<span class="sourceLineNo">902</span>   */<a name="line.902"></a>
+<span class="sourceLineNo">903</span>  public synchronized boolean isServerDead(ServerName serverName) {<a name="line.903"></a>
+<span class="sourceLineNo">904</span>    return serverName == null || deadservers.isDeadServer(serverName);<a name="line.904"></a>
+<span class="sourceLineNo">905</span>  }<a name="line.905"></a>
+<span class="sourceLineNo">906</span><a name="line.906"></a>
+<span class="sourceLineNo">907</span>  public void shutdownCluster() {<a name="line.907"></a>
+<span class="sourceLineNo">908</span>    String statusStr = "Cluster shutdown requested of master=" + this.master.getServerName();<a name="line.908"></a>
+<span class="sourceLineNo">909</span>    LOG.info(statusStr);<a name="line.909"></a>
+<span class="sourceLineNo">910</span>    this.clusterShutdown.set(true);<a name="line.910"></a>
+<span class="sourceLineNo">911</span>    if (onlineServers.isEmpty()) {<a name="line.911"></a>
+<span class="sourceLineNo">912</span>      // we do not synchronize here so this may cause a double stop, but not a big deal<a name="line.912"></a>
+<span class="sourceLineNo">913</span>      master.stop("OnlineServer=0 right after cluster shutdown set");<a name="line.913"></a>
+<span class="sourceLineNo">914</span>    }<a name="line.914"></a>
 <span class="sourceLineNo">915</span>  }<a name="line.915"></a>
 <span class="sourceLineNo">916</span><a name="line.916"></a>
-<span class="sourceLineNo">917</span>  /**<a name="line.917"></a>
-<span class="sourceLineNo">918</span>   * start chore in ServerManager<a name="line.918"></a>
-<span class="sourceLineNo">919</span>   */<a name="line.919"></a>
-<span class="sourceLineNo">920</span>  public void startChore() {<a name="line.920"></a>
-<span class="sourceLineNo">921</span>    Configuration c = master.getConfiguration();<a name="line.921"></a>
-<span class="sourceLineNo">922</span>    if (persistFlushedSequenceId) {<a name="line.922"></a>
-<span class="sourceLineNo">923</span>      // when reach here, RegionStates should loaded, firstly, we call remove deleted regions<a name="line.923"></a>
-<span class="sourceLineNo">924</span>      removeDeletedRegionFromLoadedFlushedSequenceIds();<a name="line.924"></a>
-<span class="sourceLineNo">925</span>      int flushPeriod = c.getInt(FLUSHEDSEQUENCEID_FLUSHER_INTERVAL,<a name="line.925"></a>
-<span class="sourceLineNo">926</span>          FLUSHEDSEQUENCEID_FLUSHER_INTERVAL_DEFAULT);<a name="line.926"></a>
-<span class="sourceLineNo">927</span>      flushedSeqIdFlusher = new FlushedSequenceIdFlusher(<a name="line.927"></a>
-<span class="sourceLineNo">928</span>          "FlushedSequenceIdFlusher", flushPeriod);<a name="line.928"></a>
-<span class="sourceLineNo">929</span>      master.getChoreService().scheduleChore(flushedSeqIdFlusher);<a name="line.929"></a>
-<span class="sourceLineNo">930</span>    }<a name="line.930"></a>
-<span class="sourceLineNo">931</span>  }<a name="line.931"></a>
-<span class="sourceLineNo">932</span><a name="line.932"></a>
-<span class="sourceLineNo">933</span>  /**<a name="line.933"></a>
-<span class="sourceLineNo">934</span>   * Stop the ServerManager.<a name="line.934"></a>
-<span class="sourceLineNo">935</span>   */<a name="line.935"></a>
-<span class="sourceLineNo">936</span>  public void stop() {<a name="line.936"></a>
-<span class="sourceLineNo">937</span>    if (flushedSeqIdFlusher != null) {<a name="line.937"></a>
-<span class="sourceLineNo">938</span>      flushedSeqIdFlusher.cancel();<a name="line.938"></a>
-<span class="sourceLineNo">939</span>    }<a name="line.939"></a>
-<span class="sourceLineNo">940</span>    if (persistFlushedSequenceId) {<a name="line.940"></a>
-<span class="sourceLineNo">941</span>      try {<a name="line.941"></a>
-<span class="sourceLineNo">942</span>        persistRegionLastFlushedSequenceIds();<a name="line.942"></a>
-<span class="sourceLineNo">943</span>      } catch (IOException e) {<a name="line.943"></a>
-<span class="sourceLineNo">944</span>        LOG.warn("Failed to persist last flushed sequence id of regions"<a name="line.944"></a>
-<span class="sourceLineNo">945</span>            + " to file system", e);<a name="line.945"></a>
-<span class="sourceLineNo">946</span>      }<a name="line.946"></a>
-<span class="sourceLineNo">947</span>    }<a name="line.947"></a>
-<span class="sourceLineNo">948</span>  }<a name="line.948"></a>
-<span class="sourceLineNo">949</span><a name="line.949"></a>
-<span class="sourceLineNo">950</span>  /**<a name="line.950"></a>
-<span class="sourceLineNo">951</span>   * Creates a list of possible destinations for a region. It contains the online servers, but not<a name="line.951"></a>
-<span class="sourceLineNo">952</span>   *  the draining or dying servers.<a name="line.952"></a>
-<span class="sourceLineNo">953</span>   *  @param serversToExclude can be null if there is no server to exclude<a name="line.953"></a>
-<span class="sourceLineNo">954</span>   */<a name="line.954"></a>
-<span class="sourceLineNo">955</span>  public List&lt;ServerName&gt; createDestinationServersList(final List&lt;ServerName&gt; serversToExclude){<a name="line.955"></a>
-<span class="sourceLineNo">956</span>    final List&lt;ServerName&gt; destServers = getOnlineServersList();<a name="line.956"></a>
-<span class="sourceLineNo">957</span><a name="line.957"></a>
-<span class="sourceLineNo">958</span>    if (serversToExclude != null) {<a name="line.958"></a>
-<span class="sourceLineNo">959</span>      destServers.removeAll(serversToExclude);<a name="line.959"></a>
-<span class="sourceLineNo">960</span>    }<a name="line.960"></a>
+<span class="sourceLineNo">917</span>  public boolean isClusterShutdown() {<a name="line.917"></a>
+<span class="sourceLineNo">918</span>    return this.clusterShutdown.get();<a name="line.918"></a>
+<span class="sourceLineNo">919</span>  }<a name="line.919"></a>
+<span class="sourceLineNo">920</span><a name="line.920"></a>
+<span class="sourceLineNo">921</span>  /**<a name="line.921"></a>
+<span class="sourceLineNo">922</span>   * start chore in ServerManager<a name="line.922"></a>
+<span class="sourceLineNo">923</span>   */<a name="line.923"></a>
+<span class="sourceLineNo">924</span>  public void startChore() {<a name="line.924"></a>
+<span class="sourceLineNo">925</span>    Configuration c = master.getConfiguration();<a name="line.925"></a>
+<span class="sourceLineNo">926</span>    if (persistFlushedSequenceId) {<a name="line.926"></a>
+<span class="sourceLineNo">927</span>      // when reach here, RegionStates should loaded, firstly, we call remove deleted regions<a name="line.927"></a>
+<span class="sourceLineNo">928</span>      removeDeletedRegionFromLoadedFlushedSequenceIds();<a name="line.928"></a>
+<span class="sourceLineNo">929</span>      int flushPeriod = c.getInt(FLUSHEDSEQUENCEID_FLUSHER_INTERVAL,<a name="line.929"></a>
+<span class="sourceLineNo">930</span>          FLUSHEDSEQUENCEID_FLUSHER_INTERVAL_DEFAULT);<a name="line.930"></a>
+<span class="sourceLineNo">931</span>      flushedSeqIdFlusher = new FlushedSequenceIdFlusher(<a name="line.931"></a>
+<span class="sourceLineNo">932</span>          "FlushedSequenceIdFlusher", flushPeriod);<a name="line.932"></a>
+<span class="sourceLineNo">933</span>      master.getChoreService().scheduleChore(flushedSeqIdFlusher);<a name="line.933"></a>
+<span class="sourceLineNo">934</span>    }<a name="line.934"></a>
+<span class="sourceLineNo">935</span>  }<a name="line.935"></a>
+<span class="sourceLineNo">936</span><a name="line.936"></a>
+<span class="sourceLineNo">937</span>  /**<a name="line.937"></a>
+<span class="sourceLineNo">938</span>   * Stop the ServerManager.<a name="line.938"></a>
+<span class="sourceLineNo">939</span>   */<a name="line.939"></a>
+<span class="sourceLineNo">940</span>  public void stop() {<a name="line.940"></a>
+<span class="sourceLineNo">941</span>    if (flushedSeqIdFlusher != null) {<a name="line.941"></a>
+<span class="sourceLineNo">942</span>      flushedSeqIdFlusher.cancel();<a name="line.942"></a>
+<span class="sourceLineNo">943</span>    }<a name="line.943"></a>
+<span class="sourceLineNo">944</span>    if (persistFlushedSequenceId) {<a name="line.944"></a>
+<span class="sourceLineNo">945</span>      try {<a name="line.945"></a>
+<span class="sourceLineNo">946</span>        persistRegionLastFlushedSequenceIds();<a name="line.946"></a>
+<span class="sourceLineNo">947</span>      } catch (IOException e) {<a name="line.947"></a>
+<span class="sourceLineNo">948</span>        LOG.warn("Failed to persist last flushed sequence id of regions"<a name="line.948"></a>
+<span class="sourceLineNo">949</span>            + " to file system", e);<a name="line.949"></a>
+<span class="sourceLineNo">950</span>      }<a name="line.950"></a>
+<span class="sourceLineNo">951</span>    }<a name="line.951"></a>
+<span class="sourceLineNo">952</span>  }<a name="line.952"></a>
+<span class="sourceLineNo">953</span><a name="line.953"></a>
+<span class="sourceLineNo">954</span>  /**<a name="line.954"></a>
+<span class="sourceLineNo">955</span>   * Creates a list of possible destinations for a region. It contains the online servers, but not<a name="line.955"></a>
+<span class="sourceLineNo">956</span>   *  the draining or dying servers.<a name="line.956"></a>
+<span class="sourceLineNo">957</span>   *  @param serversToExclude can be null if there is no server to exclude<a name="line.957"></a>
+<span class="sourceLineNo">958</span>   */<a name="line.958"></a>
+<span class="sourceLineNo">959</span>  public List&lt;ServerName&gt; createDestinationServersList(final List&lt;ServerName&gt; serversToExclude){<a name="line.959"></a>
+<span class="sourceLineNo">960</span>    final List&lt;ServerName&gt; destServers = getOnlineServersList();<a name="line.960"></a>
 <span class="sourceLineNo">961</span><a name="line.961"></a>
-<span class="sourceLineNo">962</span>    // Loop through the draining server list and remove them from the server list<a name="line.962"></a>
-<span class="sourceLineNo">963</span>    final List&lt;ServerName&gt; drainingServersCopy = getDrainingServersList();<a name="line.963"></a>
-<span class="sourceLineNo">964</span>    destServers.removeAll(drainingServersCopy);<a name="line.964"></a>
+<span class="sourceLineNo">962</span>    if (serversToExclude != null) {<a name="line.962"></a>
+<span class="sourceLineNo">963</span>      destServers.removeAll(serversToExclude);<a name="line.963"></a>
+<span class="sourceLineNo">964</span>    }<a name="line.964"></a>
 <span class="sourceLineNo">965</span><a name="line.965"></a>
-<span class="sourceLineNo">966</span>    return destServers;<a name="line.966"></a>
-<span class="sourceLineNo">967</span>  }<a name="line.967"></a>
-<span class="sourceLineNo">968</span><a name="line.968"></a>
-<span class="sourceLineNo">969</span>  /**<a name="line.969"></a>
-<span class="sourceLineNo">970</span>   * Calls {@link #createDestinationServersList} without server to exclude.<a name="line.970"></a>
-<span class="sourceLineNo">971</span>   */<a name="line.971"></a>
-<span class="sourceLineNo">972</span>  public List&lt;ServerName&gt; createDestinationServersList(){<a name="line.972"></a>
-<span class="sourceLineNo">973</span>    return createDestinationServersList(null);<a name="line.973"></a>
-<span class="sourceLineNo">974</span>  }<a name="line.974"></a>
-<span class="sourceLineNo">975</span><a name="line.975"></a>
-<span class="sourceLineNo">976</span>  /**<a name="line.976"></a>
-<span class="sourceLineNo">977</span>   * To clear any dead server with same host name and port of any online server<a name="line.977"></a>
-<span class="sourceLineNo">978</span>   */<a name="line.978"></a>
-<span class="sourceLineNo">979</span>  void clearDeadServersWithSameHostNameAndPortOfOnlineServer() {<a name="line.979"></a>
-<span class="sourceLineNo">980</span>    for (ServerName serverName : getOnlineServersList()) {<a name="line.980"></a>
-<span class="sourceLineNo">981</span>      deadservers.cleanAllPreviousInstances(serverName);<a name="line.981"></a>
-<span class="sourceLineNo">982</span>    }<a name="line.982"></a>
-<span class="sourceLineNo">983</span>  }<a name="line.983"></a>
-<span class="sourceLineNo">984</span><a name="line.984"></a>
-<span class="sourceLineNo">985</span>  /**<a name="line.985"></a>
-<span class="sourceLineNo">986</span>   * Called by delete table and similar to notify the ServerManager that a region was removed.<a name="line.986"></a>
-<span class="sourceLineNo">987</span>   */<a name="line.987"></a>
-<span class="sourceLineNo">988</span>  public void removeRegion(final RegionInfo regionInfo) {<a name="line.988"></a>
-<span class="sourceLineNo">989</span>    final byte[] encodedName = regionInfo.getEncodedNameAsBytes();<a name="line.989"></a>
-<span class="sourceLineNo">990</span>    storeFlushedSequenceIdsByRegion.remove(encodedName);<a name="line.990"></a>
-<span class="sourceLineNo">991</span>    flushedSequenceIdByRegion.remove(encodedName);<a name="line.991"></a>
-<span class="sourceLineNo">992</span>  }<a name="line.992"></a>
-<span class="sourceLineNo">993</span><a name="line.993"></a>
-<span class="sourceLineNo">994</span>  @VisibleForTesting<a name="line.994"></a>
-<span class="sourceLineNo">995</span>  public boolean isRegionInServerManagerStates(final RegionInfo hri) {<a name="line.995"></a>
-<span class="sourceLineNo">996</span>    final byte[] encodedName = hri.getEncodedNameAsBytes();<a name="line.996"></a>
-<span class="sourceLineNo">997</span>    return (storeFlushedSequenceIdsByRegion.containsKey(encodedName)<a name="line.997"></a>
-<span class="sourceLineNo">998</span>        || flushedSequenceIdByRegion.containsKey(encodedName));<a name="line.998"></a>
-<span class="sourceLineNo">999</span>  }<a name="line.999"></a>
-<span class="sourceLineNo">1000</span><a name="line.1000"></a>
-<span class="sourceLineNo">1001</span>  /**<a name="line.1001"></a>
-<span class="sourceLineNo">1002</span>   * Called by delete table and similar to notify the ServerManager that a region was removed.<a name="line.1002"></a>
-<span class="sourceLineNo">1003</span>   */<a name="line.1003"></a>
-<span class="sourceLineNo">1004</span>  public void removeRegions(final List&lt;RegionInfo&gt; regions) {<a name="line.1004"></a>
-<span class="sourceLineNo">1005</span>    for (RegionInfo hri: regions) {<a name="line.1005"></a>
-<span class="sourceLineNo">1006</span>      removeRegion(hri);<a name="line.1006"></a>
-<span class="sourceLineNo">1007</span>    }<a name="line.1007"></a>
-<span class="sourceLineNo">1008</span>  }<a name="line.1008"></a>
-<span class="sourceLineNo">1009</span><a name="line.1009"></a>
-<span class="sourceLineNo">1010</span>  /**<a name="line.1010"></a>
-<span class="sourceLineNo">1011</span>   * May return 0 when server is not online.<a name="line.1011"></a>
-<span class="sourceLineNo">1012</span>   */<a name="line.1012"></a>
-<span class="sourceLineNo">1013</span>  public int getVersionNumber(ServerName serverName) {<a name="line.1013"></a>
-<span class="sourceLineNo">1014</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1014"></a>
-<span class="sourceLineNo">1015</span>    return serverMetrics != null ? serverMetrics.getVersionNumber() : 0;<a name="line.1015"></a>
-<span class="sourceLineNo">1016</span>  }<a name="line.1016"></a>
-<span class="sourceLineNo">1017</span><a name="line.1017"></a>
-<span class="sourceLineNo">1018</span>  /**<a name="line.1018"></a>
-<span class="sourceLineNo">1019</span>   * May return "0.0.0" when server is not online<a name="line.1019"></a>
-<span class="sourceLineNo">1020</span>   */<a name="line.1020"></a>
-<span class="sourceLineNo">1021</span>  public String getVersion(ServerName serverName) {<a name="line.1021"></a>
-<span class="sourceLineNo">1022</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1022"></a>
-<span class="sourceLineNo">1023</span>    return serverMetrics != null ? serverMetrics.getVersion() : "0.0.0";<a name="line.1023"></a>
-<span class="sourceLineNo">1024</span>  }<a name="line.1024"></a>
-<span class="sourceLineNo">1025</span><a name="line.1025"></a>
-<span class="sourceLineNo">1026</span>  public int getInfoPort(ServerName serverName) {<a name="line.1026"></a>
-<span class="sourceLineNo">1027</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1027"></a>
-<span class="sourceLineNo">1028</span>    return serverMetrics != null ? serverMetrics.getInfoServerPort() : 0;<a name="line.1028"></a>
-<span class="sourceLineNo">1029</span>  }<a name="line.1029"></a>
-<span class="sourceLineNo">1030</span><a name="line.1030"></a>
-<span class="sourceLineNo">1031</span>  /**<a name="line.1031"></a>
-<span class="sourceLineNo">1032</span>   * Persist last flushed sequence id of each region to HDFS<a name="line.1032"></a>
-<span class="sourceLineNo">1033</span>   * @throws IOException if persit to HDFS fails<a name="line.1033"></a>
-<span class="sourceLineNo">1034</span>   */<a name="line.1034"></a>
-<span class="sourceLineNo">1035</span>  private void persistRegionLastFlushedSequenceIds() throws IOException {<a name="line.1035"></a>
-<span class="sourceLineNo">1036</span>    if (isFlushSeqIdPersistInProgress) {<a name="line.1036"></a>
-<span class="sourceLineNo">1037</span>      return;<a name="line.1037"></a>
-<span class="sourceLineNo">1038</span>    }<a name="line.1038"></a>
-<span class="sourceLineNo">1039</span>    isFlushSeqIdPersistInProgress = true;<a name="line.1039"></a>
-<span class="sourceLineNo">1040</span>    try {<a name="line.1040"></a>
-<span class="sourceLineNo">1041</span>      Configuration conf = master.getConfiguration();<a name="line.1041"></a>
-<span class="sourceLineNo">1042</span>      Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.1042"></a>
-<span class="sourceLineNo">1043</span>      Path lastFlushedSeqIdPath = new Path(rootDir, LAST_FLUSHED_SEQ_ID_FILE);<a name="line.1043"></a>
-<span class="sourceLineNo">1044</span>      FileSystem fs = FileSystem.get(conf);<a name="line.1044"></a>
-<span class="sourceLineNo">1045</span>      if (fs.exists(lastFlushedSeqIdPath)) {<a name="line.1045"></a>
-<span class="sourceLineNo">1046</span>        LOG.info("Rewriting .lastflushedseqids file at: "<a name="line.1046"></a>
-<span class="sourceLineNo">1047</span>            + lastFlushedSeqIdPath);<a name="line.1047"></a>
-<span class="sourceLineNo">1048</span>        if (!fs.delete(lastFlushedSeqIdPath, false)) {<a name="line.1048"></a>
-<span class="sourceLineNo">1049</span>          throw new IOException("Unable to remove existing "<a name="line.1049"></a>
-<span class="sourceLineNo">1050</span>              + lastFlushedSeqIdPath);<a name="line.1050"></a>
-<span class="sourceLineNo">1051</span>        }<a name="line.1051"></a>
-<span class="sourceLineNo">1052</span>      } else {<a name="line.1052"></a>
-<span class="sourceLineNo">1053</span>        LOG.info("Writing .lastflushedseqids file at: " + lastFlushedSeqIdPath);<a name="line.1053"></a>
-<span class="sourceLineNo">1054</span>      }<a name="line.1054"></a>
-<span class="sourceLineNo">1055</span>      FSDataOutputStream out = fs.create(lastFlushedSeqIdPath);<a name="line.1055"></a>
-<span class="sourceLineNo">1056</span>      FlushedSequenceId.Builder flushedSequenceIdBuilder =<a name="line.1056"></a>
-<span class="sourceLineNo">1057</span>          FlushedSequenceId.newBuilder();<a name="line.1057"></a>
-<span class="sourceLineNo">1058</span>      try {<a name="line.1058"></a>
-<span class="sourceLineNo">1059</span>        for (Entry&lt;byte[], Long&gt; entry : flushedSequenceIdByRegion.entrySet()) {<a name="line.1059"></a>
-<span class="sourceLineNo">1060</span>          FlushedRegionSequenceId.Builder flushedRegionSequenceIdBuilder =<a name="line.1060"></a>
-<span class="sourceLineNo">1061</span>              FlushedRegionSequenceId.newBuilder();<a name="line.1061"></a>
-<span class="sourceLineNo">1062</span>          flushedRegionSequenceIdBuilder.setRegionEncodedName(<a name="line.1062"></a>
-<span class="sourceLineNo">1063</span>              ByteString.copyFrom(entry.getKey()));<a name="line.1063"></a>
-<span class="sourceLineNo">1064</span>          flushedRegionSequenceIdBuilder.setSeqId(entry.getValue());<a name="line.1064"></a>
-<span class="sourceLineNo">1065</span>          ConcurrentNavigableMap&lt;byte[], Long&gt; storeSeqIds =<a name="line.1065"></a>
-<span class="sourceLineNo">1066</span>              storeFlushedSequenceIdsByRegion.get(entry.getKey());<a name="line.1066"></a>
-<span class="sourceLineNo">1067</span>          if (storeSeqIds != null) {<a name="line.1067"></a>
-<span class="sourceLineNo">1068</span>            for (Entry&lt;byte[], Long&gt; store : storeSeqIds.entrySet()) {<a name="line.1068"></a>
-<span class="sourceLineNo">1069</span>              FlushedStoreSequenceId.Builder flushedStoreSequenceIdBuilder =<a name="line.1069"></a>
-<span class="sourceLineNo">1070</span>                  FlushedStoreSequenceId.newBuilder();<a name="line.1070"></a>
-<span class="sourceLineNo">1071</span>              flushedStoreSequenceIdBuilder.setFamily(ByteString.copyFrom(store.getKey()));<a name="line.1071"></a>
-<span class="sourceLineNo">1072</span>              flushedStoreSequenceIdBuilder.setSeqId(store.getValue());<a name="line.1072"></a>
-<span class="sourceLineNo">1073</span>              flushedRegionSequenceIdBuilder.addStores(flushedStoreSequenceIdBuilder);<a name="line.1073"></a>
-<span class="sourceLineNo">1074</span>            }<a name="line.1074"></a>
-<span class="sourceLineNo">1075</span>          }<a name="line.1075"></a>
-<span class="sourceLineNo">1076</span>          flushedSequenceIdBuilder.addRegionSequenceId(flushedRegionSequenceIdBuilder);<a name="line.1076"></a>
-<span class="sourceLineNo">1077</span>        }<a name="line.1077"></a>
-<span class="sourceLineNo">1078</span>        flushedSequenceIdBuilder.build().writeDelimitedTo(out);<a name="line.1078"></a>
-<span class="sourceLineNo">1079</span>      } finally {<a name="line.1079"></a>
-<span class="sourceLineNo">1080</span>        if (out != null) {<a name="line.1080"></a>
-<span class="sourceLineNo">1081</span>          out.close();<a name="line.1081"></a>
-<span class="sourceLineNo">1082</span>        }<a name="line.1082"></a>
-<span class="sourceLineNo">1083</span>      }<a name="line.1083"></a>
-<span class="sourceLineNo">1084</span>    } finally {<a name="line.1084"></a>
-<span class="sourceLineNo">1085</span>      isFlushSeqIdPersistInProgress = false;<a name="line.1085"></a>
-<span class="sourceLineNo">1086</span>    }<a name="line.1086"></a>
-<span class="sourceLineNo">1087</span>  }<a name="line.1087"></a>
-<span class="sourceLineNo">1088</span><a name="line.1088"></a>
-<span class="sourceLineNo">1089</span>  /**<a name="line.1089"></a>
-<span class="sourceLineNo">1090</span>   * Load last flushed sequence id of each region from HDFS, if persisted<a name="line.1090"></a>
-<span class="sourceLineNo">1091</span>   */<a name="line.1091"></a>
-<span class="sourceLineNo">1092</span>  public void loadLastFlushedSequenceIds() throws IOException {<a name="line.1092"></a>
-<span class="sourceLineNo">1093</span>    if (!persistFlushedSequenceId) {<a name="line.1093"></a>
-<span class="sourceLineNo">1094</span>      return;<a name="line.1094"></a>
-<span class="sourceLineNo">1095</span>    }<a name="line.1095"></a>
-<span class="sourceLineNo">1096</span>    Configuration conf = master.getConfiguration();<a name="line.1096"></a>
-<span class="sourceLineNo">1097</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.1097"></a>
-<span class="sourceLineNo">1098</span>    Path lastFlushedSeqIdPath = new Path(rootDir, LAST_FLUSHED_SEQ_ID_FILE);<a name="line.1098"></a>
-<span class="sourceLineNo">1099</span>    FileSystem fs = FileSystem.get(conf);<a name="line.1099"></a>
-<span class="sourceLineNo">1100</span>    if (!fs.exists(lastFlushedSeqIdPath)) {<a name="line.1100"></a>
-<span class="sourceLineNo">1101</span>      LOG.info("No .lastflushedseqids found at" + lastFlushedSeqIdPath<a name="line.1101"></a>
-<span class="sourceLineNo">1102</span>          + " will record last flushed sequence id"<a name="line.1102"></a>
-<span class="sourceLineNo">1103</span>          + " for regions by regionserver report all over again");<a name="line.1103"></a>
-<span class="sourceLineNo">1104</span>      return;<a name="line.1104"></a>
-<span class="sourceLineNo">1105</span>    } else {<a name="line.1105"></a>
-<span class="sourceLineNo">1106</span>      LOG.info("begin to load .lastflushedseqids at " + lastFlushedSeqIdPath);<a name="line.1106"></a>
-<span class="sourceLineNo">1107</span>    }<a name="line.1107"></a>
-<span class="sourceLineNo">1108</span>    FSDataInputStream in = fs.open(lastFlushedSeqIdPath);<a name="line.1108"></a>
-<span class="sourceLineNo">1109</span>    try {<a name="line.1109"></a>
-<span class="sourceLineNo">1110</span>      FlushedSequenceId flushedSequenceId =<a name="line.1110"></a>
-<span class="sourceLineNo">1111</span>          FlushedSequenceId.parseDelimitedFrom(in);<a name="line.1111"></a>
-<span class="sourceLineNo">1112</span>      if (flushedSequenceId == null) {<a name="line.1112"></a>
-<span class="sourceLineNo">1113</span>        LOG.info(".lastflushedseqids found at {} is empty", lastFlushedSeqIdPath);<a name="line.1113"></a>
-<span class="sourceLineNo">1114</span>        return;<a name="line.1114"></a>
-<span class="sourceLineNo">1115</span>      }<a name="line.1115"></a>
-<span class="sourceLineNo">1116</span>      for (FlushedRegionSequenceId flushedRegionSequenceId : flushedSequenceId<a name="line.1116"></a>
-<span class="sourceLineNo">1117</span>          .getRegionSequenceIdList()) {<a name="line.1117"></a>
-<span class="sourceLineNo">1118</span>        byte[] encodedRegionName = flushedRegionSequenceId<a name="line.1118"></a>
-<span class="sourceLineNo">1119</span>            .getRegionEncodedName().toByteArray();<a name="line.1119"></a>
-<span class="sourceLineNo">1120</span>        flushedSequenceIdByRegion<a name="line.1120"></a>
-<span class="sourceLineNo">1121</span>            .putIfAbsent(encodedRegionName, flushedRegionSequenceId.getSeqId());<a name="line.1121"></a>
-<span class="sourceLineNo">1122</span>        if (flushedRegionSequenceId.getStoresList() != null<a name="line.1122"></a>
-<span class="sourceLineNo">1123</span>            &amp;&amp; flushedRegionSequenceId.getStoresList().size() != 0) {<a name="line.1123"></a>
-<span class="sourceLineNo">1124</span>          ConcurrentNavigableMap&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.1124"></a>
-<span class="sourceLineNo">1125</span>              computeIfAbsent(storeFlushedSequenceIdsByRegion, encodedRegionName,<a name="line.1125"></a>
-<span class="sourceLineNo">1126</span>                () -&gt; new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR));<a name="line.1126"></a>
-<span class="sourceLineNo">1127</span>          for (FlushedStoreSequenceId flushedStoreSequenceId : flushedRegionSequenceId<a name="line.1127"></a>
-<span class="sourceLineNo">1128</span>              .getStoresList()) {<a name="line.1128"></a>
-<span class="sourceLineNo">1129</span>            storeFlushedSequenceId<a name="line.1129"></a>
-<span class="sourceLineNo">1130</span>                .put(flushedStoreSequenceId.getFamily().toByteArray(),<a name="line.1130"></a>
-<span class="sourceLineNo">1131</span>                    flushedStoreSequenceId.getSeqId());<a name="line.1131"></a>
-<span class="sourceLineNo">1132</span>          }<a name="line.1132"></a>
-<span class="sourceLineNo">1133</span>        }<a name="line.1133"></a>
-<span class="sourceLineNo">1134</span>      }<a name="line.1134"></a>
-<span class="sourceLineNo">1135</span>    } finally {<a name="line.1135"></a>
-<span class="sourceLineNo">1136</span>      in.close();<a name="line.1136"></a>
-<span class="sourceLineNo">1137</span>    }<a name="line.1137"></a>
-<span class="sourceLineNo">1138</span>  }<a name="line.1138"></a>
-<span class="sourceLineNo">1139</span><a name="line.1139"></a>
-<span class="sourceLineNo">1140</span>  /**<a name="line.1140"></a>
-<span class="sourceLineNo">1141</span>   * Regions may have been removed between latest persist of FlushedSequenceIds<a name="line.1141"></a>
-<span class="sourceLineNo">1142</span>   * and master abort. So after loading FlushedSequenceIds from file, and after<a name="line.1142"></a>
-<span class="sourceLineNo">1143</span>   * meta loaded, we need to remove the deleted region according to RegionStates.<a name="line.1143"></a>
-<span class="sourceLineNo">1144</span>   */<a name="line.1144"></a>
-<span class="sourceLineNo">1145</span>  public void removeDeletedRegionFromLoadedFlushedSequenceIds() {<a name="line.1145"></a>
-<span class="sourceLineNo">1146</span>    RegionStates regionStates = master.getAssignmentManager().getRegionStates();<a name="line.1146"></a>
-<span class="sourceLineNo">1147</span>    Iterator&lt;byte[]&gt; it = flushedSequenceIdByRegion.keySet().iterator();<a name="line.1147"></a>
-<span class="sourceLineNo">1148</span>    while(it.hasNext()) {<a name="line.1148"></a>
-<span class="sourceLineNo">1149</span>      byte[] regionEncodedName = it.next();<a name="line.1149"></a>
-<span class="sourceLineNo">1150</span>      if (regionStates.getRegionState(Bytes.toStringBinary(regionEncodedName)) == null) {<a name="line.1150"></a>
-<span class="sourceLineNo">1151</span>        it.remove();<a name="line.1151"></a>
-<span class="sourceLineNo">1152</span>        storeFlushedSequenceIdsByRegion.remove(regionEncodedName);<a name="line.1152"></a>
-<span class="sourceLineNo">1153</span>      }<a name="line.1153"></a>
-<span class="sourceLineNo">1154</span>    }<a name="line.1154"></a>
-<span class="sourceLineNo">1155</span>  }<a name="line.1155"></a>
-<span class="sourceLineNo">1156</span><a name="line.1156"></a>
-<span class="sourceLineNo">1157</span>  private class FlushedSequenceIdFlusher extends ScheduledChore {<a name="line.1157"></a>
-<span class="sourceLineNo">1158</span><a name="line.1158"></a>
-<span class="sourceLineNo">1159</span>    public FlushedSequenceIdFlusher(String name, int p) {<a name="line.1159"></a>
-<span class="sourceLineNo">1160</span>      super(name, master, p, 60 * 1000); //delay one minute before first execute<a name="line.1160"></a>
-<span class="sourceLineNo">1161</span>    }<a name="line.1161"></a>
+<span class="sourceLineNo">966</span>    // Loop through the draining server list and remove them from the server list<a name="line.966"></a>
+<span class="sourceLineNo">967</span>    final List&lt;ServerName&gt; drainingServersCopy = getDrainingServersList();<a name="line.967"></a>
+<span class="sourceLineNo">968</span>    destServers.removeAll(drainingServersCopy);<a name="line.968"></a>
+<span class="sourceLineNo">969</span><a name="line.969"></a>
+<span class="sourceLineNo">970</span>    return destServers;<a name="line.970"></a>
+<span class="sourceLineNo">971</span>  }<a name="line.971"></a>
+<span class="sourceLineNo">972</span><a name="line.972"></a>
+<span class="sourceLineNo">973</span>  /**<a name="line.973"></a>
+<span class="sourceLineNo">974</span>   * Calls {@link #createDestinationServersList} without server to exclude.<a name="line.974"></a>
+<span class="sourceLineNo">975</span>   */<a name="line.975"></a>
+<span class="sourceLineNo">976</span>  public List&lt;ServerName&gt; createDestinationServersList(){<a name="line.976"></a>
+<span class="sourceLineNo">977</span>    return createDestinationServersList(null);<a name="line.977"></a>
+<span class="sourceLineNo">978</span>  }<a name="line.978"></a>
+<span class="sourceLineNo">979</span><a name="line.979"></a>
+<span class="sourceLineNo">980</span>  /**<a name="line.980"></a>
+<span class="sourceLineNo">981</span>   * To clear any dead server with same host name and port of any online server<a name="line.981"></a>
+<span class="sourceLineNo">982</span>   */<a name="line.982"></a>
+<span class="sourceLineNo">983</span>  void clearDeadServersWithSameHostNameAndPortOfOnlineServer() {<a name="line.983"></a>
+<span class="sourceLineNo">984</span>    for (ServerName serverName : getOnlineServersList()) {<a name="line.984"></a>
+<span class="sourceLineNo">985</span>      deadservers.cleanAllPreviousInstances(serverName);<a name="line.985"></a>
+<span class="sourceLineNo">986</span>    }<a name="line.986"></a>
+<span class="sourceLineNo">987</span>  }<a name="line.987"></a>
+<span class="sourceLineNo">988</span><a name="line.988"></a>
+<span class="sourceLineNo">989</span>  /**<a name="line.989"></a>
+<span class="sourceLineNo">990</span>   * Called by delete table and similar to notify the ServerManager that a region was removed.<a name="line.990"></a>
+<span class="sourceLineNo">991</span>   */<a name="line.991"></a>
+<span class="sourceLineNo">992</span>  public void removeRegion(final RegionInfo regionInfo) {<a name="line.992"></a>
+<span class="sourceLineNo">993</span>    final byte[] encodedName = regionInfo.getEncodedNameAsBytes();<a name="line.993"></a>
+<span class="sourceLineNo">994</span>    storeFlushedSequenceIdsByRegion.remove(encodedName);<a name="line.994"></a>
+<span class="sourceLineNo">995</span>    flushedSequenceIdByRegion.remove(encodedName);<a name="line.995"></a>
+<span class="sourceLineNo">996</span>  }<a name="line.996"></a>
+<span class="sourceLineNo">997</span><a name="line.997"></a>
+<span class="sourceLineNo">998</span>  @VisibleForTesting<a name="line.998"></a>
+<span class="sourceLineNo">999</span>  public boolean isRegionInServerManagerStates(final RegionInfo hri) {<a name="line.999"></a>
+<span class="sourceLineNo">1000</span>    final byte[] encodedName = hri.getEncodedNameAsBytes();<a name="line.1000"></a>
+<span class="sourceLineNo">1001</span>    return (storeFlushedSequenceIdsByRegion.containsKey(encodedName)<a name="line.1001"></a>
+<span class="sourceLineNo">1002</span>        || flushedSequenceIdByRegion.containsKey(encodedName));<a name="line.1002"></a>
+<span class="sourceLineNo">1003</span>  }<a name="line.1003"></a>
+<span class="sourceLineNo">1004</span><a name="line.1004"></a>
+<span class="sourceLineNo">1005</span>  /**<a name="line.1005"></a>
+<span class="sourceLineNo">1006</span>   * Called by delete table and similar to notify the ServerManager that a region was removed.<a name="line.1006"></a>
+<span class="sourceLineNo">1007</span>   */<a name="line.1007"></a>
+<span class="sourceLineNo">1008</span>  public void removeRegions(final List&lt;RegionInfo&gt; regions) {<a name="line.1008"></a>
+<span class="sourceLineNo">1009</span>    for (RegionInfo hri: regions) {<a name="line.1009"></a>
+<span class="sourceLineNo">1010</span>      removeRegion(hri);<a name="line.1010"></a>
+<span class="sourceLineNo">1011</span>    }<a name="line.1011"></a>
+<span class="sourceLineNo">1012</span>  }<a name="line.1012"></a>
+<span class="sourceLineNo">1013</span><a name="line.1013"></a>
+<span class="sourceLineNo">1014</span>  /**<a name="line.1014"></a>
+<span class="sourceLineNo">1015</span>   * May return 0 when server is not online.<a name="line.1015"></a>
+<span class="sourceLineNo">1016</span>   */<a name="line.1016"></a>
+<span class="sourceLineNo">1017</span>  public int getVersionNumber(ServerName serverName) {<a name="line.1017"></a>
+<span class="sourceLineNo">1018</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1018"></a>
+<span class="sourceLineNo">1019</span>    return serverMetrics != null ? serverMetrics.getVersionNumber() : 0;<a name="line.1019"></a>
+<span class="sourceLineNo">1020</span>  }<a name="line.1020"></a>
+<span class="sourceLineNo">1021</span><a name="line.1021"></a>
+<span class="sourceLineNo">1022</span>  /**<a name="line.1022"></a>
+<span class="sourceLineNo">1023</span>   * May return "0.0.0" when server is not online<a name="line.1023"></a>
+<span class="sourceLineNo">1024</span>   */<a name="line.1024"></a>
+<span class="sourceLineNo">1025</span>  public String getVersion(ServerName serverName) {<a name="line.1025"></a>
+<span class="sourceLineNo">1026</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1026"></a>
+<span class="sourceLineNo">1027</span>    return serverMetrics != null ? serverMetrics.getVersion() : "0.0.0";<a name="line.1027"></a>
+<span class="sourceLineNo">1028</span>  }<a name="line.1028"></a>
+<span class="sourceLineNo">1029</span><a name="line.1029"></a>
+<span class="sourceLineNo">1030</span>  public int getInfoPort(ServerName serverName) {<a name="line.1030"></a>
+<span class="sourceLineNo">1031</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1031"></a>
+<span class="sourceLineNo">1032</span>    return serverMetrics != null ? serverMetrics.getInfoServerPort() : 0;<a name="line.1032"></a>
+<span class="sourceLineNo">1033</span>  }<a name="line.1033"></a>
+<span class="sourceLineNo">1034</span><a name="line.1034"></a>
+<span class="sourceLineNo">1035</span>  /**<a name="line.1035"></a>
+<span class="sourceLineNo">1036</span>   * Persist last flushed sequence id of each region to HDFS<a name="line.1036"></a>
+<span class="sourceLineNo">1037</span>   * @throws IOException if persit to HDFS fails<a name="line.1037"></a>
+<span class="sourceLineNo">1038</span>   */<a name="line.1038"></a>
+<span class="sourceLineNo">1039</span>  private void persistRegionLastFlushedSequenceIds() throws IOException {<a name="line.1039"></a>
+<span class="sourceLineNo">1040</span>    if (isFlushSeqIdPersistInProgress) {<a name="line.1040"></a>
+<span class="sourceLineNo">1041</span>      return;<a name="line.1041"></a>
+<span class="sourceLineNo">1042</span>    }<a name="line.1042"></a>
+<span class="sourceLineNo">1043</span>    isFlushSeqIdPersistInProgress = true;<a name="line.1043"></a>
+<span class="sourceLineNo">1044</span>    try {<a name="line.1044"></a>
+<span class="sourceLineNo">1045</span>      Configuration conf = master.getConfiguration();<a name="line.1045"></a>
+<span class="sourceLineNo">1046</span>      Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.1046"></a>
+<span class="sourceLineNo">1047</span>      Path lastFlushedSeqIdPath = new Path(rootDir, LAST_FLUSHED_SEQ_ID_FILE);<a name="line.1047"></a>
+<span class="sourceLineNo">1048</span>      FileSystem fs = FileSystem.get(conf);<a name="line.1048"></a>
+<span class="sourceLineNo">1049</span>      if (fs.exists(lastFlushedSeqIdPath)) {<a name="line.1049"></a>
+<span class="sourceLineNo">1050</span>        LOG.info("Rewriting .lastflushedseqids file at: "<a name="line.1050"></a>
+<span class="sourceLineNo">1051</span>            + lastFlushedSeqIdPath);<a name="line.1051"></a>
+<span class="sourceLineNo">1052</span>        if (!fs.delete(lastFlushedSeqIdPath, false)) {<a name="line.1052"></a>
+<span class="sourceLineNo">1053</span>          throw new IOException("Unable to remove existing "<a name="line.1053"></a>
+<span class="sourceLineNo">1054</span>              + lastFlushedSeqIdPath);<a name="line.1054"></a>
+<span class="sourceLineNo">1055</span>        }<a name="line.1055"></a>
+<span class="sourceLineNo">1056</span>      } else {<a name="line.1056"></a>
+<span class="sourceLineNo">1057</span>        LOG.info("Writing .lastflushedseqids file at: " + lastFlushedSeqIdPath);<a name="line.1057"></a>
+<span class="sourceLineNo">1058</span>      }<a name="line.1058"></a>
+<span class="sourceLineNo">1059</span>      FSDataOutputStream out = fs.create(lastFlushedSeqIdPath);<a name="line.1059"></a>
+<span class="sourceLineNo">1060</span>      FlushedSequenceId.Builder flushedSequenceIdBuilder =<a name="line.1060"></a>
+<span class="sourceLineNo">1061</span>          FlushedSequenceId.newBuilder();<a name="line.1061"></a>
+<span class="sourceLineNo">1062</span>      try {<a name="line.1062"></a>
+<span class="sourceLineNo">1063</span>        for (Entry&lt;byte[], Long&gt; entry : flushedSequenceIdByRegion.entrySet()) {<a name="line.1063"></a>
+<span class="sourceLineNo">1064</span>          FlushedRegionSequenceId.Builder flushedRegionSequenceIdBuilder =<a name="line.1064"></a>
+<span class="sourceLineNo">1065</span>              FlushedRegionSequenceId.newBuilder();<a name="line.1065"></a>
+<span class="sourceLineNo">1066</span>          flushedRegionSequenceIdBuilder.setRegionEncodedName(<a name="line.1066"></a>
+<span class="sourceLineNo">1067</span>              ByteString.copyFrom(entry.getKey()));<a name="line.1067"></a>
+<span class="sourceLineNo">1068</span>          flushedRegionSequenceIdBuilder.setSeqId(entry.getValue());<a name="line.1068"></a>
+<span class="sourceLineNo">1069</span>          ConcurrentNavigableMap&lt;byte[], Long&gt; storeSeqIds =<a name="line.1069"></a>
+<span class="sourceLineNo">1070</span>              storeFlushedSequenceIdsByRegion.get(entry.getKey());<a name="line.1070"></a>
+<span class="sourceLineNo">1071</span>          if (storeSeqIds != null) {<a name="line.1071"></a>
+<span class="sourceLineNo">1072</span>            for (Entry&lt;byte[], Long&gt; store : storeSeqIds.entrySet()) {<a name="line.1072"></a>
+<span class="sourceLineNo">1073</span>              FlushedStoreSequenceId.Builder flushedStoreSequenceIdBuilder =<a name="line.1073"></a>
+<span class="sourceLineNo">1074</span>                  FlushedStoreSequenceId.newBuilder();<a name="line.1074"></a>
+<span class="sourceLineNo">1075</span>              flushedStoreSequenceIdBuilder.setFamily(ByteString.copyFrom(store.getKey()));<a name="line.1075"></a>
+<span class="sourceLineNo">1076</span>              flushedStoreSequenceIdBuilder.setSeqId(store.getValue());<a name="line.1076"></a>
+<span class="sourceLineNo">1077</span>              flushedRegionSequenceIdBuilder.addStores(flushedStoreSequenceIdBuilder);<a name="line.1077"></a>
+<span class="sourceLineNo">1078</span>            }<a name="line.1078"></a>
+<span class="sourceLineNo">1079</span>          }<a name="line.1079"></a>
+<span class="sourceLineNo">1080</span>          flushedSequenceIdBuilder.addRegionSequenceId(flushedRegionSequenceIdBuilder);<a name="line.1080"></a>
+<span class="sourceLineNo">1081</span>        }<a name="line.1081"></a>
+<span class="sourceLineNo">1082</span>        flushedSequenceIdBuilder.build().writeDelimitedTo(out);<a name="line.1082"></a>
+<span class="sourceLineNo">1083</span>      } finally {<a name="line.1083"></a>
+<span class="sourceLineNo">1084</span>        if (out != null) {<a name="line.1084"></a>
+<span class="sourceLineNo">1085</span>          out.close();<a name="line.1085"></a>
+<span class="sourceLineNo">1086</span>        }<a name="line.1086"></a>
+<span class="sourceLineNo">1087</span>      }<a name="line.1087"></a>
+<span class="sourceLineNo">1088</span>    } finally {<a name="line.1088"></a>
+<span class="sourceLineNo">1089</span>      isFlushSeqIdPersistInProgress = false;<a name="line.1089"></a>
+<span class="sourceLineNo">1090</span>    }<a name="line.1090"></a>
+<span class="sourceLineNo">1091</span>  }<a name="line.1091"></a>
+<span class="sourceLineNo">1092</span><a name="line.1092"></a>
+<span class="sourceLineNo">1093</span>  /**<a name="line.1093"></a>
+<span class="sourceLineNo">1094</span>   * Load last flushed sequence id of each region from HDFS, if persisted<a name="line.1094"></a>
+<span class="sourceLineNo">1095</span>   */<a name="line.1095"></a>
+<span class="sourceLineNo">1096</span>  public void loadLastFlushedSequenceIds() throws IOException {<a name="line.1096"></a>
+<span class="sourceLineNo">1097</span>    if (!persistFlushedSequenceId) {<a name="line.1097"></a>
+<span class="sourceLineNo">1098</span>      return;<a name="line.1098"></a>
+<span class="sourceLineNo">1099</span>    }<a name="line.1099"></a>
+<span class="sourceLineNo">1100</span>    Configuration conf = master.getConfiguration();<a name="line.1100"></a>
+<span class="sourceLineNo">1101</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.1101"></a>
+<span class="sourceLineNo">1102</span>    Path lastFlushedSeqIdPath = new Path(rootDir, LAST_FLUSHED_SEQ_ID_FILE);<a name="line.1102"></a>
+<span class="sourceLineNo">1103</span>    FileSystem fs = FileSystem.get(conf);<a name="line.1103"></a>
+<span class="sourceLineNo">1104</span>    if (!fs.exists(lastFlushedSeqIdPath)) {<a name="line.1104"></a>
+<span class="sourceLineNo">1105</span>      LOG.info("No .lastflushedseqids found at" + lastFlushedSeqIdPath<a name="line.1105"></a>
+<span class="sourceLineNo">1106</span>          + " will record last flushed sequence id"<a name="line.1106"></a>
+<span class="sourceLineNo">1107</span>          + " for regions by regionserver report all over again");<a name="line.1107"></a>
+<span class="sourceLineNo">1108</span>      return;<a name="line.1108"></a>
+<span class="sourceLineNo">1109</span>    } else {<a name="line.1109"></a>
+<span class="sourceLineNo">1110</span>      LOG.info("begin to load .lastflushedseqids at " + lastFlushedSeqIdPath);<a name="line.1110"></a>
+<span class="sourceLineNo">1111</span>    }<a name="line.1111"></a>
+<span class="sourceLineNo">1112</span>    FSDataInputStream in = fs.open(lastFlushedSeqIdPath);<a name="line.1112"></a>
+<span class="sourceLineNo">1113</span>    try {<a name="line.1113"></a>
+<span class="sourceLineNo">1114</span>      FlushedSequenceId flushedSequenceId =<a name="line.1114"></a>
+<span class="sourceLineNo">1115</span>          FlushedSequenceId.parseDelimitedFrom(in);<a name="line.1115"></a>
+<span class="sourceLineNo">1116</span>      if (flushedSequenceId == null) {<a name="line.1116"></a>
+<span class="sourceLineNo">1117</span>        LOG.info(".lastflushedseqids found at {} is empty", lastFlushedSeqIdPath);<a name="line.1117"></a>
+<span class="sourceLineNo">1118</span>        return;<a name="line.1118"></a>
+<span class="sourceLineNo">1119</span>      }<a name="line.1119"></a>
+<span class="sourceLineNo">1120</span>      for (FlushedRegionSequenceId flushedRegionSequenceId : flushedSequenceId<a name="line.1120"></a>
+<span class="sourceLineNo">1121</span>          .getRegionSequenceIdList()) {<a name="line.1121"></a>
+<span class="sourceLineNo">1122</span>        byte[] encodedRegionName = flushedRegionSequenceId<a name="line.1122"></a>
+<span class="sourceLineNo">1123</span>            .getRegionEncodedName().toByteArray();<a name="line.1123"></a>
+<span class="sourceLineNo">1124</span>        flushedSequenceIdByRegion<a name="line.1124"></a>
+<span class="sourceLineNo">1125</span>            .putIfAbsent(encodedRegionName, flushedRegionSequenceId.getSeqId());<a name="line.1125"></a>
+<span class="sourceLineNo">1126</span>        if (flushedRegionSequenceId.getStoresList() != null<a name="line.1126"></a>
+<span class="sourceLineNo">1127</span>            &amp;&amp; flushedRegionSequenceId.getStoresList().size() != 0) {<a name="line.1127"></a>
+<span class="sourceLineNo">1128</span>          ConcurrentNavigableMap&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.1128"></a>
+<span class="sourceLineNo">1129</span>              computeIfAbsent(storeFlushedSequenceIdsByRegion, encodedRegionName,<a name="line.1129"></a>
+<span class="sourceLineNo">1130</span>                () -&gt; new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR));<a name="line.1130"></a>
+<span class="sourceLineNo">1131</span>          for (FlushedStoreSequenceId flushedStoreSequenceId : flushedRegionSequenceId<a name="line.1131"></a>
+<span class="sourceLineNo">1132</span>              .getStoresList()) {<a name="line.1132"></a>
+<span class="sourceLineNo">1133</span>            storeFlushedSequenceId<a name="line.1133"></a>
+<span class="sourceLineNo">1134</span>                .put(flushedStoreSequenceId.getFamily().toByteArray(),<a name="line.1134"></a>
+<span class="sourceLineNo">1135</span>                    flushedStoreSequenceId.getSeqId());<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>      }<a name="line.1138"></a>
+<span class="sourceLineNo">1139</span>    } finally {<a name="line.1139"></a>
+<span class="sourceLineNo">1140</span>      in.close();<a name="line.1140"></a>
+<span class="sourceLineNo">1141</span>    }<a name="line.1141"></a>
+<span class="sourceLineNo">1142</span>  }<a name="line.1142"></a>
+<span class="sourceLineNo">1143</span><a name="line.1143"></a>
+<span class="sourceLineNo">1144</span>  /**<a name="line.1144"></a>
+<span class="sourceLineNo">1145</span>   * Regions may have been removed between latest persist of FlushedSequenceIds<a name="line.1145"></a>
+<span class="sourceLineNo">1146</span>   * and master abort. So after loading FlushedSequenceIds from file, and after<a name="line.1146"></a>
+<span class="sourceLineNo">1147</span>   * meta loaded, we need to remove the deleted region according to RegionStates.<a name="line.1147"></a>
+<span class="sourceLineNo">1148</span>   */<a name="line.1148"></a>
+<span class="sourceLineNo">1149</span>  public void removeDeletedRegionFromLoadedFlushedSequenceIds() {<a name="line.1149"></a>
+<span class="sourceLineNo">1150</span>    RegionStates regionStates = master.getAssignmentManager().getRegionStates();<a name="line.1150"></a>
+<span class="sourceLineNo">1151</span>    Iterator&lt;byte[]&gt; it = flushedSequenceIdByRegion.keySet().iterator();<a name="line.1151"></a>
+<span class="sourceLineNo">1152</span>    while(it.hasNext()) {<a name="line.1152"></a>
+<span class="sourceLineNo">1153</span>      byte[] regionEncodedName = it.next();<a name="line.1153"></a>
+<span class="sourceLineNo">1154</span>      if (regionStates.getRegionState(Bytes.toStringBinary(regionEncodedName)) == null) {<a name="line.1154"></a>
+<span class="sourceLineNo">1155</span>        it.remove();<a name="line.1155"></a>
+<span class="sourceLineNo">1156</span>        storeFlushedSequenceIdsByRegion.remove(regionEncodedName);<a name="line.1156"></a>
+<span class="sourceLineNo">1157</span>      }<a name="line.1157"></a>
+<span class="sourceLineNo">1158</span>    }<a name="line.1158"></a>
+<span class="sourceLineNo">1159</span>  }<a name="line.1159"></a>
+<span class="sourceLineNo">1160</span><a name="line.1160"></a>
+<span class="sourceLineNo">1161</span>  private class FlushedSequenceIdFlusher extends ScheduledChore {<a name="line.1161"></a>
 <span class="sourceLineNo">1162</span><a name="line.1162"></a>
-<span class="sourceLineNo">1163</span>    @Override<a name="line.1163"></a>
-<span class="sourceLineNo">1164</span>    protected void chore() {<a name="line.1164"></a>
-<span class="sourceLineNo">1165</span>      try {<a name="line.1165"></a>
-<span class="sourceLineNo">1166</span>        persistRegionLastFlushedSequenceIds();<a name="line.1166"></a>
-<span class="sourceLineNo">1167</span>      } catch (IOException e) {<a name="line.1167"></a>
-<span class="sourceLineNo">1168</span>        LOG.debug("Failed to persist last flushed sequence id of regions"<a name="line.1168"></a>
-<span class="sourceLineNo">1169</span>            + " to file system", e);<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>  }<a name="line.1172"></a>
-<span class="sourceLineNo">1173</span>}<a name="line.1173"></a>
+<span class="sourceLineNo">1163</span>    public FlushedSequenceIdFlusher(String name, int p) {<a name="line.1163"></a>
+<span class="sourceLineNo">1164</span>      super(name, master, p, 60 * 1000); //delay one minute before first execute<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>    @Override<a name="line.1167"></a>
+<span class="sourceLineNo">1168</span>    protected void chore() {<a name="line.1168"></a>
+<span class="sourceLineNo">1169</span>      try {<a name="line.1169"></a>
+<span class="sourceLineNo">1170</span>        persistRegionLastFlushedSequenceIds();<a name="line.1170"></a>
+<span class="sourceLineNo">1171</span>      } catch (IOException e) {<a name="line.1171"></a>
+<span class="sourceLineNo">1172</span>        LOG.debug("Failed to persist last flushed sequence id of regions"<a name="line.1172"></a>
+<span class="sourceLineNo">1173</span>            + " to file system", e);<a name="line.1173"></a>
+<span class="sourceLineNo">1174</span>      }<a name="line.1174"></a>
+<span class="sourceLineNo">1175</span>    }<a name="line.1175"></a>
+<span class="sourceLineNo">1176</span>  }<a name="line.1176"></a>
+<span class="sourceLineNo">1177</span>}<a name="line.1177"></a>
 
 
 
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/master/ServerManager.html b/devapidocs/src-html/org/apache/hadoop/hbase/master/ServerManager.html
index 7f98dd8..99dd552 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/master/ServerManager.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/master/ServerManager.html
@@ -59,1126 +59,1130 @@
 <span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.client.AsyncClusterConnection;<a name="line.51"></a>
 <span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.client.AsyncRegionServerAdmin;<a name="line.52"></a>
 <span class="sourceLineNo">053</span>import org.apache.hadoop.hbase.client.RegionInfo;<a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.apache.hadoop.hbase.master.assignment.RegionStates;<a name="line.54"></a>
-<span class="sourceLineNo">055</span>import org.apache.hadoop.hbase.monitoring.MonitoredTask;<a name="line.55"></a>
-<span class="sourceLineNo">056</span>import org.apache.hadoop.hbase.procedure2.Procedure;<a name="line.56"></a>
-<span class="sourceLineNo">057</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.57"></a>
-<span class="sourceLineNo">058</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.58"></a>
-<span class="sourceLineNo">059</span>import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;<a name="line.59"></a>
-<span class="sourceLineNo">060</span>import org.apache.hadoop.hbase.util.FutureUtils;<a name="line.60"></a>
-<span class="sourceLineNo">061</span>import org.apache.hadoop.hbase.zookeeper.ZKUtil;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>import org.apache.hadoop.hbase.zookeeper.ZKWatcher;<a name="line.62"></a>
-<span class="sourceLineNo">063</span>import org.apache.hadoop.hbase.zookeeper.ZNodePaths;<a name="line.63"></a>
-<span class="sourceLineNo">064</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.64"></a>
-<span class="sourceLineNo">065</span>import org.apache.zookeeper.KeeperException;<a name="line.65"></a>
-<span class="sourceLineNo">066</span>import org.slf4j.Logger;<a name="line.66"></a>
-<span class="sourceLineNo">067</span>import org.slf4j.LoggerFactory;<a name="line.67"></a>
-<span class="sourceLineNo">068</span><a name="line.68"></a>
-<span class="sourceLineNo">069</span>import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;<a name="line.69"></a>
-<span class="sourceLineNo">070</span>import org.apache.hbase.thirdparty.com.google.protobuf.ByteString;<a name="line.70"></a>
-<span class="sourceLineNo">071</span>import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations;<a name="line.71"></a>
-<span class="sourceLineNo">072</span><a name="line.72"></a>
-<span class="sourceLineNo">073</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.73"></a>
-<span class="sourceLineNo">074</span>import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter;<a name="line.74"></a>
-<span class="sourceLineNo">075</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.RegionStoreSequenceIds;<a name="line.75"></a>
-<span class="sourceLineNo">076</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.StoreSequenceId;<a name="line.76"></a>
-<span class="sourceLineNo">077</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedRegionSequenceId;<a name="line.77"></a>
-<span class="sourceLineNo">078</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedSequenceId;<a name="line.78"></a>
-<span class="sourceLineNo">079</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedStoreSequenceId;<a name="line.79"></a>
-<span class="sourceLineNo">080</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest;<a name="line.80"></a>
-<span class="sourceLineNo">081</span><a name="line.81"></a>
-<span class="sourceLineNo">082</span>/**<a name="line.82"></a>
-<span class="sourceLineNo">083</span> * The ServerManager class manages info about region servers.<a name="line.83"></a>
-<span class="sourceLineNo">084</span> * &lt;p&gt;<a name="line.84"></a>
-<span class="sourceLineNo">085</span> * Maintains lists of online and dead servers.  Processes the startups,<a name="line.85"></a>
-<span class="sourceLineNo">086</span> * shutdowns, and deaths of region servers.<a name="line.86"></a>
-<span class="sourceLineNo">087</span> * &lt;p&gt;<a name="line.87"></a>
-<span class="sourceLineNo">088</span> * Servers are distinguished in two different ways.  A given server has a<a name="line.88"></a>
-<span class="sourceLineNo">089</span> * location, specified by hostname and port, and of which there can only be one<a name="line.89"></a>
-<span class="sourceLineNo">090</span> * online at any given time.  A server instance is specified by the location<a name="line.90"></a>
-<span class="sourceLineNo">091</span> * (hostname and port) as well as the startcode (timestamp from when the server<a name="line.91"></a>
-<span class="sourceLineNo">092</span> * was started).  This is used to differentiate a restarted instance of a given<a name="line.92"></a>
-<span class="sourceLineNo">093</span> * server from the original instance.<a name="line.93"></a>
-<span class="sourceLineNo">094</span> * &lt;p&gt;<a name="line.94"></a>
-<span class="sourceLineNo">095</span> * If a sever is known not to be running any more, it is called dead. The dead<a name="line.95"></a>
-<span class="sourceLineNo">096</span> * server needs to be handled by a ServerShutdownHandler.  If the handler is not<a name="line.96"></a>
-<span class="sourceLineNo">097</span> * enabled yet, the server can't be handled right away so it is queued up.<a name="line.97"></a>
-<span class="sourceLineNo">098</span> * After the handler is enabled, the server will be submitted to a handler to handle.<a name="line.98"></a>
-<span class="sourceLineNo">099</span> * However, the handler may be just partially enabled.  If so,<a name="line.99"></a>
-<span class="sourceLineNo">100</span> * the server cannot be fully processed, and be queued up for further processing.<a name="line.100"></a>
-<span class="sourceLineNo">101</span> * A server is fully processed only after the handler is fully enabled<a name="line.101"></a>
-<span class="sourceLineNo">102</span> * and has completed the handling.<a name="line.102"></a>
-<span class="sourceLineNo">103</span> */<a name="line.103"></a>
-<span class="sourceLineNo">104</span>@InterfaceAudience.Private<a name="line.104"></a>
-<span class="sourceLineNo">105</span>public class ServerManager {<a name="line.105"></a>
-<span class="sourceLineNo">106</span>  public static final String WAIT_ON_REGIONSERVERS_MAXTOSTART =<a name="line.106"></a>
-<span class="sourceLineNo">107</span>      "hbase.master.wait.on.regionservers.maxtostart";<a name="line.107"></a>
-<span class="sourceLineNo">108</span><a name="line.108"></a>
-<span class="sourceLineNo">109</span>  public static final String WAIT_ON_REGIONSERVERS_MINTOSTART =<a name="line.109"></a>
-<span class="sourceLineNo">110</span>      "hbase.master.wait.on.regionservers.mintostart";<a name="line.110"></a>
-<span class="sourceLineNo">111</span><a name="line.111"></a>
-<span class="sourceLineNo">112</span>  public static final String WAIT_ON_REGIONSERVERS_TIMEOUT =<a name="line.112"></a>
-<span class="sourceLineNo">113</span>      "hbase.master.wait.on.regionservers.timeout";<a name="line.113"></a>
-<span class="sourceLineNo">114</span><a name="line.114"></a>
-<span class="sourceLineNo">115</span>  public static final String WAIT_ON_REGIONSERVERS_INTERVAL =<a name="line.115"></a>
-<span class="sourceLineNo">116</span>      "hbase.master.wait.on.regionservers.interval";<a name="line.116"></a>
-<span class="sourceLineNo">117</span><a name="line.117"></a>
-<span class="sourceLineNo">118</span>  /**<a name="line.118"></a>
-<span class="sourceLineNo">119</span>   * see HBASE-20727<a name="line.119"></a>
-<span class="sourceLineNo">120</span>   * if set to true, flushedSequenceIdByRegion and storeFlushedSequenceIdsByRegion<a name="line.120"></a>
-<span class="sourceLineNo">121</span>   * will be persisted to HDFS and loaded when master restart to speed up log split<a name="line.121"></a>
-<span class="sourceLineNo">122</span>   */<a name="line.122"></a>
-<span class="sourceLineNo">123</span>  public static final String PERSIST_FLUSHEDSEQUENCEID =<a name="line.123"></a>
-<span class="sourceLineNo">124</span>      "hbase.master.persist.flushedsequenceid.enabled";<a name="line.124"></a>
-<span class="sourceLineNo">125</span><a name="line.125"></a>
-<span class="sourceLineNo">126</span>  public static final boolean PERSIST_FLUSHEDSEQUENCEID_DEFAULT = true;<a name="line.126"></a>
-<span class="sourceLineNo">127</span><a name="line.127"></a>
-<span class="sourceLineNo">128</span>  public static final String FLUSHEDSEQUENCEID_FLUSHER_INTERVAL =<a name="line.128"></a>
-<span class="sourceLineNo">129</span>      "hbase.master.flushedsequenceid.flusher.interval";<a name="line.129"></a>
-<span class="sourceLineNo">130</span><a name="line.130"></a>
-<span class="sourceLineNo">131</span>  public static final int FLUSHEDSEQUENCEID_FLUSHER_INTERVAL_DEFAULT =<a name="line.131"></a>
-<span class="sourceLineNo">132</span>      3 * 60 * 60 * 1000; // 3 hours<a name="line.132"></a>
-<span class="sourceLineNo">133</span><a name="line.133"></a>
-<span class="sourceLineNo">134</span>  public static final String MAX_CLOCK_SKEW_MS = "hbase.master.maxclockskew";<a name="line.134"></a>
-<span class="sourceLineNo">135</span><a name="line.135"></a>
-<span class="sourceLineNo">136</span>  private static final Logger LOG = LoggerFactory.getLogger(ServerManager.class);<a name="line.136"></a>
-<span class="sourceLineNo">137</span><a name="line.137"></a>
-<span class="sourceLineNo">138</span>  // Set if we are to shutdown the cluster.<a name="line.138"></a>
-<span class="sourceLineNo">139</span>  private AtomicBoolean clusterShutdown = new AtomicBoolean(false);<a name="line.139"></a>
-<span class="sourceLineNo">140</span><a name="line.140"></a>
-<span class="sourceLineNo">141</span>  /**<a name="line.141"></a>
-<span class="sourceLineNo">142</span>   * The last flushed sequence id for a region.<a name="line.142"></a>
-<span class="sourceLineNo">143</span>   */<a name="line.143"></a>
-<span class="sourceLineNo">144</span>  private final ConcurrentNavigableMap&lt;byte[], Long&gt; flushedSequenceIdByRegion =<a name="line.144"></a>
-<span class="sourceLineNo">145</span>    new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.145"></a>
-<span class="sourceLineNo">146</span><a name="line.146"></a>
-<span class="sourceLineNo">147</span>  private boolean persistFlushedSequenceId = true;<a name="line.147"></a>
-<span class="sourceLineNo">148</span>  private volatile boolean isFlushSeqIdPersistInProgress = false;<a name="line.148"></a>
-<span class="sourceLineNo">149</span>  /** File on hdfs to store last flushed sequence id of regions */<a name="line.149"></a>
-<span class="sourceLineNo">150</span>  private static final String LAST_FLUSHED_SEQ_ID_FILE = ".lastflushedseqids";<a name="line.150"></a>
-<span class="sourceLineNo">151</span>  private  FlushedSequenceIdFlusher flushedSeqIdFlusher;<a name="line.151"></a>
-<span class="sourceLineNo">152</span><a name="line.152"></a>
+<span class="sourceLineNo">054</span>import org.apache.hadoop.hbase.ipc.RemoteWithExtrasException;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>import org.apache.hadoop.hbase.master.assignment.RegionStates;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>import org.apache.hadoop.hbase.monitoring.MonitoredTask;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>import org.apache.hadoop.hbase.procedure2.Procedure;<a name="line.57"></a>
+<span class="sourceLineNo">058</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.58"></a>
+<span class="sourceLineNo">059</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.59"></a>
+<span class="sourceLineNo">060</span>import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;<a name="line.60"></a>
+<span class="sourceLineNo">061</span>import org.apache.hadoop.hbase.util.FutureUtils;<a name="line.61"></a>
+<span class="sourceLineNo">062</span>import org.apache.hadoop.hbase.zookeeper.ZKUtil;<a name="line.62"></a>
+<span class="sourceLineNo">063</span>import org.apache.hadoop.hbase.zookeeper.ZKWatcher;<a name="line.63"></a>
+<span class="sourceLineNo">064</span>import org.apache.hadoop.hbase.zookeeper.ZNodePaths;<a name="line.64"></a>
+<span class="sourceLineNo">065</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.65"></a>
+<span class="sourceLineNo">066</span>import org.apache.zookeeper.KeeperException;<a name="line.66"></a>
+<span class="sourceLineNo">067</span>import org.slf4j.Logger;<a name="line.67"></a>
+<span class="sourceLineNo">068</span>import org.slf4j.LoggerFactory;<a name="line.68"></a>
+<span class="sourceLineNo">069</span><a name="line.69"></a>
+<span class="sourceLineNo">070</span>import org.apache.hbase.thirdparty.com.google.common.annotations.VisibleForTesting;<a name="line.70"></a>
+<span class="sourceLineNo">071</span>import org.apache.hbase.thirdparty.com.google.protobuf.ByteString;<a name="line.71"></a>
+<span class="sourceLineNo">072</span>import org.apache.hbase.thirdparty.com.google.protobuf.UnsafeByteOperations;<a name="line.72"></a>
+<span class="sourceLineNo">073</span><a name="line.73"></a>
+<span class="sourceLineNo">074</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.74"></a>
+<span class="sourceLineNo">075</span>import org.apache.hadoop.hbase.shaded.protobuf.RequestConverter;<a name="line.75"></a>
+<span class="sourceLineNo">076</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.RegionStoreSequenceIds;<a name="line.76"></a>
+<span class="sourceLineNo">077</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.ClusterStatusProtos.StoreSequenceId;<a name="line.77"></a>
+<span class="sourceLineNo">078</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedRegionSequenceId;<a name="line.78"></a>
+<span class="sourceLineNo">079</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedSequenceId;<a name="line.79"></a>
+<span class="sourceLineNo">080</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos.FlushedStoreSequenceId;<a name="line.80"></a>
+<span class="sourceLineNo">081</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.RegionServerStatusProtos.RegionServerStartupRequest;<a name="line.81"></a>
+<span class="sourceLineNo">082</span><a name="line.82"></a>
+<span class="sourceLineNo">083</span>/**<a name="line.83"></a>
+<span class="sourceLineNo">084</span> * The ServerManager class manages info about region servers.<a name="line.84"></a>
+<span class="sourceLineNo">085</span> * &lt;p&gt;<a name="line.85"></a>
+<span class="sourceLineNo">086</span> * Maintains lists of online and dead servers.  Processes the startups,<a name="line.86"></a>
+<span class="sourceLineNo">087</span> * shutdowns, and deaths of region servers.<a name="line.87"></a>
+<span class="sourceLineNo">088</span> * &lt;p&gt;<a name="line.88"></a>
+<span class="sourceLineNo">089</span> * Servers are distinguished in two different ways.  A given server has a<a name="line.89"></a>
+<span class="sourceLineNo">090</span> * location, specified by hostname and port, and of which there can only be one<a name="line.90"></a>
+<span class="sourceLineNo">091</span> * online at any given time.  A server instance is specified by the location<a name="line.91"></a>
+<span class="sourceLineNo">092</span> * (hostname and port) as well as the startcode (timestamp from when the server<a name="line.92"></a>
+<span class="sourceLineNo">093</span> * was started).  This is used to differentiate a restarted instance of a given<a name="line.93"></a>
+<span class="sourceLineNo">094</span> * server from the original instance.<a name="line.94"></a>
+<span class="sourceLineNo">095</span> * &lt;p&gt;<a name="line.95"></a>
+<span class="sourceLineNo">096</span> * If a sever is known not to be running any more, it is called dead. The dead<a name="line.96"></a>
+<span class="sourceLineNo">097</span> * server needs to be handled by a ServerShutdownHandler.  If the handler is not<a name="line.97"></a>
+<span class="sourceLineNo">098</span> * enabled yet, the server can't be handled right away so it is queued up.<a name="line.98"></a>
+<span class="sourceLineNo">099</span> * After the handler is enabled, the server will be submitted to a handler to handle.<a name="line.99"></a>
+<span class="sourceLineNo">100</span> * However, the handler may be just partially enabled.  If so,<a name="line.100"></a>
+<span class="sourceLineNo">101</span> * the server cannot be fully processed, and be queued up for further processing.<a name="line.101"></a>
+<span class="sourceLineNo">102</span> * A server is fully processed only after the handler is fully enabled<a name="line.102"></a>
+<span class="sourceLineNo">103</span> * and has completed the handling.<a name="line.103"></a>
+<span class="sourceLineNo">104</span> */<a name="line.104"></a>
+<span class="sourceLineNo">105</span>@InterfaceAudience.Private<a name="line.105"></a>
+<span class="sourceLineNo">106</span>public class ServerManager {<a name="line.106"></a>
+<span class="sourceLineNo">107</span>  public static final String WAIT_ON_REGIONSERVERS_MAXTOSTART =<a name="line.107"></a>
+<span class="sourceLineNo">108</span>      "hbase.master.wait.on.regionservers.maxtostart";<a name="line.108"></a>
+<span class="sourceLineNo">109</span><a name="line.109"></a>
+<span class="sourceLineNo">110</span>  public static final String WAIT_ON_REGIONSERVERS_MINTOSTART =<a name="line.110"></a>
+<span class="sourceLineNo">111</span>      "hbase.master.wait.on.regionservers.mintostart";<a name="line.111"></a>
+<span class="sourceLineNo">112</span><a name="line.112"></a>
+<span class="sourceLineNo">113</span>  public static final String WAIT_ON_REGIONSERVERS_TIMEOUT =<a name="line.113"></a>
+<span class="sourceLineNo">114</span>      "hbase.master.wait.on.regionservers.timeout";<a name="line.114"></a>
+<span class="sourceLineNo">115</span><a name="line.115"></a>
+<span class="sourceLineNo">116</span>  public static final String WAIT_ON_REGIONSERVERS_INTERVAL =<a name="line.116"></a>
+<span class="sourceLineNo">117</span>      "hbase.master.wait.on.regionservers.interval";<a name="line.117"></a>
+<span class="sourceLineNo">118</span><a name="line.118"></a>
+<span class="sourceLineNo">119</span>  /**<a name="line.119"></a>
+<span class="sourceLineNo">120</span>   * see HBASE-20727<a name="line.120"></a>
+<span class="sourceLineNo">121</span>   * if set to true, flushedSequenceIdByRegion and storeFlushedSequenceIdsByRegion<a name="line.121"></a>
+<span class="sourceLineNo">122</span>   * will be persisted to HDFS and loaded when master restart to speed up log split<a name="line.122"></a>
+<span class="sourceLineNo">123</span>   */<a name="line.123"></a>
+<span class="sourceLineNo">124</span>  public static final String PERSIST_FLUSHEDSEQUENCEID =<a name="line.124"></a>
+<span class="sourceLineNo">125</span>      "hbase.master.persist.flushedsequenceid.enabled";<a name="line.125"></a>
+<span class="sourceLineNo">126</span><a name="line.126"></a>
+<span class="sourceLineNo">127</span>  public static final boolean PERSIST_FLUSHEDSEQUENCEID_DEFAULT = true;<a name="line.127"></a>
+<span class="sourceLineNo">128</span><a name="line.128"></a>
+<span class="sourceLineNo">129</span>  public static final String FLUSHEDSEQUENCEID_FLUSHER_INTERVAL =<a name="line.129"></a>
+<span class="sourceLineNo">130</span>      "hbase.master.flushedsequenceid.flusher.interval";<a name="line.130"></a>
+<span class="sourceLineNo">131</span><a name="line.131"></a>
+<span class="sourceLineNo">132</span>  public static final int FLUSHEDSEQUENCEID_FLUSHER_INTERVAL_DEFAULT =<a name="line.132"></a>
+<span class="sourceLineNo">133</span>      3 * 60 * 60 * 1000; // 3 hours<a name="line.133"></a>
+<span class="sourceLineNo">134</span><a name="line.134"></a>
+<span class="sourceLineNo">135</span>  public static final String MAX_CLOCK_SKEW_MS = "hbase.master.maxclockskew";<a name="line.135"></a>
+<span class="sourceLineNo">136</span><a name="line.136"></a>
+<span class="sourceLineNo">137</span>  private static final Logger LOG = LoggerFactory.getLogger(ServerManager.class);<a name="line.137"></a>
+<span class="sourceLineNo">138</span><a name="line.138"></a>
+<span class="sourceLineNo">139</span>  // Set if we are to shutdown the cluster.<a name="line.139"></a>
+<span class="sourceLineNo">140</span>  private AtomicBoolean clusterShutdown = new AtomicBoolean(false);<a name="line.140"></a>
+<span class="sourceLineNo">141</span><a name="line.141"></a>
+<span class="sourceLineNo">142</span>  /**<a name="line.142"></a>
+<span class="sourceLineNo">143</span>   * The last flushed sequence id for a region.<a name="line.143"></a>
+<span class="sourceLineNo">144</span>   */<a name="line.144"></a>
+<span class="sourceLineNo">145</span>  private final ConcurrentNavigableMap&lt;byte[], Long&gt; flushedSequenceIdByRegion =<a name="line.145"></a>
+<span class="sourceLineNo">146</span>    new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.146"></a>
+<span class="sourceLineNo">147</span><a name="line.147"></a>
+<span class="sourceLineNo">148</span>  private boolean persistFlushedSequenceId = true;<a name="line.148"></a>
+<span class="sourceLineNo">149</span>  private volatile boolean isFlushSeqIdPersistInProgress = false;<a name="line.149"></a>
+<span class="sourceLineNo">150</span>  /** File on hdfs to store last flushed sequence id of regions */<a name="line.150"></a>
+<span class="sourceLineNo">151</span>  private static final String LAST_FLUSHED_SEQ_ID_FILE = ".lastflushedseqids";<a name="line.151"></a>
+<span class="sourceLineNo">152</span>  private  FlushedSequenceIdFlusher flushedSeqIdFlusher;<a name="line.152"></a>
 <span class="sourceLineNo">153</span><a name="line.153"></a>
-<span class="sourceLineNo">154</span>  /**<a name="line.154"></a>
-<span class="sourceLineNo">155</span>   * The last flushed sequence id for a store in a region.<a name="line.155"></a>
-<span class="sourceLineNo">156</span>   */<a name="line.156"></a>
-<span class="sourceLineNo">157</span>  private final ConcurrentNavigableMap&lt;byte[], ConcurrentNavigableMap&lt;byte[], Long&gt;&gt;<a name="line.157"></a>
-<span class="sourceLineNo">158</span>    storeFlushedSequenceIdsByRegion = new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.158"></a>
-<span class="sourceLineNo">159</span><a name="line.159"></a>
-<span class="sourceLineNo">160</span>  /** Map of registered servers to their current load */<a name="line.160"></a>
-<span class="sourceLineNo">161</span>  private final ConcurrentNavigableMap&lt;ServerName, ServerMetrics&gt; onlineServers =<a name="line.161"></a>
-<span class="sourceLineNo">162</span>    new ConcurrentSkipListMap&lt;&gt;();<a name="line.162"></a>
-<span class="sourceLineNo">163</span><a name="line.163"></a>
-<span class="sourceLineNo">164</span>  /** List of region servers that should not get any more new regions. */<a name="line.164"></a>
-<span class="sourceLineNo">165</span>  private final ArrayList&lt;ServerName&gt; drainingServers = new ArrayList&lt;&gt;();<a name="line.165"></a>
-<span class="sourceLineNo">166</span><a name="line.166"></a>
-<span class="sourceLineNo">167</span>  private final MasterServices master;<a name="line.167"></a>
-<span class="sourceLineNo">168</span><a name="line.168"></a>
-<span class="sourceLineNo">169</span>  private final DeadServer deadservers = new DeadServer();<a name="line.169"></a>
-<span class="sourceLineNo">170</span><a name="line.170"></a>
-<span class="sourceLineNo">171</span>  private final long maxSkew;<a name="line.171"></a>
-<span class="sourceLineNo">172</span>  private final long warningSkew;<a name="line.172"></a>
-<span class="sourceLineNo">173</span><a name="line.173"></a>
-<span class="sourceLineNo">174</span>  /** Listeners that are called on server events. */<a name="line.174"></a>
-<span class="sourceLineNo">175</span>  private List&lt;ServerListener&gt; listeners = new CopyOnWriteArrayList&lt;&gt;();<a name="line.175"></a>
-<span class="sourceLineNo">176</span><a name="line.176"></a>
-<span class="sourceLineNo">177</span>  /**<a name="line.177"></a>
-<span class="sourceLineNo">178</span>   * Constructor.<a name="line.178"></a>
-<span class="sourceLineNo">179</span>   */<a name="line.179"></a>
-<span class="sourceLineNo">180</span>  public ServerManager(final MasterServices master) {<a name="line.180"></a>
-<span class="sourceLineNo">181</span>    this.master = master;<a name="line.181"></a>
-<span class="sourceLineNo">182</span>    Configuration c = master.getConfiguration();<a name="line.182"></a>
-<span class="sourceLineNo">183</span>    maxSkew = c.getLong(MAX_CLOCK_SKEW_MS, 30000);<a name="line.183"></a>
-<span class="sourceLineNo">184</span>    warningSkew = c.getLong("hbase.master.warningclockskew", 10000);<a name="line.184"></a>
-<span class="sourceLineNo">185</span>    persistFlushedSequenceId = c.getBoolean(PERSIST_FLUSHEDSEQUENCEID,<a name="line.185"></a>
-<span class="sourceLineNo">186</span>        PERSIST_FLUSHEDSEQUENCEID_DEFAULT);<a name="line.186"></a>
-<span class="sourceLineNo">187</span>  }<a name="line.187"></a>
-<span class="sourceLineNo">188</span><a name="line.188"></a>
-<span class="sourceLineNo">189</span>  /**<a name="line.189"></a>
-<span class="sourceLineNo">190</span>   * Add the listener to the notification list.<a name="line.190"></a>
-<span class="sourceLineNo">191</span>   * @param listener The ServerListener to register<a name="line.191"></a>
-<span class="sourceLineNo">192</span>   */<a name="line.192"></a>
-<span class="sourceLineNo">193</span>  public void registerListener(final ServerListener listener) {<a name="line.193"></a>
-<span class="sourceLineNo">194</span>    this.listeners.add(listener);<a name="line.194"></a>
-<span class="sourceLineNo">195</span>  }<a name="line.195"></a>
-<span class="sourceLineNo">196</span><a name="line.196"></a>
-<span class="sourceLineNo">197</span>  /**<a name="line.197"></a>
-<span class="sourceLineNo">198</span>   * Remove the listener from the notification list.<a name="line.198"></a>
-<span class="sourceLineNo">199</span>   * @param listener The ServerListener to unregister<a name="line.199"></a>
-<span class="sourceLineNo">200</span>   */<a name="line.200"></a>
-<span class="sourceLineNo">201</span>  public boolean unregisterListener(final ServerListener listener) {<a name="line.201"></a>
-<span class="sourceLineNo">202</span>    return this.listeners.remove(listener);<a name="line.202"></a>
-<span class="sourceLineNo">203</span>  }<a name="line.203"></a>
-<span class="sourceLineNo">204</span><a name="line.204"></a>
-<span class="sourceLineNo">205</span>  /**<a name="line.205"></a>
-<span class="sourceLineNo">206</span>   * Let the server manager know a new regionserver has come online<a name="line.206"></a>
-<span class="sourceLineNo">207</span>   * @param request the startup request<a name="line.207"></a>
-<span class="sourceLineNo">208</span>   * @param versionNumber the version number of the new regionserver<a name="line.208"></a>
-<span class="sourceLineNo">209</span>   * @param version the version of the new regionserver, could contain strings like "SNAPSHOT"<a name="line.209"></a>
-<span class="sourceLineNo">210</span>   * @param ia the InetAddress from which request is received<a name="line.210"></a>
-<span class="sourceLineNo">211</span>   * @return The ServerName we know this server as.<a name="line.211"></a>
-<span class="sourceLineNo">212</span>   * @throws IOException<a name="line.212"></a>
-<span class="sourceLineNo">213</span>   */<a name="line.213"></a>
-<span class="sourceLineNo">214</span>  ServerName regionServerStartup(RegionServerStartupRequest request, int versionNumber,<a name="line.214"></a>
-<span class="sourceLineNo">215</span>      String version, InetAddress ia) throws IOException {<a name="line.215"></a>
-<span class="sourceLineNo">216</span>    // Test for case where we get a region startup message from a regionserver<a name="line.216"></a>
-<span class="sourceLineNo">217</span>    // that has been quickly restarted but whose znode expiration handler has<a name="line.217"></a>
-<span class="sourceLineNo">218</span>    // not yet run, or from a server whose fail we are currently processing.<a name="line.218"></a>
-<span class="sourceLineNo">219</span>    // Test its host+port combo is present in serverAddressToServerInfo. If it<a name="line.219"></a>
-<span class="sourceLineNo">220</span>    // is, reject the server and trigger its expiration. The next time it comes<a name="line.220"></a>
-<span class="sourceLineNo">221</span>    // in, it should have been removed from serverAddressToServerInfo and queued<a name="line.221"></a>
-<span class="sourceLineNo">222</span>    // for processing by ProcessServerShutdown.<a name="line.222"></a>
-<span class="sourceLineNo">223</span><a name="line.223"></a>
-<span class="sourceLineNo">224</span>    final String hostname =<a name="line.224"></a>
-<span class="sourceLineNo">225</span>      request.hasUseThisHostnameInstead() ? request.getUseThisHostnameInstead() : ia.getHostName();<a name="line.225"></a>
-<span class="sourceLineNo">226</span>    ServerName sn = ServerName.valueOf(hostname, request.getPort(), request.getServerStartCode());<a name="line.226"></a>
-<span class="sourceLineNo">227</span>    checkClockSkew(sn, request.getServerCurrentTime());<a name="line.227"></a>
-<span class="sourceLineNo">228</span>    checkIsDead(sn, "STARTUP");<a name="line.228"></a>
-<span class="sourceLineNo">229</span>    if (!checkAndRecordNewServer(sn, ServerMetricsBuilder.of(sn, versionNumber, version))) {<a name="line.229"></a>
-<span class="sourceLineNo">230</span>      LOG.warn(<a name="line.230"></a>
-<span class="sourceLineNo">231</span>        "THIS SHOULD NOT HAPPEN, RegionServerStartup" + " could not record the server: " + sn);<a name="line.231"></a>
-<span class="sourceLineNo">232</span>    }<a name="line.232"></a>
-<span class="sourceLineNo">233</span>    return sn;<a name="line.233"></a>
-<span class="sourceLineNo">234</span>  }<a name="line.234"></a>
-<span class="sourceLineNo">235</span><a name="line.235"></a>
-<span class="sourceLineNo">236</span>  /**<a name="line.236"></a>
-<span class="sourceLineNo">237</span>   * Updates last flushed sequence Ids for the regions on server sn<a name="line.237"></a>
-<span class="sourceLineNo">238</span>   * @param sn<a name="line.238"></a>
-<span class="sourceLineNo">239</span>   * @param hsl<a name="line.239"></a>
-<span class="sourceLineNo">240</span>   */<a name="line.240"></a>
-<span class="sourceLineNo">241</span>  private void updateLastFlushedSequenceIds(ServerName sn, ServerMetrics hsl) {<a name="line.241"></a>
-<span class="sourceLineNo">242</span>    for (Entry&lt;byte[], RegionMetrics&gt; entry : hsl.getRegionMetrics().entrySet()) {<a name="line.242"></a>
-<span class="sourceLineNo">243</span>      byte[] encodedRegionName = Bytes.toBytes(RegionInfo.encodeRegionName(entry.getKey()));<a name="line.243"></a>
-<span class="sourceLineNo">244</span>      Long existingValue = flushedSequenceIdByRegion.get(encodedRegionName);<a name="line.244"></a>
-<span class="sourceLineNo">245</span>      long l = entry.getValue().getCompletedSequenceId();<a name="line.245"></a>
-<span class="sourceLineNo">246</span>      // Don't let smaller sequence ids override greater sequence ids.<a name="line.246"></a>
-<span class="sourceLineNo">247</span>      if (LOG.isTraceEnabled()) {<a name="line.247"></a>
-<span class="sourceLineNo">248</span>        LOG.trace(Bytes.toString(encodedRegionName) + ", existingValue=" + existingValue +<a name="line.248"></a>
-<span class="sourceLineNo">249</span>          ", completeSequenceId=" + l);<a name="line.249"></a>
-<span class="sourceLineNo">250</span>      }<a name="line.250"></a>
-<span class="sourceLineNo">251</span>      if (existingValue == null || (l != HConstants.NO_SEQNUM &amp;&amp; l &gt; existingValue)) {<a name="line.251"></a>
-<span class="sourceLineNo">252</span>        flushedSequenceIdByRegion.put(encodedRegionName, l);<a name="line.252"></a>
-<span class="sourceLineNo">253</span>      } else if (l != HConstants.NO_SEQNUM &amp;&amp; l &lt; existingValue) {<a name="line.253"></a>
-<span class="sourceLineNo">254</span>        LOG.warn("RegionServer " + sn + " indicates a last flushed sequence id ("<a name="line.254"></a>
-<span class="sourceLineNo">255</span>            + l + ") that is less than the previous last flushed sequence id ("<a name="line.255"></a>
-<span class="sourceLineNo">256</span>            + existingValue + ") for region " + Bytes.toString(entry.getKey()) + " Ignoring.");<a name="line.256"></a>
-<span class="sourceLineNo">257</span>      }<a name="line.257"></a>
-<span class="sourceLineNo">258</span>      ConcurrentNavigableMap&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.258"></a>
-<span class="sourceLineNo">259</span>          computeIfAbsent(storeFlushedSequenceIdsByRegion, encodedRegionName,<a name="line.259"></a>
-<span class="sourceLineNo">260</span>            () -&gt; new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR));<a name="line.260"></a>
-<span class="sourceLineNo">261</span>      for (Entry&lt;byte[], Long&gt; storeSeqId : entry.getValue().getStoreSequenceId().entrySet()) {<a name="line.261"></a>
-<span class="sourceLineNo">262</span>        byte[] family = storeSeqId.getKey();<a name="line.262"></a>
-<span class="sourceLineNo">263</span>        existingValue = storeFlushedSequenceId.get(family);<a name="line.263"></a>
-<span class="sourceLineNo">264</span>        l = storeSeqId.getValue();<a name="line.264"></a>
-<span class="sourceLineNo">265</span>        if (LOG.isTraceEnabled()) {<a name="line.265"></a>
-<span class="sourceLineNo">266</span>          LOG.trace(Bytes.toString(encodedRegionName) + ", family=" + Bytes.toString(family) +<a name="line.266"></a>
-<span class="sourceLineNo">267</span>            ", existingValue=" + existingValue + ", completeSequenceId=" + l);<a name="line.267"></a>
-<span class="sourceLineNo">268</span>        }<a name="line.268"></a>
-<span class="sourceLineNo">269</span>        // Don't let smaller sequence ids override greater sequence ids.<a name="line.269"></a>
-<span class="sourceLineNo">270</span>        if (existingValue == null || (l != HConstants.NO_SEQNUM &amp;&amp; l &gt; existingValue.longValue())) {<a name="line.270"></a>
-<span class="sourceLineNo">271</span>          storeFlushedSequenceId.put(family, l);<a name="line.271"></a>
-<span class="sourceLineNo">272</span>        }<a name="line.272"></a>
-<span class="sourceLineNo">273</span>      }<a name="line.273"></a>
-<span class="sourceLineNo">274</span>    }<a name="line.274"></a>
-<span class="sourceLineNo">275</span>  }<a name="line.275"></a>
-<span class="sourceLineNo">276</span><a name="line.276"></a>
-<span class="sourceLineNo">277</span>  @VisibleForTesting<a name="line.277"></a>
-<span class="sourceLineNo">278</span>  public void regionServerReport(ServerName sn,<a name="line.278"></a>
-<span class="sourceLineNo">279</span>    ServerMetrics sl) throws YouAreDeadException {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>    checkIsDead(sn, "REPORT");<a name="line.280"></a>
-<span class="sourceLineNo">281</span>    if (null == this.onlineServers.replace(sn, sl)) {<a name="line.281"></a>
-<span class="sourceLineNo">282</span>      // Already have this host+port combo and its just different start code?<a name="line.282"></a>
-<span class="sourceLineNo">283</span>      // Just let the server in. Presume master joining a running cluster.<a name="line.283"></a>
-<span class="sourceLineNo">284</span>      // recordNewServer is what happens at the end of reportServerStartup.<a name="line.284"></a>
-<span class="sourceLineNo">285</span>      // The only thing we are skipping is passing back to the regionserver<a name="line.285"></a>
-<span class="sourceLineNo">286</span>      // the ServerName to use. Here we presume a master has already done<a name="line.286"></a>
-<span class="sourceLineNo">287</span>      // that so we'll press on with whatever it gave us for ServerName.<a name="line.287"></a>
-<span class="sourceLineNo">288</span>      if (!checkAndRecordNewServer(sn, sl)) {<a name="line.288"></a>
-<span class="sourceLineNo">289</span>        LOG.info("RegionServerReport ignored, could not record the server: " + sn);<a name="line.289"></a>
-<span class="sourceLineNo">290</span>        return; // Not recorded, so no need to move on<a name="line.290"></a>
-<span class="sourceLineNo">291</span>      }<a name="line.291"></a>
-<span class="sourceLineNo">292</span>    }<a name="line.292"></a>
-<span class="sourceLineNo">293</span>    updateLastFlushedSequenceIds(sn, sl);<a name="line.293"></a>
-<span class="sourceLineNo">294</span>  }<a name="line.294"></a>
-<span class="sourceLineNo">295</span><a name="line.295"></a>
-<span class="sourceLineNo">296</span>  /**<a name="line.296"></a>
-<span class="sourceLineNo">297</span>   * Check is a server of same host and port already exists,<a name="line.297"></a>
-<span class="sourceLineNo">298</span>   * if not, or the existed one got a smaller start code, record it.<a name="line.298"></a>
-<span class="sourceLineNo">299</span>   *<a name="line.299"></a>
-<span class="sourceLineNo">300</span>   * @param serverName the server to check and record<a name="line.300"></a>
-<span class="sourceLineNo">301</span>   * @param sl the server load on the server<a name="line.301"></a>
-<span class="sourceLineNo">302</span>   * @return true if the server is recorded, otherwise, false<a name="line.302"></a>
-<span class="sourceLineNo">303</span>   */<a name="line.303"></a>
-<span class="sourceLineNo">304</span>  boolean checkAndRecordNewServer(final ServerName serverName, final ServerMetrics sl) {<a name="line.304"></a>
-<span class="sourceLineNo">305</span>    ServerName existingServer = null;<a name="line.305"></a>
-<span class="sourceLineNo">306</span>    synchronized (this.onlineServers) {<a name="line.306"></a>
-<span class="sourceLineNo">307</span>      existingServer = findServerWithSameHostnamePortWithLock(serverName);<a name="line.307"></a>
-<span class="sourceLineNo">308</span>      if (existingServer != null &amp;&amp; (existingServer.getStartcode() &gt; serverName.getStartcode())) {<a name="line.308"></a>
-<span class="sourceLineNo">309</span>        LOG.info("Server serverName=" + serverName + " rejected; we already have "<a name="line.309"></a>
-<span class="sourceLineNo">310</span>            + existingServer.toString() + " registered with same hostname and port");<a name="line.310"></a>
-<span class="sourceLineNo">311</span>        return false;<a name="line.311"></a>
-<span class="sourceLineNo">312</span>      }<a name="line.312"></a>
-<span class="sourceLineNo">313</span>      recordNewServerWithLock(serverName, sl);<a name="line.313"></a>
-<span class="sourceLineNo">314</span>    }<a name="line.314"></a>
-<span class="sourceLineNo">315</span><a name="line.315"></a>
-<span class="sourceLineNo">316</span>    // Tell our listeners that a server was added<a name="line.316"></a>
-<span class="sourceLineNo">317</span>    if (!this.listeners.isEmpty()) {<a name="line.317"></a>
-<span class="sourceLineNo">318</span>      for (ServerListener listener : this.listeners) {<a name="line.318"></a>
-<span class="sourceLineNo">319</span>        listener.serverAdded(serverName);<a name="line.319"></a>
-<span class="sourceLineNo">320</span>      }<a name="line.320"></a>
-<span class="sourceLineNo">321</span>    }<a name="line.321"></a>
-<span class="sourceLineNo">322</span><a name="line.322"></a>
-<span class="sourceLineNo">323</span>    // Note that we assume that same ts means same server, and don't expire in that case.<a name="line.323"></a>
-<span class="sourceLineNo">324</span>    //  TODO: ts can theoretically collide due to clock shifts, so this is a bit hacky.<a name="line.324"></a>
-<span class="sourceLineNo">325</span>    if (existingServer != null &amp;&amp;<a name="line.325"></a>
-<span class="sourceLineNo">326</span>        (existingServer.getStartcode() &lt; serverName.getStartcode())) {<a name="line.326"></a>
-<span class="sourceLineNo">327</span>      LOG.info("Triggering server recovery; existingServer " +<a name="line.327"></a>
-<span class="sourceLineNo">328</span>          existingServer + " looks stale, new server:" + serverName);<a name="line.328"></a>
-<span class="sourceLineNo">329</span>      expireServer(existingServer);<a name="line.329"></a>
-<span class="sourceLineNo">330</span>    }<a name="line.330"></a>
-<span class="sourceLineNo">331</span>    return true;<a name="line.331"></a>
-<span class="sourceLineNo">332</span>  }<a name="line.332"></a>
-<span class="sourceLineNo">333</span><a name="line.333"></a>
-<span class="sourceLineNo">334</span>  /**<a name="line.334"></a>
-<span class="sourceLineNo">335</span>   * Find out the region servers crashed between the crash of the previous master instance and the<a name="line.335"></a>
-<span class="sourceLineNo">336</span>   * current master instance and schedule SCP for them.<a name="line.336"></a>
-<span class="sourceLineNo">337</span>   * &lt;p/&gt;<a name="line.337"></a>
-<span class="sourceLineNo">338</span>   * Since the {@code RegionServerTracker} has already helped us to construct the online servers set<a name="line.338"></a>
-<span class="sourceLineNo">339</span>   * by scanning zookeeper, now we can compare the online servers with {@code liveServersFromWALDir}<a name="line.339"></a>
-<span class="sourceLineNo">340</span>   * to find out whether there are servers which are already dead.<a name="line.340"></a>
-<span class="sourceLineNo">341</span>   * &lt;p/&gt;<a name="line.341"></a>
-<span class="sourceLineNo">342</span>   * Must be called inside the initialization method of {@code RegionServerTracker} to avoid<a name="line.342"></a>
-<span class="sourceLineNo">343</span>   * concurrency issue.<a name="line.343"></a>
-<span class="sourceLineNo">344</span>   * @param deadServersFromPE the region servers which already have a SCP associated.<a name="line.344"></a>
-<span class="sourceLineNo">345</span>   * @param liveServersFromWALDir the live region servers from wal directory.<a name="line.345"></a>
-<span class="sourceLineNo">346</span>   */<a name="line.346"></a>
-<span class="sourceLineNo">347</span>  void findDeadServersAndProcess(Set&lt;ServerName&gt; deadServersFromPE,<a name="line.347"></a>
-<span class="sourceLineNo">348</span>      Set&lt;ServerName&gt; liveServersFromWALDir) {<a name="line.348"></a>
-<span class="sourceLineNo">349</span>    deadServersFromPE.forEach(deadservers::putIfAbsent);<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    liveServersFromWALDir.stream().filter(sn -&gt; !onlineServers.containsKey(sn))<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      .forEach(this::expireServer);<a name="line.351"></a>
-<span class="sourceLineNo">352</span>  }<a name="line.352"></a>
-<span class="sourceLineNo">353</span><a name="line.353"></a>
-<span class="sourceLineNo">354</span>  /**<a name="line.354"></a>
-<span class="sourceLineNo">355</span>   * Checks if the clock skew between the server and the master. If the clock skew exceeds the<a name="line.355"></a>
-<span class="sourceLineNo">356</span>   * configured max, it will throw an exception; if it exceeds the configured warning threshold,<a name="line.356"></a>
-<span class="sourceLineNo">357</span>   * it will log a warning but start normally.<a name="line.357"></a>
-<span class="sourceLineNo">358</span>   * @param serverName Incoming servers's name<a name="line.358"></a>
-<span class="sourceLineNo">359</span>   * @param serverCurrentTime<a name="line.359"></a>
-<span class="sourceLineNo">360</span>   * @throws ClockOutOfSyncException if the skew exceeds the configured max value<a name="line.360"></a>
-<span class="sourceLineNo">361</span>   */<a name="line.361"></a>
-<span class="sourceLineNo">362</span>  private void checkClockSkew(final ServerName serverName, final long serverCurrentTime)<a name="line.362"></a>
-<span class="sourceLineNo">363</span>      throws ClockOutOfSyncException {<a name="line.363"></a>
-<span class="sourceLineNo">364</span>    long skew = Math.abs(EnvironmentEdgeManager.currentTime() - serverCurrentTime);<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    if (skew &gt; maxSkew) {<a name="line.365"></a>
-<span class="sourceLineNo">366</span>      String message = "Server " + serverName + " has been " +<a name="line.366"></a>
-<span class="sourceLineNo">367</span>        "rejected; Reported time is too far out of sync with master.  " +<a name="line.367"></a>
-<span class="sourceLineNo">368</span>        "Time difference of " + skew + "ms &gt; max allowed of " + maxSkew + "ms";<a name="line.368"></a>
-<span class="sourceLineNo">369</span>      LOG.warn(message);<a name="line.369"></a>
-<span class="sourceLineNo">370</span>      throw new ClockOutOfSyncException(message);<a name="line.370"></a>
-<span class="sourceLineNo">371</span>    } else if (skew &gt; warningSkew){<a name="line.371"></a>
-<span class="sourceLineNo">372</span>      String message = "Reported time for server " + serverName + " is out of sync with master " +<a name="line.372"></a>
-<span class="sourceLineNo">373</span>        "by " + skew + "ms. (Warning threshold is " + warningSkew + "ms; " +<a name="line.373"></a>
-<span class="sourceLineNo">374</span>        "error threshold is " + maxSkew + "ms)";<a name="line.374"></a>
-<span class="sourceLineNo">375</span>      LOG.warn(message);<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    }<a name="line.376"></a>
-<span class="sourceLineNo">377</span>  }<a name="line.377"></a>
-<span class="sourceLineNo">378</span><a name="line.378"></a>
-<span class="sourceLineNo">379</span>  /**<a name="line.379"></a>
-<span class="sourceLineNo">380</span>   * Called when RegionServer first reports in for duty and thereafter each<a name="line.380"></a>
-<span class="sourceLineNo">381</span>   * time it heartbeats to make sure it is has not been figured for dead.<a name="line.381"></a>
-<span class="sourceLineNo">382</span>   * If this server is on the dead list, reject it with a YouAreDeadException.<a name="line.382"></a>
-<span class="sourceLineNo">383</span>   * If it was dead but came back with a new start code, remove the old entry<a name="line.383"></a>
-<span class="sourceLineNo">384</span>   * from the dead list.<a name="line.384"></a>
-<span class="sourceLineNo">385</span>   * @param what START or REPORT<a name="line.385"></a>
-<span class="sourceLineNo">386</span>   */<a name="line.386"></a>
-<span class="sourceLineNo">387</span>  private void checkIsDead(final ServerName serverName, final String what)<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      throws YouAreDeadException {<a name="line.388"></a>
-<span class="sourceLineNo">389</span>    if (this.deadservers.isDeadServer(serverName)) {<a name="line.389"></a>
-<span class="sourceLineNo">390</span>      // Exact match: host name, port and start code all match with existing one of the<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      // dead servers. So, this server must be dead. Tell it to kill itself.<a name="line.391"></a>
-<span class="sourceLineNo">392</span>      String message = "Server " + what + " rejected; currently processing " +<a name="line.392"></a>
-<span class="sourceLineNo">393</span>          serverName + " as dead server";<a name="line.393"></a>
-<span class="sourceLineNo">394</span>      LOG.debug(message);<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      throw new YouAreDeadException(message);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    }<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    // Remove dead server with same hostname and port of newly checking in rs after master<a name="line.397"></a>
-<span class="sourceLineNo">398</span>    // initialization. See HBASE-5916 for more information.<a name="line.398"></a>
-<span class="sourceLineNo">399</span>    if ((this.master == null || this.master.isInitialized()) &amp;&amp;<a name="line.399"></a>
-<span class="sourceLineNo">400</span>        this.deadservers.cleanPreviousInstance(serverName)) {<a name="line.400"></a>
-<span class="sourceLineNo">401</span>      // This server has now become alive after we marked it as dead.<a name="line.401"></a>
-<span class="sourceLineNo">402</span>      // We removed it's previous entry from the dead list to reflect it.<a name="line.402"></a>
-<span class="sourceLineNo">403</span>      LOG.debug("{} {} came back up, removed it from the dead servers list", what, serverName);<a name="line.403"></a>
-<span class="sourceLineNo">404</span>    }<a name="line.404"></a>
-<span class="sourceLineNo">405</span>  }<a name="line.405"></a>
-<span class="sourceLineNo">406</span><a name="line.406"></a>
-<span class="sourceLineNo">407</span>  /**<a name="line.407"></a>
-<span class="sourceLineNo">408</span>   * Assumes onlineServers is locked.<a name="line.408"></a>
-<span class="sourceLineNo">409</span>   * @return ServerName with matching hostname and port.<a name="line.409"></a>
-<span class="sourceLineNo">410</span>   */<a name="line.410"></a>
-<span class="sourceLineNo">411</span>  private ServerName findServerWithSameHostnamePortWithLock(<a name="line.411"></a>
-<span class="sourceLineNo">412</span>      final ServerName serverName) {<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    ServerName end = ServerName.valueOf(serverName.getHostname(), serverName.getPort(),<a name="line.413"></a>
-<span class="sourceLineNo">414</span>        Long.MAX_VALUE);<a name="line.414"></a>
-<span class="sourceLineNo">415</span><a name="line.415"></a>
-<span class="sourceLineNo">416</span>    ServerName r = onlineServers.lowerKey(end);<a name="line.416"></a>
-<span class="sourceLineNo">417</span>    if (r != null) {<a name="line.417"></a>
-<span class="sourceLineNo">418</span>      if (ServerName.isSameAddress(r, serverName)) {<a name="line.418"></a>
-<span class="sourceLineNo">419</span>        return r;<a name="line.419"></a>
-<span class="sourceLineNo">420</span>      }<a name="line.420"></a>
-<span class="sourceLineNo">421</span>    }<a name="line.421"></a>
-<span class="sourceLineNo">422</span>    return null;<a name="line.422"></a>
-<span class="sourceLineNo">423</span>  }<a name="line.423"></a>
-<span class="sourceLineNo">424</span><a name="line.424"></a>
-<span class="sourceLineNo">425</span>  /**<a name="line.425"></a>
-<span class="sourceLineNo">426</span>   * Adds the onlineServers list. onlineServers should be locked.<a name="line.426"></a>
-<span class="sourceLineNo">427</span>   * @param serverName The remote servers name.<a name="line.427"></a>
-<span class="sourceLineNo">428</span>   */<a name="line.428"></a>
-<span class="sourceLineNo">429</span>  @VisibleForTesting<a name="line.429"></a>
-<span class="sourceLineNo">430</span>  void recordNewServerWithLock(final ServerName serverName, final ServerMetrics sl) {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>    LOG.info("Registering regionserver=" + serverName);<a name="line.431"></a>
-<span class="sourceLineNo">432</span>    this.onlineServers.put(serverName, sl);<a name="line.432"></a>
-<span class="sourceLineNo">433</span>  }<a name="line.433"></a>
-<span class="sourceLineNo">434</span><a name="line.434"></a>
-<span class="sourceLineNo">435</span>  @VisibleForTesting<a name="line.435"></a>
-<span class="sourceLineNo">436</span>  public ConcurrentNavigableMap&lt;byte[], Long&gt; getFlushedSequenceIdByRegion() {<a name="line.436"></a>
-<span class="sourceLineNo">437</span>    return flushedSequenceIdByRegion;<a name="line.437"></a>
-<span class="sourceLineNo">438</span>  }<a name="line.438"></a>
-<span class="sourceLineNo">439</span><a name="line.439"></a>
-<span class="sourceLineNo">440</span>  public RegionStoreSequenceIds getLastFlushedSequenceId(byte[] encodedRegionName) {<a name="line.440"></a>
-<span class="sourceLineNo">441</span>    RegionStoreSequenceIds.Builder builder = RegionStoreSequenceIds.newBuilder();<a name="line.441"></a>
-<span class="sourceLineNo">442</span>    Long seqId = flushedSequenceIdByRegion.get(encodedRegionName);<a name="line.442"></a>
-<span class="sourceLineNo">443</span>    builder.setLastFlushedSequenceId(seqId != null ? seqId.longValue() : HConstants.NO_SEQNUM);<a name="line.443"></a>
-<span class="sourceLineNo">444</span>    Map&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.444"></a>
-<span class="sourceLineNo">445</span>        storeFlushedSequenceIdsByRegion.get(encodedRegionName);<a name="line.445"></a>
-<span class="sourceLineNo">446</span>    if (storeFlushedSequenceId != null) {<a name="line.446"></a>
-<span class="sourceLineNo">447</span>      for (Map.Entry&lt;byte[], Long&gt; entry : storeFlushedSequenceId.entrySet()) {<a name="line.447"></a>
-<span class="sourceLineNo">448</span>        builder.addStoreSequenceId(StoreSequenceId.newBuilder()<a name="line.448"></a>
-<span class="sourceLineNo">449</span>            .setFamilyName(UnsafeByteOperations.unsafeWrap(entry.getKey()))<a name="line.449"></a>
-<span class="sourceLineNo">450</span>            .setSequenceId(entry.getValue().longValue()).build());<a name="line.450"></a>
-<span class="sourceLineNo">451</span>      }<a name="line.451"></a>
-<span class="sourceLineNo">452</span>    }<a name="line.452"></a>
-<span class="sourceLineNo">453</span>    return builder.build();<a name="line.453"></a>
-<span class="sourceLineNo">454</span>  }<a name="line.454"></a>
-<span class="sourceLineNo">455</span><a name="line.455"></a>
-<span class="sourceLineNo">456</span>  /**<a name="line.456"></a>
-<span class="sourceLineNo">457</span>   * @param serverName<a name="line.457"></a>
-<span class="sourceLineNo">458</span>   * @return ServerMetrics if serverName is known else null<a name="line.458"></a>
-<span class="sourceLineNo">459</span>   */<a name="line.459"></a>
-<span class="sourceLineNo">460</span>  public ServerMetrics getLoad(final ServerName serverName) {<a name="line.460"></a>
-<span class="sourceLineNo">461</span>    return this.onlineServers.get(serverName);<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  }<a name="line.462"></a>
-<span class="sourceLineNo">463</span><a name="line.463"></a>
-<span class="sourceLineNo">464</span>  /**<a name="line.464"></a>
-<span class="sourceLineNo">465</span>   * Compute the average load across all region servers.<a name="line.465"></a>
-<span class="sourceLineNo">466</span>   * Currently, this uses a very naive computation - just uses the number of<a name="line.466"></a>
-<span class="sourceLineNo">467</span>   * regions being served, ignoring stats about number of requests.<a name="line.467"></a>
-<span class="sourceLineNo">468</span>   * @return the average load<a name="line.468"></a>
-<span class="sourceLineNo">469</span>   */<a name="line.469"></a>
-<span class="sourceLineNo">470</span>  public double getAverageLoad() {<a name="line.470"></a>
-<span class="sourceLineNo">471</span>    int totalLoad = 0;<a name="line.471"></a>
-<span class="sourceLineNo">472</span>    int numServers = 0;<a name="line.472"></a>
-<span class="sourceLineNo">473</span>    for (ServerMetrics sl : this.onlineServers.values()) {<a name="line.473"></a>
-<span class="sourceLineNo">474</span>      numServers++;<a name="line.474"></a>
-<span class="sourceLineNo">475</span>      totalLoad += sl.getRegionMetrics().size();<a name="line.475"></a>
-<span class="sourceLineNo">476</span>    }<a name="line.476"></a>
-<span class="sourceLineNo">477</span>    return numServers == 0 ? 0 :<a name="line.477"></a>
-<span class="sourceLineNo">478</span>      (double)totalLoad / (double)numServers;<a name="line.478"></a>
-<span class="sourceLineNo">479</span>  }<a name="line.479"></a>
-<span class="sourceLineNo">480</span><a name="line.480"></a>
-<span class="sourceLineNo">481</span>  /** @return the count of active regionservers */<a name="line.481"></a>
-<span class="sourceLineNo">482</span>  public int countOfRegionServers() {<a name="line.482"></a>
-<span class="sourceLineNo">483</span>    // Presumes onlineServers is a concurrent map<a name="line.483"></a>
-<span class="sourceLineNo">484</span>    return this.onlineServers.size();<a name="line.484"></a>
-<span class="sourceLineNo">485</span>  }<a name="line.485"></a>
-<span class="sourceLineNo">486</span><a name="line.486"></a>
-<span class="sourceLineNo">487</span>  /**<a name="line.487"></a>
-<span class="sourceLineNo">488</span>   * @return Read-only map of servers to serverinfo<a name="line.488"></a>
-<span class="sourceLineNo">489</span>   */<a name="line.489"></a>
-<span class="sourceLineNo">490</span>  public Map&lt;ServerName, ServerMetrics&gt; getOnlineServers() {<a name="line.490"></a>
-<span class="sourceLineNo">491</span>    // Presumption is that iterating the returned Map is OK.<a name="line.491"></a>
-<span class="sourceLineNo">492</span>    synchronized (this.onlineServers) {<a name="line.492"></a>
-<span class="sourceLineNo">493</span>      return Collections.unmodifiableMap(this.onlineServers);<a name="line.493"></a>
-<span class="sourceLineNo">494</span>    }<a name="line.494"></a>
-<span class="sourceLineNo">495</span>  }<a name="line.495"></a>
-<span class="sourceLineNo">496</span><a name="line.496"></a>
-<span class="sourceLineNo">497</span>  public DeadServer getDeadServers() {<a name="line.497"></a>
-<span class="sourceLineNo">498</span>    return this.deadservers;<a name="line.498"></a>
-<span class="sourceLineNo">499</span>  }<a name="line.499"></a>
-<span class="sourceLineNo">500</span><a name="line.500"></a>
-<span class="sourceLineNo">501</span>  /**<a name="line.501"></a>
-<span class="sourceLineNo">502</span>   * Checks if any dead servers are currently in progress.<a name="line.502"></a>
-<span class="sourceLineNo">503</span>   * @return true if any RS are being processed as dead, false if not<a name="line.503"></a>
-<span class="sourceLineNo">504</span>   */<a name="line.504"></a>
-<span class="sourceLineNo">505</span>  public boolean areDeadServersInProgress() {<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    return this.deadservers.areDeadServersInProgress();<a name="line.506"></a>
-<span class="sourceLineNo">507</span>  }<a name="line.507"></a>
-<span class="sourceLineNo">508</span><a name="line.508"></a>
-<span class="sourceLineNo">509</span>  void letRegionServersShutdown() {<a name="line.509"></a>
-<span class="sourceLineNo">510</span>    long previousLogTime = 0;<a name="line.510"></a>
-<span class="sourceLineNo">511</span>    ServerName sn = master.getServerName();<a name="line.511"></a>
-<span class="sourceLineNo">512</span>    ZKWatcher zkw = master.getZooKeeper();<a name="line.512"></a>
-<span class="sourceLineNo">513</span>    int onlineServersCt;<a name="line.513"></a>
-<span class="sourceLineNo">514</span>    while ((onlineServersCt = onlineServers.size()) &gt; 0){<a name="line.514"></a>
-<span class="sourceLineNo">515</span><a name="line.515"></a>
-<span class="sourceLineNo">516</span>      if (System.currentTimeMillis() &gt; (previousLogTime + 1000)) {<a name="line.516"></a>
-<span class="sourceLineNo">517</span>        Set&lt;ServerName&gt; remainingServers = onlineServers.keySet();<a name="line.517"></a>
-<span class="sourceLineNo">518</span>        synchronized (onlineServers) {<a name="line.518"></a>
-<span class="sourceLineNo">519</span>          if (remainingServers.size() == 1 &amp;&amp; remainingServers.contains(sn)) {<a name="line.519"></a>
-<span class="sourceLineNo">520</span>            // Master will delete itself later.<a name="line.520"></a>
-<span class="sourceLineNo">521</span>            return;<a name="line.521"></a>
-<span class="sourceLineNo">522</span>          }<a name="line.522"></a>
-<span class="sourceLineNo">523</span>        }<a name="line.523"></a>
-<span class="sourceLineNo">524</span>        StringBuilder sb = new StringBuilder();<a name="line.524"></a>
-<span class="sourceLineNo">525</span>        // It's ok here to not sync on onlineServers - merely logging<a name="line.525"></a>
-<span class="sourceLineNo">526</span>        for (ServerName key : remainingServers) {<a name="line.526"></a>
-<span class="sourceLineNo">527</span>          if (sb.length() &gt; 0) {<a name="line.527"></a>
-<span class="sourceLineNo">528</span>            sb.append(", ");<a name="line.528"></a>
-<span class="sourceLineNo">529</span>          }<a name="line.529"></a>
-<span class="sourceLineNo">530</span>          sb.append(key);<a name="line.530"></a>
-<span class="sourceLineNo">531</span>        }<a name="line.531"></a>
-<span class="sourceLineNo">532</span>        LOG.info("Waiting on regionserver(s) " + sb.toString());<a name="line.532"></a>
-<span class="sourceLineNo">533</span>        previousLogTime = System.currentTimeMillis();<a name="line.533"></a>
-<span class="sourceLineNo">534</span>      }<a name="line.534"></a>
-<span class="sourceLineNo">535</span><a name="line.535"></a>
-<span class="sourceLineNo">536</span>      try {<a name="line.536"></a>
-<span class="sourceLineNo">537</span>        List&lt;String&gt; servers = getRegionServersInZK(zkw);<a name="line.537"></a>
-<span class="sourceLineNo">538</span>        if (servers == null || servers.isEmpty() || (servers.size() == 1<a name="line.538"></a>
-<span class="sourceLineNo">539</span>            &amp;&amp; servers.contains(sn.toString()))) {<a name="line.539"></a>
-<span class="sourceLineNo">540</span>          LOG.info("ZK shows there is only the master self online, exiting now");<a name="line.540"></a>
-<span class="sourceLineNo">541</span>          // Master could have lost some ZK events, no need to wait more.<a name="line.541"></a>
-<span class="sourceLineNo">542</span>          break;<a name="line.542"></a>
-<span class="sourceLineNo">543</span>        }<a name="line.543"></a>
-<span class="sourceLineNo">544</span>      } catch (KeeperException ke) {<a name="line.544"></a>
-<span class="sourceLineNo">545</span>        LOG.warn("Failed to list regionservers", ke);<a name="line.545"></a>
-<span class="sourceLineNo">546</span>        // ZK is malfunctioning, don't hang here<a name="line.546"></a>
-<span class="sourceLineNo">547</span>        break;<a name="line.547"></a>
-<span class="sourceLineNo">548</span>      }<a name="line.548"></a>
-<span class="sourceLineNo">549</span>      synchronized (onlineServers) {<a name="line.549"></a>
-<span class="sourceLineNo">550</span>        try {<a name="line.550"></a>
-<span class="sourceLineNo">551</span>          if (onlineServersCt == onlineServers.size()) onlineServers.wait(100);<a name="line.551"></a>
-<span class="sourceLineNo">552</span>        } catch (InterruptedException ignored) {<a name="line.552"></a>
-<span class="sourceLineNo">553</span>          // continue<a name="line.553"></a>
-<span class="sourceLineNo">554</span>        }<a name="line.554"></a>
-<span class="sourceLineNo">555</span>      }<a name="line.555"></a>
-<span class="sourceLineNo">556</span>    }<a name="line.556"></a>
-<span class="sourceLineNo">557</span>  }<a name="line.557"></a>
-<span class="sourceLineNo">558</span><a name="line.558"></a>
-<span class="sourceLineNo">559</span>  private List&lt;String&gt; getRegionServersInZK(final ZKWatcher zkw)<a name="line.559"></a>
-<span class="sourceLineNo">560</span>  throws KeeperException {<a name="line.560"></a>
-<span class="sourceLineNo">561</span>    return ZKUtil.listChildrenNoWatch(zkw, zkw.getZNodePaths().rsZNode);<a name="line.561"></a>
-<span class="sourceLineNo">562</span>  }<a name="line.562"></a>
-<span class="sourceLineNo">563</span><a name="line.563"></a>
-<span class="sourceLineNo">564</span>  /**<a name="line.564"></a>
-<span class="sourceLineNo">565</span>   * Expire the passed server. Add it to list of dead servers and queue a shutdown processing.<a name="line.565"></a>
-<span class="sourceLineNo">566</span>   * @return pid if we queued a ServerCrashProcedure else {@link Procedure#NO_PROC_ID} if we did<a name="line.566"></a>
-<span class="sourceLineNo">567</span>   *         not (could happen for many reasons including the fact that its this server that is<a name="line.567"></a>
-<span class="sourceLineNo">568</span>   *         going down or we already have queued an SCP for this server or SCP processing is<a name="line.568"></a>
-<span class="sourceLineNo">569</span>   *         currently disabled because we are in startup phase).<a name="line.569"></a>
-<span class="sourceLineNo">570</span>   */<a name="line.570"></a>
-<span class="sourceLineNo">571</span>  @VisibleForTesting // Redo test so we can make this protected.<a name="line.571"></a>
-<span class="sourceLineNo">572</span>  public synchronized long expireServer(final ServerName serverName) {<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    return expireServer(serverName, false);<a name="line.573"></a>
-<span class="sourceLineNo">574</span><a name="line.574"></a>
-<span class="sourceLineNo">575</span>  }<a name="line.575"></a>
-<span class="sourceLineNo">576</span><a name="line.576"></a>
-<span class="sourceLineNo">577</span>  synchronized long expireServer(final ServerName serverName, boolean force) {<a name="line.577"></a>
-<span class="sourceLineNo">578</span>    // THIS server is going down... can't handle our own expiration.<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    if (serverName.equals(master.getServerName())) {<a name="line.579"></a>
-<span class="sourceLineNo">580</span>      if (!(master.isAborted() || master.isStopped())) {<a name="line.580"></a>
-<span class="sourceLineNo">581</span>        master.stop("We lost our znode?");<a name="line.581"></a>
-<span class="sourceLineNo">582</span>      }<a name="line.582"></a>
-<span class="sourceLineNo">583</span>      return Procedure.NO_PROC_ID;<a name="line.583"></a>
-<span class="sourceLineNo">584</span>    }<a name="line.584"></a>
-<span class="sourceLineNo">585</span>    if (this.deadservers.isDeadServer(serverName)) {<a name="line.585"></a>
-<span class="sourceLineNo">586</span>      LOG.warn("Expiration called on {} but already in DeadServer", serverName);<a name="line.586"></a>
-<span class="sourceLineNo">587</span>      return Procedure.NO_PROC_ID;<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    }<a name="line.588"></a>
-<span class="sourceLineNo">589</span>    moveFromOnlineToDeadServers(serverName);<a name="line.589"></a>
-<span class="sourceLineNo">590</span><a name="line.590"></a>
-<span class="sourceLineNo">591</span>    // If server is in draining mode, remove corresponding znode<a name="line.591"></a>
-<span class="sourceLineNo">592</span>    // In some tests, the mocked HM may not have ZK Instance, hence null check<a name="line.592"></a>
-<span class="sourceLineNo">593</span>    if (master.getZooKeeper() != null) {<a name="line.593"></a>
-<span class="sourceLineNo">594</span>      String drainingZnode = ZNodePaths<a name="line.594"></a>
-<span class="sourceLineNo">595</span>        .joinZNode(master.getZooKeeper().getZNodePaths().drainingZNode, serverName.getServerName());<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      try {<a name="line.596"></a>
-<span class="sourceLineNo">597</span>        ZKUtil.deleteNodeFailSilent(master.getZooKeeper(), drainingZnode);<a name="line.597"></a>
-<span class="sourceLineNo">598</span>      } catch (KeeperException e) {<a name="line.598"></a>
-<span class="sourceLineNo">599</span>        LOG.warn("Error deleting the draining znode for stopping server " + serverName.getServerName(), e);<a name="line.599"></a>
-<span class="sourceLineNo">600</span>      }<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    }<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    <a name="line.602"></a>
-<span class="sourceLineNo">603</span>    // If cluster is going down, yes, servers are going to be expiring; don't<a name="line.603"></a>
-<span class="sourceLineNo">604</span>    // process as a dead server<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    if (isClusterShutdown()) {<a name="line.605"></a>
-<span class="sourceLineNo">606</span>      LOG.info("Cluster shutdown set; " + serverName +<a name="line.606"></a>
-<span class="sourceLineNo">607</span>        " expired; onlineServers=" + this.onlineServers.size());<a name="line.607"></a>
-<span class="sourceLineNo">608</span>      if (this.onlineServers.isEmpty()) {<a name="line.608"></a>
-<span class="sourceLineNo">609</span>        master.stop("Cluster shutdown set; onlineServer=0");<a name="line.609"></a>
-<span class="sourceLineNo">610</span>      }<a name="line.610"></a>
-<span class="sourceLineNo">611</span>      return Procedure.NO_PROC_ID;<a name="line.611"></a>
-<span class="sourceLineNo">612</span>    }<a name="line.612"></a>
-<span class="sourceLineNo">613</span>    LOG.info("Processing expiration of " + serverName + " on " + this.master.getServerName());<a name="line.613"></a>
-<span class="sourceLineNo">614</span>    long pid = master.getAssignmentManager().submitServerCrash(serverName, true, force);<a name="line.614"></a>
-<span class="sourceLineNo">615</span>    // Tell our listeners that a server was removed<a name="line.615"></a>
-<span class="sourceLineNo">616</span>    if (!this.listeners.isEmpty()) {<a name="line.616"></a>
-<span class="sourceLineNo">617</span>      this.listeners.stream().forEach(l -&gt; l.serverRemoved(serverName));<a name="line.617"></a>
-<span class="sourceLineNo">618</span>    }<a name="line.618"></a>
-<span class="sourceLineNo">619</span>    // trigger a persist of flushedSeqId<a name="line.619"></a>
-<span class="sourceLineNo">620</span>    if (flushedSeqIdFlusher != null) {<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      flushedSeqIdFlusher.triggerNow();<a name="line.621"></a>
-<span class="sourceLineNo">622</span>    }<a name="line.622"></a>
-<span class="sourceLineNo">623</span>    return pid;<a name="line.623"></a>
-<span class="sourceLineNo">624</span>  }<a name="line.624"></a>
-<span class="sourceLineNo">625</span><a name="line.625"></a>
-<span class="sourceLineNo">626</span>  /**<a name="line.626"></a>
-<span class="sourceLineNo">627</span>   * Called when server has expired.<a name="line.627"></a>
-<span class="sourceLineNo">628</span>   */<a name="line.628"></a>
-<span class="sourceLineNo">629</span>  // Locking in this class needs cleanup.<a name="line.629"></a>
-<span class="sourceLineNo">630</span>  @VisibleForTesting<a name="line.630"></a>
-<span class="sourceLineNo">631</span>  public synchronized void moveFromOnlineToDeadServers(final ServerName sn) {<a name="line.631"></a>
-<span class="sourceLineNo">632</span>    synchronized (this.onlineServers) {<a name="line.632"></a>
-<span class="sourceLineNo">633</span>      boolean online = this.onlineServers.containsKey(sn);<a name="line.633"></a>
-<span class="sourceLineNo">634</span>      if (online) {<a name="line.634"></a>
-<span class="sourceLineNo">635</span>        // Remove the server from the known servers lists and update load info BUT<a name="line.635"></a>
-<span class="sourceLineNo">636</span>        // add to deadservers first; do this so it'll show in dead servers list if<a name="line.636"></a>
-<span class="sourceLineNo">637</span>        // not in online servers list.<a name="line.637"></a>
-<span class="sourceLineNo">638</span>        this.deadservers.putIfAbsent(sn);<a name="line.638"></a>
-<span class="sourceLineNo">639</span>        this.onlineServers.remove(sn);<a name="line.639"></a>
-<span class="sourceLineNo">640</span>        onlineServers.notifyAll();<a name="line.640"></a>
-<span class="sourceLineNo">641</span>      } else {<a name="line.641"></a>
-<span class="sourceLineNo">642</span>        // If not online, that is odd but may happen if 'Unknown Servers' -- where meta<a name="line.642"></a>
-<span class="sourceLineNo">643</span>        // has references to servers not online nor in dead servers list. If<a name="line.643"></a>
-<span class="sourceLineNo">644</span>        // 'Unknown Server', don't add to DeadServers else will be there for ever.<a name="line.644"></a>
-<span class="sourceLineNo">645</span>        LOG.trace("Expiration of {} but server not online", sn);<a name="line.645"></a>
-<span class="sourceLineNo">646</span>      }<a name="line.646"></a>
-<span class="sourceLineNo">647</span>    }<a name="line.647"></a>
-<span class="sourceLineNo">648</span>  }<a name="line.648"></a>
-<span class="sourceLineNo">649</span><a name="line.649"></a>
-<span class="sourceLineNo">650</span>  /*<a name="line.650"></a>
-<span class="sourceLineNo">651</span>   * Remove the server from the drain list.<a name="line.651"></a>
-<span class="sourceLineNo">652</span>   */<a name="line.652"></a>
-<span class="sourceLineNo">653</span>  public synchronized boolean removeServerFromDrainList(final ServerName sn) {<a name="line.653"></a>
-<span class="sourceLineNo">654</span>    // Warn if the server (sn) is not online.  ServerName is of the form:<a name="line.654"></a>
-<span class="sourceLineNo">655</span>    // &lt;hostname&gt; , &lt;port&gt; , &lt;startcode&gt;<a name="line.655"></a>
-<span class="sourceLineNo">656</span><a name="line.656"></a>
-<span class="sourceLineNo">657</span>    if (!this.isServerOnline(sn)) {<a name="line.657"></a>
-<span class="sourceLineNo">658</span>      LOG.warn("Server " + sn + " is not currently online. " +<a name="line.658"></a>
-<span class="sourceLineNo">659</span>               "Removing from draining list anyway, as requested.");<a name="line.659"></a>
-<span class="sourceLineNo">660</span>    }<a name="line.660"></a>
-<span class="sourceLineNo">661</span>    // Remove the server from the draining servers lists.<a name="line.661"></a>
-<span class="sourceLineNo">662</span>    return this.drainingServers.remove(sn);<a name="line.662"></a>
-<span class="sourceLineNo">663</span>  }<a name="line.663"></a>
-<span class="sourceLineNo">664</span><a name="line.664"></a>
-<span class="sourceLineNo">665</span>  /**<a name="line.665"></a>
-<span class="sourceLineNo">666</span>   * Add the server to the drain list.<a name="line.666"></a>
-<span class="sourceLineNo">667</span>   * @param sn<a name="line.667"></a>
-<span class="sourceLineNo">668</span>   * @return True if the server is added or the server is already on the drain list.<a name="line.668"></a>
-<span class="sourceLineNo">669</span>   */<a name="line.669"></a>
-<span class="sourceLineNo">670</span>  public synchronized boolean addServerToDrainList(final ServerName sn) {<a name="line.670"></a>
-<span class="sourceLineNo">671</span>    // Warn if the server (sn) is not online.  ServerName is of the form:<a name="line.671"></a>
-<span class="sourceLineNo">672</span>    // &lt;hostname&gt; , &lt;port&gt; , &lt;startcode&gt;<a name="line.672"></a>
-<span class="sourceLineNo">673</span><a name="line.673"></a>
-<span class="sourceLineNo">674</span>    if (!this.isServerOnline(sn)) {<a name="line.674"></a>
-<span class="sourceLineNo">675</span>      LOG.warn("Server " + sn + " is not currently online. " +<a name="line.675"></a>
-<span class="sourceLineNo">676</span>               "Ignoring request to add it to draining list.");<a name="line.676"></a>
-<span class="sourceLineNo">677</span>      return false;<a name="line.677"></a>
-<span class="sourceLineNo">678</span>    }<a name="line.678"></a>
-<span class="sourceLineNo">679</span>    // Add the server to the draining servers lists, if it's not already in<a name="line.679"></a>
-<span class="sourceLineNo">680</span>    // it.<a name="line.680"></a>
-<span class="sourceLineNo">681</span>    if (this.drainingServers.contains(sn)) {<a name="line.681"></a>
-<span class="sourceLineNo">682</span>      LOG.warn("Server " + sn + " is already in the draining server list." +<a name="line.682"></a>
-<span class="sourceLineNo">683</span>               "Ignoring request to add it again.");<a name="line.683"></a>
-<span class="sourceLineNo">684</span>      return true;<a name="line.684"></a>
-<span class="sourceLineNo">685</span>    }<a name="line.685"></a>
-<span class="sourceLineNo">686</span>    LOG.info("Server " + sn + " added to draining server list.");<a name="line.686"></a>
-<span class="sourceLineNo">687</span>    return this.drainingServers.add(sn);<a name="line.687"></a>
-<span class="sourceLineNo">688</span>  }<a name="line.688"></a>
-<span class="sourceLineNo">689</span><a name="line.689"></a>
-<span class="sourceLineNo">690</span>  /**<a name="line.690"></a>
-<span class="sourceLineNo">691</span>   * Contacts a region server and waits up to timeout ms<a name="line.691"></a>
-<span class="sourceLineNo">692</span>   * to close the region.  This bypasses the active hmaster.<a name="line.692"></a>
-<span class="sourceLineNo">693</span>   * Pass -1 as timeout if you do not want to wait on result.<a name="line.693"></a>
-<span class="sourceLineNo">694</span>   */<a name="line.694"></a>
-<span class="sourceLineNo">695</span>  public static void closeRegionSilentlyAndWait(AsyncClusterConnection connection,<a name="line.695"></a>
-<span class="sourceLineNo">696</span>      ServerName server, RegionInfo region, long timeout) throws IOException, InterruptedException {<a name="line.696"></a>
-<span class="sourceLineNo">697</span>    AsyncRegionServerAdmin admin = connection.getRegionServerAdmin(server);<a name="line.697"></a>
-<span class="sourceLineNo">698</span>    try {<a name="line.698"></a>
-<span class="sourceLineNo">699</span>      FutureUtils.get(<a name="line.699"></a>
-<span class="sourceLineNo">700</span>        admin.closeRegion(ProtobufUtil.buildCloseRegionRequest(server, region.getRegionName())));<a name="line.700"></a>
-<span class="sourceLineNo">701</span>    } catch (IOException e) {<a name="line.701"></a>
-<span class="sourceLineNo">702</span>      LOG.warn("Exception when closing region: " + region.getRegionNameAsString(), e);<a name="line.702"></a>
-<span class="sourceLineNo">703</span>    }<a name="line.703"></a>
-<span class="sourceLineNo">704</span>    if (timeout &lt; 0) {<a name="line.704"></a>
-<span class="sourceLineNo">705</span>      return;<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    }<a name="line.706"></a>
-<span class="sourceLineNo">707</span>    long expiration = timeout + System.currentTimeMillis();<a name="line.707"></a>
-<span class="sourceLineNo">708</span>    while (System.currentTimeMillis() &lt; expiration) {<a name="line.708"></a>
-<span class="sourceLineNo">709</span>      try {<a name="line.709"></a>
-<span class="sourceLineNo">710</span>        RegionInfo rsRegion = ProtobufUtil.toRegionInfo(FutureUtils<a name="line.710"></a>
-<span class="sourceLineNo">711</span>          .get(<a name="line.711"></a>
-<span class="sourceLineNo">712</span>            admin.getRegionInfo(RequestConverter.buildGetRegionInfoRequest(region.getRegionName())))<a name="line.712"></a>
-<span class="sourceLineNo">713</span>          .getRegionInfo());<a name="line.713"></a>
-<span class="sourceLineNo">714</span>        if (rsRegion == null) {<a name="line.714"></a>
-<span class="sourceLineNo">715</span>          return;<a name="line.715"></a>
-<span class="sourceLineNo">716</span>        }<a name="line.716"></a>
-<span class="sourceLineNo">717</span>      } catch (IOException ioe) {<a name="line.717"></a>
-<span class="sourceLineNo">718</span>        if (ioe instanceof NotServingRegionException) {<a name="line.718"></a>
-<span class="sourceLineNo">719</span>          // no need to retry again<a name="line.719"></a>
-<span class="sourceLineNo">720</span>          return;<a name="line.720"></a>
-<span class="sourceLineNo">721</span>        }<a name="line.721"></a>
-<span class="sourceLineNo">722</span>        LOG.warn("Exception when retrieving regioninfo from: " + region.getRegionNameAsString(),<a name="line.722"></a>
-<span class="sourceLineNo">723</span>          ioe);<a name="line.723"></a>
-<span class="sourceLineNo">724</span>      }<a name="line.724"></a>
-<span class="sourceLineNo">725</span>      Thread.sleep(1000);<a name="line.725"></a>
-<span class="sourceLineNo">726</span>    }<a name="line.726"></a>
-<span class="sourceLineNo">727</span>    throw new IOException("Region " + region + " failed to close within" + " timeout " + timeout);<a name="line.727"></a>
-<span class="sourceLineNo">728</span>  }<a name="line.728"></a>
-<span class="sourceLineNo">729</span><a name="line.729"></a>
-<span class="sourceLineNo">730</span>  /**<a name="line.730"></a>
-<span class="sourceLineNo">731</span>   * Calculate min necessary to start. This is not an absolute. It is just<a name="line.731"></a>
-<span class="sourceLineNo">732</span>   * a friction that will cause us hang around a bit longer waiting on<a name="line.732"></a>
-<span class="sourceLineNo">733</span>   * RegionServers to check-in.<a name="line.733"></a>
-<span class="sourceLineNo">734</span>   */<a name="line.734"></a>
-<span class="sourceLineNo">735</span>  private int getMinToStart() {<a name="line.735"></a>
-<span class="sourceLineNo">736</span>    if (master.isInMaintenanceMode()) {<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      // If in maintenance mode, then master hosting meta will be the only server available<a name="line.737"></a>
-<span class="sourceLineNo">738</span>      return 1;<a name="line.738"></a>
-<span class="sourceLineNo">739</span>    }<a name="line.739"></a>
-<span class="sourceLineNo">740</span><a name="line.740"></a>
-<span class="sourceLineNo">741</span>    int minimumRequired = 1;<a name="line.741"></a>
-<span class="sourceLineNo">742</span>    if (LoadBalancer.isTablesOnMaster(master.getConfiguration()) &amp;&amp;<a name="line.742"></a>
-<span class="sourceLineNo">743</span>        LoadBalancer.isSystemTablesOnlyOnMaster(master.getConfiguration())) {<a name="line.743"></a>
-<span class="sourceLineNo">744</span>      // If Master is carrying regions it will show up as a 'server', but is not handling user-<a name="line.744"></a>
-<span class="sourceLineNo">745</span>      // space regions, so we need a second server.<a name="line.745"></a>
-<span class="sourceLineNo">746</span>      minimumRequired = 2;<a name="line.746"></a>
-<span class="sourceLineNo">747</span>    }<a name="line.747"></a>
-<span class="sourceLineNo">748</span><a name="line.748"></a>
-<span class="sourceLineNo">749</span>    int minToStart = this.master.getConfiguration().getInt(WAIT_ON_REGIONSERVERS_MINTOSTART, -1);<a name="line.749"></a>
-<span class="sourceLineNo">750</span>    // Ensure we are never less than minimumRequired else stuff won't work.<a name="line.750"></a>
-<span class="sourceLineNo">751</span>    return Math.max(minToStart, minimumRequired);<a name="line.751"></a>
-<span class="sourceLineNo">752</span>  }<a name="line.752"></a>
-<span class="sourceLineNo">753</span><a name="line.753"></a>
-<span class="sourceLineNo">754</span>  /**<a name="line.754"></a>
-<span class="sourceLineNo">755</span>   * Wait for the region servers to report in.<a name="line.755"></a>
-<span class="sourceLineNo">756</span>   * We will wait until one of this condition is met:<a name="line.756"></a>
-<span class="sourceLineNo">757</span>   *  - the master is stopped<a name="line.757"></a>
-<span class="sourceLineNo">758</span>   *  - the 'hbase.master.wait.on.regionservers.maxtostart' number of<a name="line.758"></a>
-<span class="sourceLineNo">759</span>   *    region servers is reached<a name="line.759"></a>
-<span class="sourceLineNo">760</span>   *  - the 'hbase.master.wait.on.regionservers.mintostart' is reached AND<a name="line.760"></a>
-<span class="sourceLineNo">761</span>   *   there have been no new region server in for<a name="line.761"></a>
-<span class="sourceLineNo">762</span>   *      'hbase.master.wait.on.regionservers.interval' time AND<a name="line.762"></a>
-<span class="sourceLineNo">763</span>   *   the 'hbase.master.wait.on.regionservers.timeout' is reached<a name="line.763"></a>
-<span class="sourceLineNo">764</span>   *<a name="line.764"></a>
-<span class="sourceLineNo">765</span>   * @throws InterruptedException<a name="line.765"></a>
-<span class="sourceLineNo">766</span>   */<a name="line.766"></a>
-<span class="sourceLineNo">767</span>  public void waitForRegionServers(MonitoredTask status) throws InterruptedException {<a name="line.767"></a>
-<span class="sourceLineNo">768</span>    final long interval = this.master.getConfiguration().<a name="line.768"></a>
-<span class="sourceLineNo">769</span>        getLong(WAIT_ON_REGIONSERVERS_INTERVAL, 1500);<a name="line.769"></a>
-<span class="sourceLineNo">770</span>    final long timeout = this.master.getConfiguration().<a name="line.770"></a>
-<span class="sourceLineNo">771</span>        getLong(WAIT_ON_REGIONSERVERS_TIMEOUT, 4500);<a name="line.771"></a>
-<span class="sourceLineNo">772</span>    // Min is not an absolute; just a friction making us wait longer on server checkin.<a name="line.772"></a>
-<span class="sourceLineNo">773</span>    int minToStart = getMinToStart();<a name="line.773"></a>
-<span class="sourceLineNo">774</span>    int maxToStart = this.master.getConfiguration().<a name="line.774"></a>
-<span class="sourceLineNo">775</span>        getInt(WAIT_ON_REGIONSERVERS_MAXTOSTART, Integer.MAX_VALUE);<a name="line.775"></a>
-<span class="sourceLineNo">776</span>    if (maxToStart &lt; minToStart) {<a name="line.776"></a>
-<span class="sourceLineNo">777</span>      LOG.warn(String.format("The value of '%s' (%d) is set less than '%s' (%d), ignoring.",<a name="line.777"></a>
-<span class="sourceLineNo">778</span>          WAIT_ON_REGIONSERVERS_MAXTOSTART, maxToStart,<a name="line.778"></a>
-<span class="sourceLineNo">779</span>          WAIT_ON_REGIONSERVERS_MINTOSTART, minToStart));<a name="line.779"></a>
-<span class="sourceLineNo">780</span>      maxToStart = Integer.MAX_VALUE;<a name="line.780"></a>
-<span class="sourceLineNo">781</span>    }<a name="line.781"></a>
-<span class="sourceLineNo">782</span><a name="line.782"></a>
-<span class="sourceLineNo">783</span>    long now =  System.currentTimeMillis();<a name="line.783"></a>
-<span class="sourceLineNo">784</span>    final long startTime = now;<a name="line.784"></a>
-<span class="sourceLineNo">785</span>    long slept = 0;<a name="line.785"></a>
-<span class="sourceLineNo">786</span>    long lastLogTime = 0;<a name="line.786"></a>
-<span class="sourceLineNo">787</span>    long lastCountChange = startTime;<a name="line.787"></a>
-<span class="sourceLineNo">788</span>    int count = countOfRegionServers();<a name="line.788"></a>
-<span class="sourceLineNo">789</span>    int oldCount = 0;<a name="line.789"></a>
-<span class="sourceLineNo">790</span>    // This while test is a little hard to read. We try to comment it in below but in essence:<a name="line.790"></a>
-<span class="sourceLineNo">791</span>    // Wait if Master is not stopped and the number of regionservers that have checked-in is<a name="line.791"></a>
-<span class="sourceLineNo">792</span>    // less than the maxToStart. Both of these conditions will be true near universally.<a name="line.792"></a>
-<span class="sourceLineNo">793</span>    // Next, we will keep cycling if ANY of the following three conditions are true:<a name="line.793"></a>
-<span class="sourceLineNo">794</span>    // 1. The time since a regionserver registered is &lt; interval (means servers are actively checking in).<a name="line.794"></a>
-<span class="sourceLineNo">795</span>    // 2. We are under the total timeout.<a name="line.795"></a>
-<span class="sourceLineNo">796</span>    // 3. The count of servers is &lt; minimum.<a name="line.796"></a>
-<span class="sourceLineNo">797</span>    for (ServerListener listener: this.listeners) {<a name="line.797"></a>
-<span class="sourceLineNo">798</span>      listener.waiting();<a name="line.798"></a>
-<span class="sourceLineNo">799</span>    }<a name="line.799"></a>
-<span class="sourceLineNo">800</span>    while (!this.master.isStopped() &amp;&amp; !isClusterShutdown() &amp;&amp; count &lt; maxToStart &amp;&amp;<a name="line.800"></a>
-<span class="sourceLineNo">801</span>        ((lastCountChange + interval) &gt; now || timeout &gt; slept || count &lt; minToStart)) {<a name="line.801"></a>
-<span class="sourceLineNo">802</span>      // Log some info at every interval time or if there is a change<a name="line.802"></a>
-<span class="sourceLineNo">803</span>      if (oldCount != count || lastLogTime + interval &lt; now) {<a name="line.803"></a>
-<span class="sourceLineNo">804</span>        lastLogTime = now;<a name="line.804"></a>
-<span class="sourceLineNo">805</span>        String msg =<a name="line.805"></a>
-<span class="sourceLineNo">806</span>            "Waiting on regionserver count=" + count + "; waited="+<a name="line.806"></a>
-<span class="sourceLineNo">807</span>                slept + "ms, expecting min=" + minToStart + " server(s), max="+ getStrForMax(maxToStart) +<a name="line.807"></a>
-<span class="sourceLineNo">808</span>                " server(s), " + "timeout=" + timeout + "ms, lastChange=" + (lastCountChange - now) + "ms";<a name="line.808"></a>
-<span class="sourceLineNo">809</span>        LOG.info(msg);<a name="line.809"></a>
-<span class="sourceLineNo">810</span>        status.setStatus(msg);<a name="line.810"></a>
-<span class="sourceLineNo">811</span>      }<a name="line.811"></a>
-<span class="sourceLineNo">812</span><a name="line.812"></a>
-<span class="sourceLineNo">813</span>      // We sleep for some time<a name="line.813"></a>
-<span class="sourceLineNo">814</span>      final long sleepTime = 50;<a name="line.814"></a>
-<span class="sourceLineNo">815</span>      Thread.sleep(sleepTime);<a name="line.815"></a>
-<span class="sourceLineNo">816</span>      now =  System.currentTimeMillis();<a name="line.816"></a>
-<span class="sourceLineNo">817</span>      slept = now - startTime;<a name="line.817"></a>
-<span class="sourceLineNo">818</span><a name="line.818"></a>
-<span class="sourceLineNo">819</span>      oldCount = count;<a name="line.819"></a>
-<span class="sourceLineNo">820</span>      count = countOfRegionServers();<a name="line.820"></a>
-<span class="sourceLineNo">821</span>      if (count != oldCount) {<a name="line.821"></a>
-<span class="sourceLineNo">822</span>        lastCountChange = now;<a name="line.822"></a>
-<span class="sourceLineNo">823</span>      }<a name="line.823"></a>
-<span class="sourceLineNo">824</span>    }<a name="line.824"></a>
-<span class="sourceLineNo">825</span>    // Did we exit the loop because cluster is going down?<a name="line.825"></a>
-<span class="sourceLineNo">826</span>    if (isClusterShutdown()) {<a name="line.826"></a>
-<span class="sourceLineNo">827</span>      this.master.stop("Cluster shutdown");<a name="line.827"></a>
+<span class="sourceLineNo">154</span><a name="line.154"></a>
+<span class="sourceLineNo">155</span>  /**<a name="line.155"></a>
+<span class="sourceLineNo">156</span>   * The last flushed sequence id for a store in a region.<a name="line.156"></a>
+<span class="sourceLineNo">157</span>   */<a name="line.157"></a>
+<span class="sourceLineNo">158</span>  private final ConcurrentNavigableMap&lt;byte[], ConcurrentNavigableMap&lt;byte[], Long&gt;&gt;<a name="line.158"></a>
+<span class="sourceLineNo">159</span>    storeFlushedSequenceIdsByRegion = new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.159"></a>
+<span class="sourceLineNo">160</span><a name="line.160"></a>
+<span class="sourceLineNo">161</span>  /** Map of registered servers to their current load */<a name="line.161"></a>
+<span class="sourceLineNo">162</span>  private final ConcurrentNavigableMap&lt;ServerName, ServerMetrics&gt; onlineServers =<a name="line.162"></a>
+<span class="sourceLineNo">163</span>    new ConcurrentSkipListMap&lt;&gt;();<a name="line.163"></a>
+<span class="sourceLineNo">164</span><a name="line.164"></a>
+<span class="sourceLineNo">165</span>  /** List of region servers that should not get any more new regions. */<a name="line.165"></a>
+<span class="sourceLineNo">166</span>  private final ArrayList&lt;ServerName&gt; drainingServers = new ArrayList&lt;&gt;();<a name="line.166"></a>
+<span class="sourceLineNo">167</span><a name="line.167"></a>
+<span class="sourceLineNo">168</span>  private final MasterServices master;<a name="line.168"></a>
+<span class="sourceLineNo">169</span><a name="line.169"></a>
+<span class="sourceLineNo">170</span>  private final DeadServer deadservers = new DeadServer();<a name="line.170"></a>
+<span class="sourceLineNo">171</span><a name="line.171"></a>
+<span class="sourceLineNo">172</span>  private final long maxSkew;<a name="line.172"></a>
+<span class="sourceLineNo">173</span>  private final long warningSkew;<a name="line.173"></a>
+<span class="sourceLineNo">174</span><a name="line.174"></a>
+<span class="sourceLineNo">175</span>  /** Listeners that are called on server events. */<a name="line.175"></a>
+<span class="sourceLineNo">176</span>  private List&lt;ServerListener&gt; listeners = new CopyOnWriteArrayList&lt;&gt;();<a name="line.176"></a>
+<span class="sourceLineNo">177</span><a name="line.177"></a>
+<span class="sourceLineNo">178</span>  /**<a name="line.178"></a>
+<span class="sourceLineNo">179</span>   * Constructor.<a name="line.179"></a>
+<span class="sourceLineNo">180</span>   */<a name="line.180"></a>
+<span class="sourceLineNo">181</span>  public ServerManager(final MasterServices master) {<a name="line.181"></a>
+<span class="sourceLineNo">182</span>    this.master = master;<a name="line.182"></a>
+<span class="sourceLineNo">183</span>    Configuration c = master.getConfiguration();<a name="line.183"></a>
+<span class="sourceLineNo">184</span>    maxSkew = c.getLong(MAX_CLOCK_SKEW_MS, 30000);<a name="line.184"></a>
+<span class="sourceLineNo">185</span>    warningSkew = c.getLong("hbase.master.warningclockskew", 10000);<a name="line.185"></a>
+<span class="sourceLineNo">186</span>    persistFlushedSequenceId = c.getBoolean(PERSIST_FLUSHEDSEQUENCEID,<a name="line.186"></a>
+<span class="sourceLineNo">187</span>        PERSIST_FLUSHEDSEQUENCEID_DEFAULT);<a name="line.187"></a>
+<span class="sourceLineNo">188</span>  }<a name="line.188"></a>
+<span class="sourceLineNo">189</span><a name="line.189"></a>
+<span class="sourceLineNo">190</span>  /**<a name="line.190"></a>
+<span class="sourceLineNo">191</span>   * Add the listener to the notification list.<a name="line.191"></a>
+<span class="sourceLineNo">192</span>   * @param listener The ServerListener to register<a name="line.192"></a>
+<span class="sourceLineNo">193</span>   */<a name="line.193"></a>
+<span class="sourceLineNo">194</span>  public void registerListener(final ServerListener listener) {<a name="line.194"></a>
+<span class="sourceLineNo">195</span>    this.listeners.add(listener);<a name="line.195"></a>
+<span class="sourceLineNo">196</span>  }<a name="line.196"></a>
+<span class="sourceLineNo">197</span><a name="line.197"></a>
+<span class="sourceLineNo">198</span>  /**<a name="line.198"></a>
+<span class="sourceLineNo">199</span>   * Remove the listener from the notification list.<a name="line.199"></a>
+<span class="sourceLineNo">200</span>   * @param listener The ServerListener to unregister<a name="line.200"></a>
+<span class="sourceLineNo">201</span>   */<a name="line.201"></a>
+<span class="sourceLineNo">202</span>  public boolean unregisterListener(final ServerListener listener) {<a name="line.202"></a>
+<span class="sourceLineNo">203</span>    return this.listeners.remove(listener);<a name="line.203"></a>
+<span class="sourceLineNo">204</span>  }<a name="line.204"></a>
+<span class="sourceLineNo">205</span><a name="line.205"></a>
+<span class="sourceLineNo">206</span>  /**<a name="line.206"></a>
+<span class="sourceLineNo">207</span>   * Let the server manager know a new regionserver has come online<a name="line.207"></a>
+<span class="sourceLineNo">208</span>   * @param request the startup request<a name="line.208"></a>
+<span class="sourceLineNo">209</span>   * @param versionNumber the version number of the new regionserver<a name="line.209"></a>
+<span class="sourceLineNo">210</span>   * @param version the version of the new regionserver, could contain strings like "SNAPSHOT"<a name="line.210"></a>
+<span class="sourceLineNo">211</span>   * @param ia the InetAddress from which request is received<a name="line.211"></a>
+<span class="sourceLineNo">212</span>   * @return The ServerName we know this server as.<a name="line.212"></a>
+<span class="sourceLineNo">213</span>   * @throws IOException<a name="line.213"></a>
+<span class="sourceLineNo">214</span>   */<a name="line.214"></a>
+<span class="sourceLineNo">215</span>  ServerName regionServerStartup(RegionServerStartupRequest request, int versionNumber,<a name="line.215"></a>
+<span class="sourceLineNo">216</span>      String version, InetAddress ia) throws IOException {<a name="line.216"></a>
+<span class="sourceLineNo">217</span>    // Test for case where we get a region startup message from a regionserver<a name="line.217"></a>
+<span class="sourceLineNo">218</span>    // that has been quickly restarted but whose znode expiration handler has<a name="line.218"></a>
+<span class="sourceLineNo">219</span>    // not yet run, or from a server whose fail we are currently processing.<a name="line.219"></a>
+<span class="sourceLineNo">220</span>    // Test its host+port combo is present in serverAddressToServerInfo. If it<a name="line.220"></a>
+<span class="sourceLineNo">221</span>    // is, reject the server and trigger its expiration. The next time it comes<a name="line.221"></a>
+<span class="sourceLineNo">222</span>    // in, it should have been removed from serverAddressToServerInfo and queued<a name="line.222"></a>
+<span class="sourceLineNo">223</span>    // for processing by ProcessServerShutdown.<a name="line.223"></a>
+<span class="sourceLineNo">224</span><a name="line.224"></a>
+<span class="sourceLineNo">225</span>    final String hostname =<a name="line.225"></a>
+<span class="sourceLineNo">226</span>      request.hasUseThisHostnameInstead() ? request.getUseThisHostnameInstead() : ia.getHostName();<a name="line.226"></a>
+<span class="sourceLineNo">227</span>    ServerName sn = ServerName.valueOf(hostname, request.getPort(), request.getServerStartCode());<a name="line.227"></a>
+<span class="sourceLineNo">228</span>    checkClockSkew(sn, request.getServerCurrentTime());<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    checkIsDead(sn, "STARTUP");<a name="line.229"></a>
+<span class="sourceLineNo">230</span>    if (!checkAndRecordNewServer(sn, ServerMetricsBuilder.of(sn, versionNumber, version))) {<a name="line.230"></a>
+<span class="sourceLineNo">231</span>      LOG.warn(<a name="line.231"></a>
+<span class="sourceLineNo">232</span>        "THIS SHOULD NOT HAPPEN, RegionServerStartup" + " could not record the server: " + sn);<a name="line.232"></a>
+<span class="sourceLineNo">233</span>    }<a name="line.233"></a>
+<span class="sourceLineNo">234</span>    return sn;<a name="line.234"></a>
+<span class="sourceLineNo">235</span>  }<a name="line.235"></a>
+<span class="sourceLineNo">236</span><a name="line.236"></a>
+<span class="sourceLineNo">237</span>  /**<a name="line.237"></a>
+<span class="sourceLineNo">238</span>   * Updates last flushed sequence Ids for the regions on server sn<a name="line.238"></a>
+<span class="sourceLineNo">239</span>   * @param sn<a name="line.239"></a>
+<span class="sourceLineNo">240</span>   * @param hsl<a name="line.240"></a>
+<span class="sourceLineNo">241</span>   */<a name="line.241"></a>
+<span class="sourceLineNo">242</span>  private void updateLastFlushedSequenceIds(ServerName sn, ServerMetrics hsl) {<a name="line.242"></a>
+<span class="sourceLineNo">243</span>    for (Entry&lt;byte[], RegionMetrics&gt; entry : hsl.getRegionMetrics().entrySet()) {<a name="line.243"></a>
+<span class="sourceLineNo">244</span>      byte[] encodedRegionName = Bytes.toBytes(RegionInfo.encodeRegionName(entry.getKey()));<a name="line.244"></a>
+<span class="sourceLineNo">245</span>      Long existingValue = flushedSequenceIdByRegion.get(encodedRegionName);<a name="line.245"></a>
+<span class="sourceLineNo">246</span>      long l = entry.getValue().getCompletedSequenceId();<a name="line.246"></a>
+<span class="sourceLineNo">247</span>      // Don't let smaller sequence ids override greater sequence ids.<a name="line.247"></a>
+<span class="sourceLineNo">248</span>      if (LOG.isTraceEnabled()) {<a name="line.248"></a>
+<span class="sourceLineNo">249</span>        LOG.trace(Bytes.toString(encodedRegionName) + ", existingValue=" + existingValue +<a name="line.249"></a>
+<span class="sourceLineNo">250</span>          ", completeSequenceId=" + l);<a name="line.250"></a>
+<span class="sourceLineNo">251</span>      }<a name="line.251"></a>
+<span class="sourceLineNo">252</span>      if (existingValue == null || (l != HConstants.NO_SEQNUM &amp;&amp; l &gt; existingValue)) {<a name="line.252"></a>
+<span class="sourceLineNo">253</span>        flushedSequenceIdByRegion.put(encodedRegionName, l);<a name="line.253"></a>
+<span class="sourceLineNo">254</span>      } else if (l != HConstants.NO_SEQNUM &amp;&amp; l &lt; existingValue) {<a name="line.254"></a>
+<span class="sourceLineNo">255</span>        LOG.warn("RegionServer " + sn + " indicates a last flushed sequence id ("<a name="line.255"></a>
+<span class="sourceLineNo">256</span>            + l + ") that is less than the previous last flushed sequence id ("<a name="line.256"></a>
+<span class="sourceLineNo">257</span>            + existingValue + ") for region " + Bytes.toString(entry.getKey()) + " Ignoring.");<a name="line.257"></a>
+<span class="sourceLineNo">258</span>      }<a name="line.258"></a>
+<span class="sourceLineNo">259</span>      ConcurrentNavigableMap&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.259"></a>
+<span class="sourceLineNo">260</span>          computeIfAbsent(storeFlushedSequenceIdsByRegion, encodedRegionName,<a name="line.260"></a>
+<span class="sourceLineNo">261</span>            () -&gt; new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR));<a name="line.261"></a>
+<span class="sourceLineNo">262</span>      for (Entry&lt;byte[], Long&gt; storeSeqId : entry.getValue().getStoreSequenceId().entrySet()) {<a name="line.262"></a>
+<span class="sourceLineNo">263</span>        byte[] family = storeSeqId.getKey();<a name="line.263"></a>
+<span class="sourceLineNo">264</span>        existingValue = storeFlushedSequenceId.get(family);<a name="line.264"></a>
+<span class="sourceLineNo">265</span>        l = storeSeqId.getValue();<a name="line.265"></a>
+<span class="sourceLineNo">266</span>        if (LOG.isTraceEnabled()) {<a name="line.266"></a>
+<span class="sourceLineNo">267</span>          LOG.trace(Bytes.toString(encodedRegionName) + ", family=" + Bytes.toString(family) +<a name="line.267"></a>
+<span class="sourceLineNo">268</span>            ", existingValue=" + existingValue + ", completeSequenceId=" + l);<a name="line.268"></a>
+<span class="sourceLineNo">269</span>        }<a name="line.269"></a>
+<span class="sourceLineNo">270</span>        // Don't let smaller sequence ids override greater sequence ids.<a name="line.270"></a>
+<span class="sourceLineNo">271</span>        if (existingValue == null || (l != HConstants.NO_SEQNUM &amp;&amp; l &gt; existingValue.longValue())) {<a name="line.271"></a>
+<span class="sourceLineNo">272</span>          storeFlushedSequenceId.put(family, l);<a name="line.272"></a>
+<span class="sourceLineNo">273</span>        }<a name="line.273"></a>
+<span class="sourceLineNo">274</span>      }<a name="line.274"></a>
+<span class="sourceLineNo">275</span>    }<a name="line.275"></a>
+<span class="sourceLineNo">276</span>  }<a name="line.276"></a>
+<span class="sourceLineNo">277</span><a name="line.277"></a>
+<span class="sourceLineNo">278</span>  @VisibleForTesting<a name="line.278"></a>
+<span class="sourceLineNo">279</span>  public void regionServerReport(ServerName sn,<a name="line.279"></a>
+<span class="sourceLineNo">280</span>    ServerMetrics sl) throws YouAreDeadException {<a name="line.280"></a>
+<span class="sourceLineNo">281</span>    checkIsDead(sn, "REPORT");<a name="line.281"></a>
+<span class="sourceLineNo">282</span>    if (null == this.onlineServers.replace(sn, sl)) {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>      // Already have this host+port combo and its just different start code?<a name="line.283"></a>
+<span class="sourceLineNo">284</span>      // Just let the server in. Presume master joining a running cluster.<a name="line.284"></a>
+<span class="sourceLineNo">285</span>      // recordNewServer is what happens at the end of reportServerStartup.<a name="line.285"></a>
+<span class="sourceLineNo">286</span>      // The only thing we are skipping is passing back to the regionserver<a name="line.286"></a>
+<span class="sourceLineNo">287</span>      // the ServerName to use. Here we presume a master has already done<a name="line.287"></a>
+<span class="sourceLineNo">288</span>      // that so we'll press on with whatever it gave us for ServerName.<a name="line.288"></a>
+<span class="sourceLineNo">289</span>      if (!checkAndRecordNewServer(sn, sl)) {<a name="line.289"></a>
+<span class="sourceLineNo">290</span>        LOG.info("RegionServerReport ignored, could not record the server: " + sn);<a name="line.290"></a>
+<span class="sourceLineNo">291</span>        return; // Not recorded, so no need to move on<a name="line.291"></a>
+<span class="sourceLineNo">292</span>      }<a name="line.292"></a>
+<span class="sourceLineNo">293</span>    }<a name="line.293"></a>
+<span class="sourceLineNo">294</span>    updateLastFlushedSequenceIds(sn, sl);<a name="line.294"></a>
+<span class="sourceLineNo">295</span>  }<a name="line.295"></a>
+<span class="sourceLineNo">296</span><a name="line.296"></a>
+<span class="sourceLineNo">297</span>  /**<a name="line.297"></a>
+<span class="sourceLineNo">298</span>   * Check is a server of same host and port already exists,<a name="line.298"></a>
+<span class="sourceLineNo">299</span>   * if not, or the existed one got a smaller start code, record it.<a name="line.299"></a>
+<span class="sourceLineNo">300</span>   *<a name="line.300"></a>
+<span class="sourceLineNo">301</span>   * @param serverName the server to check and record<a name="line.301"></a>
+<span class="sourceLineNo">302</span>   * @param sl the server load on the server<a name="line.302"></a>
+<span class="sourceLineNo">303</span>   * @return true if the server is recorded, otherwise, false<a name="line.303"></a>
+<span class="sourceLineNo">304</span>   */<a name="line.304"></a>
+<span class="sourceLineNo">305</span>  boolean checkAndRecordNewServer(final ServerName serverName, final ServerMetrics sl) {<a name="line.305"></a>
+<span class="sourceLineNo">306</span>    ServerName existingServer = null;<a name="line.306"></a>
+<span class="sourceLineNo">307</span>    synchronized (this.onlineServers) {<a name="line.307"></a>
+<span class="sourceLineNo">308</span>      existingServer = findServerWithSameHostnamePortWithLock(serverName);<a name="line.308"></a>
+<span class="sourceLineNo">309</span>      if (existingServer != null &amp;&amp; (existingServer.getStartcode() &gt; serverName.getStartcode())) {<a name="line.309"></a>
+<span class="sourceLineNo">310</span>        LOG.info("Server serverName=" + serverName + " rejected; we already have "<a name="line.310"></a>
+<span class="sourceLineNo">311</span>            + existingServer.toString() + " registered with same hostname and port");<a name="line.311"></a>
+<span class="sourceLineNo">312</span>        return false;<a name="line.312"></a>
+<span class="sourceLineNo">313</span>      }<a name="line.313"></a>
+<span class="sourceLineNo">314</span>      recordNewServerWithLock(serverName, sl);<a name="line.314"></a>
+<span class="sourceLineNo">315</span>    }<a name="line.315"></a>
+<span class="sourceLineNo">316</span><a name="line.316"></a>
+<span class="sourceLineNo">317</span>    // Tell our listeners that a server was added<a name="line.317"></a>
+<span class="sourceLineNo">318</span>    if (!this.listeners.isEmpty()) {<a name="line.318"></a>
+<span class="sourceLineNo">319</span>      for (ServerListener listener : this.listeners) {<a name="line.319"></a>
+<span class="sourceLineNo">320</span>        listener.serverAdded(serverName);<a name="line.320"></a>
+<span class="sourceLineNo">321</span>      }<a name="line.321"></a>
+<span class="sourceLineNo">322</span>    }<a name="line.322"></a>
+<span class="sourceLineNo">323</span><a name="line.323"></a>
+<span class="sourceLineNo">324</span>    // Note that we assume that same ts means same server, and don't expire in that case.<a name="line.324"></a>
+<span class="sourceLineNo">325</span>    //  TODO: ts can theoretically collide due to clock shifts, so this is a bit hacky.<a name="line.325"></a>
+<span class="sourceLineNo">326</span>    if (existingServer != null &amp;&amp;<a name="line.326"></a>
+<span class="sourceLineNo">327</span>        (existingServer.getStartcode() &lt; serverName.getStartcode())) {<a name="line.327"></a>
+<span class="sourceLineNo">328</span>      LOG.info("Triggering server recovery; existingServer " +<a name="line.328"></a>
+<span class="sourceLineNo">329</span>          existingServer + " looks stale, new server:" + serverName);<a name="line.329"></a>
+<span class="sourceLineNo">330</span>      expireServer(existingServer);<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    }<a name="line.331"></a>
+<span class="sourceLineNo">332</span>    return true;<a name="line.332"></a>
+<span class="sourceLineNo">333</span>  }<a name="line.333"></a>
+<span class="sourceLineNo">334</span><a name="line.334"></a>
+<span class="sourceLineNo">335</span>  /**<a name="line.335"></a>
+<span class="sourceLineNo">336</span>   * Find out the region servers crashed between the crash of the previous master instance and the<a name="line.336"></a>
+<span class="sourceLineNo">337</span>   * current master instance and schedule SCP for them.<a name="line.337"></a>
+<span class="sourceLineNo">338</span>   * &lt;p/&gt;<a name="line.338"></a>
+<span class="sourceLineNo">339</span>   * Since the {@code RegionServerTracker} has already helped us to construct the online servers set<a name="line.339"></a>
+<span class="sourceLineNo">340</span>   * by scanning zookeeper, now we can compare the online servers with {@code liveServersFromWALDir}<a name="line.340"></a>
+<span class="sourceLineNo">341</span>   * to find out whether there are servers which are already dead.<a name="line.341"></a>
+<span class="sourceLineNo">342</span>   * &lt;p/&gt;<a name="line.342"></a>
+<span class="sourceLineNo">343</span>   * Must be called inside the initialization method of {@code RegionServerTracker} to avoid<a name="line.343"></a>
+<span class="sourceLineNo">344</span>   * concurrency issue.<a name="line.344"></a>
+<span class="sourceLineNo">345</span>   * @param deadServersFromPE the region servers which already have a SCP associated.<a name="line.345"></a>
+<span class="sourceLineNo">346</span>   * @param liveServersFromWALDir the live region servers from wal directory.<a name="line.346"></a>
+<span class="sourceLineNo">347</span>   */<a name="line.347"></a>
+<span class="sourceLineNo">348</span>  void findDeadServersAndProcess(Set&lt;ServerName&gt; deadServersFromPE,<a name="line.348"></a>
+<span class="sourceLineNo">349</span>      Set&lt;ServerName&gt; liveServersFromWALDir) {<a name="line.349"></a>
+<span class="sourceLineNo">350</span>    deadServersFromPE.forEach(deadservers::putIfAbsent);<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    liveServersFromWALDir.stream().filter(sn -&gt; !onlineServers.containsKey(sn))<a name="line.351"></a>
+<span class="sourceLineNo">352</span>      .forEach(this::expireServer);<a name="line.352"></a>
+<span class="sourceLineNo">353</span>  }<a name="line.353"></a>
+<span class="sourceLineNo">354</span><a name="line.354"></a>
+<span class="sourceLineNo">355</span>  /**<a name="line.355"></a>
+<span class="sourceLineNo">356</span>   * Checks if the clock skew between the server and the master. If the clock skew exceeds the<a name="line.356"></a>
+<span class="sourceLineNo">357</span>   * configured max, it will throw an exception; if it exceeds the configured warning threshold,<a name="line.357"></a>
+<span class="sourceLineNo">358</span>   * it will log a warning but start normally.<a name="line.358"></a>
+<span class="sourceLineNo">359</span>   * @param serverName Incoming servers's name<a name="line.359"></a>
+<span class="sourceLineNo">360</span>   * @param serverCurrentTime<a name="line.360"></a>
+<span class="sourceLineNo">361</span>   * @throws ClockOutOfSyncException if the skew exceeds the configured max value<a name="line.361"></a>
+<span class="sourceLineNo">362</span>   */<a name="line.362"></a>
+<span class="sourceLineNo">363</span>  private void checkClockSkew(final ServerName serverName, final long serverCurrentTime)<a name="line.363"></a>
+<span class="sourceLineNo">364</span>      throws ClockOutOfSyncException {<a name="line.364"></a>
+<span class="sourceLineNo">365</span>    long skew = Math.abs(EnvironmentEdgeManager.currentTime() - serverCurrentTime);<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    if (skew &gt; maxSkew) {<a name="line.366"></a>
+<span class="sourceLineNo">367</span>      String message = "Server " + serverName + " has been " +<a name="line.367"></a>
+<span class="sourceLineNo">368</span>        "rejected; Reported time is too far out of sync with master.  " +<a name="line.368"></a>
+<span class="sourceLineNo">369</span>        "Time difference of " + skew + "ms &gt; max allowed of " + maxSkew + "ms";<a name="line.369"></a>
+<span class="sourceLineNo">370</span>      LOG.warn(message);<a name="line.370"></a>
+<span class="sourceLineNo">371</span>      throw new ClockOutOfSyncException(message);<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    } else if (skew &gt; warningSkew){<a name="line.372"></a>
+<span class="sourceLineNo">373</span>      String message = "Reported time for server " + serverName + " is out of sync with master " +<a name="line.373"></a>
+<span class="sourceLineNo">374</span>        "by " + skew + "ms. (Warning threshold is " + warningSkew + "ms; " +<a name="line.374"></a>
+<span class="sourceLineNo">375</span>        "error threshold is " + maxSkew + "ms)";<a name="line.375"></a>
+<span class="sourceLineNo">376</span>      LOG.warn(message);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    }<a name="line.377"></a>
+<span class="sourceLineNo">378</span>  }<a name="line.378"></a>
+<span class="sourceLineNo">379</span><a name="line.379"></a>
+<span class="sourceLineNo">380</span>  /**<a name="line.380"></a>
+<span class="sourceLineNo">381</span>   * Called when RegionServer first reports in for duty and thereafter each<a name="line.381"></a>
+<span class="sourceLineNo">382</span>   * time it heartbeats to make sure it is has not been figured for dead.<a name="line.382"></a>
+<span class="sourceLineNo">383</span>   * If this server is on the dead list, reject it with a YouAreDeadException.<a name="line.383"></a>
+<span class="sourceLineNo">384</span>   * If it was dead but came back with a new start code, remove the old entry<a name="line.384"></a>
+<span class="sourceLineNo">385</span>   * from the dead list.<a name="line.385"></a>
+<span class="sourceLineNo">386</span>   * @param what START or REPORT<a name="line.386"></a>
+<span class="sourceLineNo">387</span>   */<a name="line.387"></a>
+<span class="sourceLineNo">388</span>  private void checkIsDead(final ServerName serverName, final String what)<a name="line.388"></a>
+<span class="sourceLineNo">389</span>      throws YouAreDeadException {<a name="line.389"></a>
+<span class="sourceLineNo">390</span>    if (this.deadservers.isDeadServer(serverName)) {<a name="line.390"></a>
+<span class="sourceLineNo">391</span>      // Exact match: host name, port and start code all match with existing one of the<a name="line.391"></a>
+<span class="sourceLineNo">392</span>      // dead servers. So, this server must be dead. Tell it to kill itself.<a name="line.392"></a>
+<span class="sourceLineNo">393</span>      String message = "Server " + what + " rejected; currently processing " +<a name="line.393"></a>
+<span class="sourceLineNo">394</span>          serverName + " as dead server";<a name="line.394"></a>
+<span class="sourceLineNo">395</span>      LOG.debug(message);<a name="line.395"></a>
+<span class="sourceLineNo">396</span>      throw new YouAreDeadException(message);<a name="line.396"></a>
+<span class="sourceLineNo">397</span>    }<a name="line.397"></a>
+<span class="sourceLineNo">398</span>    // Remove dead server with same hostname and port of newly checking in rs after master<a name="line.398"></a>
+<span class="sourceLineNo">399</span>    // initialization. See HBASE-5916 for more information.<a name="line.399"></a>
+<span class="sourceLineNo">400</span>    if ((this.master == null || this.master.isInitialized()) &amp;&amp;<a name="line.400"></a>
+<span class="sourceLineNo">401</span>        this.deadservers.cleanPreviousInstance(serverName)) {<a name="line.401"></a>
+<span class="sourceLineNo">402</span>      // This server has now become alive after we marked it as dead.<a name="line.402"></a>
+<span class="sourceLineNo">403</span>      // We removed it's previous entry from the dead list to reflect it.<a name="line.403"></a>
+<span class="sourceLineNo">404</span>      LOG.debug("{} {} came back up, removed it from the dead servers list", what, serverName);<a name="line.404"></a>
+<span class="sourceLineNo">405</span>    }<a name="line.405"></a>
+<span class="sourceLineNo">406</span>  }<a name="line.406"></a>
+<span class="sourceLineNo">407</span><a name="line.407"></a>
+<span class="sourceLineNo">408</span>  /**<a name="line.408"></a>
+<span class="sourceLineNo">409</span>   * Assumes onlineServers is locked.<a name="line.409"></a>
+<span class="sourceLineNo">410</span>   * @return ServerName with matching hostname and port.<a name="line.410"></a>
+<span class="sourceLineNo">411</span>   */<a name="line.411"></a>
+<span class="sourceLineNo">412</span>  private ServerName findServerWithSameHostnamePortWithLock(<a name="line.412"></a>
+<span class="sourceLineNo">413</span>      final ServerName serverName) {<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    ServerName end = ServerName.valueOf(serverName.getHostname(), serverName.getPort(),<a name="line.414"></a>
+<span class="sourceLineNo">415</span>        Long.MAX_VALUE);<a name="line.415"></a>
+<span class="sourceLineNo">416</span><a name="line.416"></a>
+<span class="sourceLineNo">417</span>    ServerName r = onlineServers.lowerKey(end);<a name="line.417"></a>
+<span class="sourceLineNo">418</span>    if (r != null) {<a name="line.418"></a>
+<span class="sourceLineNo">419</span>      if (ServerName.isSameAddress(r, serverName)) {<a name="line.419"></a>
+<span class="sourceLineNo">420</span>        return r;<a name="line.420"></a>
+<span class="sourceLineNo">421</span>      }<a name="line.421"></a>
+<span class="sourceLineNo">422</span>    }<a name="line.422"></a>
+<span class="sourceLineNo">423</span>    return null;<a name="line.423"></a>
+<span class="sourceLineNo">424</span>  }<a name="line.424"></a>
+<span class="sourceLineNo">425</span><a name="line.425"></a>
+<span class="sourceLineNo">426</span>  /**<a name="line.426"></a>
+<span class="sourceLineNo">427</span>   * Adds the onlineServers list. onlineServers should be locked.<a name="line.427"></a>
+<span class="sourceLineNo">428</span>   * @param serverName The remote servers name.<a name="line.428"></a>
+<span class="sourceLineNo">429</span>   */<a name="line.429"></a>
+<span class="sourceLineNo">430</span>  @VisibleForTesting<a name="line.430"></a>
+<span class="sourceLineNo">431</span>  void recordNewServerWithLock(final ServerName serverName, final ServerMetrics sl) {<a name="line.431"></a>
+<span class="sourceLineNo">432</span>    LOG.info("Registering regionserver=" + serverName);<a name="line.432"></a>
+<span class="sourceLineNo">433</span>    this.onlineServers.put(serverName, sl);<a name="line.433"></a>
+<span class="sourceLineNo">434</span>  }<a name="line.434"></a>
+<span class="sourceLineNo">435</span><a name="line.435"></a>
+<span class="sourceLineNo">436</span>  @VisibleForTesting<a name="line.436"></a>
+<span class="sourceLineNo">437</span>  public ConcurrentNavigableMap&lt;byte[], Long&gt; getFlushedSequenceIdByRegion() {<a name="line.437"></a>
+<span class="sourceLineNo">438</span>    return flushedSequenceIdByRegion;<a name="line.438"></a>
+<span class="sourceLineNo">439</span>  }<a name="line.439"></a>
+<span class="sourceLineNo">440</span><a name="line.440"></a>
+<span class="sourceLineNo">441</span>  public RegionStoreSequenceIds getLastFlushedSequenceId(byte[] encodedRegionName) {<a name="line.441"></a>
+<span class="sourceLineNo">442</span>    RegionStoreSequenceIds.Builder builder = RegionStoreSequenceIds.newBuilder();<a name="line.442"></a>
+<span class="sourceLineNo">443</span>    Long seqId = flushedSequenceIdByRegion.get(encodedRegionName);<a name="line.443"></a>
+<span class="sourceLineNo">444</span>    builder.setLastFlushedSequenceId(seqId != null ? seqId.longValue() : HConstants.NO_SEQNUM);<a name="line.444"></a>
+<span class="sourceLineNo">445</span>    Map&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.445"></a>
+<span class="sourceLineNo">446</span>        storeFlushedSequenceIdsByRegion.get(encodedRegionName);<a name="line.446"></a>
+<span class="sourceLineNo">447</span>    if (storeFlushedSequenceId != null) {<a name="line.447"></a>
+<span class="sourceLineNo">448</span>      for (Map.Entry&lt;byte[], Long&gt; entry : storeFlushedSequenceId.entrySet()) {<a name="line.448"></a>
+<span class="sourceLineNo">449</span>        builder.addStoreSequenceId(StoreSequenceId.newBuilder()<a name="line.449"></a>
+<span class="sourceLineNo">450</span>            .setFamilyName(UnsafeByteOperations.unsafeWrap(entry.getKey()))<a name="line.450"></a>
+<span class="sourceLineNo">451</span>            .setSequenceId(entry.getValue().longValue()).build());<a name="line.451"></a>
+<span class="sourceLineNo">452</span>      }<a name="line.452"></a>
+<span class="sourceLineNo">453</span>    }<a name="line.453"></a>
+<span class="sourceLineNo">454</span>    return builder.build();<a name="line.454"></a>
+<span class="sourceLineNo">455</span>  }<a name="line.455"></a>
+<span class="sourceLineNo">456</span><a name="line.456"></a>
+<span class="sourceLineNo">457</span>  /**<a name="line.457"></a>
+<span class="sourceLineNo">458</span>   * @param serverName<a name="line.458"></a>
+<span class="sourceLineNo">459</span>   * @return ServerMetrics if serverName is known else null<a name="line.459"></a>
+<span class="sourceLineNo">460</span>   */<a name="line.460"></a>
+<span class="sourceLineNo">461</span>  public ServerMetrics getLoad(final ServerName serverName) {<a name="line.461"></a>
+<span class="sourceLineNo">462</span>    return this.onlineServers.get(serverName);<a name="line.462"></a>
+<span class="sourceLineNo">463</span>  }<a name="line.463"></a>
+<span class="sourceLineNo">464</span><a name="line.464"></a>
+<span class="sourceLineNo">465</span>  /**<a name="line.465"></a>
+<span class="sourceLineNo">466</span>   * Compute the average load across all region servers.<a name="line.466"></a>
+<span class="sourceLineNo">467</span>   * Currently, this uses a very naive computation - just uses the number of<a name="line.467"></a>
+<span class="sourceLineNo">468</span>   * regions being served, ignoring stats about number of requests.<a name="line.468"></a>
+<span class="sourceLineNo">469</span>   * @return the average load<a name="line.469"></a>
+<span class="sourceLineNo">470</span>   */<a name="line.470"></a>
+<span class="sourceLineNo">471</span>  public double getAverageLoad() {<a name="line.471"></a>
+<span class="sourceLineNo">472</span>    int totalLoad = 0;<a name="line.472"></a>
+<span class="sourceLineNo">473</span>    int numServers = 0;<a name="line.473"></a>
+<span class="sourceLineNo">474</span>    for (ServerMetrics sl : this.onlineServers.values()) {<a name="line.474"></a>
+<span class="sourceLineNo">475</span>      numServers++;<a name="line.475"></a>
+<span class="sourceLineNo">476</span>      totalLoad += sl.getRegionMetrics().size();<a name="line.476"></a>
+<span class="sourceLineNo">477</span>    }<a name="line.477"></a>
+<span class="sourceLineNo">478</span>    return numServers == 0 ? 0 :<a name="line.478"></a>
+<span class="sourceLineNo">479</span>      (double)totalLoad / (double)numServers;<a name="line.479"></a>
+<span class="sourceLineNo">480</span>  }<a name="line.480"></a>
+<span class="sourceLineNo">481</span><a name="line.481"></a>
+<span class="sourceLineNo">482</span>  /** @return the count of active regionservers */<a name="line.482"></a>
+<span class="sourceLineNo">483</span>  public int countOfRegionServers() {<a name="line.483"></a>
+<span class="sourceLineNo">484</span>    // Presumes onlineServers is a concurrent map<a name="line.484"></a>
+<span class="sourceLineNo">485</span>    return this.onlineServers.size();<a name="line.485"></a>
+<span class="sourceLineNo">486</span>  }<a name="line.486"></a>
+<span class="sourceLineNo">487</span><a name="line.487"></a>
+<span class="sourceLineNo">488</span>  /**<a name="line.488"></a>
+<span class="sourceLineNo">489</span>   * @return Read-only map of servers to serverinfo<a name="line.489"></a>
+<span class="sourceLineNo">490</span>   */<a name="line.490"></a>
+<span class="sourceLineNo">491</span>  public Map&lt;ServerName, ServerMetrics&gt; getOnlineServers() {<a name="line.491"></a>
+<span class="sourceLineNo">492</span>    // Presumption is that iterating the returned Map is OK.<a name="line.492"></a>
+<span class="sourceLineNo">493</span>    synchronized (this.onlineServers) {<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      return Collections.unmodifiableMap(this.onlineServers);<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    }<a name="line.495"></a>
+<span class="sourceLineNo">496</span>  }<a name="line.496"></a>
+<span class="sourceLineNo">497</span><a name="line.497"></a>
+<span class="sourceLineNo">498</span>  public DeadServer getDeadServers() {<a name="line.498"></a>
+<span class="sourceLineNo">499</span>    return this.deadservers;<a name="line.499"></a>
+<span class="sourceLineNo">500</span>  }<a name="line.500"></a>
+<span class="sourceLineNo">501</span><a name="line.501"></a>
+<span class="sourceLineNo">502</span>  /**<a name="line.502"></a>
+<span class="sourceLineNo">503</span>   * Checks if any dead servers are currently in progress.<a name="line.503"></a>
+<span class="sourceLineNo">504</span>   * @return true if any RS are being processed as dead, false if not<a name="line.504"></a>
+<span class="sourceLineNo">505</span>   */<a name="line.505"></a>
+<span class="sourceLineNo">506</span>  public boolean areDeadServersInProgress() {<a name="line.506"></a>
+<span class="sourceLineNo">507</span>    return this.deadservers.areDeadServersInProgress();<a name="line.507"></a>
+<span class="sourceLineNo">508</span>  }<a name="line.508"></a>
+<span class="sourceLineNo">509</span><a name="line.509"></a>
+<span class="sourceLineNo">510</span>  void letRegionServersShutdown() {<a name="line.510"></a>
+<span class="sourceLineNo">511</span>    long previousLogTime = 0;<a name="line.511"></a>
+<span class="sourceLineNo">512</span>    ServerName sn = master.getServerName();<a name="line.512"></a>
+<span class="sourceLineNo">513</span>    ZKWatcher zkw = master.getZooKeeper();<a name="line.513"></a>
+<span class="sourceLineNo">514</span>    int onlineServersCt;<a name="line.514"></a>
+<span class="sourceLineNo">515</span>    while ((onlineServersCt = onlineServers.size()) &gt; 0){<a name="line.515"></a>
+<span class="sourceLineNo">516</span><a name="line.516"></a>
+<span class="sourceLineNo">517</span>      if (System.currentTimeMillis() &gt; (previousLogTime + 1000)) {<a name="line.517"></a>
+<span class="sourceLineNo">518</span>        Set&lt;ServerName&gt; remainingServers = onlineServers.keySet();<a name="line.518"></a>
+<span class="sourceLineNo">519</span>        synchronized (onlineServers) {<a name="line.519"></a>
+<span class="sourceLineNo">520</span>          if (remainingServers.size() == 1 &amp;&amp; remainingServers.contains(sn)) {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>            // Master will delete itself later.<a name="line.521"></a>
+<span class="sourceLineNo">522</span>            return;<a name="line.522"></a>
+<span class="sourceLineNo">523</span>          }<a name="line.523"></a>
+<span class="sourceLineNo">524</span>        }<a name="line.524"></a>
+<span class="sourceLineNo">525</span>        StringBuilder sb = new StringBuilder();<a name="line.525"></a>
+<span class="sourceLineNo">526</span>        // It's ok here to not sync on onlineServers - merely logging<a name="line.526"></a>
+<span class="sourceLineNo">527</span>        for (ServerName key : remainingServers) {<a name="line.527"></a>
+<span class="sourceLineNo">528</span>          if (sb.length() &gt; 0) {<a name="line.528"></a>
+<span class="sourceLineNo">529</span>            sb.append(", ");<a name="line.529"></a>
+<span class="sourceLineNo">530</span>          }<a name="line.530"></a>
+<span class="sourceLineNo">531</span>          sb.append(key);<a name="line.531"></a>
+<span class="sourceLineNo">532</span>        }<a name="line.532"></a>
+<span class="sourceLineNo">533</span>        LOG.info("Waiting on regionserver(s) " + sb.toString());<a name="line.533"></a>
+<span class="sourceLineNo">534</span>        previousLogTime = System.currentTimeMillis();<a name="line.534"></a>
+<span class="sourceLineNo">535</span>      }<a name="line.535"></a>
+<span class="sourceLineNo">536</span><a name="line.536"></a>
+<span class="sourceLineNo">537</span>      try {<a name="line.537"></a>
+<span class="sourceLineNo">538</span>        List&lt;String&gt; servers = getRegionServersInZK(zkw);<a name="line.538"></a>
+<span class="sourceLineNo">539</span>        if (servers == null || servers.isEmpty() || (servers.size() == 1<a name="line.539"></a>
+<span class="sourceLineNo">540</span>            &amp;&amp; servers.contains(sn.toString()))) {<a name="line.540"></a>
+<span class="sourceLineNo">541</span>          LOG.info("ZK shows there is only the master self online, exiting now");<a name="line.541"></a>
+<span class="sourceLineNo">542</span>          // Master could have lost some ZK events, no need to wait more.<a name="line.542"></a>
+<span class="sourceLineNo">543</span>          break;<a name="line.543"></a>
+<span class="sourceLineNo">544</span>        }<a name="line.544"></a>
+<span class="sourceLineNo">545</span>      } catch (KeeperException ke) {<a name="line.545"></a>
+<span class="sourceLineNo">546</span>        LOG.warn("Failed to list regionservers", ke);<a name="line.546"></a>
+<span class="sourceLineNo">547</span>        // ZK is malfunctioning, don't hang here<a name="line.547"></a>
+<span class="sourceLineNo">548</span>        break;<a name="line.548"></a>
+<span class="sourceLineNo">549</span>      }<a name="line.549"></a>
+<span class="sourceLineNo">550</span>      synchronized (onlineServers) {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>        try {<a name="line.551"></a>
+<span class="sourceLineNo">552</span>          if (onlineServersCt == onlineServers.size()) onlineServers.wait(100);<a name="line.552"></a>
+<span class="sourceLineNo">553</span>        } catch (InterruptedException ignored) {<a name="line.553"></a>
+<span class="sourceLineNo">554</span>          // continue<a name="line.554"></a>
+<span class="sourceLineNo">555</span>        }<a name="line.555"></a>
+<span class="sourceLineNo">556</span>      }<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    }<a name="line.557"></a>
+<span class="sourceLineNo">558</span>  }<a name="line.558"></a>
+<span class="sourceLineNo">559</span><a name="line.559"></a>
+<span class="sourceLineNo">560</span>  private List&lt;String&gt; getRegionServersInZK(final ZKWatcher zkw)<a name="line.560"></a>
+<span class="sourceLineNo">561</span>  throws KeeperException {<a name="line.561"></a>
+<span class="sourceLineNo">562</span>    return ZKUtil.listChildrenNoWatch(zkw, zkw.getZNodePaths().rsZNode);<a name="line.562"></a>
+<span class="sourceLineNo">563</span>  }<a name="line.563"></a>
+<span class="sourceLineNo">564</span><a name="line.564"></a>
+<span class="sourceLineNo">565</span>  /**<a name="line.565"></a>
+<span class="sourceLineNo">566</span>   * Expire the passed server. Add it to list of dead servers and queue a shutdown processing.<a name="line.566"></a>
+<span class="sourceLineNo">567</span>   * @return pid if we queued a ServerCrashProcedure else {@link Procedure#NO_PROC_ID} if we did<a name="line.567"></a>
+<span class="sourceLineNo">568</span>   *         not (could happen for many reasons including the fact that its this server that is<a name="line.568"></a>
+<span class="sourceLineNo">569</span>   *         going down or we already have queued an SCP for this server or SCP processing is<a name="line.569"></a>
+<span class="sourceLineNo">570</span>   *         currently disabled because we are in startup phase).<a name="line.570"></a>
+<span class="sourceLineNo">571</span>   */<a name="line.571"></a>
+<span class="sourceLineNo">572</span>  @VisibleForTesting // Redo test so we can make this protected.<a name="line.572"></a>
+<span class="sourceLineNo">573</span>  public synchronized long expireServer(final ServerName serverName) {<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    return expireServer(serverName, false);<a name="line.574"></a>
+<span class="sourceLineNo">575</span><a name="line.575"></a>
+<span class="sourceLineNo">576</span>  }<a name="line.576"></a>
+<span class="sourceLineNo">577</span><a name="line.577"></a>
+<span class="sourceLineNo">578</span>  synchronized long expireServer(final ServerName serverName, boolean force) {<a name="line.578"></a>
+<span class="sourceLineNo">579</span>    // THIS server is going down... can't handle our own expiration.<a name="line.579"></a>
+<span class="sourceLineNo">580</span>    if (serverName.equals(master.getServerName())) {<a name="line.580"></a>
+<span class="sourceLineNo">581</span>      if (!(master.isAborted() || master.isStopped())) {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>        master.stop("We lost our znode?");<a name="line.582"></a>
+<span class="sourceLineNo">583</span>      }<a name="line.583"></a>
+<span class="sourceLineNo">584</span>      return Procedure.NO_PROC_ID;<a name="line.584"></a>
+<span class="sourceLineNo">585</span>    }<a name="line.585"></a>
+<span class="sourceLineNo">586</span>    if (this.deadservers.isDeadServer(serverName)) {<a name="line.586"></a>
+<span class="sourceLineNo">587</span>      LOG.warn("Expiration called on {} but already in DeadServer", serverName);<a name="line.587"></a>
+<span class="sourceLineNo">588</span>      return Procedure.NO_PROC_ID;<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    }<a name="line.589"></a>
+<span class="sourceLineNo">590</span>    moveFromOnlineToDeadServers(serverName);<a name="line.590"></a>
+<span class="sourceLineNo">591</span><a name="line.591"></a>
+<span class="sourceLineNo">592</span>    // If server is in draining mode, remove corresponding znode<a name="line.592"></a>
+<span class="sourceLineNo">593</span>    // In some tests, the mocked HM may not have ZK Instance, hence null check<a name="line.593"></a>
+<span class="sourceLineNo">594</span>    if (master.getZooKeeper() != null) {<a name="line.594"></a>
+<span class="sourceLineNo">595</span>      String drainingZnode = ZNodePaths<a name="line.595"></a>
+<span class="sourceLineNo">596</span>        .joinZNode(master.getZooKeeper().getZNodePaths().drainingZNode, serverName.getServerName());<a name="line.596"></a>
+<span class="sourceLineNo">597</span>      try {<a name="line.597"></a>
+<span class="sourceLineNo">598</span>        ZKUtil.deleteNodeFailSilent(master.getZooKeeper(), drainingZnode);<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      } catch (KeeperException e) {<a name="line.599"></a>
+<span class="sourceLineNo">600</span>        LOG.warn("Error deleting the draining znode for stopping server " + serverName.getServerName(), e);<a name="line.600"></a>
+<span class="sourceLineNo">601</span>      }<a name="line.601"></a>
+<span class="sourceLineNo">602</span>    }<a name="line.602"></a>
+<span class="sourceLineNo">603</span>    <a name="line.603"></a>
+<span class="sourceLineNo">604</span>    // If cluster is going down, yes, servers are going to be expiring; don't<a name="line.604"></a>
+<span class="sourceLineNo">605</span>    // process as a dead server<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    if (isClusterShutdown()) {<a name="line.606"></a>
+<span class="sourceLineNo">607</span>      LOG.info("Cluster shutdown set; " + serverName +<a name="line.607"></a>
+<span class="sourceLineNo">608</span>        " expired; onlineServers=" + this.onlineServers.size());<a name="line.608"></a>
+<span class="sourceLineNo">609</span>      if (this.onlineServers.isEmpty()) {<a name="line.609"></a>
+<span class="sourceLineNo">610</span>        master.stop("Cluster shutdown set; onlineServer=0");<a name="line.610"></a>
+<span class="sourceLineNo">611</span>      }<a name="line.611"></a>
+<span class="sourceLineNo">612</span>      return Procedure.NO_PROC_ID;<a name="line.612"></a>
+<span class="sourceLineNo">613</span>    }<a name="line.613"></a>
+<span class="sourceLineNo">614</span>    LOG.info("Processing expiration of " + serverName + " on " + this.master.getServerName());<a name="line.614"></a>
+<span class="sourceLineNo">615</span>    long pid = master.getAssignmentManager().submitServerCrash(serverName, true, force);<a name="line.615"></a>
+<span class="sourceLineNo">616</span>    // Tell our listeners that a server was removed<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    if (!this.listeners.isEmpty()) {<a name="line.617"></a>
+<span class="sourceLineNo">618</span>      this.listeners.stream().forEach(l -&gt; l.serverRemoved(serverName));<a name="line.618"></a>
+<span class="sourceLineNo">619</span>    }<a name="line.619"></a>
+<span class="sourceLineNo">620</span>    // trigger a persist of flushedSeqId<a name="line.620"></a>
+<span class="sourceLineNo">621</span>    if (flushedSeqIdFlusher != null) {<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      flushedSeqIdFlusher.triggerNow();<a name="line.622"></a>
+<span class="sourceLineNo">623</span>    }<a name="line.623"></a>
+<span class="sourceLineNo">624</span>    return pid;<a name="line.624"></a>
+<span class="sourceLineNo">625</span>  }<a name="line.625"></a>
+<span class="sourceLineNo">626</span><a name="line.626"></a>
+<span class="sourceLineNo">627</span>  /**<a name="line.627"></a>
+<span class="sourceLineNo">628</span>   * Called when server has expired.<a name="line.628"></a>
+<span class="sourceLineNo">629</span>   */<a name="line.629"></a>
+<span class="sourceLineNo">630</span>  // Locking in this class needs cleanup.<a name="line.630"></a>
+<span class="sourceLineNo">631</span>  @VisibleForTesting<a name="line.631"></a>
+<span class="sourceLineNo">632</span>  public synchronized void moveFromOnlineToDeadServers(final ServerName sn) {<a name="line.632"></a>
+<span class="sourceLineNo">633</span>    synchronized (this.onlineServers) {<a name="line.633"></a>
+<span class="sourceLineNo">634</span>      boolean online = this.onlineServers.containsKey(sn);<a name="line.634"></a>
+<span class="sourceLineNo">635</span>      if (online) {<a name="line.635"></a>
+<span class="sourceLineNo">636</span>        // Remove the server from the known servers lists and update load info BUT<a name="line.636"></a>
+<span class="sourceLineNo">637</span>        // add to deadservers first; do this so it'll show in dead servers list if<a name="line.637"></a>
+<span class="sourceLineNo">638</span>        // not in online servers list.<a name="line.638"></a>
+<span class="sourceLineNo">639</span>        this.deadservers.putIfAbsent(sn);<a name="line.639"></a>
+<span class="sourceLineNo">640</span>        this.onlineServers.remove(sn);<a name="line.640"></a>
+<span class="sourceLineNo">641</span>        onlineServers.notifyAll();<a name="line.641"></a>
+<span class="sourceLineNo">642</span>      } else {<a name="line.642"></a>
+<span class="sourceLineNo">643</span>        // If not online, that is odd but may happen if 'Unknown Servers' -- where meta<a name="line.643"></a>
+<span class="sourceLineNo">644</span>        // has references to servers not online nor in dead servers list. If<a name="line.644"></a>
+<span class="sourceLineNo">645</span>        // 'Unknown Server', don't add to DeadServers else will be there for ever.<a name="line.645"></a>
+<span class="sourceLineNo">646</span>        LOG.trace("Expiration of {} but server not online", sn);<a name="line.646"></a>
+<span class="sourceLineNo">647</span>      }<a name="line.647"></a>
+<span class="sourceLineNo">648</span>    }<a name="line.648"></a>
+<span class="sourceLineNo">649</span>  }<a name="line.649"></a>
+<span class="sourceLineNo">650</span><a name="line.650"></a>
+<span class="sourceLineNo">651</span>  /*<a name="line.651"></a>
+<span class="sourceLineNo">652</span>   * Remove the server from the drain list.<a name="line.652"></a>
+<span class="sourceLineNo">653</span>   */<a name="line.653"></a>
+<span class="sourceLineNo">654</span>  public synchronized boolean removeServerFromDrainList(final ServerName sn) {<a name="line.654"></a>
+<span class="sourceLineNo">655</span>    // Warn if the server (sn) is not online.  ServerName is of the form:<a name="line.655"></a>
+<span class="sourceLineNo">656</span>    // &lt;hostname&gt; , &lt;port&gt; , &lt;startcode&gt;<a name="line.656"></a>
+<span class="sourceLineNo">657</span><a name="line.657"></a>
+<span class="sourceLineNo">658</span>    if (!this.isServerOnline(sn)) {<a name="line.658"></a>
+<span class="sourceLineNo">659</span>      LOG.warn("Server " + sn + " is not currently online. " +<a name="line.659"></a>
+<span class="sourceLineNo">660</span>               "Removing from draining list anyway, as requested.");<a name="line.660"></a>
+<span class="sourceLineNo">661</span>    }<a name="line.661"></a>
+<span class="sourceLineNo">662</span>    // Remove the server from the draining servers lists.<a name="line.662"></a>
+<span class="sourceLineNo">663</span>    return this.drainingServers.remove(sn);<a name="line.663"></a>
+<span class="sourceLineNo">664</span>  }<a name="line.664"></a>
+<span class="sourceLineNo">665</span><a name="line.665"></a>
+<span class="sourceLineNo">666</span>  /**<a name="line.666"></a>
+<span class="sourceLineNo">667</span>   * Add the server to the drain list.<a name="line.667"></a>
+<span class="sourceLineNo">668</span>   * @param sn<a name="line.668"></a>
+<span class="sourceLineNo">669</span>   * @return True if the server is added or the server is already on the drain list.<a name="line.669"></a>
+<span class="sourceLineNo">670</span>   */<a name="line.670"></a>
+<span class="sourceLineNo">671</span>  public synchronized boolean addServerToDrainList(final ServerName sn) {<a name="line.671"></a>
+<span class="sourceLineNo">672</span>    // Warn if the server (sn) is not online.  ServerName is of the form:<a name="line.672"></a>
+<span class="sourceLineNo">673</span>    // &lt;hostname&gt; , &lt;port&gt; , &lt;startcode&gt;<a name="line.673"></a>
+<span class="sourceLineNo">674</span><a name="line.674"></a>
+<span class="sourceLineNo">675</span>    if (!this.isServerOnline(sn)) {<a name="line.675"></a>
+<span class="sourceLineNo">676</span>      LOG.warn("Server " + sn + " is not currently online. " +<a name="line.676"></a>
+<span class="sourceLineNo">677</span>               "Ignoring request to add it to draining list.");<a name="line.677"></a>
+<span class="sourceLineNo">678</span>      return false;<a name="line.678"></a>
+<span class="sourceLineNo">679</span>    }<a name="line.679"></a>
+<span class="sourceLineNo">680</span>    // Add the server to the draining servers lists, if it's not already in<a name="line.680"></a>
+<span class="sourceLineNo">681</span>    // it.<a name="line.681"></a>
+<span class="sourceLineNo">682</span>    if (this.drainingServers.contains(sn)) {<a name="line.682"></a>
+<span class="sourceLineNo">683</span>      LOG.warn("Server " + sn + " is already in the draining server list." +<a name="line.683"></a>
+<span class="sourceLineNo">684</span>               "Ignoring request to add it again.");<a name="line.684"></a>
+<span class="sourceLineNo">685</span>      return true;<a name="line.685"></a>
+<span class="sourceLineNo">686</span>    }<a name="line.686"></a>
+<span class="sourceLineNo">687</span>    LOG.info("Server " + sn + " added to draining server list.");<a name="line.687"></a>
+<span class="sourceLineNo">688</span>    return this.drainingServers.add(sn);<a name="line.688"></a>
+<span class="sourceLineNo">689</span>  }<a name="line.689"></a>
+<span class="sourceLineNo">690</span><a name="line.690"></a>
+<span class="sourceLineNo">691</span>  /**<a name="line.691"></a>
+<span class="sourceLineNo">692</span>   * Contacts a region server and waits up to timeout ms<a name="line.692"></a>
+<span class="sourceLineNo">693</span>   * to close the region.  This bypasses the active hmaster.<a name="line.693"></a>
+<span class="sourceLineNo">694</span>   * Pass -1 as timeout if you do not want to wait on result.<a name="line.694"></a>
+<span class="sourceLineNo">695</span>   */<a name="line.695"></a>
+<span class="sourceLineNo">696</span>  public static void closeRegionSilentlyAndWait(AsyncClusterConnection connection,<a name="line.696"></a>
+<span class="sourceLineNo">697</span>      ServerName server, RegionInfo region, long timeout) throws IOException, InterruptedException {<a name="line.697"></a>
+<span class="sourceLineNo">698</span>    AsyncRegionServerAdmin admin = connection.getRegionServerAdmin(server);<a name="line.698"></a>
+<span class="sourceLineNo">699</span>    try {<a name="line.699"></a>
+<span class="sourceLineNo">700</span>      FutureUtils.get(<a name="line.700"></a>
+<span class="sourceLineNo">701</span>        admin.closeRegion(ProtobufUtil.buildCloseRegionRequest(server, region.getRegionName())));<a name="line.701"></a>
+<span class="sourceLineNo">702</span>    } catch (IOException e) {<a name="line.702"></a>
+<span class="sourceLineNo">703</span>      LOG.warn("Exception when closing region: " + region.getRegionNameAsString(), e);<a name="line.703"></a>
+<span class="sourceLineNo">704</span>    }<a name="line.704"></a>
+<span class="sourceLineNo">705</span>    if (timeout &lt; 0) {<a name="line.705"></a>
+<span class="sourceLineNo">706</span>      return;<a name="line.706"></a>
+<span class="sourceLineNo">707</span>    }<a name="line.707"></a>
+<span class="sourceLineNo">708</span>    long expiration = timeout + System.currentTimeMillis();<a name="line.708"></a>
+<span class="sourceLineNo">709</span>    while (System.currentTimeMillis() &lt; expiration) {<a name="line.709"></a>
+<span class="sourceLineNo">710</span>      try {<a name="line.710"></a>
+<span class="sourceLineNo">711</span>        RegionInfo rsRegion = ProtobufUtil.toRegionInfo(FutureUtils<a name="line.711"></a>
+<span class="sourceLineNo">712</span>          .get(<a name="line.712"></a>
+<span class="sourceLineNo">713</span>            admin.getRegionInfo(RequestConverter.buildGetRegionInfoRequest(region.getRegionName())))<a name="line.713"></a>
+<span class="sourceLineNo">714</span>          .getRegionInfo());<a name="line.714"></a>
+<span class="sourceLineNo">715</span>        if (rsRegion == null) {<a name="line.715"></a>
+<span class="sourceLineNo">716</span>          return;<a name="line.716"></a>
+<span class="sourceLineNo">717</span>        }<a name="line.717"></a>
+<span class="sourceLineNo">718</span>      } catch (IOException ioe) {<a name="line.718"></a>
+<span class="sourceLineNo">719</span>        if (ioe instanceof NotServingRegionException ||<a name="line.719"></a>
+<span class="sourceLineNo">720</span>          (ioe instanceof RemoteWithExtrasException &amp;&amp;<a name="line.720"></a>
+<span class="sourceLineNo">721</span>            ((RemoteWithExtrasException)ioe).unwrapRemoteException()<a name="line.721"></a>
+<span class="sourceLineNo">722</span>              instanceof NotServingRegionException)) {<a name="line.722"></a>
+<span class="sourceLineNo">723</span>          // no need to retry again<a name="line.723"></a>
+<span class="sourceLineNo">724</span>          return;<a name="line.724"></a>
+<span class="sourceLineNo">725</span>        }<a name="line.725"></a>
+<span class="sourceLineNo">726</span>        LOG.warn("Exception when retrieving regioninfo from: " + region.getRegionNameAsString(),<a name="line.726"></a>
+<span class="sourceLineNo">727</span>          ioe);<a name="line.727"></a>
+<span class="sourceLineNo">728</span>      }<a name="line.728"></a>
+<span class="sourceLineNo">729</span>      Thread.sleep(1000);<a name="line.729"></a>
+<span class="sourceLineNo">730</span>    }<a name="line.730"></a>
+<span class="sourceLineNo">731</span>    throw new IOException("Region " + region + " failed to close within" + " timeout " + timeout);<a name="line.731"></a>
+<span class="sourceLineNo">732</span>  }<a name="line.732"></a>
+<span class="sourceLineNo">733</span><a name="line.733"></a>
+<span class="sourceLineNo">734</span>  /**<a name="line.734"></a>
+<span class="sourceLineNo">735</span>   * Calculate min necessary to start. This is not an absolute. It is just<a name="line.735"></a>
+<span class="sourceLineNo">736</span>   * a friction that will cause us hang around a bit longer waiting on<a name="line.736"></a>
+<span class="sourceLineNo">737</span>   * RegionServers to check-in.<a name="line.737"></a>
+<span class="sourceLineNo">738</span>   */<a name="line.738"></a>
+<span class="sourceLineNo">739</span>  private int getMinToStart() {<a name="line.739"></a>
+<span class="sourceLineNo">740</span>    if (master.isInMaintenanceMode()) {<a name="line.740"></a>
+<span class="sourceLineNo">741</span>      // If in maintenance mode, then master hosting meta will be the only server available<a name="line.741"></a>
+<span class="sourceLineNo">742</span>      return 1;<a name="line.742"></a>
+<span class="sourceLineNo">743</span>    }<a name="line.743"></a>
+<span class="sourceLineNo">744</span><a name="line.744"></a>
+<span class="sourceLineNo">745</span>    int minimumRequired = 1;<a name="line.745"></a>
+<span class="sourceLineNo">746</span>    if (LoadBalancer.isTablesOnMaster(master.getConfiguration()) &amp;&amp;<a name="line.746"></a>
+<span class="sourceLineNo">747</span>        LoadBalancer.isSystemTablesOnlyOnMaster(master.getConfiguration())) {<a name="line.747"></a>
+<span class="sourceLineNo">748</span>      // If Master is carrying regions it will show up as a 'server', but is not handling user-<a name="line.748"></a>
+<span class="sourceLineNo">749</span>      // space regions, so we need a second server.<a name="line.749"></a>
+<span class="sourceLineNo">750</span>      minimumRequired = 2;<a name="line.750"></a>
+<span class="sourceLineNo">751</span>    }<a name="line.751"></a>
+<span class="sourceLineNo">752</span><a name="line.752"></a>
+<span class="sourceLineNo">753</span>    int minToStart = this.master.getConfiguration().getInt(WAIT_ON_REGIONSERVERS_MINTOSTART, -1);<a name="line.753"></a>
+<span class="sourceLineNo">754</span>    // Ensure we are never less than minimumRequired else stuff won't work.<a name="line.754"></a>
+<span class="sourceLineNo">755</span>    return Math.max(minToStart, minimumRequired);<a name="line.755"></a>
+<span class="sourceLineNo">756</span>  }<a name="line.756"></a>
+<span class="sourceLineNo">757</span><a name="line.757"></a>
+<span class="sourceLineNo">758</span>  /**<a name="line.758"></a>
+<span class="sourceLineNo">759</span>   * Wait for the region servers to report in.<a name="line.759"></a>
+<span class="sourceLineNo">760</span>   * We will wait until one of this condition is met:<a name="line.760"></a>
+<span class="sourceLineNo">761</span>   *  - the master is stopped<a name="line.761"></a>
+<span class="sourceLineNo">762</span>   *  - the 'hbase.master.wait.on.regionservers.maxtostart' number of<a name="line.762"></a>
+<span class="sourceLineNo">763</span>   *    region servers is reached<a name="line.763"></a>
+<span class="sourceLineNo">764</span>   *  - the 'hbase.master.wait.on.regionservers.mintostart' is reached AND<a name="line.764"></a>
+<span class="sourceLineNo">765</span>   *   there have been no new region server in for<a name="line.765"></a>
+<span class="sourceLineNo">766</span>   *      'hbase.master.wait.on.regionservers.interval' time AND<a name="line.766"></a>
+<span class="sourceLineNo">767</span>   *   the 'hbase.master.wait.on.regionservers.timeout' is reached<a name="line.767"></a>
+<span class="sourceLineNo">768</span>   *<a name="line.768"></a>
+<span class="sourceLineNo">769</span>   * @throws InterruptedException<a name="line.769"></a>
+<span class="sourceLineNo">770</span>   */<a name="line.770"></a>
+<span class="sourceLineNo">771</span>  public void waitForRegionServers(MonitoredTask status) throws InterruptedException {<a name="line.771"></a>
+<span class="sourceLineNo">772</span>    final long interval = this.master.getConfiguration().<a name="line.772"></a>
+<span class="sourceLineNo">773</span>        getLong(WAIT_ON_REGIONSERVERS_INTERVAL, 1500);<a name="line.773"></a>
+<span class="sourceLineNo">774</span>    final long timeout = this.master.getConfiguration().<a name="line.774"></a>
+<span class="sourceLineNo">775</span>        getLong(WAIT_ON_REGIONSERVERS_TIMEOUT, 4500);<a name="line.775"></a>
+<span class="sourceLineNo">776</span>    // Min is not an absolute; just a friction making us wait longer on server checkin.<a name="line.776"></a>
+<span class="sourceLineNo">777</span>    int minToStart = getMinToStart();<a name="line.777"></a>
+<span class="sourceLineNo">778</span>    int maxToStart = this.master.getConfiguration().<a name="line.778"></a>
+<span class="sourceLineNo">779</span>        getInt(WAIT_ON_REGIONSERVERS_MAXTOSTART, Integer.MAX_VALUE);<a name="line.779"></a>
+<span class="sourceLineNo">780</span>    if (maxToStart &lt; minToStart) {<a name="line.780"></a>
+<span class="sourceLineNo">781</span>      LOG.warn(String.format("The value of '%s' (%d) is set less than '%s' (%d), ignoring.",<a name="line.781"></a>
+<span class="sourceLineNo">782</span>          WAIT_ON_REGIONSERVERS_MAXTOSTART, maxToStart,<a name="line.782"></a>
+<span class="sourceLineNo">783</span>          WAIT_ON_REGIONSERVERS_MINTOSTART, minToStart));<a name="line.783"></a>
+<span class="sourceLineNo">784</span>      maxToStart = Integer.MAX_VALUE;<a name="line.784"></a>
+<span class="sourceLineNo">785</span>    }<a name="line.785"></a>
+<span class="sourceLineNo">786</span><a name="line.786"></a>
+<span class="sourceLineNo">787</span>    long now =  System.currentTimeMillis();<a name="line.787"></a>
+<span class="sourceLineNo">788</span>    final long startTime = now;<a name="line.788"></a>
+<span class="sourceLineNo">789</span>    long slept = 0;<a name="line.789"></a>
+<span class="sourceLineNo">790</span>    long lastLogTime = 0;<a name="line.790"></a>
+<span class="sourceLineNo">791</span>    long lastCountChange = startTime;<a name="line.791"></a>
+<span class="sourceLineNo">792</span>    int count = countOfRegionServers();<a name="line.792"></a>
+<span class="sourceLineNo">793</span>    int oldCount = 0;<a name="line.793"></a>
+<span class="sourceLineNo">794</span>    // This while test is a little hard to read. We try to comment it in below but in essence:<a name="line.794"></a>
+<span class="sourceLineNo">795</span>    // Wait if Master is not stopped and the number of regionservers that have checked-in is<a name="line.795"></a>
+<span class="sourceLineNo">796</span>    // less than the maxToStart. Both of these conditions will be true near universally.<a name="line.796"></a>
+<span class="sourceLineNo">797</span>    // Next, we will keep cycling if ANY of the following three conditions are true:<a name="line.797"></a>
+<span class="sourceLineNo">798</span>    // 1. The time since a regionserver registered is &lt; interval (means servers are actively checking in).<a name="line.798"></a>
+<span class="sourceLineNo">799</span>    // 2. We are under the total timeout.<a name="line.799"></a>
+<span class="sourceLineNo">800</span>    // 3. The count of servers is &lt; minimum.<a name="line.800"></a>
+<span class="sourceLineNo">801</span>    for (ServerListener listener: this.listeners) {<a name="line.801"></a>
+<span class="sourceLineNo">802</span>      listener.waiting();<a name="line.802"></a>
+<span class="sourceLineNo">803</span>    }<a name="line.803"></a>
+<span class="sourceLineNo">804</span>    while (!this.master.isStopped() &amp;&amp; !isClusterShutdown() &amp;&amp; count &lt; maxToStart &amp;&amp;<a name="line.804"></a>
+<span class="sourceLineNo">805</span>        ((lastCountChange + interval) &gt; now || timeout &gt; slept || count &lt; minToStart)) {<a name="line.805"></a>
+<span class="sourceLineNo">806</span>      // Log some info at every interval time or if there is a change<a name="line.806"></a>
+<span class="sourceLineNo">807</span>      if (oldCount != count || lastLogTime + interval &lt; now) {<a name="line.807"></a>
+<span class="sourceLineNo">808</span>        lastLogTime = now;<a name="line.808"></a>
+<span class="sourceLineNo">809</span>        String msg =<a name="line.809"></a>
+<span class="sourceLineNo">810</span>            "Waiting on regionserver count=" + count + "; waited="+<a name="line.810"></a>
+<span class="sourceLineNo">811</span>                slept + "ms, expecting min=" + minToStart + " server(s), max="+ getStrForMax(maxToStart) +<a name="line.811"></a>
+<span class="sourceLineNo">812</span>                " server(s), " + "timeout=" + timeout + "ms, lastChange=" + (lastCountChange - now) + "ms";<a name="line.812"></a>
+<span class="sourceLineNo">813</span>        LOG.info(msg);<a name="line.813"></a>
+<span class="sourceLineNo">814</span>        status.setStatus(msg);<a name="line.814"></a>
+<span class="sourceLineNo">815</span>      }<a name="line.815"></a>
+<span class="sourceLineNo">816</span><a name="line.816"></a>
+<span class="sourceLineNo">817</span>      // We sleep for some time<a name="line.817"></a>
+<span class="sourceLineNo">818</span>      final long sleepTime = 50;<a name="line.818"></a>
+<span class="sourceLineNo">819</span>      Thread.sleep(sleepTime);<a name="line.819"></a>
+<span class="sourceLineNo">820</span>      now =  System.currentTimeMillis();<a name="line.820"></a>
+<span class="sourceLineNo">821</span>      slept = now - startTime;<a name="line.821"></a>
+<span class="sourceLineNo">822</span><a name="line.822"></a>
+<span class="sourceLineNo">823</span>      oldCount = count;<a name="line.823"></a>
+<span class="sourceLineNo">824</span>      count = countOfRegionServers();<a name="line.824"></a>
+<span class="sourceLineNo">825</span>      if (count != oldCount) {<a name="line.825"></a>
+<span class="sourceLineNo">826</span>        lastCountChange = now;<a name="line.826"></a>
+<span class="sourceLineNo">827</span>      }<a name="line.827"></a>
 <span class="sourceLineNo">828</span>    }<a name="line.828"></a>
-<span class="sourceLineNo">829</span>    LOG.info("Finished waiting on RegionServer count=" + count + "; waited=" + slept + "ms," +<a name="line.829"></a>
-<span class="sourceLineNo">830</span>        " expected min=" + minToStart + " server(s), max=" +  getStrForMax(maxToStart) + " server(s),"+<a name="line.830"></a>
-<span class="sourceLineNo">831</span>        " master is "+ (this.master.isStopped() ? "stopped.": "running"));<a name="line.831"></a>
-<span class="sourceLineNo">832</span>  }<a name="line.832"></a>
-<span class="sourceLineNo">833</span><a name="line.833"></a>
-<span class="sourceLineNo">834</span>  private String getStrForMax(final int max) {<a name="line.834"></a>
-<span class="sourceLineNo">835</span>    return max == Integer.MAX_VALUE? "NO_LIMIT": Integer.toString(max);<a name="line.835"></a>
+<span class="sourceLineNo">829</span>    // Did we exit the loop because cluster is going down?<a name="line.829"></a>
+<span class="sourceLineNo">830</span>    if (isClusterShutdown()) {<a name="line.830"></a>
+<span class="sourceLineNo">831</span>      this.master.stop("Cluster shutdown");<a name="line.831"></a>
+<span class="sourceLineNo">832</span>    }<a name="line.832"></a>
+<span class="sourceLineNo">833</span>    LOG.info("Finished waiting on RegionServer count=" + count + "; waited=" + slept + "ms," +<a name="line.833"></a>
+<span class="sourceLineNo">834</span>        " expected min=" + minToStart + " server(s), max=" +  getStrForMax(maxToStart) + " server(s),"+<a name="line.834"></a>
+<span class="sourceLineNo">835</span>        " master is "+ (this.master.isStopped() ? "stopped.": "running"));<a name="line.835"></a>
 <span class="sourceLineNo">836</span>  }<a name="line.836"></a>
 <span class="sourceLineNo">837</span><a name="line.837"></a>
-<span class="sourceLineNo">838</span>  /**<a name="line.838"></a>
-<span class="sourceLineNo">839</span>   * @return A copy of the internal list of online servers.<a name="line.839"></a>
-<span class="sourceLineNo">840</span>   */<a name="line.840"></a>
-<span class="sourceLineNo">841</span>  public List&lt;ServerName&gt; getOnlineServersList() {<a name="line.841"></a>
-<span class="sourceLineNo">842</span>    // TODO: optimize the load balancer call so we don't need to make a new list<a name="line.842"></a>
-<span class="sourceLineNo">843</span>    // TODO: FIX. THIS IS POPULAR CALL.<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    return new ArrayList&lt;&gt;(this.onlineServers.keySet());<a name="line.844"></a>
-<span class="sourceLineNo">845</span>  }<a name="line.845"></a>
-<span class="sourceLineNo">846</span><a name="line.846"></a>
-<span class="sourceLineNo">847</span>  /**<a name="line.847"></a>
-<span class="sourceLineNo">848</span>   * @param keys The target server name<a name="line.848"></a>
-<span class="sourceLineNo">849</span>   * @param idleServerPredicator Evaluates the server on the given load<a name="line.849"></a>
-<span class="sourceLineNo">850</span>   * @return A copy of the internal list of online servers matched by the predicator<a name="line.850"></a>
-<span class="sourceLineNo">851</span>   */<a name="line.851"></a>
-<span class="sourceLineNo">852</span>  public List&lt;ServerName&gt; getOnlineServersListWithPredicator(List&lt;ServerName&gt; keys,<a name="line.852"></a>
-<span class="sourceLineNo">853</span>    Predicate&lt;ServerMetrics&gt; idleServerPredicator) {<a name="line.853"></a>
-<span class="sourceLineNo">854</span>    List&lt;ServerName&gt; names = new ArrayList&lt;&gt;();<a name="line.854"></a>
-<span class="sourceLineNo">855</span>    if (keys != null &amp;&amp; idleServerPredicator != null) {<a name="line.855"></a>
-<span class="sourceLineNo">856</span>      keys.forEach(name -&gt; {<a name="line.856"></a>
-<span class="sourceLineNo">857</span>        ServerMetrics load = onlineServers.get(name);<a name="line.857"></a>
-<span class="sourceLineNo">858</span>        if (load != null) {<a name="line.858"></a>
-<span class="sourceLineNo">859</span>          if (idleServerPredicator.test(load)) {<a name="line.859"></a>
-<span class="sourceLineNo">860</span>            names.add(name);<a name="line.860"></a>
-<span class="sourceLineNo">861</span>          }<a name="line.861"></a>
-<span class="sourceLineNo">862</span>        }<a name="line.862"></a>
-<span class="sourceLineNo">863</span>      });<a name="line.863"></a>
-<span class="sourceLineNo">864</span>    }<a name="line.864"></a>
-<span class="sourceLineNo">865</span>    return names;<a name="line.865"></a>
-<span class="sourceLineNo">866</span>  }<a name="line.866"></a>
-<span class="sourceLineNo">867</span><a name="line.867"></a>
-<span class="sourceLineNo">868</span>  /**<a name="line.868"></a>
-<span class="sourceLineNo">869</span>   * @return A copy of the internal list of draining servers.<a name="line.869"></a>
-<span class="sourceLineNo">870</span>   */<a name="line.870"></a>
-<span class="sourceLineNo">871</span>  public List&lt;ServerName&gt; getDrainingServersList() {<a name="line.871"></a>
-<span class="sourceLineNo">872</span>    return new ArrayList&lt;&gt;(this.drainingServers);<a name="line.872"></a>
-<span class="sourceLineNo">873</span>  }<a name="line.873"></a>
-<span class="sourceLineNo">874</span><a name="line.874"></a>
-<span class="sourceLineNo">875</span>  public boolean isServerOnline(ServerName serverName) {<a name="line.875"></a>
-<span class="sourceLineNo">876</span>    return serverName != null &amp;&amp; onlineServers.containsKey(serverName);<a name="line.876"></a>
+<span class="sourceLineNo">838</span>  private String getStrForMax(final int max) {<a name="line.838"></a>
+<span class="sourceLineNo">839</span>    return max == Integer.MAX_VALUE? "NO_LIMIT": Integer.toString(max);<a name="line.839"></a>
+<span class="sourceLineNo">840</span>  }<a name="line.840"></a>
+<span class="sourceLineNo">841</span><a name="line.841"></a>
+<span class="sourceLineNo">842</span>  /**<a name="line.842"></a>
+<span class="sourceLineNo">843</span>   * @return A copy of the internal list of online servers.<a name="line.843"></a>
+<span class="sourceLineNo">844</span>   */<a name="line.844"></a>
+<span class="sourceLineNo">845</span>  public List&lt;ServerName&gt; getOnlineServersList() {<a name="line.845"></a>
+<span class="sourceLineNo">846</span>    // TODO: optimize the load balancer call so we don't need to make a new list<a name="line.846"></a>
+<span class="sourceLineNo">847</span>    // TODO: FIX. THIS IS POPULAR CALL.<a name="line.847"></a>
+<span class="sourceLineNo">848</span>    return new ArrayList&lt;&gt;(this.onlineServers.keySet());<a name="line.848"></a>
+<span class="sourceLineNo">849</span>  }<a name="line.849"></a>
+<span class="sourceLineNo">850</span><a name="line.850"></a>
+<span class="sourceLineNo">851</span>  /**<a name="line.851"></a>
+<span class="sourceLineNo">852</span>   * @param keys The target server name<a name="line.852"></a>
+<span class="sourceLineNo">853</span>   * @param idleServerPredicator Evaluates the server on the given load<a name="line.853"></a>
+<span class="sourceLineNo">854</span>   * @return A copy of the internal list of online servers matched by the predicator<a name="line.854"></a>
+<span class="sourceLineNo">855</span>   */<a name="line.855"></a>
+<span class="sourceLineNo">856</span>  public List&lt;ServerName&gt; getOnlineServersListWithPredicator(List&lt;ServerName&gt; keys,<a name="line.856"></a>
+<span class="sourceLineNo">857</span>    Predicate&lt;ServerMetrics&gt; idleServerPredicator) {<a name="line.857"></a>
+<span class="sourceLineNo">858</span>    List&lt;ServerName&gt; names = new ArrayList&lt;&gt;();<a name="line.858"></a>
+<span class="sourceLineNo">859</span>    if (keys != null &amp;&amp; idleServerPredicator != null) {<a name="line.859"></a>
+<span class="sourceLineNo">860</span>      keys.forEach(name -&gt; {<a name="line.860"></a>
+<span class="sourceLineNo">861</span>        ServerMetrics load = onlineServers.get(name);<a name="line.861"></a>
+<span class="sourceLineNo">862</span>        if (load != null) {<a name="line.862"></a>
+<span class="sourceLineNo">863</span>          if (idleServerPredicator.test(load)) {<a name="line.863"></a>
+<span class="sourceLineNo">864</span>            names.add(name);<a name="line.864"></a>
+<span class="sourceLineNo">865</span>          }<a name="line.865"></a>
+<span class="sourceLineNo">866</span>        }<a name="line.866"></a>
+<span class="sourceLineNo">867</span>      });<a name="line.867"></a>
+<span class="sourceLineNo">868</span>    }<a name="line.868"></a>
+<span class="sourceLineNo">869</span>    return names;<a name="line.869"></a>
+<span class="sourceLineNo">870</span>  }<a name="line.870"></a>
+<span class="sourceLineNo">871</span><a name="line.871"></a>
+<span class="sourceLineNo">872</span>  /**<a name="line.872"></a>
+<span class="sourceLineNo">873</span>   * @return A copy of the internal list of draining servers.<a name="line.873"></a>
+<span class="sourceLineNo">874</span>   */<a name="line.874"></a>
+<span class="sourceLineNo">875</span>  public List&lt;ServerName&gt; getDrainingServersList() {<a name="line.875"></a>
+<span class="sourceLineNo">876</span>    return new ArrayList&lt;&gt;(this.drainingServers);<a name="line.876"></a>
 <span class="sourceLineNo">877</span>  }<a name="line.877"></a>
 <span class="sourceLineNo">878</span><a name="line.878"></a>
-<span class="sourceLineNo">879</span>  public enum ServerLiveState {<a name="line.879"></a>
-<span class="sourceLineNo">880</span>    LIVE,<a name="line.880"></a>
-<span class="sourceLineNo">881</span>    DEAD,<a name="line.881"></a>
-<span class="sourceLineNo">882</span>    UNKNOWN<a name="line.882"></a>
-<span class="sourceLineNo">883</span>  }<a name="line.883"></a>
-<span class="sourceLineNo">884</span><a name="line.884"></a>
-<span class="sourceLineNo">885</span>  /**<a name="line.885"></a>
-<span class="sourceLineNo">886</span>   * @return whether the server is online, dead, or unknown.<a name="line.886"></a>
-<span class="sourceLineNo">887</span>   */<a name="line.887"></a>
-<span class="sourceLineNo">888</span>  public synchronized ServerLiveState isServerKnownAndOnline(ServerName serverName) {<a name="line.888"></a>
-<span class="sourceLineNo">889</span>    return onlineServers.containsKey(serverName) ? ServerLiveState.LIVE<a name="line.889"></a>
-<span class="sourceLineNo">890</span>      : (deadservers.isDeadServer(serverName) ? ServerLiveState.DEAD : ServerLiveState.UNKNOWN);<a name="line.890"></a>
-<span class="sourceLineNo">891</span>  }<a name="line.891"></a>
-<span class="sourceLineNo">892</span><a name="line.892"></a>
-<span class="sourceLineNo">893</span>  /**<a name="line.893"></a>
-<span class="sourceLineNo">894</span>   * Check if a server is known to be dead.  A server can be online,<a name="line.894"></a>
-<span class="sourceLineNo">895</span>   * or known to be dead, or unknown to this manager (i.e, not online,<a name="line.895"></a>
-<span class="sourceLineNo">896</span>   * not known to be dead either; it is simply not tracked by the<a name="line.896"></a>
-<span class="sourceLineNo">897</span>   * master any more, for example, a very old previous instance).<a name="line.897"></a>
-<span class="sourceLineNo">898</span>   */<a name="line.898"></a>
-<span class="sourceLineNo">899</span>  public synchronized boolean isServerDead(ServerName serverName) {<a name="line.899"></a>
-<span class="sourceLineNo">900</span>    return serverName == null || deadservers.isDeadServer(serverName);<a name="line.900"></a>
-<span class="sourceLineNo">901</span>  }<a name="line.901"></a>
-<span class="sourceLineNo">902</span><a name="line.902"></a>
-<span class="sourceLineNo">903</span>  public void shutdownCluster() {<a name="line.903"></a>
-<span class="sourceLineNo">904</span>    String statusStr = "Cluster shutdown requested of master=" + this.master.getServerName();<a name="line.904"></a>
-<span class="sourceLineNo">905</span>    LOG.info(statusStr);<a name="line.905"></a>
-<span class="sourceLineNo">906</span>    this.clusterShutdown.set(true);<a name="line.906"></a>
-<span class="sourceLineNo">907</span>    if (onlineServers.isEmpty()) {<a name="line.907"></a>
-<span class="sourceLineNo">908</span>      // we do not synchronize here so this may cause a double stop, but not a big deal<a name="line.908"></a>
-<span class="sourceLineNo">909</span>      master.stop("OnlineServer=0 right after cluster shutdown set");<a name="line.909"></a>
-<span class="sourceLineNo">910</span>    }<a name="line.910"></a>
-<span class="sourceLineNo">911</span>  }<a name="line.911"></a>
-<span class="sourceLineNo">912</span><a name="line.912"></a>
-<span class="sourceLineNo">913</span>  public boolean isClusterShutdown() {<a name="line.913"></a>
-<span class="sourceLineNo">914</span>    return this.clusterShutdown.get();<a name="line.914"></a>
+<span class="sourceLineNo">879</span>  public boolean isServerOnline(ServerName serverName) {<a name="line.879"></a>
+<span class="sourceLineNo">880</span>    return serverName != null &amp;&amp; onlineServers.containsKey(serverName);<a name="line.880"></a>
+<span class="sourceLineNo">881</span>  }<a name="line.881"></a>
+<span class="sourceLineNo">882</span><a name="line.882"></a>
+<span class="sourceLineNo">883</span>  public enum ServerLiveState {<a name="line.883"></a>
+<span class="sourceLineNo">884</span>    LIVE,<a name="line.884"></a>
+<span class="sourceLineNo">885</span>    DEAD,<a name="line.885"></a>
+<span class="sourceLineNo">886</span>    UNKNOWN<a name="line.886"></a>
+<span class="sourceLineNo">887</span>  }<a name="line.887"></a>
+<span class="sourceLineNo">888</span><a name="line.888"></a>
+<span class="sourceLineNo">889</span>  /**<a name="line.889"></a>
+<span class="sourceLineNo">890</span>   * @return whether the server is online, dead, or unknown.<a name="line.890"></a>
+<span class="sourceLineNo">891</span>   */<a name="line.891"></a>
+<span class="sourceLineNo">892</span>  public synchronized ServerLiveState isServerKnownAndOnline(ServerName serverName) {<a name="line.892"></a>
+<span class="sourceLineNo">893</span>    return onlineServers.containsKey(serverName) ? ServerLiveState.LIVE<a name="line.893"></a>
+<span class="sourceLineNo">894</span>      : (deadservers.isDeadServer(serverName) ? ServerLiveState.DEAD : ServerLiveState.UNKNOWN);<a name="line.894"></a>
+<span class="sourceLineNo">895</span>  }<a name="line.895"></a>
+<span class="sourceLineNo">896</span><a name="line.896"></a>
+<span class="sourceLineNo">897</span>  /**<a name="line.897"></a>
+<span class="sourceLineNo">898</span>   * Check if a server is known to be dead.  A server can be online,<a name="line.898"></a>
+<span class="sourceLineNo">899</span>   * or known to be dead, or unknown to this manager (i.e, not online,<a name="line.899"></a>
+<span class="sourceLineNo">900</span>   * not known to be dead either; it is simply not tracked by the<a name="line.900"></a>
+<span class="sourceLineNo">901</span>   * master any more, for example, a very old previous instance).<a name="line.901"></a>
+<span class="sourceLineNo">902</span>   */<a name="line.902"></a>
+<span class="sourceLineNo">903</span>  public synchronized boolean isServerDead(ServerName serverName) {<a name="line.903"></a>
+<span class="sourceLineNo">904</span>    return serverName == null || deadservers.isDeadServer(serverName);<a name="line.904"></a>
+<span class="sourceLineNo">905</span>  }<a name="line.905"></a>
+<span class="sourceLineNo">906</span><a name="line.906"></a>
+<span class="sourceLineNo">907</span>  public void shutdownCluster() {<a name="line.907"></a>
+<span class="sourceLineNo">908</span>    String statusStr = "Cluster shutdown requested of master=" + this.master.getServerName();<a name="line.908"></a>
+<span class="sourceLineNo">909</span>    LOG.info(statusStr);<a name="line.909"></a>
+<span class="sourceLineNo">910</span>    this.clusterShutdown.set(true);<a name="line.910"></a>
+<span class="sourceLineNo">911</span>    if (onlineServers.isEmpty()) {<a name="line.911"></a>
+<span class="sourceLineNo">912</span>      // we do not synchronize here so this may cause a double stop, but not a big deal<a name="line.912"></a>
+<span class="sourceLineNo">913</span>      master.stop("OnlineServer=0 right after cluster shutdown set");<a name="line.913"></a>
+<span class="sourceLineNo">914</span>    }<a name="line.914"></a>
 <span class="sourceLineNo">915</span>  }<a name="line.915"></a>
 <span class="sourceLineNo">916</span><a name="line.916"></a>
-<span class="sourceLineNo">917</span>  /**<a name="line.917"></a>
-<span class="sourceLineNo">918</span>   * start chore in ServerManager<a name="line.918"></a>
-<span class="sourceLineNo">919</span>   */<a name="line.919"></a>
-<span class="sourceLineNo">920</span>  public void startChore() {<a name="line.920"></a>
-<span class="sourceLineNo">921</span>    Configuration c = master.getConfiguration();<a name="line.921"></a>
-<span class="sourceLineNo">922</span>    if (persistFlushedSequenceId) {<a name="line.922"></a>
-<span class="sourceLineNo">923</span>      // when reach here, RegionStates should loaded, firstly, we call remove deleted regions<a name="line.923"></a>
-<span class="sourceLineNo">924</span>      removeDeletedRegionFromLoadedFlushedSequenceIds();<a name="line.924"></a>
-<span class="sourceLineNo">925</span>      int flushPeriod = c.getInt(FLUSHEDSEQUENCEID_FLUSHER_INTERVAL,<a name="line.925"></a>
-<span class="sourceLineNo">926</span>          FLUSHEDSEQUENCEID_FLUSHER_INTERVAL_DEFAULT);<a name="line.926"></a>
-<span class="sourceLineNo">927</span>      flushedSeqIdFlusher = new FlushedSequenceIdFlusher(<a name="line.927"></a>
-<span class="sourceLineNo">928</span>          "FlushedSequenceIdFlusher", flushPeriod);<a name="line.928"></a>
-<span class="sourceLineNo">929</span>      master.getChoreService().scheduleChore(flushedSeqIdFlusher);<a name="line.929"></a>
-<span class="sourceLineNo">930</span>    }<a name="line.930"></a>
-<span class="sourceLineNo">931</span>  }<a name="line.931"></a>
-<span class="sourceLineNo">932</span><a name="line.932"></a>
-<span class="sourceLineNo">933</span>  /**<a name="line.933"></a>
-<span class="sourceLineNo">934</span>   * Stop the ServerManager.<a name="line.934"></a>
-<span class="sourceLineNo">935</span>   */<a name="line.935"></a>
-<span class="sourceLineNo">936</span>  public void stop() {<a name="line.936"></a>
-<span class="sourceLineNo">937</span>    if (flushedSeqIdFlusher != null) {<a name="line.937"></a>
-<span class="sourceLineNo">938</span>      flushedSeqIdFlusher.cancel();<a name="line.938"></a>
-<span class="sourceLineNo">939</span>    }<a name="line.939"></a>
-<span class="sourceLineNo">940</span>    if (persistFlushedSequenceId) {<a name="line.940"></a>
-<span class="sourceLineNo">941</span>      try {<a name="line.941"></a>
-<span class="sourceLineNo">942</span>        persistRegionLastFlushedSequenceIds();<a name="line.942"></a>
-<span class="sourceLineNo">943</span>      } catch (IOException e) {<a name="line.943"></a>
-<span class="sourceLineNo">944</span>        LOG.warn("Failed to persist last flushed sequence id of regions"<a name="line.944"></a>
-<span class="sourceLineNo">945</span>            + " to file system", e);<a name="line.945"></a>
-<span class="sourceLineNo">946</span>      }<a name="line.946"></a>
-<span class="sourceLineNo">947</span>    }<a name="line.947"></a>
-<span class="sourceLineNo">948</span>  }<a name="line.948"></a>
-<span class="sourceLineNo">949</span><a name="line.949"></a>
-<span class="sourceLineNo">950</span>  /**<a name="line.950"></a>
-<span class="sourceLineNo">951</span>   * Creates a list of possible destinations for a region. It contains the online servers, but not<a name="line.951"></a>
-<span class="sourceLineNo">952</span>   *  the draining or dying servers.<a name="line.952"></a>
-<span class="sourceLineNo">953</span>   *  @param serversToExclude can be null if there is no server to exclude<a name="line.953"></a>
-<span class="sourceLineNo">954</span>   */<a name="line.954"></a>
-<span class="sourceLineNo">955</span>  public List&lt;ServerName&gt; createDestinationServersList(final List&lt;ServerName&gt; serversToExclude){<a name="line.955"></a>
-<span class="sourceLineNo">956</span>    final List&lt;ServerName&gt; destServers = getOnlineServersList();<a name="line.956"></a>
-<span class="sourceLineNo">957</span><a name="line.957"></a>
-<span class="sourceLineNo">958</span>    if (serversToExclude != null) {<a name="line.958"></a>
-<span class="sourceLineNo">959</span>      destServers.removeAll(serversToExclude);<a name="line.959"></a>
-<span class="sourceLineNo">960</span>    }<a name="line.960"></a>
+<span class="sourceLineNo">917</span>  public boolean isClusterShutdown() {<a name="line.917"></a>
+<span class="sourceLineNo">918</span>    return this.clusterShutdown.get();<a name="line.918"></a>
+<span class="sourceLineNo">919</span>  }<a name="line.919"></a>
+<span class="sourceLineNo">920</span><a name="line.920"></a>
+<span class="sourceLineNo">921</span>  /**<a name="line.921"></a>
+<span class="sourceLineNo">922</span>   * start chore in ServerManager<a name="line.922"></a>
+<span class="sourceLineNo">923</span>   */<a name="line.923"></a>
+<span class="sourceLineNo">924</span>  public void startChore() {<a name="line.924"></a>
+<span class="sourceLineNo">925</span>    Configuration c = master.getConfiguration();<a name="line.925"></a>
+<span class="sourceLineNo">926</span>    if (persistFlushedSequenceId) {<a name="line.926"></a>
+<span class="sourceLineNo">927</span>      // when reach here, RegionStates should loaded, firstly, we call remove deleted regions<a name="line.927"></a>
+<span class="sourceLineNo">928</span>      removeDeletedRegionFromLoadedFlushedSequenceIds();<a name="line.928"></a>
+<span class="sourceLineNo">929</span>      int flushPeriod = c.getInt(FLUSHEDSEQUENCEID_FLUSHER_INTERVAL,<a name="line.929"></a>
+<span class="sourceLineNo">930</span>          FLUSHEDSEQUENCEID_FLUSHER_INTERVAL_DEFAULT);<a name="line.930"></a>
+<span class="sourceLineNo">931</span>      flushedSeqIdFlusher = new FlushedSequenceIdFlusher(<a name="line.931"></a>
+<span class="sourceLineNo">932</span>          "FlushedSequenceIdFlusher", flushPeriod);<a name="line.932"></a>
+<span class="sourceLineNo">933</span>      master.getChoreService().scheduleChore(flushedSeqIdFlusher);<a name="line.933"></a>
+<span class="sourceLineNo">934</span>    }<a name="line.934"></a>
+<span class="sourceLineNo">935</span>  }<a name="line.935"></a>
+<span class="sourceLineNo">936</span><a name="line.936"></a>
+<span class="sourceLineNo">937</span>  /**<a name="line.937"></a>
+<span class="sourceLineNo">938</span>   * Stop the ServerManager.<a name="line.938"></a>
+<span class="sourceLineNo">939</span>   */<a name="line.939"></a>
+<span class="sourceLineNo">940</span>  public void stop() {<a name="line.940"></a>
+<span class="sourceLineNo">941</span>    if (flushedSeqIdFlusher != null) {<a name="line.941"></a>
+<span class="sourceLineNo">942</span>      flushedSeqIdFlusher.cancel();<a name="line.942"></a>
+<span class="sourceLineNo">943</span>    }<a name="line.943"></a>
+<span class="sourceLineNo">944</span>    if (persistFlushedSequenceId) {<a name="line.944"></a>
+<span class="sourceLineNo">945</span>      try {<a name="line.945"></a>
+<span class="sourceLineNo">946</span>        persistRegionLastFlushedSequenceIds();<a name="line.946"></a>
+<span class="sourceLineNo">947</span>      } catch (IOException e) {<a name="line.947"></a>
+<span class="sourceLineNo">948</span>        LOG.warn("Failed to persist last flushed sequence id of regions"<a name="line.948"></a>
+<span class="sourceLineNo">949</span>            + " to file system", e);<a name="line.949"></a>
+<span class="sourceLineNo">950</span>      }<a name="line.950"></a>
+<span class="sourceLineNo">951</span>    }<a name="line.951"></a>
+<span class="sourceLineNo">952</span>  }<a name="line.952"></a>
+<span class="sourceLineNo">953</span><a name="line.953"></a>
+<span class="sourceLineNo">954</span>  /**<a name="line.954"></a>
+<span class="sourceLineNo">955</span>   * Creates a list of possible destinations for a region. It contains the online servers, but not<a name="line.955"></a>
+<span class="sourceLineNo">956</span>   *  the draining or dying servers.<a name="line.956"></a>
+<span class="sourceLineNo">957</span>   *  @param serversToExclude can be null if there is no server to exclude<a name="line.957"></a>
+<span class="sourceLineNo">958</span>   */<a name="line.958"></a>
+<span class="sourceLineNo">959</span>  public List&lt;ServerName&gt; createDestinationServersList(final List&lt;ServerName&gt; serversToExclude){<a name="line.959"></a>
+<span class="sourceLineNo">960</span>    final List&lt;ServerName&gt; destServers = getOnlineServersList();<a name="line.960"></a>
 <span class="sourceLineNo">961</span><a name="line.961"></a>
-<span class="sourceLineNo">962</span>    // Loop through the draining server list and remove them from the server list<a name="line.962"></a>
-<span class="sourceLineNo">963</span>    final List&lt;ServerName&gt; drainingServersCopy = getDrainingServersList();<a name="line.963"></a>
-<span class="sourceLineNo">964</span>    destServers.removeAll(drainingServersCopy);<a name="line.964"></a>
+<span class="sourceLineNo">962</span>    if (serversToExclude != null) {<a name="line.962"></a>
+<span class="sourceLineNo">963</span>      destServers.removeAll(serversToExclude);<a name="line.963"></a>
+<span class="sourceLineNo">964</span>    }<a name="line.964"></a>
 <span class="sourceLineNo">965</span><a name="line.965"></a>
-<span class="sourceLineNo">966</span>    return destServers;<a name="line.966"></a>
-<span class="sourceLineNo">967</span>  }<a name="line.967"></a>
-<span class="sourceLineNo">968</span><a name="line.968"></a>
-<span class="sourceLineNo">969</span>  /**<a name="line.969"></a>
-<span class="sourceLineNo">970</span>   * Calls {@link #createDestinationServersList} without server to exclude.<a name="line.970"></a>
-<span class="sourceLineNo">971</span>   */<a name="line.971"></a>
-<span class="sourceLineNo">972</span>  public List&lt;ServerName&gt; createDestinationServersList(){<a name="line.972"></a>
-<span class="sourceLineNo">973</span>    return createDestinationServersList(null);<a name="line.973"></a>
-<span class="sourceLineNo">974</span>  }<a name="line.974"></a>
-<span class="sourceLineNo">975</span><a name="line.975"></a>
-<span class="sourceLineNo">976</span>  /**<a name="line.976"></a>
-<span class="sourceLineNo">977</span>   * To clear any dead server with same host name and port of any online server<a name="line.977"></a>
-<span class="sourceLineNo">978</span>   */<a name="line.978"></a>
-<span class="sourceLineNo">979</span>  void clearDeadServersWithSameHostNameAndPortOfOnlineServer() {<a name="line.979"></a>
-<span class="sourceLineNo">980</span>    for (ServerName serverName : getOnlineServersList()) {<a name="line.980"></a>
-<span class="sourceLineNo">981</span>      deadservers.cleanAllPreviousInstances(serverName);<a name="line.981"></a>
-<span class="sourceLineNo">982</span>    }<a name="line.982"></a>
-<span class="sourceLineNo">983</span>  }<a name="line.983"></a>
-<span class="sourceLineNo">984</span><a name="line.984"></a>
-<span class="sourceLineNo">985</span>  /**<a name="line.985"></a>
-<span class="sourceLineNo">986</span>   * Called by delete table and similar to notify the ServerManager that a region was removed.<a name="line.986"></a>
-<span class="sourceLineNo">987</span>   */<a name="line.987"></a>
-<span class="sourceLineNo">988</span>  public void removeRegion(final RegionInfo regionInfo) {<a name="line.988"></a>
-<span class="sourceLineNo">989</span>    final byte[] encodedName = regionInfo.getEncodedNameAsBytes();<a name="line.989"></a>
-<span class="sourceLineNo">990</span>    storeFlushedSequenceIdsByRegion.remove(encodedName);<a name="line.990"></a>
-<span class="sourceLineNo">991</span>    flushedSequenceIdByRegion.remove(encodedName);<a name="line.991"></a>
-<span class="sourceLineNo">992</span>  }<a name="line.992"></a>
-<span class="sourceLineNo">993</span><a name="line.993"></a>
-<span class="sourceLineNo">994</span>  @VisibleForTesting<a name="line.994"></a>
-<span class="sourceLineNo">995</span>  public boolean isRegionInServerManagerStates(final RegionInfo hri) {<a name="line.995"></a>
-<span class="sourceLineNo">996</span>    final byte[] encodedName = hri.getEncodedNameAsBytes();<a name="line.996"></a>
-<span class="sourceLineNo">997</span>    return (storeFlushedSequenceIdsByRegion.containsKey(encodedName)<a name="line.997"></a>
-<span class="sourceLineNo">998</span>        || flushedSequenceIdByRegion.containsKey(encodedName));<a name="line.998"></a>
-<span class="sourceLineNo">999</span>  }<a name="line.999"></a>
-<span class="sourceLineNo">1000</span><a name="line.1000"></a>
-<span class="sourceLineNo">1001</span>  /**<a name="line.1001"></a>
-<span class="sourceLineNo">1002</span>   * Called by delete table and similar to notify the ServerManager that a region was removed.<a name="line.1002"></a>
-<span class="sourceLineNo">1003</span>   */<a name="line.1003"></a>
-<span class="sourceLineNo">1004</span>  public void removeRegions(final List&lt;RegionInfo&gt; regions) {<a name="line.1004"></a>
-<span class="sourceLineNo">1005</span>    for (RegionInfo hri: regions) {<a name="line.1005"></a>
-<span class="sourceLineNo">1006</span>      removeRegion(hri);<a name="line.1006"></a>
-<span class="sourceLineNo">1007</span>    }<a name="line.1007"></a>
-<span class="sourceLineNo">1008</span>  }<a name="line.1008"></a>
-<span class="sourceLineNo">1009</span><a name="line.1009"></a>
-<span class="sourceLineNo">1010</span>  /**<a name="line.1010"></a>
-<span class="sourceLineNo">1011</span>   * May return 0 when server is not online.<a name="line.1011"></a>
-<span class="sourceLineNo">1012</span>   */<a name="line.1012"></a>
-<span class="sourceLineNo">1013</span>  public int getVersionNumber(ServerName serverName) {<a name="line.1013"></a>
-<span class="sourceLineNo">1014</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1014"></a>
-<span class="sourceLineNo">1015</span>    return serverMetrics != null ? serverMetrics.getVersionNumber() : 0;<a name="line.1015"></a>
-<span class="sourceLineNo">1016</span>  }<a name="line.1016"></a>
-<span class="sourceLineNo">1017</span><a name="line.1017"></a>
-<span class="sourceLineNo">1018</span>  /**<a name="line.1018"></a>
-<span class="sourceLineNo">1019</span>   * May return "0.0.0" when server is not online<a name="line.1019"></a>
-<span class="sourceLineNo">1020</span>   */<a name="line.1020"></a>
-<span class="sourceLineNo">1021</span>  public String getVersion(ServerName serverName) {<a name="line.1021"></a>
-<span class="sourceLineNo">1022</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1022"></a>
-<span class="sourceLineNo">1023</span>    return serverMetrics != null ? serverMetrics.getVersion() : "0.0.0";<a name="line.1023"></a>
-<span class="sourceLineNo">1024</span>  }<a name="line.1024"></a>
-<span class="sourceLineNo">1025</span><a name="line.1025"></a>
-<span class="sourceLineNo">1026</span>  public int getInfoPort(ServerName serverName) {<a name="line.1026"></a>
-<span class="sourceLineNo">1027</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1027"></a>
-<span class="sourceLineNo">1028</span>    return serverMetrics != null ? serverMetrics.getInfoServerPort() : 0;<a name="line.1028"></a>
-<span class="sourceLineNo">1029</span>  }<a name="line.1029"></a>
-<span class="sourceLineNo">1030</span><a name="line.1030"></a>
-<span class="sourceLineNo">1031</span>  /**<a name="line.1031"></a>
-<span class="sourceLineNo">1032</span>   * Persist last flushed sequence id of each region to HDFS<a name="line.1032"></a>
-<span class="sourceLineNo">1033</span>   * @throws IOException if persit to HDFS fails<a name="line.1033"></a>
-<span class="sourceLineNo">1034</span>   */<a name="line.1034"></a>
-<span class="sourceLineNo">1035</span>  private void persistRegionLastFlushedSequenceIds() throws IOException {<a name="line.1035"></a>
-<span class="sourceLineNo">1036</span>    if (isFlushSeqIdPersistInProgress) {<a name="line.1036"></a>
-<span class="sourceLineNo">1037</span>      return;<a name="line.1037"></a>
-<span class="sourceLineNo">1038</span>    }<a name="line.1038"></a>
-<span class="sourceLineNo">1039</span>    isFlushSeqIdPersistInProgress = true;<a name="line.1039"></a>
-<span class="sourceLineNo">1040</span>    try {<a name="line.1040"></a>
-<span class="sourceLineNo">1041</span>      Configuration conf = master.getConfiguration();<a name="line.1041"></a>
-<span class="sourceLineNo">1042</span>      Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.1042"></a>
-<span class="sourceLineNo">1043</span>      Path lastFlushedSeqIdPath = new Path(rootDir, LAST_FLUSHED_SEQ_ID_FILE);<a name="line.1043"></a>
-<span class="sourceLineNo">1044</span>      FileSystem fs = FileSystem.get(conf);<a name="line.1044"></a>
-<span class="sourceLineNo">1045</span>      if (fs.exists(lastFlushedSeqIdPath)) {<a name="line.1045"></a>
-<span class="sourceLineNo">1046</span>        LOG.info("Rewriting .lastflushedseqids file at: "<a name="line.1046"></a>
-<span class="sourceLineNo">1047</span>            + lastFlushedSeqIdPath);<a name="line.1047"></a>
-<span class="sourceLineNo">1048</span>        if (!fs.delete(lastFlushedSeqIdPath, false)) {<a name="line.1048"></a>
-<span class="sourceLineNo">1049</span>          throw new IOException("Unable to remove existing "<a name="line.1049"></a>
-<span class="sourceLineNo">1050</span>              + lastFlushedSeqIdPath);<a name="line.1050"></a>
-<span class="sourceLineNo">1051</span>        }<a name="line.1051"></a>
-<span class="sourceLineNo">1052</span>      } else {<a name="line.1052"></a>
-<span class="sourceLineNo">1053</span>        LOG.info("Writing .lastflushedseqids file at: " + lastFlushedSeqIdPath);<a name="line.1053"></a>
-<span class="sourceLineNo">1054</span>      }<a name="line.1054"></a>
-<span class="sourceLineNo">1055</span>      FSDataOutputStream out = fs.create(lastFlushedSeqIdPath);<a name="line.1055"></a>
-<span class="sourceLineNo">1056</span>      FlushedSequenceId.Builder flushedSequenceIdBuilder =<a name="line.1056"></a>
-<span class="sourceLineNo">1057</span>          FlushedSequenceId.newBuilder();<a name="line.1057"></a>
-<span class="sourceLineNo">1058</span>      try {<a name="line.1058"></a>
-<span class="sourceLineNo">1059</span>        for (Entry&lt;byte[], Long&gt; entry : flushedSequenceIdByRegion.entrySet()) {<a name="line.1059"></a>
-<span class="sourceLineNo">1060</span>          FlushedRegionSequenceId.Builder flushedRegionSequenceIdBuilder =<a name="line.1060"></a>
-<span class="sourceLineNo">1061</span>              FlushedRegionSequenceId.newBuilder();<a name="line.1061"></a>
-<span class="sourceLineNo">1062</span>          flushedRegionSequenceIdBuilder.setRegionEncodedName(<a name="line.1062"></a>
-<span class="sourceLineNo">1063</span>              ByteString.copyFrom(entry.getKey()));<a name="line.1063"></a>
-<span class="sourceLineNo">1064</span>          flushedRegionSequenceIdBuilder.setSeqId(entry.getValue());<a name="line.1064"></a>
-<span class="sourceLineNo">1065</span>          ConcurrentNavigableMap&lt;byte[], Long&gt; storeSeqIds =<a name="line.1065"></a>
-<span class="sourceLineNo">1066</span>              storeFlushedSequenceIdsByRegion.get(entry.getKey());<a name="line.1066"></a>
-<span class="sourceLineNo">1067</span>          if (storeSeqIds != null) {<a name="line.1067"></a>
-<span class="sourceLineNo">1068</span>            for (Entry&lt;byte[], Long&gt; store : storeSeqIds.entrySet()) {<a name="line.1068"></a>
-<span class="sourceLineNo">1069</span>              FlushedStoreSequenceId.Builder flushedStoreSequenceIdBuilder =<a name="line.1069"></a>
-<span class="sourceLineNo">1070</span>                  FlushedStoreSequenceId.newBuilder();<a name="line.1070"></a>
-<span class="sourceLineNo">1071</span>              flushedStoreSequenceIdBuilder.setFamily(ByteString.copyFrom(store.getKey()));<a name="line.1071"></a>
-<span class="sourceLineNo">1072</span>              flushedStoreSequenceIdBuilder.setSeqId(store.getValue());<a name="line.1072"></a>
-<span class="sourceLineNo">1073</span>              flushedRegionSequenceIdBuilder.addStores(flushedStoreSequenceIdBuilder);<a name="line.1073"></a>
-<span class="sourceLineNo">1074</span>            }<a name="line.1074"></a>
-<span class="sourceLineNo">1075</span>          }<a name="line.1075"></a>
-<span class="sourceLineNo">1076</span>          flushedSequenceIdBuilder.addRegionSequenceId(flushedRegionSequenceIdBuilder);<a name="line.1076"></a>
-<span class="sourceLineNo">1077</span>        }<a name="line.1077"></a>
-<span class="sourceLineNo">1078</span>        flushedSequenceIdBuilder.build().writeDelimitedTo(out);<a name="line.1078"></a>
-<span class="sourceLineNo">1079</span>      } finally {<a name="line.1079"></a>
-<span class="sourceLineNo">1080</span>        if (out != null) {<a name="line.1080"></a>
-<span class="sourceLineNo">1081</span>          out.close();<a name="line.1081"></a>
-<span class="sourceLineNo">1082</span>        }<a name="line.1082"></a>
-<span class="sourceLineNo">1083</span>      }<a name="line.1083"></a>
-<span class="sourceLineNo">1084</span>    } finally {<a name="line.1084"></a>
-<span class="sourceLineNo">1085</span>      isFlushSeqIdPersistInProgress = false;<a name="line.1085"></a>
-<span class="sourceLineNo">1086</span>    }<a name="line.1086"></a>
-<span class="sourceLineNo">1087</span>  }<a name="line.1087"></a>
-<span class="sourceLineNo">1088</span><a name="line.1088"></a>
-<span class="sourceLineNo">1089</span>  /**<a name="line.1089"></a>
-<span class="sourceLineNo">1090</span>   * Load last flushed sequence id of each region from HDFS, if persisted<a name="line.1090"></a>
-<span class="sourceLineNo">1091</span>   */<a name="line.1091"></a>
-<span class="sourceLineNo">1092</span>  public void loadLastFlushedSequenceIds() throws IOException {<a name="line.1092"></a>
-<span class="sourceLineNo">1093</span>    if (!persistFlushedSequenceId) {<a name="line.1093"></a>
-<span class="sourceLineNo">1094</span>      return;<a name="line.1094"></a>
-<span class="sourceLineNo">1095</span>    }<a name="line.1095"></a>
-<span class="sourceLineNo">1096</span>    Configuration conf = master.getConfiguration();<a name="line.1096"></a>
-<span class="sourceLineNo">1097</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.1097"></a>
-<span class="sourceLineNo">1098</span>    Path lastFlushedSeqIdPath = new Path(rootDir, LAST_FLUSHED_SEQ_ID_FILE);<a name="line.1098"></a>
-<span class="sourceLineNo">1099</span>    FileSystem fs = FileSystem.get(conf);<a name="line.1099"></a>
-<span class="sourceLineNo">1100</span>    if (!fs.exists(lastFlushedSeqIdPath)) {<a name="line.1100"></a>
-<span class="sourceLineNo">1101</span>      LOG.info("No .lastflushedseqids found at" + lastFlushedSeqIdPath<a name="line.1101"></a>
-<span class="sourceLineNo">1102</span>          + " will record last flushed sequence id"<a name="line.1102"></a>
-<span class="sourceLineNo">1103</span>          + " for regions by regionserver report all over again");<a name="line.1103"></a>
-<span class="sourceLineNo">1104</span>      return;<a name="line.1104"></a>
-<span class="sourceLineNo">1105</span>    } else {<a name="line.1105"></a>
-<span class="sourceLineNo">1106</span>      LOG.info("begin to load .lastflushedseqids at " + lastFlushedSeqIdPath);<a name="line.1106"></a>
-<span class="sourceLineNo">1107</span>    }<a name="line.1107"></a>
-<span class="sourceLineNo">1108</span>    FSDataInputStream in = fs.open(lastFlushedSeqIdPath);<a name="line.1108"></a>
-<span class="sourceLineNo">1109</span>    try {<a name="line.1109"></a>
-<span class="sourceLineNo">1110</span>      FlushedSequenceId flushedSequenceId =<a name="line.1110"></a>
-<span class="sourceLineNo">1111</span>          FlushedSequenceId.parseDelimitedFrom(in);<a name="line.1111"></a>
-<span class="sourceLineNo">1112</span>      if (flushedSequenceId == null) {<a name="line.1112"></a>
-<span class="sourceLineNo">1113</span>        LOG.info(".lastflushedseqids found at {} is empty", lastFlushedSeqIdPath);<a name="line.1113"></a>
-<span class="sourceLineNo">1114</span>        return;<a name="line.1114"></a>
-<span class="sourceLineNo">1115</span>      }<a name="line.1115"></a>
-<span class="sourceLineNo">1116</span>      for (FlushedRegionSequenceId flushedRegionSequenceId : flushedSequenceId<a name="line.1116"></a>
-<span class="sourceLineNo">1117</span>          .getRegionSequenceIdList()) {<a name="line.1117"></a>
-<span class="sourceLineNo">1118</span>        byte[] encodedRegionName = flushedRegionSequenceId<a name="line.1118"></a>
-<span class="sourceLineNo">1119</span>            .getRegionEncodedName().toByteArray();<a name="line.1119"></a>
-<span class="sourceLineNo">1120</span>        flushedSequenceIdByRegion<a name="line.1120"></a>
-<span class="sourceLineNo">1121</span>            .putIfAbsent(encodedRegionName, flushedRegionSequenceId.getSeqId());<a name="line.1121"></a>
-<span class="sourceLineNo">1122</span>        if (flushedRegionSequenceId.getStoresList() != null<a name="line.1122"></a>
-<span class="sourceLineNo">1123</span>            &amp;&amp; flushedRegionSequenceId.getStoresList().size() != 0) {<a name="line.1123"></a>
-<span class="sourceLineNo">1124</span>          ConcurrentNavigableMap&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.1124"></a>
-<span class="sourceLineNo">1125</span>              computeIfAbsent(storeFlushedSequenceIdsByRegion, encodedRegionName,<a name="line.1125"></a>
-<span class="sourceLineNo">1126</span>                () -&gt; new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR));<a name="line.1126"></a>
-<span class="sourceLineNo">1127</span>          for (FlushedStoreSequenceId flushedStoreSequenceId : flushedRegionSequenceId<a name="line.1127"></a>
-<span class="sourceLineNo">1128</span>              .getStoresList()) {<a name="line.1128"></a>
-<span class="sourceLineNo">1129</span>            storeFlushedSequenceId<a name="line.1129"></a>
-<span class="sourceLineNo">1130</span>                .put(flushedStoreSequenceId.getFamily().toByteArray(),<a name="line.1130"></a>
-<span class="sourceLineNo">1131</span>                    flushedStoreSequenceId.getSeqId());<a name="line.1131"></a>
-<span class="sourceLineNo">1132</span>          }<a name="line.1132"></a>
-<span class="sourceLineNo">1133</span>        }<a name="line.1133"></a>
-<span class="sourceLineNo">1134</span>      }<a name="line.1134"></a>
-<span class="sourceLineNo">1135</span>    } finally {<a name="line.1135"></a>
-<span class="sourceLineNo">1136</span>      in.close();<a name="line.1136"></a>
-<span class="sourceLineNo">1137</span>    }<a name="line.1137"></a>
-<span class="sourceLineNo">1138</span>  }<a name="line.1138"></a>
-<span class="sourceLineNo">1139</span><a name="line.1139"></a>
-<span class="sourceLineNo">1140</span>  /**<a name="line.1140"></a>
-<span class="sourceLineNo">1141</span>   * Regions may have been removed between latest persist of FlushedSequenceIds<a name="line.1141"></a>
-<span class="sourceLineNo">1142</span>   * and master abort. So after loading FlushedSequenceIds from file, and after<a name="line.1142"></a>
-<span class="sourceLineNo">1143</span>   * meta loaded, we need to remove the deleted region according to RegionStates.<a name="line.1143"></a>
-<span class="sourceLineNo">1144</span>   */<a name="line.1144"></a>
-<span class="sourceLineNo">1145</span>  public void removeDeletedRegionFromLoadedFlushedSequenceIds() {<a name="line.1145"></a>
-<span class="sourceLineNo">1146</span>    RegionStates regionStates = master.getAssignmentManager().getRegionStates();<a name="line.1146"></a>
-<span class="sourceLineNo">1147</span>    Iterator&lt;byte[]&gt; it = flushedSequenceIdByRegion.keySet().iterator();<a name="line.1147"></a>
-<span class="sourceLineNo">1148</span>    while(it.hasNext()) {<a name="line.1148"></a>
-<span class="sourceLineNo">1149</span>      byte[] regionEncodedName = it.next();<a name="line.1149"></a>
-<span class="sourceLineNo">1150</span>      if (regionStates.getRegionState(Bytes.toStringBinary(regionEncodedName)) == null) {<a name="line.1150"></a>
-<span class="sourceLineNo">1151</span>        it.remove();<a name="line.1151"></a>
-<span class="sourceLineNo">1152</span>        storeFlushedSequenceIdsByRegion.remove(regionEncodedName);<a name="line.1152"></a>
-<span class="sourceLineNo">1153</span>      }<a name="line.1153"></a>
-<span class="sourceLineNo">1154</span>    }<a name="line.1154"></a>
-<span class="sourceLineNo">1155</span>  }<a name="line.1155"></a>
-<span class="sourceLineNo">1156</span><a name="line.1156"></a>
-<span class="sourceLineNo">1157</span>  private class FlushedSequenceIdFlusher extends ScheduledChore {<a name="line.1157"></a>
-<span class="sourceLineNo">1158</span><a name="line.1158"></a>
-<span class="sourceLineNo">1159</span>    public FlushedSequenceIdFlusher(String name, int p) {<a name="line.1159"></a>
-<span class="sourceLineNo">1160</span>      super(name, master, p, 60 * 1000); //delay one minute before first execute<a name="line.1160"></a>
-<span class="sourceLineNo">1161</span>    }<a name="line.1161"></a>
+<span class="sourceLineNo">966</span>    // Loop through the draining server list and remove them from the server list<a name="line.966"></a>
+<span class="sourceLineNo">967</span>    final List&lt;ServerName&gt; drainingServersCopy = getDrainingServersList();<a name="line.967"></a>
+<span class="sourceLineNo">968</span>    destServers.removeAll(drainingServersCopy);<a name="line.968"></a>
+<span class="sourceLineNo">969</span><a name="line.969"></a>
+<span class="sourceLineNo">970</span>    return destServers;<a name="line.970"></a>
+<span class="sourceLineNo">971</span>  }<a name="line.971"></a>
+<span class="sourceLineNo">972</span><a name="line.972"></a>
+<span class="sourceLineNo">973</span>  /**<a name="line.973"></a>
+<span class="sourceLineNo">974</span>   * Calls {@link #createDestinationServersList} without server to exclude.<a name="line.974"></a>
+<span class="sourceLineNo">975</span>   */<a name="line.975"></a>
+<span class="sourceLineNo">976</span>  public List&lt;ServerName&gt; createDestinationServersList(){<a name="line.976"></a>
+<span class="sourceLineNo">977</span>    return createDestinationServersList(null);<a name="line.977"></a>
+<span class="sourceLineNo">978</span>  }<a name="line.978"></a>
+<span class="sourceLineNo">979</span><a name="line.979"></a>
+<span class="sourceLineNo">980</span>  /**<a name="line.980"></a>
+<span class="sourceLineNo">981</span>   * To clear any dead server with same host name and port of any online server<a name="line.981"></a>
+<span class="sourceLineNo">982</span>   */<a name="line.982"></a>
+<span class="sourceLineNo">983</span>  void clearDeadServersWithSameHostNameAndPortOfOnlineServer() {<a name="line.983"></a>
+<span class="sourceLineNo">984</span>    for (ServerName serverName : getOnlineServersList()) {<a name="line.984"></a>
+<span class="sourceLineNo">985</span>      deadservers.cleanAllPreviousInstances(serverName);<a name="line.985"></a>
+<span class="sourceLineNo">986</span>    }<a name="line.986"></a>
+<span class="sourceLineNo">987</span>  }<a name="line.987"></a>
+<span class="sourceLineNo">988</span><a name="line.988"></a>
+<span class="sourceLineNo">989</span>  /**<a name="line.989"></a>
+<span class="sourceLineNo">990</span>   * Called by delete table and similar to notify the ServerManager that a region was removed.<a name="line.990"></a>
+<span class="sourceLineNo">991</span>   */<a name="line.991"></a>
+<span class="sourceLineNo">992</span>  public void removeRegion(final RegionInfo regionInfo) {<a name="line.992"></a>
+<span class="sourceLineNo">993</span>    final byte[] encodedName = regionInfo.getEncodedNameAsBytes();<a name="line.993"></a>
+<span class="sourceLineNo">994</span>    storeFlushedSequenceIdsByRegion.remove(encodedName);<a name="line.994"></a>
+<span class="sourceLineNo">995</span>    flushedSequenceIdByRegion.remove(encodedName);<a name="line.995"></a>
+<span class="sourceLineNo">996</span>  }<a name="line.996"></a>
+<span class="sourceLineNo">997</span><a name="line.997"></a>
+<span class="sourceLineNo">998</span>  @VisibleForTesting<a name="line.998"></a>
+<span class="sourceLineNo">999</span>  public boolean isRegionInServerManagerStates(final RegionInfo hri) {<a name="line.999"></a>
+<span class="sourceLineNo">1000</span>    final byte[] encodedName = hri.getEncodedNameAsBytes();<a name="line.1000"></a>
+<span class="sourceLineNo">1001</span>    return (storeFlushedSequenceIdsByRegion.containsKey(encodedName)<a name="line.1001"></a>
+<span class="sourceLineNo">1002</span>        || flushedSequenceIdByRegion.containsKey(encodedName));<a name="line.1002"></a>
+<span class="sourceLineNo">1003</span>  }<a name="line.1003"></a>
+<span class="sourceLineNo">1004</span><a name="line.1004"></a>
+<span class="sourceLineNo">1005</span>  /**<a name="line.1005"></a>
+<span class="sourceLineNo">1006</span>   * Called by delete table and similar to notify the ServerManager that a region was removed.<a name="line.1006"></a>
+<span class="sourceLineNo">1007</span>   */<a name="line.1007"></a>
+<span class="sourceLineNo">1008</span>  public void removeRegions(final List&lt;RegionInfo&gt; regions) {<a name="line.1008"></a>
+<span class="sourceLineNo">1009</span>    for (RegionInfo hri: regions) {<a name="line.1009"></a>
+<span class="sourceLineNo">1010</span>      removeRegion(hri);<a name="line.1010"></a>
+<span class="sourceLineNo">1011</span>    }<a name="line.1011"></a>
+<span class="sourceLineNo">1012</span>  }<a name="line.1012"></a>
+<span class="sourceLineNo">1013</span><a name="line.1013"></a>
+<span class="sourceLineNo">1014</span>  /**<a name="line.1014"></a>
+<span class="sourceLineNo">1015</span>   * May return 0 when server is not online.<a name="line.1015"></a>
+<span class="sourceLineNo">1016</span>   */<a name="line.1016"></a>
+<span class="sourceLineNo">1017</span>  public int getVersionNumber(ServerName serverName) {<a name="line.1017"></a>
+<span class="sourceLineNo">1018</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1018"></a>
+<span class="sourceLineNo">1019</span>    return serverMetrics != null ? serverMetrics.getVersionNumber() : 0;<a name="line.1019"></a>
+<span class="sourceLineNo">1020</span>  }<a name="line.1020"></a>
+<span class="sourceLineNo">1021</span><a name="line.1021"></a>
+<span class="sourceLineNo">1022</span>  /**<a name="line.1022"></a>
+<span class="sourceLineNo">1023</span>   * May return "0.0.0" when server is not online<a name="line.1023"></a>
+<span class="sourceLineNo">1024</span>   */<a name="line.1024"></a>
+<span class="sourceLineNo">1025</span>  public String getVersion(ServerName serverName) {<a name="line.1025"></a>
+<span class="sourceLineNo">1026</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1026"></a>
+<span class="sourceLineNo">1027</span>    return serverMetrics != null ? serverMetrics.getVersion() : "0.0.0";<a name="line.1027"></a>
+<span class="sourceLineNo">1028</span>  }<a name="line.1028"></a>
+<span class="sourceLineNo">1029</span><a name="line.1029"></a>
+<span class="sourceLineNo">1030</span>  public int getInfoPort(ServerName serverName) {<a name="line.1030"></a>
+<span class="sourceLineNo">1031</span>    ServerMetrics serverMetrics = onlineServers.get(serverName);<a name="line.1031"></a>
+<span class="sourceLineNo">1032</span>    return serverMetrics != null ? serverMetrics.getInfoServerPort() : 0;<a name="line.1032"></a>
+<span class="sourceLineNo">1033</span>  }<a name="line.1033"></a>
+<span class="sourceLineNo">1034</span><a name="line.1034"></a>
+<span class="sourceLineNo">1035</span>  /**<a name="line.1035"></a>
+<span class="sourceLineNo">1036</span>   * Persist last flushed sequence id of each region to HDFS<a name="line.1036"></a>
+<span class="sourceLineNo">1037</span>   * @throws IOException if persit to HDFS fails<a name="line.1037"></a>
+<span class="sourceLineNo">1038</span>   */<a name="line.1038"></a>
+<span class="sourceLineNo">1039</span>  private void persistRegionLastFlushedSequenceIds() throws IOException {<a name="line.1039"></a>
+<span class="sourceLineNo">1040</span>    if (isFlushSeqIdPersistInProgress) {<a name="line.1040"></a>
+<span class="sourceLineNo">1041</span>      return;<a name="line.1041"></a>
+<span class="sourceLineNo">1042</span>    }<a name="line.1042"></a>
+<span class="sourceLineNo">1043</span>    isFlushSeqIdPersistInProgress = true;<a name="line.1043"></a>
+<span class="sourceLineNo">1044</span>    try {<a name="line.1044"></a>
+<span class="sourceLineNo">1045</span>      Configuration conf = master.getConfiguration();<a name="line.1045"></a>
+<span class="sourceLineNo">1046</span>      Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.1046"></a>
+<span class="sourceLineNo">1047</span>      Path lastFlushedSeqIdPath = new Path(rootDir, LAST_FLUSHED_SEQ_ID_FILE);<a name="line.1047"></a>
+<span class="sourceLineNo">1048</span>      FileSystem fs = FileSystem.get(conf);<a name="line.1048"></a>
+<span class="sourceLineNo">1049</span>      if (fs.exists(lastFlushedSeqIdPath)) {<a name="line.1049"></a>
+<span class="sourceLineNo">1050</span>        LOG.info("Rewriting .lastflushedseqids file at: "<a name="line.1050"></a>
+<span class="sourceLineNo">1051</span>            + lastFlushedSeqIdPath);<a name="line.1051"></a>
+<span class="sourceLineNo">1052</span>        if (!fs.delete(lastFlushedSeqIdPath, false)) {<a name="line.1052"></a>
+<span class="sourceLineNo">1053</span>          throw new IOException("Unable to remove existing "<a name="line.1053"></a>
+<span class="sourceLineNo">1054</span>              + lastFlushedSeqIdPath);<a name="line.1054"></a>
+<span class="sourceLineNo">1055</span>        }<a name="line.1055"></a>
+<span class="sourceLineNo">1056</span>      } else {<a name="line.1056"></a>
+<span class="sourceLineNo">1057</span>        LOG.info("Writing .lastflushedseqids file at: " + lastFlushedSeqIdPath);<a name="line.1057"></a>
+<span class="sourceLineNo">1058</span>      }<a name="line.1058"></a>
+<span class="sourceLineNo">1059</span>      FSDataOutputStream out = fs.create(lastFlushedSeqIdPath);<a name="line.1059"></a>
+<span class="sourceLineNo">1060</span>      FlushedSequenceId.Builder flushedSequenceIdBuilder =<a name="line.1060"></a>
+<span class="sourceLineNo">1061</span>          FlushedSequenceId.newBuilder();<a name="line.1061"></a>
+<span class="sourceLineNo">1062</span>      try {<a name="line.1062"></a>
+<span class="sourceLineNo">1063</span>        for (Entry&lt;byte[], Long&gt; entry : flushedSequenceIdByRegion.entrySet()) {<a name="line.1063"></a>
+<span class="sourceLineNo">1064</span>          FlushedRegionSequenceId.Builder flushedRegionSequenceIdBuilder =<a name="line.1064"></a>
+<span class="sourceLineNo">1065</span>              FlushedRegionSequenceId.newBuilder();<a name="line.1065"></a>
+<span class="sourceLineNo">1066</span>          flushedRegionSequenceIdBuilder.setRegionEncodedName(<a name="line.1066"></a>
+<span class="sourceLineNo">1067</span>              ByteString.copyFrom(entry.getKey()));<a name="line.1067"></a>
+<span class="sourceLineNo">1068</span>          flushedRegionSequenceIdBuilder.setSeqId(entry.getValue());<a name="line.1068"></a>
+<span class="sourceLineNo">1069</span>          ConcurrentNavigableMap&lt;byte[], Long&gt; storeSeqIds =<a name="line.1069"></a>
+<span class="sourceLineNo">1070</span>              storeFlushedSequenceIdsByRegion.get(entry.getKey());<a name="line.1070"></a>
+<span class="sourceLineNo">1071</span>          if (storeSeqIds != null) {<a name="line.1071"></a>
+<span class="sourceLineNo">1072</span>            for (Entry&lt;byte[], Long&gt; store : storeSeqIds.entrySet()) {<a name="line.1072"></a>
+<span class="sourceLineNo">1073</span>              FlushedStoreSequenceId.Builder flushedStoreSequenceIdBuilder =<a name="line.1073"></a>
+<span class="sourceLineNo">1074</span>                  FlushedStoreSequenceId.newBuilder();<a name="line.1074"></a>
+<span class="sourceLineNo">1075</span>              flushedStoreSequenceIdBuilder.setFamily(ByteString.copyFrom(store.getKey()));<a name="line.1075"></a>
+<span class="sourceLineNo">1076</span>              flushedStoreSequenceIdBuilder.setSeqId(store.getValue());<a name="line.1076"></a>
+<span class="sourceLineNo">1077</span>              flushedRegionSequenceIdBuilder.addStores(flushedStoreSequenceIdBuilder);<a name="line.1077"></a>
+<span class="sourceLineNo">1078</span>            }<a name="line.1078"></a>
+<span class="sourceLineNo">1079</span>          }<a name="line.1079"></a>
+<span class="sourceLineNo">1080</span>          flushedSequenceIdBuilder.addRegionSequenceId(flushedRegionSequenceIdBuilder);<a name="line.1080"></a>
+<span class="sourceLineNo">1081</span>        }<a name="line.1081"></a>
+<span class="sourceLineNo">1082</span>        flushedSequenceIdBuilder.build().writeDelimitedTo(out);<a name="line.1082"></a>
+<span class="sourceLineNo">1083</span>      } finally {<a name="line.1083"></a>
+<span class="sourceLineNo">1084</span>        if (out != null) {<a name="line.1084"></a>
+<span class="sourceLineNo">1085</span>          out.close();<a name="line.1085"></a>
+<span class="sourceLineNo">1086</span>        }<a name="line.1086"></a>
+<span class="sourceLineNo">1087</span>      }<a name="line.1087"></a>
+<span class="sourceLineNo">1088</span>    } finally {<a name="line.1088"></a>
+<span class="sourceLineNo">1089</span>      isFlushSeqIdPersistInProgress = false;<a name="line.1089"></a>
+<span class="sourceLineNo">1090</span>    }<a name="line.1090"></a>
+<span class="sourceLineNo">1091</span>  }<a name="line.1091"></a>
+<span class="sourceLineNo">1092</span><a name="line.1092"></a>
+<span class="sourceLineNo">1093</span>  /**<a name="line.1093"></a>
+<span class="sourceLineNo">1094</span>   * Load last flushed sequence id of each region from HDFS, if persisted<a name="line.1094"></a>
+<span class="sourceLineNo">1095</span>   */<a name="line.1095"></a>
+<span class="sourceLineNo">1096</span>  public void loadLastFlushedSequenceIds() throws IOException {<a name="line.1096"></a>
+<span class="sourceLineNo">1097</span>    if (!persistFlushedSequenceId) {<a name="line.1097"></a>
+<span class="sourceLineNo">1098</span>      return;<a name="line.1098"></a>
+<span class="sourceLineNo">1099</span>    }<a name="line.1099"></a>
+<span class="sourceLineNo">1100</span>    Configuration conf = master.getConfiguration();<a name="line.1100"></a>
+<span class="sourceLineNo">1101</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.1101"></a>
+<span class="sourceLineNo">1102</span>    Path lastFlushedSeqIdPath = new Path(rootDir, LAST_FLUSHED_SEQ_ID_FILE);<a name="line.1102"></a>
+<span class="sourceLineNo">1103</span>    FileSystem fs = FileSystem.get(conf);<a name="line.1103"></a>
+<span class="sourceLineNo">1104</span>    if (!fs.exists(lastFlushedSeqIdPath)) {<a name="line.1104"></a>
+<span class="sourceLineNo">1105</span>      LOG.info("No .lastflushedseqids found at" + lastFlushedSeqIdPath<a name="line.1105"></a>
+<span class="sourceLineNo">1106</span>          + " will record last flushed sequence id"<a name="line.1106"></a>
+<span class="sourceLineNo">1107</span>          + " for regions by regionserver report all over again");<a name="line.1107"></a>
+<span class="sourceLineNo">1108</span>      return;<a name="line.1108"></a>
+<span class="sourceLineNo">1109</span>    } else {<a name="line.1109"></a>
+<span class="sourceLineNo">1110</span>      LOG.info("begin to load .lastflushedseqids at " + lastFlushedSeqIdPath);<a name="line.1110"></a>
+<span class="sourceLineNo">1111</span>    }<a name="line.1111"></a>
+<span class="sourceLineNo">1112</span>    FSDataInputStream in = fs.open(lastFlushedSeqIdPath);<a name="line.1112"></a>
+<span class="sourceLineNo">1113</span>    try {<a name="line.1113"></a>
+<span class="sourceLineNo">1114</span>      FlushedSequenceId flushedSequenceId =<a name="line.1114"></a>
+<span class="sourceLineNo">1115</span>          FlushedSequenceId.parseDelimitedFrom(in);<a name="line.1115"></a>
+<span class="sourceLineNo">1116</span>      if (flushedSequenceId == null) {<a name="line.1116"></a>
+<span class="sourceLineNo">1117</span>        LOG.info(".lastflushedseqids found at {} is empty", lastFlushedSeqIdPath);<a name="line.1117"></a>
+<span class="sourceLineNo">1118</span>        return;<a name="line.1118"></a>
+<span class="sourceLineNo">1119</span>      }<a name="line.1119"></a>
+<span class="sourceLineNo">1120</span>      for (FlushedRegionSequenceId flushedRegionSequenceId : flushedSequenceId<a name="line.1120"></a>
+<span class="sourceLineNo">1121</span>          .getRegionSequenceIdList()) {<a name="line.1121"></a>
+<span class="sourceLineNo">1122</span>        byte[] encodedRegionName = flushedRegionSequenceId<a name="line.1122"></a>
+<span class="sourceLineNo">1123</span>            .getRegionEncodedName().toByteArray();<a name="line.1123"></a>
+<span class="sourceLineNo">1124</span>        flushedSequenceIdByRegion<a name="line.1124"></a>
+<span class="sourceLineNo">1125</span>            .putIfAbsent(encodedRegionName, flushedRegionSequenceId.getSeqId());<a name="line.1125"></a>
+<span class="sourceLineNo">1126</span>        if (flushedRegionSequenceId.getStoresList() != null<a name="line.1126"></a>
+<span class="sourceLineNo">1127</span>            &amp;&amp; flushedRegionSequenceId.getStoresList().size() != 0) {<a name="line.1127"></a>
+<span class="sourceLineNo">1128</span>          ConcurrentNavigableMap&lt;byte[], Long&gt; storeFlushedSequenceId =<a name="line.1128"></a>
+<span class="sourceLineNo">1129</span>              computeIfAbsent(storeFlushedSequenceIdsByRegion, encodedRegionName,<a name="line.1129"></a>
+<span class="sourceLineNo">1130</span>                () -&gt; new ConcurrentSkipListMap&lt;&gt;(Bytes.BYTES_COMPARATOR));<a name="line.1130"></a>
+<span class="sourceLineNo">1131</span>          for (FlushedStoreSequenceId flushedStoreSequenceId : flushedRegionSequenceId<a name="line.1131"></a>
+<span class="sourceLineNo">1132</span>              .getStoresList()) {<a name="line.1132"></a>
+<span class="sourceLineNo">1133</span>            storeFlushedSequenceId<a name="line.1133"></a>
+<span class="sourceLineNo">1134</span>                .put(flushedStoreSequenceId.getFamily().toByteArray(),<a name="line.1134"></a>
+<span class="sourceLineNo">1135</span>                    flushedStoreSequenceId.getSeqId());<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>      }<a name="line.1138"></a>
+<span class="sourceLineNo">1139</span>    } finally {<a name="line.1139"></a>
+<span class="sourceLineNo">1140</span>      in.close();<a name="line.1140"></a>
+<span class="sourceLineNo">1141</span>    }<a name="line.1141"></a>
+<span class="sourceLineNo">1142</span>  }<a name="line.1142"></a>
+<span class="sourceLineNo">1143</span><a name="line.1143"></a>
+<span class="sourceLineNo">1144</span>  /**<a name="line.1144"></a>
+<span class="sourceLineNo">1145</span>   * Regions may have been removed between latest persist of FlushedSequenceIds<a name="line.1145"></a>
+<span class="sourceLineNo">1146</span>   * and master abort. So after loading FlushedSequenceIds from file, and after<a name="line.1146"></a>
+<span class="sourceLineNo">1147</span>   * meta loaded, we need to remove the deleted region according to RegionStates.<a name="line.1147"></a>
+<span class="sourceLineNo">1148</span>   */<a name="line.1148"></a>
+<span class="sourceLineNo">1149</span>  public void removeDeletedRegionFromLoadedFlushedSequenceIds() {<a name="line.1149"></a>
+<span class="sourceLineNo">1150</span>    RegionStates regionStates = master.getAssignmentManager().getRegionStates();<a name="line.1150"></a>
+<span class="sourceLineNo">1151</span>    Iterator&lt;byte[]&gt; it = flushedSequenceIdByRegion.keySet().iterator();<a name="line.1151"></a>
+<span class="sourceLineNo">1152</span>    while(it.hasNext()) {<a name="line.1152"></a>
+<span class="sourceLineNo">1153</span>      byte[] regionEncodedName = it.next();<a name="line.1153"></a>
+<span class="sourceLineNo">1154</span>      if (regionStates.getRegionState(Bytes.toStringBinary(regionEncodedName)) == null) {<a name="line.1154"></a>
+<span class="sourceLineNo">1155</span>        it.remove();<a name="line.1155"></a>
+<span class="sourceLineNo">1156</span>        storeFlushedSequenceIdsByRegion.remove(regionEncodedName);<a name="line.1156"></a>
+<span class="sourceLineNo">1157</span>      }<a name="line.1157"></a>
+<span class="sourceLineNo">1158</span>    }<a name="line.1158"></a>
+<span class="sourceLineNo">1159</span>  }<a name="line.1159"></a>
+<span class="sourceLineNo">1160</span><a name="line.1160"></a>
+<span class="sourceLineNo">1161</span>  private class FlushedSequenceIdFlusher extends ScheduledChore {<a name="line.1161"></a>
 <span class="sourceLineNo">1162</span><a name="line.1162"></a>
-<span class="sourceLineNo">1163</span>    @Override<a name="line.1163"></a>
-<span class="sourceLineNo">1164</span>    protected void chore() {<a name="line.1164"></a>
-<span class="sourceLineNo">1165</span>      try {<a name="line.1165"></a>
-<span class="sourceLineNo">1166</span>        persistRegionLastFlushedSequenceIds();<a name="line.1166"></a>
-<span class="sourceLineNo">1167</span>      } catch (IOException e) {<a name="line.1167"></a>
-<span class="sourceLineNo">1168</span>        LOG.debug("Failed to persist last flushed sequence id of regions"<a name="line.1168"></a>
-<span class="sourceLineNo">1169</span>            + " to file system", e);<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>  }<a name="line.1172"></a>
-<span class="sourceLineNo">1173</span>}<a name="line.1173"></a>
+<span class="sourceLineNo">1163</span>    public FlushedSequenceIdFlusher(String name, int p) {<a name="line.1163"></a>
+<span class="sourceLineNo">1164</span>      super(name, master, p, 60 * 1000); //delay one minute before first execute<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>    @Override<a name="line.1167"></a>
+<span class="sourceLineNo">1168</span>    protected void chore() {<a name="line.1168"></a>
+<span class="sourceLineNo">1169</span>      try {<a name="line.1169"></a>
+<span class="sourceLineNo">1170</span>        persistRegionLastFlushedSequenceIds();<a name="line.1170"></a>
+<span class="sourceLineNo">1171</span>      } catch (IOException e) {<a name="line.1171"></a>
+<span class="sourceLineNo">1172</span>        LOG.debug("Failed to persist last flushed sequence id of regions"<a name="line.1172"></a>
+<span class="sourceLineNo">1173</span>            + " to file system", e);<a name="line.1173"></a>
+<span class="sourceLineNo">1174</span>      }<a name="line.1174"></a>
+<span class="sourceLineNo">1175</span>    }<a name="line.1175"></a>
+<span class="sourceLineNo">1176</span>  }<a name="line.1176"></a>
+<span class="sourceLineNo">1177</span>}<a name="line.1177"></a>
 
 
 
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.RSGroupInfoHolder.html b/devapidocs/src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.RSGroupInfoHolder.html
index 61bfb38..6399539 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.RSGroupInfoHolder.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.RSGroupInfoHolder.html
@@ -1235,32 +1235,36 @@
 <span class="sourceLineNo">1227</span>      throw new ConstraintException(RSGroupInfo.DEFAULT_GROUP + " can't be rename");<a name="line.1227"></a>
 <span class="sourceLineNo">1228</span>    }<a name="line.1228"></a>
 <span class="sourceLineNo">1229</span>    checkGroupName(newName);<a name="line.1229"></a>
-<span class="sourceLineNo">1230</span><a name="line.1230"></a>
+<span class="sourceLineNo">1230</span>    //getRSGroupInfo validates old RSGroup existence.<a name="line.1230"></a>
 <span class="sourceLineNo">1231</span>    RSGroupInfo oldRSG = getRSGroupInfo(oldName);<a name="line.1231"></a>
 <span class="sourceLineNo">1232</span>    Map&lt;String, RSGroupInfo&gt; rsGroupMap = holder.groupName2Group;<a name="line.1232"></a>
-<span class="sourceLineNo">1233</span>    Map&lt;String, RSGroupInfo&gt; newGroupMap = Maps.newHashMap(rsGroupMap);<a name="line.1233"></a>
-<span class="sourceLineNo">1234</span>    newGroupMap.remove(oldRSG.getName());<a name="line.1234"></a>
-<span class="sourceLineNo">1235</span>    RSGroupInfo newRSG = new RSGroupInfo(newName, oldRSG.getServers());<a name="line.1235"></a>
-<span class="sourceLineNo">1236</span>    newGroupMap.put(newName, newRSG);<a name="line.1236"></a>
-<span class="sourceLineNo">1237</span>    flushConfig(newGroupMap);<a name="line.1237"></a>
-<span class="sourceLineNo">1238</span>    Set&lt;TableName&gt; updateTables =<a name="line.1238"></a>
-<span class="sourceLineNo">1239</span>      masterServices.getTableDescriptors().getAll().values()<a name="line.1239"></a>
-<span class="sourceLineNo">1240</span>                    .stream()<a name="line.1240"></a>
-<span class="sourceLineNo">1241</span>                    .filter(t -&gt; oldName.equals(t.getRegionServerGroup().orElse(null)))<a name="line.1241"></a>
-<span class="sourceLineNo">1242</span>                    .map(TableDescriptor::getTableName)<a name="line.1242"></a>
-<span class="sourceLineNo">1243</span>                    .collect(Collectors.toSet());<a name="line.1243"></a>
-<span class="sourceLineNo">1244</span>    setRSGroup(updateTables, newName);<a name="line.1244"></a>
-<span class="sourceLineNo">1245</span>  }<a name="line.1245"></a>
-<span class="sourceLineNo">1246</span><a name="line.1246"></a>
-<span class="sourceLineNo">1247</span>  @Override<a name="line.1247"></a>
-<span class="sourceLineNo">1248</span>  public synchronized void updateRSGroupConfig(String groupName, Map&lt;String, String&gt; configuration)<a name="line.1248"></a>
-<span class="sourceLineNo">1249</span>      throws IOException {<a name="line.1249"></a>
-<span class="sourceLineNo">1250</span>    RSGroupInfo rsGroupInfo = getRSGroupInfo(groupName);<a name="line.1250"></a>
-<span class="sourceLineNo">1251</span>    rsGroupInfo.getConfiguration().forEach((k, v) -&gt; rsGroupInfo.removeConfiguration(k));<a name="line.1251"></a>
-<span class="sourceLineNo">1252</span>    configuration.forEach((k, v) -&gt; rsGroupInfo.setConfiguration(k, v));<a name="line.1252"></a>
-<span class="sourceLineNo">1253</span>    flushConfig();<a name="line.1253"></a>
-<span class="sourceLineNo">1254</span>  }<a name="line.1254"></a>
-<span class="sourceLineNo">1255</span>}<a name="line.1255"></a>
+<span class="sourceLineNo">1233</span>    if (rsGroupMap.containsKey(newName)) {<a name="line.1233"></a>
+<span class="sourceLineNo">1234</span>      throw new ConstraintException("Group already exists: " + newName);<a name="line.1234"></a>
+<span class="sourceLineNo">1235</span>    }<a name="line.1235"></a>
+<span class="sourceLineNo">1236</span><a name="line.1236"></a>
+<span class="sourceLineNo">1237</span>    Map&lt;String, RSGroupInfo&gt; newGroupMap = Maps.newHashMap(rsGroupMap);<a name="line.1237"></a>
+<span class="sourceLineNo">1238</span>    newGroupMap.remove(oldRSG.getName());<a name="line.1238"></a>
+<span class="sourceLineNo">1239</span>    RSGroupInfo newRSG = new RSGroupInfo(newName, oldRSG.getServers());<a name="line.1239"></a>
+<span class="sourceLineNo">1240</span>    newGroupMap.put(newName, newRSG);<a name="line.1240"></a>
+<span class="sourceLineNo">1241</span>    flushConfig(newGroupMap);<a name="line.1241"></a>
+<span class="sourceLineNo">1242</span>    Set&lt;TableName&gt; updateTables =<a name="line.1242"></a>
+<span class="sourceLineNo">1243</span>      masterServices.getTableDescriptors().getAll().values()<a name="line.1243"></a>
+<span class="sourceLineNo">1244</span>                    .stream()<a name="line.1244"></a>
+<span class="sourceLineNo">1245</span>                    .filter(t -&gt; oldName.equals(t.getRegionServerGroup().orElse(null)))<a name="line.1245"></a>
+<span class="sourceLineNo">1246</span>                    .map(TableDescriptor::getTableName)<a name="line.1246"></a>
+<span class="sourceLineNo">1247</span>                    .collect(Collectors.toSet());<a name="line.1247"></a>
+<span class="sourceLineNo">1248</span>    setRSGroup(updateTables, newName);<a name="line.1248"></a>
+<span class="sourceLineNo">1249</span>  }<a name="line.1249"></a>
+<span class="sourceLineNo">1250</span><a name="line.1250"></a>
+<span class="sourceLineNo">1251</span>  @Override<a name="line.1251"></a>
+<span class="sourceLineNo">1252</span>  public synchronized void updateRSGroupConfig(String groupName, Map&lt;String, String&gt; configuration)<a name="line.1252"></a>
+<span class="sourceLineNo">1253</span>      throws IOException {<a name="line.1253"></a>
+<span class="sourceLineNo">1254</span>    RSGroupInfo rsGroupInfo = getRSGroupInfo(groupName);<a name="line.1254"></a>
+<span class="sourceLineNo">1255</span>    rsGroupInfo.getConfiguration().forEach((k, v) -&gt; rsGroupInfo.removeConfiguration(k));<a name="line.1255"></a>
+<span class="sourceLineNo">1256</span>    configuration.forEach((k, v) -&gt; rsGroupInfo.setConfiguration(k, v));<a name="line.1256"></a>
+<span class="sourceLineNo">1257</span>    flushConfig();<a name="line.1257"></a>
+<span class="sourceLineNo">1258</span>  }<a name="line.1258"></a>
+<span class="sourceLineNo">1259</span>}<a name="line.1259"></a>
 
 
 
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.RSGroupMappingScript.html b/devapidocs/src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.RSGroupMappingScript.html
index 61bfb38..6399539 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.RSGroupMappingScript.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.RSGroupMappingScript.html
@@ -1235,32 +1235,36 @@
 <span class="sourceLineNo">1227</span>      throw new ConstraintException(RSGroupInfo.DEFAULT_GROUP + " can't be rename");<a name="line.1227"></a>
 <span class="sourceLineNo">1228</span>    }<a name="line.1228"></a>
 <span class="sourceLineNo">1229</span>    checkGroupName(newName);<a name="line.1229"></a>
-<span class="sourceLineNo">1230</span><a name="line.1230"></a>
+<span class="sourceLineNo">1230</span>    //getRSGroupInfo validates old RSGroup existence.<a name="line.1230"></a>
 <span class="sourceLineNo">1231</span>    RSGroupInfo oldRSG = getRSGroupInfo(oldName);<a name="line.1231"></a>
 <span class="sourceLineNo">1232</span>    Map&lt;String, RSGroupInfo&gt; rsGroupMap = holder.groupName2Group;<a name="line.1232"></a>
-<span class="sourceLineNo">1233</span>    Map&lt;String, RSGroupInfo&gt; newGroupMap = Maps.newHashMap(rsGroupMap);<a name="line.1233"></a>
-<span class="sourceLineNo">1234</span>    newGroupMap.remove(oldRSG.getName());<a name="line.1234"></a>
-<span class="sourceLineNo">1235</span>    RSGroupInfo newRSG = new RSGroupInfo(newName, oldRSG.getServers());<a name="line.1235"></a>
-<span class="sourceLineNo">1236</span>    newGroupMap.put(newName, newRSG);<a name="line.1236"></a>
-<span class="sourceLineNo">1237</span>    flushConfig(newGroupMap);<a name="line.1237"></a>
-<span class="sourceLineNo">1238</span>    Set&lt;TableName&gt; updateTables =<a name="line.1238"></a>
-<span class="sourceLineNo">1239</span>      masterServices.getTableDescriptors().getAll().values()<a name="line.1239"></a>
-<span class="sourceLineNo">1240</span>                    .stream()<a name="line.1240"></a>
-<span class="sourceLineNo">1241</span>                    .filter(t -&gt; oldName.equals(t.getRegionServerGroup().orElse(null)))<a name="line.1241"></a>
-<span class="sourceLineNo">1242</span>                    .map(TableDescriptor::getTableName)<a name="line.1242"></a>
-<span class="sourceLineNo">1243</span>                    .collect(Collectors.toSet());<a name="line.1243"></a>
-<span class="sourceLineNo">1244</span>    setRSGroup(updateTables, newName);<a name="line.1244"></a>
-<span class="sourceLineNo">1245</span>  }<a name="line.1245"></a>
-<span class="sourceLineNo">1246</span><a name="line.1246"></a>
-<span class="sourceLineNo">1247</span>  @Override<a name="line.1247"></a>
-<span class="sourceLineNo">1248</span>  public synchronized void updateRSGroupConfig(String groupName, Map&lt;String, String&gt; configuration)<a name="line.1248"></a>
-<span class="sourceLineNo">1249</span>      throws IOException {<a name="line.1249"></a>
-<span class="sourceLineNo">1250</span>    RSGroupInfo rsGroupInfo = getRSGroupInfo(groupName);<a name="line.1250"></a>
-<span class="sourceLineNo">1251</span>    rsGroupInfo.getConfiguration().forEach((k, v) -&gt; rsGroupInfo.removeConfiguration(k));<a name="line.1251"></a>
-<span class="sourceLineNo">1252</span>    configuration.forEach((k, v) -&gt; rsGroupInfo.setConfiguration(k, v));<a name="line.1252"></a>
-<span class="sourceLineNo">1253</span>    flushConfig();<a name="line.1253"></a>
-<span class="sourceLineNo">1254</span>  }<a name="line.1254"></a>
-<span class="sourceLineNo">1255</span>}<a name="line.1255"></a>
+<span class="sourceLineNo">1233</span>    if (rsGroupMap.containsKey(newName)) {<a name="line.1233"></a>
+<span class="sourceLineNo">1234</span>      throw new ConstraintException("Group already exists: " + newName);<a name="line.1234"></a>
+<span class="sourceLineNo">1235</span>    }<a name="line.1235"></a>
+<span class="sourceLineNo">1236</span><a name="line.1236"></a>
+<span class="sourceLineNo">1237</span>    Map&lt;String, RSGroupInfo&gt; newGroupMap = Maps.newHashMap(rsGroupMap);<a name="line.1237"></a>
+<span class="sourceLineNo">1238</span>    newGroupMap.remove(oldRSG.getName());<a name="line.1238"></a>
+<span class="sourceLineNo">1239</span>    RSGroupInfo newRSG = new RSGroupInfo(newName, oldRSG.getServers());<a name="line.1239"></a>
+<span class="sourceLineNo">1240</span>    newGroupMap.put(newName, newRSG);<a name="line.1240"></a>
+<span class="sourceLineNo">1241</span>    flushConfig(newGroupMap);<a name="line.1241"></a>
+<span class="sourceLineNo">1242</span>    Set&lt;TableName&gt; updateTables =<a name="line.1242"></a>
+<span class="sourceLineNo">1243</span>      masterServices.getTableDescriptors().getAll().values()<a name="line.1243"></a>
+<span class="sourceLineNo">1244</span>                    .stream()<a name="line.1244"></a>
+<span class="sourceLineNo">1245</span>                    .filter(t -&gt; oldName.equals(t.getRegionServerGroup().orElse(null)))<a name="line.1245"></a>
+<span class="sourceLineNo">1246</span>                    .map(TableDescriptor::getTableName)<a name="line.1246"></a>
+<span class="sourceLineNo">1247</span>                    .collect(Collectors.toSet());<a name="line.1247"></a>
+<span class="sourceLineNo">1248</span>    setRSGroup(updateTables, newName);<a name="line.1248"></a>
+<span class="sourceLineNo">1249</span>  }<a name="line.1249"></a>
+<span class="sourceLineNo">1250</span><a name="line.1250"></a>
+<span class="sourceLineNo">1251</span>  @Override<a name="line.1251"></a>
+<span class="sourceLineNo">1252</span>  public synchronized void updateRSGroupConfig(String groupName, Map&lt;String, String&gt; configuration)<a name="line.1252"></a>
+<span class="sourceLineNo">1253</span>      throws IOException {<a name="line.1253"></a>
+<span class="sourceLineNo">1254</span>    RSGroupInfo rsGroupInfo = getRSGroupInfo(groupName);<a name="line.1254"></a>
+<span class="sourceLineNo">1255</span>    rsGroupInfo.getConfiguration().forEach((k, v) -&gt; rsGroupInfo.removeConfiguration(k));<a name="line.1255"></a>
+<span class="sourceLineNo">1256</span>    configuration.forEach((k, v) -&gt; rsGroupInfo.setConfiguration(k, v));<a name="line.1256"></a>
+<span class="sourceLineNo">1257</span>    flushConfig();<a name="line.1257"></a>
+<span class="sourceLineNo">1258</span>  }<a name="line.1258"></a>
+<span class="sourceLineNo">1259</span>}<a name="line.1259"></a>
 
 
 
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.RSGroupStartupWorker.html b/devapidocs/src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.RSGroupStartupWorker.html
index 61bfb38..6399539 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.RSGroupStartupWorker.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.RSGroupStartupWorker.html
@@ -1235,32 +1235,36 @@
 <span class="sourceLineNo">1227</span>      throw new ConstraintException(RSGroupInfo.DEFAULT_GROUP + " can't be rename");<a name="line.1227"></a>
 <span class="sourceLineNo">1228</span>    }<a name="line.1228"></a>
 <span class="sourceLineNo">1229</span>    checkGroupName(newName);<a name="line.1229"></a>
-<span class="sourceLineNo">1230</span><a name="line.1230"></a>
+<span class="sourceLineNo">1230</span>    //getRSGroupInfo validates old RSGroup existence.<a name="line.1230"></a>
 <span class="sourceLineNo">1231</span>    RSGroupInfo oldRSG = getRSGroupInfo(oldName);<a name="line.1231"></a>
 <span class="sourceLineNo">1232</span>    Map&lt;String, RSGroupInfo&gt; rsGroupMap = holder.groupName2Group;<a name="line.1232"></a>
-<span class="sourceLineNo">1233</span>    Map&lt;String, RSGroupInfo&gt; newGroupMap = Maps.newHashMap(rsGroupMap);<a name="line.1233"></a>
-<span class="sourceLineNo">1234</span>    newGroupMap.remove(oldRSG.getName());<a name="line.1234"></a>
-<span class="sourceLineNo">1235</span>    RSGroupInfo newRSG = new RSGroupInfo(newName, oldRSG.getServers());<a name="line.1235"></a>
-<span class="sourceLineNo">1236</span>    newGroupMap.put(newName, newRSG);<a name="line.1236"></a>
-<span class="sourceLineNo">1237</span>    flushConfig(newGroupMap);<a name="line.1237"></a>
-<span class="sourceLineNo">1238</span>    Set&lt;TableName&gt; updateTables =<a name="line.1238"></a>
-<span class="sourceLineNo">1239</span>      masterServices.getTableDescriptors().getAll().values()<a name="line.1239"></a>
-<span class="sourceLineNo">1240</span>                    .stream()<a name="line.1240"></a>
-<span class="sourceLineNo">1241</span>                    .filter(t -&gt; oldName.equals(t.getRegionServerGroup().orElse(null)))<a name="line.1241"></a>
-<span class="sourceLineNo">1242</span>                    .map(TableDescriptor::getTableName)<a name="line.1242"></a>
-<span class="sourceLineNo">1243</span>                    .collect(Collectors.toSet());<a name="line.1243"></a>
-<span class="sourceLineNo">1244</span>    setRSGroup(updateTables, newName);<a name="line.1244"></a>
-<span class="sourceLineNo">1245</span>  }<a name="line.1245"></a>
-<span class="sourceLineNo">1246</span><a name="line.1246"></a>
-<span class="sourceLineNo">1247</span>  @Override<a name="line.1247"></a>
-<span class="sourceLineNo">1248</span>  public synchronized void updateRSGroupConfig(String groupName, Map&lt;String, String&gt; configuration)<a name="line.1248"></a>
-<span class="sourceLineNo">1249</span>      throws IOException {<a name="line.1249"></a>
-<span class="sourceLineNo">1250</span>    RSGroupInfo rsGroupInfo = getRSGroupInfo(groupName);<a name="line.1250"></a>
-<span class="sourceLineNo">1251</span>    rsGroupInfo.getConfiguration().forEach((k, v) -&gt; rsGroupInfo.removeConfiguration(k));<a name="line.1251"></a>
-<span class="sourceLineNo">1252</span>    configuration.forEach((k, v) -&gt; rsGroupInfo.setConfiguration(k, v));<a name="line.1252"></a>
-<span class="sourceLineNo">1253</span>    flushConfig();<a name="line.1253"></a>
-<span class="sourceLineNo">1254</span>  }<a name="line.1254"></a>
-<span class="sourceLineNo">1255</span>}<a name="line.1255"></a>
+<span class="sourceLineNo">1233</span>    if (rsGroupMap.containsKey(newName)) {<a name="line.1233"></a>
+<span class="sourceLineNo">1234</span>      throw new ConstraintException("Group already exists: " + newName);<a name="line.1234"></a>
+<span class="sourceLineNo">1235</span>    }<a name="line.1235"></a>
+<span class="sourceLineNo">1236</span><a name="line.1236"></a>
+<span class="sourceLineNo">1237</span>    Map&lt;String, RSGroupInfo&gt; newGroupMap = Maps.newHashMap(rsGroupMap);<a name="line.1237"></a>
+<span class="sourceLineNo">1238</span>    newGroupMap.remove(oldRSG.getName());<a name="line.1238"></a>
+<span class="sourceLineNo">1239</span>    RSGroupInfo newRSG = new RSGroupInfo(newName, oldRSG.getServers());<a name="line.1239"></a>
+<span class="sourceLineNo">1240</span>    newGroupMap.put(newName, newRSG);<a name="line.1240"></a>
+<span class="sourceLineNo">1241</span>    flushConfig(newGroupMap);<a name="line.1241"></a>
+<span class="sourceLineNo">1242</span>    Set&lt;TableName&gt; updateTables =<a name="line.1242"></a>
+<span class="sourceLineNo">1243</span>      masterServices.getTableDescriptors().getAll().values()<a name="line.1243"></a>
+<span class="sourceLineNo">1244</span>                    .stream()<a name="line.1244"></a>
+<span class="sourceLineNo">1245</span>                    .filter(t -&gt; oldName.equals(t.getRegionServerGroup().orElse(null)))<a name="line.1245"></a>
+<span class="sourceLineNo">1246</span>                    .map(TableDescriptor::getTableName)<a name="line.1246"></a>
+<span class="sourceLineNo">1247</span>                    .collect(Collectors.toSet());<a name="line.1247"></a>
+<span class="sourceLineNo">1248</span>    setRSGroup(updateTables, newName);<a name="line.1248"></a>
+<span class="sourceLineNo">1249</span>  }<a name="line.1249"></a>
+<span class="sourceLineNo">1250</span><a name="line.1250"></a>
+<span class="sourceLineNo">1251</span>  @Override<a name="line.1251"></a>
+<span class="sourceLineNo">1252</span>  public synchronized void updateRSGroupConfig(String groupName, Map&lt;String, String&gt; configuration)<a name="line.1252"></a>
+<span class="sourceLineNo">1253</span>      throws IOException {<a name="line.1253"></a>
+<span class="sourceLineNo">1254</span>    RSGroupInfo rsGroupInfo = getRSGroupInfo(groupName);<a name="line.1254"></a>
+<span class="sourceLineNo">1255</span>    rsGroupInfo.getConfiguration().forEach((k, v) -&gt; rsGroupInfo.removeConfiguration(k));<a name="line.1255"></a>
+<span class="sourceLineNo">1256</span>    configuration.forEach((k, v) -&gt; rsGroupInfo.setConfiguration(k, v));<a name="line.1256"></a>
+<span class="sourceLineNo">1257</span>    flushConfig();<a name="line.1257"></a>
+<span class="sourceLineNo">1258</span>  }<a name="line.1258"></a>
+<span class="sourceLineNo">1259</span>}<a name="line.1259"></a>
 
 
 
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.html b/devapidocs/src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.html
index 61bfb38..6399539 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/rsgroup/RSGroupInfoManagerImpl.html
@@ -1235,32 +1235,36 @@
 <span class="sourceLineNo">1227</span>      throw new ConstraintException(RSGroupInfo.DEFAULT_GROUP + " can't be rename");<a name="line.1227"></a>
 <span class="sourceLineNo">1228</span>    }<a name="line.1228"></a>
 <span class="sourceLineNo">1229</span>    checkGroupName(newName);<a name="line.1229"></a>
-<span class="sourceLineNo">1230</span><a name="line.1230"></a>
+<span class="sourceLineNo">1230</span>    //getRSGroupInfo validates old RSGroup existence.<a name="line.1230"></a>
 <span class="sourceLineNo">1231</span>    RSGroupInfo oldRSG = getRSGroupInfo(oldName);<a name="line.1231"></a>
 <span class="sourceLineNo">1232</span>    Map&lt;String, RSGroupInfo&gt; rsGroupMap = holder.groupName2Group;<a name="line.1232"></a>
-<span class="sourceLineNo">1233</span>    Map&lt;String, RSGroupInfo&gt; newGroupMap = Maps.newHashMap(rsGroupMap);<a name="line.1233"></a>
-<span class="sourceLineNo">1234</span>    newGroupMap.remove(oldRSG.getName());<a name="line.1234"></a>
-<span class="sourceLineNo">1235</span>    RSGroupInfo newRSG = new RSGroupInfo(newName, oldRSG.getServers());<a name="line.1235"></a>
-<span class="sourceLineNo">1236</span>    newGroupMap.put(newName, newRSG);<a name="line.1236"></a>
-<span class="sourceLineNo">1237</span>    flushConfig(newGroupMap);<a name="line.1237"></a>
-<span class="sourceLineNo">1238</span>    Set&lt;TableName&gt; updateTables =<a name="line.1238"></a>
-<span class="sourceLineNo">1239</span>      masterServices.getTableDescriptors().getAll().values()<a name="line.1239"></a>
-<span class="sourceLineNo">1240</span>                    .stream()<a name="line.1240"></a>
-<span class="sourceLineNo">1241</span>                    .filter(t -&gt; oldName.equals(t.getRegionServerGroup().orElse(null)))<a name="line.1241"></a>
-<span class="sourceLineNo">1242</span>                    .map(TableDescriptor::getTableName)<a name="line.1242"></a>
-<span class="sourceLineNo">1243</span>                    .collect(Collectors.toSet());<a name="line.1243"></a>
-<span class="sourceLineNo">1244</span>    setRSGroup(updateTables, newName);<a name="line.1244"></a>
-<span class="sourceLineNo">1245</span>  }<a name="line.1245"></a>
-<span class="sourceLineNo">1246</span><a name="line.1246"></a>
-<span class="sourceLineNo">1247</span>  @Override<a name="line.1247"></a>
-<span class="sourceLineNo">1248</span>  public synchronized void updateRSGroupConfig(String groupName, Map&lt;String, String&gt; configuration)<a name="line.1248"></a>
-<span class="sourceLineNo">1249</span>      throws IOException {<a name="line.1249"></a>
-<span class="sourceLineNo">1250</span>    RSGroupInfo rsGroupInfo = getRSGroupInfo(groupName);<a name="line.1250"></a>
-<span class="sourceLineNo">1251</span>    rsGroupInfo.getConfiguration().forEach((k, v) -&gt; rsGroupInfo.removeConfiguration(k));<a name="line.1251"></a>
-<span class="sourceLineNo">1252</span>    configuration.forEach((k, v) -&gt; rsGroupInfo.setConfiguration(k, v));<a name="line.1252"></a>
-<span class="sourceLineNo">1253</span>    flushConfig();<a name="line.1253"></a>
-<span class="sourceLineNo">1254</span>  }<a name="line.1254"></a>
-<span class="sourceLineNo">1255</span>}<a name="line.1255"></a>
+<span class="sourceLineNo">1233</span>    if (rsGroupMap.containsKey(newName)) {<a name="line.1233"></a>
+<span class="sourceLineNo">1234</span>      throw new ConstraintException("Group already exists: " + newName);<a name="line.1234"></a>
+<span class="sourceLineNo">1235</span>    }<a name="line.1235"></a>
+<span class="sourceLineNo">1236</span><a name="line.1236"></a>
+<span class="sourceLineNo">1237</span>    Map&lt;String, RSGroupInfo&gt; newGroupMap = Maps.newHashMap(rsGroupMap);<a name="line.1237"></a>
+<span class="sourceLineNo">1238</span>    newGroupMap.remove(oldRSG.getName());<a name="line.1238"></a>
+<span class="sourceLineNo">1239</span>    RSGroupInfo newRSG = new RSGroupInfo(newName, oldRSG.getServers());<a name="line.1239"></a>
+<span class="sourceLineNo">1240</span>    newGroupMap.put(newName, newRSG);<a name="line.1240"></a>
+<span class="sourceLineNo">1241</span>    flushConfig(newGroupMap);<a name="line.1241"></a>
+<span class="sourceLineNo">1242</span>    Set&lt;TableName&gt; updateTables =<a name="line.1242"></a>
+<span class="sourceLineNo">1243</span>      masterServices.getTableDescriptors().getAll().values()<a name="line.1243"></a>
+<span class="sourceLineNo">1244</span>                    .stream()<a name="line.1244"></a>
+<span class="sourceLineNo">1245</span>                    .filter(t -&gt; oldName.equals(t.getRegionServerGroup().orElse(null)))<a name="line.1245"></a>
+<span class="sourceLineNo">1246</span>                    .map(TableDescriptor::getTableName)<a name="line.1246"></a>
+<span class="sourceLineNo">1247</span>                    .collect(Collectors.toSet());<a name="line.1247"></a>
+<span class="sourceLineNo">1248</span>    setRSGroup(updateTables, newName);<a name="line.1248"></a>
+<span class="sourceLineNo">1249</span>  }<a name="line.1249"></a>
+<span class="sourceLineNo">1250</span><a name="line.1250"></a>
+<span class="sourceLineNo">1251</span>  @Override<a name="line.1251"></a>
+<span class="sourceLineNo">1252</span>  public synchronized void updateRSGroupConfig(String groupName, Map&lt;String, String&gt; configuration)<a name="line.1252"></a>
+<span class="sourceLineNo">1253</span>      throws IOException {<a name="line.1253"></a>
+<span class="sourceLineNo">1254</span>    RSGroupInfo rsGroupInfo = getRSGroupInfo(groupName);<a name="line.1254"></a>
+<span class="sourceLineNo">1255</span>    rsGroupInfo.getConfiguration().forEach((k, v) -&gt; rsGroupInfo.removeConfiguration(k));<a name="line.1255"></a>
+<span class="sourceLineNo">1256</span>    configuration.forEach((k, v) -&gt; rsGroupInfo.setConfiguration(k, v));<a name="line.1256"></a>
+<span class="sourceLineNo">1257</span>    flushConfig();<a name="line.1257"></a>
+<span class="sourceLineNo">1258</span>  }<a name="line.1258"></a>
+<span class="sourceLineNo">1259</span>}<a name="line.1259"></a>
 
 
 
diff --git a/downloads.html b/downloads.html
index d30211e..fa2e420 100644
--- a/downloads.html
+++ b/downloads.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
@@ -191,6 +202,37 @@
 <tr class="b">
       
 <td style="test-align: left">
+        2.3.0
+      </td>
+      
+<td style="test-align: left">
+        2020/07/13
+      </td>
+      
+<td style="test-align: left">
+        <a class="externalLink" href="https://downloads.apache.org/hbase/2.3.0/api_compare_2.2.0_to_2.3.0RC3.html">2.2.0 vs 2.3.0</a>
+      </td>
+      
+<td style="test-align: left">
+        <a class="externalLink" href="https://downloads.apache.org/hbase/2.3.0/CHANGES.md">Changes</a>
+      </td>
+      
+<td style="test-align: left">
+        <a class="externalLink" href="https://downloads.apache.org/hbase/2.3.0/RELEASENOTES.md">Release Notes</a>
+      </td>
+      
+<td style="test-align: left">
+        <a class="externalLink" href="https://www.apache.org/dyn/closer.lua/hbase/2.3.0/hbase-2.3.0-src.tar.gz">src</a> (<a class="externalLink" href="https://downloads.apache.org/hbase/2.3.0/hbase-2.3.0-src.tar.gz.sha512">sha512</a> <a class="externalLink" href="https://downloads.apache.org/hbase/2.3.0/hbase-2.3.0-src.tar.gz.asc">asc</a>) <br />
+        <a class="externalLink" href="https://www.apache.org/dyn/closer.lua/hbase/2.3.0/hbase-2.3.0-bin.tar.gz">bin</a> (<a class="externalLink" href="https://downloads.apache.org/hbase/2.3.0/hbase-2.3.0-bin.tar.gz.sha512">sha512</a> <a class="externalLink" href="https://downloads.apache.org/hbase/2.3.0/hbase-2.3.0-bin.tar.gz.asc">asc</a>) <br />
+        <a class="externalLink" href="https://www.apache.org/dyn/closer.lua/hbase/2.3.0/hbase-2.3.0-client-bin.tar.gz">client-bin</a> (<a class="externalLink" href="https://downloads.apache.org/hbase/2.3.0/hbase-2.3.0-client-bin.tar.gz.sha512">sha512</a> <a class="externalLink" href="https://downloads.apache.org/hbase/2.3.0/hbase-2.3.0-client-bin.tar.gz.asc">asc</a>)
+      </td>
+      
+<td></td>
+    </tr>
+    
+<tr class="a">
+      
+<td style="test-align: left">
         2.2.5
       </td>
       
@@ -219,7 +261,7 @@
 <td><i>stable release</i></td>
     </tr>
     
-<tr class="a">
+<tr class="b">
       
 <td style="test-align: left">
         1.6.0
@@ -249,7 +291,7 @@
 <td></td>
     </tr>
     
-<tr class="b">
+<tr class="a">
       
 <td style="test-align: left">
         1.4.13
@@ -277,7 +319,7 @@
       </td>
     </tr>
     
-<tr class="a">
+<tr class="b">
       
 <td style="test-align: left">
         1.3.6
diff --git a/export_control.html b/export_control.html
index 18ac219..b62ae4d 100644
--- a/export_control.html
+++ b/export_control.html
@@ -113,6 +113,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/index.html b/index.html
index 04106c4..d5a3e09 100644
--- a/index.html
+++ b/index.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/issue-tracking.html b/issue-tracking.html
index 78a26a2..7c280ed 100644
--- a/issue-tracking.html
+++ b/issue-tracking.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/mail-lists.html b/mail-lists.html
index 3d77887..f89f96b 100644
--- a/mail-lists.html
+++ b/mail-lists.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/metrics.html b/metrics.html
index 46a87a4..bf78413 100644
--- a/metrics.html
+++ b/metrics.html
@@ -113,6 +113,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/old_news.html b/old_news.html
index 66903ea..2f59a2b 100644
--- a/old_news.html
+++ b/old_news.html
@@ -113,6 +113,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/plugin-management.html b/plugin-management.html
index f164ab8..d0aa253 100644
--- a/plugin-management.html
+++ b/plugin-management.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/plugins.html b/plugins.html
index 6e3cb7e..efee83f 100644
--- a/plugins.html
+++ b/plugins.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/poweredbyhbase.html b/poweredbyhbase.html
index ddd36d2..1289ceb 100644
--- a/poweredbyhbase.html
+++ b/poweredbyhbase.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/project-info.html b/project-info.html
index 340a9fd..c62d416 100644
--- a/project-info.html
+++ b/project-info.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/project-reports.html b/project-reports.html
index 19281c1..3316650 100644
--- a/project-reports.html
+++ b/project-reports.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/project-summary.html b/project-summary.html
index d7090af..116496e 100644
--- a/project-summary.html
+++ b/project-summary.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/pseudo-distributed.html b/pseudo-distributed.html
index 974a79b..2558a3e 100644
--- a/pseudo-distributed.html
+++ b/pseudo-distributed.html
@@ -113,6 +113,17 @@ Running Apache HBase (TM) in pseudo-distributed mode
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/replication.html b/replication.html
index 5c1ae73..5c1963b 100644
--- a/replication.html
+++ b/replication.html
@@ -113,6 +113,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/resources.html b/resources.html
index dc0c0bc..0ca81cc 100644
--- a/resources.html
+++ b/resources.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/source-repository.html b/source-repository.html
index 4e84375..af3c1b8 100644
--- a/source-repository.html
+++ b/source-repository.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/sponsors.html b/sponsors.html
index 9ff5bc6..34b28c3 100644
--- a/sponsors.html
+++ b/sponsors.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/supportingprojects.html b/supportingprojects.html
index d2fe2ba..24b0cea 100644
--- a/supportingprojects.html
+++ b/supportingprojects.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/team-list.html b/team-list.html
index 0b57104..8ccda5d 100644
--- a/team-list.html
+++ b/team-list.html
@@ -111,6 +111,17 @@
                   <li><a href="2.2/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
               </ul>
             </li>
+            <li class="dropdown-submenu">
+<a href="" title="2.3 Documentation">2.3 Documentation</a>
+              <ul class="dropdown-menu">
+                  <li><a href="2.3/book.html" target="_blank" title="Ref Guide">Ref Guide</a></li>
+                  <li><a href="2.3/apache_hbase_reference_guide.pdf" target="_blank" title="Reference Guide (PDF)">Reference Guide (PDF)</a></li>
+                  <li><a href="2.3/apidocs/index.html" target="_blank" title="User API">User API</a></li>
+                  <li><a href="2.3/testapidocs/index.html" target="_blank" title="User API (Test)">User API (Test)</a></li>
+                  <li><a href="2.3/devapidocs/index.html" target="_blank" title="Developer API">Developer API</a></li>
+                  <li><a href="2.3/testdevapidocs/index.html" target="_blank" title="Developer API (Test)">Developer API (Test)</a></li>
+              </ul>
+            </li>
         </ul>
       </li>
       <li class="dropdown">
diff --git a/testdevapidocs/index-all.html b/testdevapidocs/index-all.html
index 7d72c51..cb76a0e 100644
--- a/testdevapidocs/index-all.html
+++ b/testdevapidocs/index-all.html
@@ -67876,6 +67876,8 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/rsgroup/TestRSGroupsWithACL.html#testRenameRSGroup--">testRenameRSGroup()</a></span> - Method in class org.apache.hadoop.hbase.rsgroup.<a href="org/apache/hadoop/hbase/rsgroup/TestRSGroupsWithACL.html" title="class in org.apache.hadoop.hbase.rsgroup">TestRSGroupsWithACL</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#testRenameRSGroupConstraints--">testRenameRSGroupConstraints()</a></span> - Method in class org.apache.hadoop.hbase.rsgroup.<a href="org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html" title="class in org.apache.hadoop.hbase.rsgroup">TestRSGroupsAdmin1</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/master/assignment/TestAssignmentManager.html#testReopen--">testReopen()</a></span> - Method in class org.apache.hadoop.hbase.master.assignment.<a href="org/apache/hadoop/hbase/master/assignment/TestAssignmentManager.html" title="class in org.apache.hadoop.hbase.master.assignment">TestAssignmentManager</a></dt>
 <dd>&nbsp;</dd>
 <dt><a href="org/apache/hadoop/hbase/master/procedure/TestReopenTableRegionsProcedureBackoff.html" title="class in org.apache.hadoop.hbase.master.procedure"><span class="typeNameLink">TestReopenTableRegionsProcedureBackoff</span></a> - Class in <a href="org/apache/hadoop/hbase/master/procedure/package-summary.html">org.apache.hadoop.hbase.master.procedure</a></dt>
@@ -68006,6 +68008,8 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/client/TestReplicaWithCluster.html#testReplicaAndReplication--">testReplicaAndReplication()</a></span> - Method in class org.apache.hadoop.hbase.client.<a href="org/apache/hadoop/hbase/client/TestReplicaWithCluster.html" title="class in org.apache.hadoop.hbase.client">TestReplicaWithCluster</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#testReplicaCleanup--">testReplicaCleanup()</a></span> - Method in class org.apache.hadoop.hbase.client.<a href="org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html" title="class in org.apache.hadoop.hbase.client">TestMetaWithReplicasBasic</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplica.html#testReplicaCost--">testReplicaCost()</a></span> - Method in class org.apache.hadoop.hbase.master.balancer.<a href="org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplica.html" title="class in org.apache.hadoop.hbase.master.balancer">TestStochasticLoadBalancerRegionReplica</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplica.html#testReplicaCostForReplicas--">testReplicaCostForReplicas()</a></span> - Method in class org.apache.hadoop.hbase.master.balancer.<a href="org/apache/hadoop/hbase/master/balancer/TestStochasticLoadBalancerRegionReplica.html" title="class in org.apache.hadoop.hbase.master.balancer">TestStochasticLoadBalancerRegionReplica</a></dt>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/backup/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/backup/package-tree.html
index fa6650a..88e37d3 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/backup/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/backup/package-tree.html
@@ -150,8 +150,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/TestIncrementalBackupMergeWithFailures.FailurePhase.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">TestIncrementalBackupMergeWithFailures.FailurePhase</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/TestBackupDeleteWithFailures.Failure.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">TestBackupDeleteWithFailures.Failure</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/TestIncrementalBackupMergeWithFailures.FailurePhase.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">TestIncrementalBackupMergeWithFailures.FailurePhase</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/chaos/actions/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/chaos/actions/package-tree.html
index 93d1d32..93a914e 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/chaos/actions/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/chaos/actions/package-tree.html
@@ -159,8 +159,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.chaos.actions.<a href="../../../../../../org/apache/hadoop/hbase/chaos/actions/RollingBatchSuspendResumeRsAction.SuspendOrResume.html" title="enum in org.apache.hadoop.hbase.chaos.actions"><span class="typeNameLink">RollingBatchSuspendResumeRsAction.SuspendOrResume</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.chaos.actions.<a href="../../../../../../org/apache/hadoop/hbase/chaos/actions/RollingBatchRestartRsAction.KillOrStart.html" title="enum in org.apache.hadoop.hbase.chaos.actions"><span class="typeNameLink">RollingBatchRestartRsAction.KillOrStart</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.chaos.actions.<a href="../../../../../../org/apache/hadoop/hbase/chaos/actions/RollingBatchSuspendResumeRsAction.SuspendOrResume.html" title="enum in org.apache.hadoop.hbase.chaos.actions"><span class="typeNameLink">RollingBatchSuspendResumeRsAction.SuspendOrResume</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html b/testdevapidocs/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html
index 45d2e8c..bc5db8a 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html
@@ -18,7 +18,7 @@
     catch(err) {
     }
 //-->
-var methods = {"i0":9,"i1":10,"i2":10,"i3":10};
+var methods = {"i0":9,"i1":10,"i2":10,"i3":10,"i4":10};
 var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]};
 var altColor = "altColor";
 var rowColor = "rowColor";
@@ -114,7 +114,7 @@ var activeTableTab = "activeTableTab";
 <li class="blockList">
 <hr>
 <br>
-<pre>public class <a href="../../../../../src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#line.43">TestMetaWithReplicasBasic</a>
+<pre>public class <a href="../../../../../src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#line.45">TestMetaWithReplicasBasic</a>
 extends <a href="../../../../../org/apache/hadoop/hbase/client/MetaWithReplicasTestBase.html" title="class in org.apache.hadoop.hbase.client">MetaWithReplicasTestBase</a></pre>
 </li>
 </ul>
@@ -191,6 +191,10 @@ extends <a href="../../../../../org/apache/hadoop/hbase/client/MetaWithReplicasT
 </tr>
 <tr id="i3" class="rowColor">
 <td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#testReplicaCleanup--">testReplicaCleanup</a></span>()</code>&nbsp;</td>
+</tr>
+<tr id="i4" class="altColor">
+<td class="colFirst"><code>void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#testZookeeperNodesForReplicas--">testZookeeperNodesForReplicas</a></span>()</code>&nbsp;</td>
 </tr>
 </table>
@@ -228,7 +232,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/client/MetaWithReplicasT
 <ul class="blockListLast">
 <li class="blockList">
 <h4>CLASS_RULE</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/HBaseClassTestRule.html" title="class in org.apache.hadoop.hbase">HBaseClassTestRule</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#line.46">CLASS_RULE</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/HBaseClassTestRule.html" title="class in org.apache.hadoop.hbase">HBaseClassTestRule</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#line.48">CLASS_RULE</a></pre>
 </li>
 </ul>
 </li>
@@ -245,7 +249,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/client/MetaWithReplicasT
 <ul class="blockListLast">
 <li class="blockList">
 <h4>TestMetaWithReplicasBasic</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#line.43">TestMetaWithReplicasBasic</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#line.45">TestMetaWithReplicasBasic</a>()</pre>
 </li>
 </ul>
 </li>
@@ -262,7 +266,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/client/MetaWithReplicasT
 <ul class="blockList">
 <li class="blockList">
 <h4>setUp</h4>
-<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#line.50">setUp</a>()
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#line.52">setUp</a>()
                   throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -276,7 +280,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/client/MetaWithReplicasT
 <ul class="blockList">
 <li class="blockList">
 <h4>testMetaHTDReplicaCount</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#line.55">testMetaHTDReplicaCount</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#line.57">testMetaHTDReplicaCount</a>()
                              throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -290,7 +294,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/client/MetaWithReplicasT
 <ul class="blockList">
 <li class="blockList">
 <h4>testZookeeperNodesForReplicas</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#line.61">testZookeeperNodesForReplicas</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#line.63">testZookeeperNodesForReplicas</a>()
                                    throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -298,13 +302,27 @@ extends <a href="../../../../../org/apache/hadoop/hbase/client/MetaWithReplicasT
 </dl>
 </li>
 </ul>
+<a name="testReplicaCleanup--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>testReplicaCleanup</h4>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#line.86">testReplicaCleanup</a>()
+                        throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
+<dl>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></code></dd>
+</dl>
+</li>
+</ul>
 <a name="testAccessingUnknownTables--">
 <!--   -->
 </a>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>testAccessingUnknownTables</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#line.84">testAccessingUnknownTables</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html#line.107">testAccessingUnknownTables</a>()
                                 throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/package-tree.html
index f32920e..d4d7436 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/io/hfile/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/io/hfile/package-tree.html
@@ -165,8 +165,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TagUsage.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">TagUsage</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TestCacheOnWrite.CacheOnWriteType.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">TestCacheOnWrite.CacheOnWriteType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/TagUsage.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">TagUsage</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/package-tree.html
index 4b9ea63..01e2d11 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/package-tree.html
@@ -654,18 +654,18 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/IntegrationTestRegionReplicaPerf.Stat.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">IntegrationTestRegionReplicaPerf.Stat</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.Service.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.Service</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HBaseClusterManager.CommandProvider.Operation.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HBaseClusterManager.CommandProvider.Operation</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/IntegrationTestDDLMasterFailover.ACTION.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">IntegrationTestDDLMasterFailover.ACTION</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/PerformanceEvaluation.Counter.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">PerformanceEvaluation.Counter</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ClusterManager.ServiceType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ClusterManager.ServiceType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.HealthSummary.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.HealthSummary</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HBaseClusterManager.Signal.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HBaseClusterManager.Signal</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/IntegrationTestDDLMasterFailover.ACTION.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">IntegrationTestDDLMasterFailover.ACTION</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.RoleCommand.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.RoleCommand</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ScanPerformanceEvaluation.ScanCounter.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ScanPerformanceEvaluation.ScanCounter</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HBaseClusterManager.Signal.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HBaseClusterManager.Signal</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.RoleState.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.RoleState</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ResourceChecker.Phase.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ResourceChecker.Phase</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ClusterManager.ServiceType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ClusterManager.ServiceType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/IntegrationTestRegionReplicaPerf.Stat.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">IntegrationTestRegionReplicaPerf.Stat</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HBaseClusterManager.CommandProvider.Operation.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HBaseClusterManager.CommandProvider.Operation</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.RoleState.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.RoleState</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
index 52aa6c8..11b8fb7 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
@@ -242,9 +242,9 @@
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
 <li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestYieldProcedures.TestStateMachineProcedure.State.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestYieldProcedures.TestStateMachineProcedure.State</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestStateMachineProcedure.TestSMProcedureState.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestStateMachineProcedure.TestSMProcedureState</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestProcedureRecovery.TestStateMachineProcedure.State.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestProcedureRecovery.TestStateMachineProcedure.State</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestProcedureBypass.StuckStateMachineState.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestProcedureBypass.StuckStateMachineState</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestProcedureRecovery.TestStateMachineProcedure.State.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestProcedureRecovery.TestStateMachineProcedure.State</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestStateMachineProcedure.TestSMProcedureState.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestStateMachineProcedure.TestSMProcedureState</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
index a2c770e..c07b48d 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
@@ -706,11 +706,11 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/DataBlockEncodingTool.Manipulation.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">DataBlockEncodingTool.Manipulation</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestCacheOnWriteInSchema.CacheOnWriteType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestCacheOnWriteInSchema.CacheOnWriteType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestMultiLogThreshold.ActionType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestMultiLogThreshold.ActionType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestRegionServerReadRequestMetrics.Metric.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestRegionServerReadRequestMetrics.Metric</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestAtomicOperation.TestStep.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestAtomicOperation.TestStep</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestCacheOnWriteInSchema.CacheOnWriteType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestCacheOnWriteInSchema.CacheOnWriteType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/DataBlockEncodingTool.Manipulation.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">DataBlockEncodingTool.Manipulation</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html b/testdevapidocs/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html
index 286cf3d..28c294c 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html
@@ -18,7 +18,7 @@
     catch(err) {
     }
 //-->
-var methods = {"i0":10,"i1":10,"i2":9,"i3":9,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10};
+var methods = {"i0":10,"i1":10,"i2":9,"i3":9,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10};
 var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]};
 var altColor = "altColor";
 var rowColor = "rowColor";
@@ -114,7 +114,7 @@ var activeTableTab = "activeTableTab";
 <li class="blockList">
 <hr>
 <br>
-<pre>public class <a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.60">TestRSGroupsAdmin1</a>
+<pre>public class <a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.61">TestRSGroupsAdmin1</a>
 extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase.html" title="class in org.apache.hadoop.hbase.rsgroup">TestRSGroupsBase</a></pre>
 </li>
 </ul>
@@ -250,14 +250,18 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 </tr>
 <tr id="i13" class="rowColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#testRSGroupListDoesNotContainFailedTableCreation--">testRSGroupListDoesNotContainFailedTableCreation</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#testRenameRSGroupConstraints--">testRenameRSGroupConstraints</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i14" class="altColor">
 <td class="colFirst"><code>void</code></td>
-<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#testTableMoveTruncateAndDrop--">testTableMoveTruncateAndDrop</a></span>()</code>&nbsp;</td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#testRSGroupListDoesNotContainFailedTableCreation--">testRSGroupListDoesNotContainFailedTableCreation</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i15" class="rowColor">
 <td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#testTableMoveTruncateAndDrop--">testTableMoveTruncateAndDrop</a></span>()</code>&nbsp;</td>
+</tr>
+<tr id="i16" class="altColor">
+<td class="colFirst"><code>void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#testValidGroupNames--">testValidGroupNames</a></span>()</code>&nbsp;</td>
 </tr>
 </table>
@@ -295,7 +299,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockList">
 <li class="blockList">
 <h4>CLASS_RULE</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/HBaseClassTestRule.html" title="class in org.apache.hadoop.hbase">HBaseClassTestRule</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.63">CLASS_RULE</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/HBaseClassTestRule.html" title="class in org.apache.hadoop.hbase">HBaseClassTestRule</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.64">CLASS_RULE</a></pre>
 </li>
 </ul>
 <a name="LOG">
@@ -304,7 +308,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockListLast">
 <li class="blockList">
 <h4>LOG</h4>
-<pre>private static final&nbsp;org.slf4j.Logger <a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.66">LOG</a></pre>
+<pre>private static final&nbsp;org.slf4j.Logger <a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.67">LOG</a></pre>
 </li>
 </ul>
 </li>
@@ -321,7 +325,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockListLast">
 <li class="blockList">
 <h4>TestRSGroupsAdmin1</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.60">TestRSGroupsAdmin1</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.61">TestRSGroupsAdmin1</a>()</pre>
 </li>
 </ul>
 </li>
@@ -338,7 +342,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockList">
 <li class="blockList">
 <h4>setUp</h4>
-<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.69">setUp</a>()
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.70">setUp</a>()
                   throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -352,7 +356,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockList">
 <li class="blockList">
 <h4>tearDown</h4>
-<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.74">tearDown</a>()
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.75">tearDown</a>()
                      throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -366,7 +370,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockList">
 <li class="blockList">
 <h4>beforeMethod</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.79">beforeMethod</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.80">beforeMethod</a>()
                   throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -380,7 +384,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockList">
 <li class="blockList">
 <h4>afterMethod</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.84">afterMethod</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.85">afterMethod</a>()
                  throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -394,7 +398,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockList">
 <li class="blockList">
 <h4>testValidGroupNames</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.89">testValidGroupNames</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.90">testValidGroupNames</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>
@@ -408,7 +412,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockList">
 <li class="blockList">
 <h4>testBogusArgs</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.108">testBogusArgs</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.109">testBogusArgs</a>()
                    throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -422,7 +426,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockList">
 <li class="blockList">
 <h4>testNamespaceConstraint</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.145">testNamespaceConstraint</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.146">testNamespaceConstraint</a>()
                              throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -436,7 +440,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockList">
 <li class="blockList">
 <h4>testNamespaceConstraint2</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.183">testNamespaceConstraint2</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.184">testNamespaceConstraint2</a>()
                               throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -450,7 +454,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockList">
 <li class="blockList">
 <h4>testFailRemoveGroup</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.205">testFailRemoveGroup</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.206">testFailRemoveGroup</a>()
                          throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a>,
                                 <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InterruptedException.html?is-external=true" title="class or interface in java.lang">InterruptedException</a></pre>
 <dl>
@@ -466,7 +470,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockList">
 <li class="blockList">
 <h4>testMultiTableMove</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.238">testMultiTableMove</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.239">testMultiTableMove</a>()
                         throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -480,7 +484,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockList">
 <li class="blockList">
 <h4>testTableMoveTruncateAndDrop</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.292">testTableMoveTruncateAndDrop</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.293">testTableMoveTruncateAndDrop</a>()
                                   throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -494,7 +498,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockList">
 <li class="blockList">
 <h4>testDisabledTableMove</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.350">testDisabledTableMove</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.351">testDisabledTableMove</a>()
                            throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -508,7 +512,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockList">
 <li class="blockList">
 <h4>testNonExistentTableMove</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.382">testNonExistentTableMove</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.383">testNonExistentTableMove</a>()
                               throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -522,7 +526,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockList">
 <li class="blockList">
 <h4>testRSGroupListDoesNotContainFailedTableCreation</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.413">testRSGroupListDoesNotContainFailedTableCreation</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.414">testRSGroupListDoesNotContainFailedTableCreation</a>()
                                                       throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -536,7 +540,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <ul class="blockList">
 <li class="blockList">
 <h4>testNotMoveTableToNullRSGroupWhenCreatingExistingTable</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.465">testNotMoveTableToNullRSGroupWhenCreatingExistingTable</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.466">testNotMoveTableToNullRSGroupWhenCreatingExistingTable</a>()
                                                             throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -547,10 +551,10 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 <a name="testRenameRSGroup--">
 <!--   -->
 </a>
-<ul class="blockListLast">
+<ul class="blockList">
 <li class="blockList">
 <h4>testRenameRSGroup</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.495">testRenameRSGroup</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.496">testRenameRSGroup</a>()
                        throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -558,6 +562,20 @@ extends <a href="../../../../../org/apache/hadoop/hbase/rsgroup/TestRSGroupsBase
 </dl>
 </li>
 </ul>
+<a name="testRenameRSGroupConstraints--">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>testRenameRSGroupConstraints</h4>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html#line.540">testRenameRSGroupConstraints</a>()
+                                  throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
+<dl>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></code></dd>
+</dl>
+</li>
+</ul>
 </li>
 </ul>
 </li>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html
index 9f53873..5119ec3 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html
@@ -253,10 +253,10 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestBigLinkedList.Verify.Counts.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestBigLinkedList.Verify.Counts</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestBigLinkedList.Generator.Counts.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestBigLinkedList.Generator.Counts</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestLoadAndVerify.Counters.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestLoadAndVerify.Counters</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.Counters.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestWithCellVisibilityLoadAndVerify.Counters</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestLoadAndVerify.Counters.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestLoadAndVerify.Counters</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestBigLinkedList.Verify.Counts.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestBigLinkedList.Verify.Counts</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html
index 1673bf6..e4634e7 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html
@@ -164,9 +164,9 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
+<li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/IOTestProvider.AllowedOperations.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">IOTestProvider.AllowedOperations</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/FaultyFSLog.FailureType.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">FaultyFSLog.FailureType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/TestWALSplit.Corruptions.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">TestWALSplit.Corruptions</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/IOTestProvider.AllowedOperations.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">IOTestProvider.AllowedOperations</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html
index 8df1485..c546e63 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/client/TestMetaWithReplicasBasic.html
@@ -28,75 +28,98 @@
 <span class="sourceLineNo">020</span>import static org.junit.Assert.assertEquals;<a name="line.20"></a>
 <span class="sourceLineNo">021</span>import static org.junit.Assert.assertThrows;<a name="line.21"></a>
 <span class="sourceLineNo">022</span>import static org.junit.Assert.assertTrue;<a name="line.22"></a>
-<span class="sourceLineNo">023</span><a name="line.23"></a>
+<span class="sourceLineNo">023</span>import java.util.List;<a name="line.23"></a>
 <span class="sourceLineNo">024</span>import org.apache.hadoop.conf.Configuration;<a name="line.24"></a>
 <span class="sourceLineNo">025</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.25"></a>
 <span class="sourceLineNo">026</span>import org.apache.hadoop.hbase.HConstants;<a name="line.26"></a>
 <span class="sourceLineNo">027</span>import org.apache.hadoop.hbase.TableName;<a name="line.27"></a>
 <span class="sourceLineNo">028</span>import org.apache.hadoop.hbase.TableNotFoundException;<a name="line.28"></a>
-<span class="sourceLineNo">029</span>import org.apache.hadoop.hbase.testclassification.MediumTests;<a name="line.29"></a>
-<span class="sourceLineNo">030</span>import org.apache.hadoop.hbase.testclassification.MiscTests;<a name="line.30"></a>
-<span class="sourceLineNo">031</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.31"></a>
-<span class="sourceLineNo">032</span>import org.apache.hadoop.hbase.zookeeper.ZKUtil;<a name="line.32"></a>
-<span class="sourceLineNo">033</span>import org.apache.hadoop.hbase.zookeeper.ZKWatcher;<a name="line.33"></a>
-<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.zookeeper.ZNodePaths;<a name="line.34"></a>
-<span class="sourceLineNo">035</span>import org.junit.BeforeClass;<a name="line.35"></a>
-<span class="sourceLineNo">036</span>import org.junit.ClassRule;<a name="line.36"></a>
-<span class="sourceLineNo">037</span>import org.junit.Test;<a name="line.37"></a>
-<span class="sourceLineNo">038</span>import org.junit.experimental.categories.Category;<a name="line.38"></a>
-<span class="sourceLineNo">039</span><a name="line.39"></a>
-<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.40"></a>
+<span class="sourceLineNo">029</span>import org.apache.hadoop.hbase.master.HMaster;<a name="line.29"></a>
+<span class="sourceLineNo">030</span>import org.apache.hadoop.hbase.testclassification.MediumTests;<a name="line.30"></a>
+<span class="sourceLineNo">031</span>import org.apache.hadoop.hbase.testclassification.MiscTests;<a name="line.31"></a>
+<span class="sourceLineNo">032</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.32"></a>
+<span class="sourceLineNo">033</span>import org.apache.hadoop.hbase.util.JVMClusterUtil;<a name="line.33"></a>
+<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.zookeeper.ZKUtil;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.zookeeper.ZKWatcher;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.zookeeper.ZNodePaths;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.junit.BeforeClass;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.junit.ClassRule;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.junit.Test;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.junit.experimental.categories.Category;<a name="line.40"></a>
 <span class="sourceLineNo">041</span><a name="line.41"></a>
-<span class="sourceLineNo">042</span>@Category({ MiscTests.class, MediumTests.class })<a name="line.42"></a>
-<span class="sourceLineNo">043</span>public class TestMetaWithReplicasBasic extends MetaWithReplicasTestBase {<a name="line.43"></a>
-<span class="sourceLineNo">044</span><a name="line.44"></a>
-<span class="sourceLineNo">045</span>  @ClassRule<a name="line.45"></a>
-<span class="sourceLineNo">046</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.46"></a>
-<span class="sourceLineNo">047</span>    HBaseClassTestRule.forClass(TestMetaWithReplicasBasic.class);<a name="line.47"></a>
-<span class="sourceLineNo">048</span><a name="line.48"></a>
-<span class="sourceLineNo">049</span>  @BeforeClass<a name="line.49"></a>
-<span class="sourceLineNo">050</span>  public static void setUp() throws Exception {<a name="line.50"></a>
-<span class="sourceLineNo">051</span>    startCluster();<a name="line.51"></a>
-<span class="sourceLineNo">052</span>  }<a name="line.52"></a>
-<span class="sourceLineNo">053</span><a name="line.53"></a>
-<span class="sourceLineNo">054</span>  @Test<a name="line.54"></a>
-<span class="sourceLineNo">055</span>  public void testMetaHTDReplicaCount() throws Exception {<a name="line.55"></a>
-<span class="sourceLineNo">056</span>    assertEquals(3,<a name="line.56"></a>
-<span class="sourceLineNo">057</span>      TEST_UTIL.getAdmin().getDescriptor(TableName.META_TABLE_NAME).getRegionReplication());<a name="line.57"></a>
-<span class="sourceLineNo">058</span>  }<a name="line.58"></a>
-<span class="sourceLineNo">059</span><a name="line.59"></a>
-<span class="sourceLineNo">060</span>  @Test<a name="line.60"></a>
-<span class="sourceLineNo">061</span>  public void testZookeeperNodesForReplicas() throws Exception {<a name="line.61"></a>
-<span class="sourceLineNo">062</span>    // Checks all the znodes exist when meta's replicas are enabled<a name="line.62"></a>
-<span class="sourceLineNo">063</span>    ZKWatcher zkw = TEST_UTIL.getZooKeeperWatcher();<a name="line.63"></a>
-<span class="sourceLineNo">064</span>    Configuration conf = TEST_UTIL.getConfiguration();<a name="line.64"></a>
-<span class="sourceLineNo">065</span>    String baseZNode =<a name="line.65"></a>
-<span class="sourceLineNo">066</span>      conf.get(HConstants.ZOOKEEPER_ZNODE_PARENT, HConstants.DEFAULT_ZOOKEEPER_ZNODE_PARENT);<a name="line.66"></a>
-<span class="sourceLineNo">067</span>    String primaryMetaZnode =<a name="line.67"></a>
-<span class="sourceLineNo">068</span>      ZNodePaths.joinZNode(baseZNode, conf.get("zookeeper.znode.metaserver", "meta-region-server"));<a name="line.68"></a>
-<span class="sourceLineNo">069</span>    // check that the data in the znode is parseable (this would also mean the znode exists)<a name="line.69"></a>
-<span class="sourceLineNo">070</span>    byte[] data = ZKUtil.getData(zkw, primaryMetaZnode);<a name="line.70"></a>
-<span class="sourceLineNo">071</span>    ProtobufUtil.toServerName(data);<a name="line.71"></a>
-<span class="sourceLineNo">072</span>    for (int i = 1; i &lt; 3; i++) {<a name="line.72"></a>
-<span class="sourceLineNo">073</span>      String secZnode = ZNodePaths.joinZNode(baseZNode,<a name="line.73"></a>
-<span class="sourceLineNo">074</span>        conf.get("zookeeper.znode.metaserver", "meta-region-server") + "-" + i);<a name="line.74"></a>
-<span class="sourceLineNo">075</span>      String str = zkw.getZNodePaths().getZNodeForReplica(i);<a name="line.75"></a>
-<span class="sourceLineNo">076</span>      assertTrue(str.equals(secZnode));<a name="line.76"></a>
-<span class="sourceLineNo">077</span>      // check that the data in the znode is parseable (this would also mean the znode exists)<a name="line.77"></a>
-<span class="sourceLineNo">078</span>      data = ZKUtil.getData(zkw, secZnode);<a name="line.78"></a>
-<span class="sourceLineNo">079</span>      ProtobufUtil.toServerName(data);<a name="line.79"></a>
-<span class="sourceLineNo">080</span>    }<a name="line.80"></a>
-<span class="sourceLineNo">081</span>  }<a name="line.81"></a>
-<span class="sourceLineNo">082</span><a name="line.82"></a>
-<span class="sourceLineNo">083</span>  @Test<a name="line.83"></a>
-<span class="sourceLineNo">084</span>  public void testAccessingUnknownTables() throws Exception {<a name="line.84"></a>
-<span class="sourceLineNo">085</span>    Configuration conf = new Configuration(TEST_UTIL.getConfiguration());<a name="line.85"></a>
-<span class="sourceLineNo">086</span>    conf.setBoolean(HConstants.USE_META_REPLICAS, true);<a name="line.86"></a>
-<span class="sourceLineNo">087</span>    Table table = TEST_UTIL.getConnection().getTable(name.getTableName());<a name="line.87"></a>
-<span class="sourceLineNo">088</span>    Get get = new Get(Bytes.toBytes("foo"));<a name="line.88"></a>
-<span class="sourceLineNo">089</span>    assertThrows(TableNotFoundException.class, () -&gt; table.get(get));<a name="line.89"></a>
-<span class="sourceLineNo">090</span>  }<a name="line.90"></a>
-<span class="sourceLineNo">091</span>}<a name="line.91"></a>
+<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.42"></a>
+<span class="sourceLineNo">043</span><a name="line.43"></a>
+<span class="sourceLineNo">044</span>@Category({ MiscTests.class, MediumTests.class })<a name="line.44"></a>
+<span class="sourceLineNo">045</span>public class TestMetaWithReplicasBasic extends MetaWithReplicasTestBase {<a name="line.45"></a>
+<span class="sourceLineNo">046</span><a name="line.46"></a>
+<span class="sourceLineNo">047</span>  @ClassRule<a name="line.47"></a>
+<span class="sourceLineNo">048</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.48"></a>
+<span class="sourceLineNo">049</span>    HBaseClassTestRule.forClass(TestMetaWithReplicasBasic.class);<a name="line.49"></a>
+<span class="sourceLineNo">050</span><a name="line.50"></a>
+<span class="sourceLineNo">051</span>  @BeforeClass<a name="line.51"></a>
+<span class="sourceLineNo">052</span>  public static void setUp() throws Exception {<a name="line.52"></a>
+<span class="sourceLineNo">053</span>    startCluster();<a name="line.53"></a>
+<span class="sourceLineNo">054</span>  }<a name="line.54"></a>
+<span class="sourceLineNo">055</span><a name="line.55"></a>
+<span class="sourceLineNo">056</span>  @Test<a name="line.56"></a>
+<span class="sourceLineNo">057</span>  public void testMetaHTDReplicaCount() throws Exception {<a name="line.57"></a>
+<span class="sourceLineNo">058</span>    assertEquals(3,<a name="line.58"></a>
+<span class="sourceLineNo">059</span>      TEST_UTIL.getAdmin().getDescriptor(TableName.META_TABLE_NAME).getRegionReplication());<a name="line.59"></a>
+<span class="sourceLineNo">060</span>  }<a name="line.60"></a>
+<span class="sourceLineNo">061</span><a name="line.61"></a>
+<span class="sourceLineNo">062</span>  @Test<a name="line.62"></a>
+<span class="sourceLineNo">063</span>  public void testZookeeperNodesForReplicas() throws Exception {<a name="line.63"></a>
+<span class="sourceLineNo">064</span>    // Checks all the znodes exist when meta's replicas are enabled<a name="line.64"></a>
+<span class="sourceLineNo">065</span>    ZKWatcher zkw = TEST_UTIL.getZooKeeperWatcher();<a name="line.65"></a>
+<span class="sourceLineNo">066</span>    Configuration conf = TEST_UTIL.getConfiguration();<a name="line.66"></a>
+<span class="sourceLineNo">067</span>    String baseZNode =<a name="line.67"></a>
+<span class="sourceLineNo">068</span>      conf.get(HConstants.ZOOKEEPER_ZNODE_PARENT, HConstants.DEFAULT_ZOOKEEPER_ZNODE_PARENT);<a name="line.68"></a>
+<span class="sourceLineNo">069</span>    String primaryMetaZnode =<a name="line.69"></a>
+<span class="sourceLineNo">070</span>      ZNodePaths.joinZNode(baseZNode, conf.get("zookeeper.znode.metaserver", "meta-region-server"));<a name="line.70"></a>
+<span class="sourceLineNo">071</span>    // check that the data in the znode is parseable (this would also mean the znode exists)<a name="line.71"></a>
+<span class="sourceLineNo">072</span>    byte[] data = ZKUtil.getData(zkw, primaryMetaZnode);<a name="line.72"></a>
+<span class="sourceLineNo">073</span>    ProtobufUtil.toServerName(data);<a name="line.73"></a>
+<span class="sourceLineNo">074</span>    for (int i = 1; i &lt; 3; i++) {<a name="line.74"></a>
+<span class="sourceLineNo">075</span>      String secZnode = ZNodePaths.joinZNode(baseZNode,<a name="line.75"></a>
+<span class="sourceLineNo">076</span>        conf.get("zookeeper.znode.metaserver", "meta-region-server") + "-" + i);<a name="line.76"></a>
+<span class="sourceLineNo">077</span>      String str = zkw.getZNodePaths().getZNodeForReplica(i);<a name="line.77"></a>
+<span class="sourceLineNo">078</span>      assertTrue(str.equals(secZnode));<a name="line.78"></a>
+<span class="sourceLineNo">079</span>      // check that the data in the znode is parseable (this would also mean the znode exists)<a name="line.79"></a>
+<span class="sourceLineNo">080</span>      data = ZKUtil.getData(zkw, secZnode);<a name="line.80"></a>
+<span class="sourceLineNo">081</span>      ProtobufUtil.toServerName(data);<a name="line.81"></a>
+<span class="sourceLineNo">082</span>    }<a name="line.82"></a>
+<span class="sourceLineNo">083</span>  }<a name="line.83"></a>
+<span class="sourceLineNo">084</span><a name="line.84"></a>
+<span class="sourceLineNo">085</span>  @Test<a name="line.85"></a>
+<span class="sourceLineNo">086</span>  public void testReplicaCleanup() throws Exception {<a name="line.86"></a>
+<span class="sourceLineNo">087</span>    ZKWatcher zkw = TEST_UTIL.getZooKeeperWatcher();<a name="line.87"></a>
+<span class="sourceLineNo">088</span>    List&lt;String&gt; metaReplicaZnodes = zkw.getMetaReplicaNodes();<a name="line.88"></a>
+<span class="sourceLineNo">089</span>    assertEquals(3, metaReplicaZnodes.size());<a name="line.89"></a>
+<span class="sourceLineNo">090</span><a name="line.90"></a>
+<span class="sourceLineNo">091</span>    final HMaster master = TEST_UTIL.getMiniHBaseCluster().getMaster();<a name="line.91"></a>
+<span class="sourceLineNo">092</span>    master.stop("Restarting");<a name="line.92"></a>
+<span class="sourceLineNo">093</span>    TEST_UTIL.waitFor(30000, () -&gt; master.isStopped());<a name="line.93"></a>
+<span class="sourceLineNo">094</span>    TEST_UTIL.getMiniHBaseCluster().getConfiguration().setInt(HConstants.META_REPLICAS_NUM, 1);<a name="line.94"></a>
+<span class="sourceLineNo">095</span><a name="line.95"></a>
+<span class="sourceLineNo">096</span>    JVMClusterUtil.MasterThread newMasterThread = TEST_UTIL.getMiniHBaseCluster().startMaster();<a name="line.96"></a>
+<span class="sourceLineNo">097</span>    final HMaster newMaster = newMasterThread.getMaster();<a name="line.97"></a>
+<span class="sourceLineNo">098</span><a name="line.98"></a>
+<span class="sourceLineNo">099</span>    //wait until new master finished meta replica assignment logic<a name="line.99"></a>
+<span class="sourceLineNo">100</span>    TEST_UTIL.waitFor(30000, () -&gt; newMaster.getMasterQuotaManager() != null);<a name="line.100"></a>
+<span class="sourceLineNo">101</span>    zkw = TEST_UTIL.getZooKeeperWatcher();<a name="line.101"></a>
+<span class="sourceLineNo">102</span>    metaReplicaZnodes = zkw.getMetaReplicaNodes();<a name="line.102"></a>
+<span class="sourceLineNo">103</span>    assertEquals(1, metaReplicaZnodes.size());<a name="line.103"></a>
+<span class="sourceLineNo">104</span><a name="line.104"></a>
+<span class="sourceLineNo">105</span>  }<a name="line.105"></a>
+<span class="sourceLineNo">106</span>  @Test<a name="line.106"></a>
+<span class="sourceLineNo">107</span>  public void testAccessingUnknownTables() throws Exception {<a name="line.107"></a>
+<span class="sourceLineNo">108</span>    Configuration conf = new Configuration(TEST_UTIL.getConfiguration());<a name="line.108"></a>
+<span class="sourceLineNo">109</span>    conf.setBoolean(HConstants.USE_META_REPLICAS, true);<a name="line.109"></a>
+<span class="sourceLineNo">110</span>    Table table = TEST_UTIL.getConnection().getTable(name.getTableName());<a name="line.110"></a>
+<span class="sourceLineNo">111</span>    Get get = new Get(Bytes.toBytes("foo"));<a name="line.111"></a>
+<span class="sourceLineNo">112</span>    assertThrows(TableNotFoundException.class, () -&gt; table.get(get));<a name="line.112"></a>
+<span class="sourceLineNo">113</span>  }<a name="line.113"></a>
+<span class="sourceLineNo">114</span>}<a name="line.114"></a>
 
 
 
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html
index 02d1311..93d7a02 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/rsgroup/TestRSGroupsAdmin1.html
@@ -27,522 +27,574 @@
 <span class="sourceLineNo">019</span><a name="line.19"></a>
 <span class="sourceLineNo">020</span>import static org.junit.Assert.assertEquals;<a name="line.20"></a>
 <span class="sourceLineNo">021</span>import static org.junit.Assert.assertFalse;<a name="line.21"></a>
-<span class="sourceLineNo">022</span>import static org.junit.Assert.assertNull;<a name="line.22"></a>
-<span class="sourceLineNo">023</span>import static org.junit.Assert.assertTrue;<a name="line.23"></a>
-<span class="sourceLineNo">024</span>import static org.junit.Assert.fail;<a name="line.24"></a>
-<span class="sourceLineNo">025</span><a name="line.25"></a>
-<span class="sourceLineNo">026</span>import java.io.IOException;<a name="line.26"></a>
-<span class="sourceLineNo">027</span>import java.util.List;<a name="line.27"></a>
-<span class="sourceLineNo">028</span>import java.util.Map;<a name="line.28"></a>
-<span class="sourceLineNo">029</span>import java.util.Set;<a name="line.29"></a>
-<span class="sourceLineNo">030</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.30"></a>
-<span class="sourceLineNo">031</span>import org.apache.hadoop.hbase.NamespaceDescriptor;<a name="line.31"></a>
-<span class="sourceLineNo">032</span>import org.apache.hadoop.hbase.ServerName;<a name="line.32"></a>
-<span class="sourceLineNo">033</span>import org.apache.hadoop.hbase.TableExistsException;<a name="line.33"></a>
-<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.TableName;<a name="line.34"></a>
-<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.TableNotFoundException;<a name="line.35"></a>
-<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.Waiter;<a name="line.36"></a>
-<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;<a name="line.37"></a>
-<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;<a name="line.38"></a>
-<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.client.TableDescriptor;<a name="line.39"></a>
-<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.client.TableDescriptorBuilder;<a name="line.40"></a>
-<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.constraint.ConstraintException;<a name="line.41"></a>
-<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.master.TableNamespaceManager;<a name="line.42"></a>
-<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.net.Address;<a name="line.43"></a>
-<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.testclassification.MediumTests;<a name="line.44"></a>
-<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.testclassification.RSGroupTests;<a name="line.45"></a>
-<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.46"></a>
-<span class="sourceLineNo">047</span>import org.junit.After;<a name="line.47"></a>
-<span class="sourceLineNo">048</span>import org.junit.AfterClass;<a name="line.48"></a>
-<span class="sourceLineNo">049</span>import org.junit.Before;<a name="line.49"></a>
-<span class="sourceLineNo">050</span>import org.junit.BeforeClass;<a name="line.50"></a>
-<span class="sourceLineNo">051</span>import org.junit.ClassRule;<a name="line.51"></a>
-<span class="sourceLineNo">052</span>import org.junit.Test;<a name="line.52"></a>
-<span class="sourceLineNo">053</span>import org.junit.experimental.categories.Category;<a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.slf4j.Logger;<a name="line.54"></a>
-<span class="sourceLineNo">055</span>import org.slf4j.LoggerFactory;<a name="line.55"></a>
-<span class="sourceLineNo">056</span><a name="line.56"></a>
-<span class="sourceLineNo">057</span>import org.apache.hbase.thirdparty.com.google.common.collect.Sets;<a name="line.57"></a>
-<span class="sourceLineNo">058</span><a name="line.58"></a>
-<span class="sourceLineNo">059</span>@Category({ RSGroupTests.class, MediumTests.class })<a name="line.59"></a>
-<span class="sourceLineNo">060</span>public class TestRSGroupsAdmin1 extends TestRSGroupsBase {<a name="line.60"></a>
-<span class="sourceLineNo">061</span><a name="line.61"></a>
-<span class="sourceLineNo">062</span>  @ClassRule<a name="line.62"></a>
-<span class="sourceLineNo">063</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.63"></a>
-<span class="sourceLineNo">064</span>    HBaseClassTestRule.forClass(TestRSGroupsAdmin1.class);<a name="line.64"></a>
-<span class="sourceLineNo">065</span><a name="line.65"></a>
-<span class="sourceLineNo">066</span>  private static final Logger LOG = LoggerFactory.getLogger(TestRSGroupsAdmin1.class);<a name="line.66"></a>
-<span class="sourceLineNo">067</span><a name="line.67"></a>
-<span class="sourceLineNo">068</span>  @BeforeClass<a name="line.68"></a>
-<span class="sourceLineNo">069</span>  public static void setUp() throws Exception {<a name="line.69"></a>
-<span class="sourceLineNo">070</span>    setUpTestBeforeClass();<a name="line.70"></a>
-<span class="sourceLineNo">071</span>  }<a name="line.71"></a>
-<span class="sourceLineNo">072</span><a name="line.72"></a>
-<span class="sourceLineNo">073</span>  @AfterClass<a name="line.73"></a>
-<span class="sourceLineNo">074</span>  public static void tearDown() throws Exception {<a name="line.74"></a>
-<span class="sourceLineNo">075</span>    tearDownAfterClass();<a name="line.75"></a>
-<span class="sourceLineNo">076</span>  }<a name="line.76"></a>
-<span class="sourceLineNo">077</span><a name="line.77"></a>
-<span class="sourceLineNo">078</span>  @Before<a name="line.78"></a>
-<span class="sourceLineNo">079</span>  public void beforeMethod() throws Exception {<a name="line.79"></a>
-<span class="sourceLineNo">080</span>    setUpBeforeMethod();<a name="line.80"></a>
-<span class="sourceLineNo">081</span>  }<a name="line.81"></a>
-<span class="sourceLineNo">082</span><a name="line.82"></a>
-<span class="sourceLineNo">083</span>  @After<a name="line.83"></a>
-<span class="sourceLineNo">084</span>  public void afterMethod() throws Exception {<a name="line.84"></a>
-<span class="sourceLineNo">085</span>    tearDownAfterMethod();<a name="line.85"></a>
-<span class="sourceLineNo">086</span>  }<a name="line.86"></a>
-<span class="sourceLineNo">087</span><a name="line.87"></a>
-<span class="sourceLineNo">088</span>  @Test<a name="line.88"></a>
-<span class="sourceLineNo">089</span>  public void testValidGroupNames() throws IOException {<a name="line.89"></a>
-<span class="sourceLineNo">090</span>    String[] badNames = { "foo*", "foo@", "-" };<a name="line.90"></a>
-<span class="sourceLineNo">091</span>    String[] goodNames = { "foo_123" };<a name="line.91"></a>
-<span class="sourceLineNo">092</span><a name="line.92"></a>
-<span class="sourceLineNo">093</span>    for (String entry : badNames) {<a name="line.93"></a>
-<span class="sourceLineNo">094</span>      try {<a name="line.94"></a>
-<span class="sourceLineNo">095</span>        ADMIN.addRSGroup(entry);<a name="line.95"></a>
-<span class="sourceLineNo">096</span>        fail("Expected a constraint exception for: " + entry);<a name="line.96"></a>
-<span class="sourceLineNo">097</span>      } catch (ConstraintException ex) {<a name="line.97"></a>
-<span class="sourceLineNo">098</span>        // expected<a name="line.98"></a>
-<span class="sourceLineNo">099</span>      }<a name="line.99"></a>
-<span class="sourceLineNo">100</span>    }<a name="line.100"></a>
-<span class="sourceLineNo">101</span><a name="line.101"></a>
-<span class="sourceLineNo">102</span>    for (String entry : goodNames) {<a name="line.102"></a>
-<span class="sourceLineNo">103</span>      ADMIN.addRSGroup(entry);<a name="line.103"></a>
-<span class="sourceLineNo">104</span>    }<a name="line.104"></a>
-<span class="sourceLineNo">105</span>  }<a name="line.105"></a>
-<span class="sourceLineNo">106</span><a name="line.106"></a>
-<span class="sourceLineNo">107</span>  @Test<a name="line.107"></a>
-<span class="sourceLineNo">108</span>  public void testBogusArgs() throws Exception {<a name="line.108"></a>
-<span class="sourceLineNo">109</span>    assertNull(ADMIN.getRSGroup(TableName.valueOf("nonexistent")));<a name="line.109"></a>
-<span class="sourceLineNo">110</span>    assertNull(ADMIN.getRSGroup(Address.fromParts("bogus", 123)));<a name="line.110"></a>
-<span class="sourceLineNo">111</span>    assertNull(ADMIN.getRSGroup("bogus"));<a name="line.111"></a>
-<span class="sourceLineNo">112</span><a name="line.112"></a>
-<span class="sourceLineNo">113</span>    try {<a name="line.113"></a>
-<span class="sourceLineNo">114</span>      ADMIN.removeRSGroup("bogus");<a name="line.114"></a>
-<span class="sourceLineNo">115</span>      fail("Expected removing bogus group to fail");<a name="line.115"></a>
-<span class="sourceLineNo">116</span>    } catch (ConstraintException ex) {<a name="line.116"></a>
-<span class="sourceLineNo">117</span>      // expected<a name="line.117"></a>
-<span class="sourceLineNo">118</span>    }<a name="line.118"></a>
-<span class="sourceLineNo">119</span><a name="line.119"></a>
-<span class="sourceLineNo">120</span>    try {<a name="line.120"></a>
-<span class="sourceLineNo">121</span>      ADMIN.setRSGroup(Sets.newHashSet(TableName.valueOf("bogustable")), "bogus");<a name="line.121"></a>
-<span class="sourceLineNo">122</span>      fail("Expected set table to bogus group fail");<a name="line.122"></a>
-<span class="sourceLineNo">123</span>    } catch (ConstraintException | TableNotFoundException ex) {<a name="line.123"></a>
-<span class="sourceLineNo">124</span>      // expected<a name="line.124"></a>
-<span class="sourceLineNo">125</span>    }<a name="line.125"></a>
-<span class="sourceLineNo">126</span><a name="line.126"></a>
-<span class="sourceLineNo">127</span>    try {<a name="line.127"></a>
-<span class="sourceLineNo">128</span>      ADMIN.moveServersToRSGroup(Sets.newHashSet(Address.fromParts("bogus", 123)), "bogus");<a name="line.128"></a>
-<span class="sourceLineNo">129</span>      fail("Expected move with bogus group to fail");<a name="line.129"></a>
-<span class="sourceLineNo">130</span>    } catch (ConstraintException ex) {<a name="line.130"></a>
-<span class="sourceLineNo">131</span>      // expected<a name="line.131"></a>
-<span class="sourceLineNo">132</span>    }<a name="line.132"></a>
-<span class="sourceLineNo">133</span><a name="line.133"></a>
-<span class="sourceLineNo">134</span>    try {<a name="line.134"></a>
-<span class="sourceLineNo">135</span>      ADMIN.balancerSwitch(true, true);<a name="line.135"></a>
-<span class="sourceLineNo">136</span>      ADMIN.balanceRSGroup("bogus");<a name="line.136"></a>
-<span class="sourceLineNo">137</span>      ADMIN.balancerSwitch(false, true);<a name="line.137"></a>
-<span class="sourceLineNo">138</span>      fail("Expected move with bogus group to fail");<a name="line.138"></a>
-<span class="sourceLineNo">139</span>    } catch (ConstraintException ex) {<a name="line.139"></a>
-<span class="sourceLineNo">140</span>      // expected<a name="line.140"></a>
-<span class="sourceLineNo">141</span>    }<a name="line.141"></a>
-<span class="sourceLineNo">142</span>  }<a name="line.142"></a>
-<span class="sourceLineNo">143</span><a name="line.143"></a>
-<span class="sourceLineNo">144</span>  @Test<a name="line.144"></a>
-<span class="sourceLineNo">145</span>  public void testNamespaceConstraint() throws Exception {<a name="line.145"></a>
-<span class="sourceLineNo">146</span>    String nsName = TABLE_PREFIX + "_foo";<a name="line.146"></a>
-<span class="sourceLineNo">147</span>    String groupName = TABLE_PREFIX + "_foo";<a name="line.147"></a>
-<span class="sourceLineNo">148</span>    LOG.info("testNamespaceConstraint");<a name="line.148"></a>
-<span class="sourceLineNo">149</span>    addGroup(groupName, 1);<a name="line.149"></a>
-<span class="sourceLineNo">150</span>    assertTrue(OBSERVER.preAddRSGroupCalled);<a name="line.150"></a>
-<span class="sourceLineNo">151</span>    assertTrue(OBSERVER.postAddRSGroupCalled);<a name="line.151"></a>
-<span class="sourceLineNo">152</span><a name="line.152"></a>
-<span class="sourceLineNo">153</span>    ADMIN.createNamespace(NamespaceDescriptor.create(nsName)<a name="line.153"></a>
-<span class="sourceLineNo">154</span>      .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName).build());<a name="line.154"></a>
-<span class="sourceLineNo">155</span>    RSGroupInfo rsGroupInfo = ADMIN.getRSGroup(groupName);<a name="line.155"></a>
-<span class="sourceLineNo">156</span>    ADMIN.moveServersToRSGroup(rsGroupInfo.getServers(), RSGroupInfo.DEFAULT_GROUP);<a name="line.156"></a>
-<span class="sourceLineNo">157</span>    // test removing a referenced group<a name="line.157"></a>
-<span class="sourceLineNo">158</span>    try {<a name="line.158"></a>
-<span class="sourceLineNo">159</span>      ADMIN.removeRSGroup(groupName);<a name="line.159"></a>
-<span class="sourceLineNo">160</span>      fail("Expected a constraint exception");<a name="line.160"></a>
-<span class="sourceLineNo">161</span>    } catch (IOException ex) {<a name="line.161"></a>
-<span class="sourceLineNo">162</span>    }<a name="line.162"></a>
-<span class="sourceLineNo">163</span>    // test modify group<a name="line.163"></a>
-<span class="sourceLineNo">164</span>    // changing with the same name is fine<a name="line.164"></a>
-<span class="sourceLineNo">165</span>    ADMIN.modifyNamespace(NamespaceDescriptor.create(nsName)<a name="line.165"></a>
-<span class="sourceLineNo">166</span>      .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName).build());<a name="line.166"></a>
-<span class="sourceLineNo">167</span>    String anotherGroup = TABLE_PREFIX + "_anotherGroup";<a name="line.167"></a>
-<span class="sourceLineNo">168</span>    ADMIN.addRSGroup(anotherGroup);<a name="line.168"></a>
-<span class="sourceLineNo">169</span>    // test add non-existent group<a name="line.169"></a>
-<span class="sourceLineNo">170</span>    ADMIN.deleteNamespace(nsName);<a name="line.170"></a>
-<span class="sourceLineNo">171</span>    ADMIN.removeRSGroup(groupName);<a name="line.171"></a>
-<span class="sourceLineNo">172</span>    assertTrue(OBSERVER.preRemoveRSGroupCalled);<a name="line.172"></a>
-<span class="sourceLineNo">173</span>    assertTrue(OBSERVER.postRemoveRSGroupCalled);<a name="line.173"></a>
-<span class="sourceLineNo">174</span>    try {<a name="line.174"></a>
-<span class="sourceLineNo">175</span>      ADMIN.createNamespace(NamespaceDescriptor.create(nsName)<a name="line.175"></a>
-<span class="sourceLineNo">176</span>        .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, "foo").build());<a name="line.176"></a>
-<span class="sourceLineNo">177</span>      fail("Expected a constraint exception");<a name="line.177"></a>
-<span class="sourceLineNo">178</span>    } catch (IOException ex) {<a name="line.178"></a>
-<span class="sourceLineNo">179</span>    }<a name="line.179"></a>
-<span class="sourceLineNo">180</span>  }<a name="line.180"></a>
-<span class="sourceLineNo">181</span><a name="line.181"></a>
-<span class="sourceLineNo">182</span>  @Test<a name="line.182"></a>
-<span class="sourceLineNo">183</span>  public void testNamespaceConstraint2() throws Exception {<a name="line.183"></a>
-<span class="sourceLineNo">184</span>    String nsName = TABLE_PREFIX + name.getMethodName();<a name="line.184"></a>
-<span class="sourceLineNo">185</span>    String groupName = TABLE_PREFIX + name.getMethodName();<a name="line.185"></a>
-<span class="sourceLineNo">186</span>    TableName tableName = TableName.valueOf(nsName, name.getMethodName());<a name="line.186"></a>
-<span class="sourceLineNo">187</span>    addGroup(groupName, 1);<a name="line.187"></a>
-<span class="sourceLineNo">188</span><a name="line.188"></a>
-<span class="sourceLineNo">189</span>    ADMIN.createNamespace(NamespaceDescriptor.create(nsName)<a name="line.189"></a>
-<span class="sourceLineNo">190</span>        .addConfiguration(RSGroupInfo.NAMESPACE_DESC_PROP_GROUP, groupName).build());<a name="line.190"></a>
-<span class="sourceLineNo">191</span><a name="line.191"></a>
-<span class="sourceLineNo">192</span>    TEST_UTIL.createTable(tableName, "C");<a name="line.192"></a>
-<span class="sourceLineNo">193</span>    TEST_UTIL.waitTableAvailable(tableName);<a name="line.193"></a>
-<span class="sourceLineNo">194</span>    RSGroupInfo rsGroup = ADMIN.getRSGroup(tableName);<a name="line.194"></a>
-<span class="sourceLineNo">195</span>    assertEquals(groupName, rsGroup.getName());<a name="line.195"></a>
-<span class="sourceLineNo">196</span><a name="line.196"></a>
-<span class="sourceLineNo">197</span>    TEST_UTIL.deleteTable(tableName);<a name="line.197"></a>
-<span class="sourceLineNo">198</span>    ADMIN.deleteNamespace(nsName);<a name="line.198"></a>
-<span class="sourceLineNo">199</span><a name="line.199"></a>
-<span class="sourceLineNo">200</span>    ADMIN.moveServersToRSGroup(rsGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);<a name="line.200"></a>
-<span class="sourceLineNo">201</span>    ADMIN.removeRSGroup(groupName);<a name="line.201"></a>
-<span class="sourceLineNo">202</span>  }<a name="line.202"></a>
-<span class="sourceLineNo">203</span><a name="line.203"></a>
-<span class="sourceLineNo">204</span>  @Test<a name="line.204"></a>
-<span class="sourceLineNo">205</span>  public void testFailRemoveGroup() throws IOException, InterruptedException {<a name="line.205"></a>
-<span class="sourceLineNo">206</span>    int initNumGroups = ADMIN.listRSGroups().size();<a name="line.206"></a>
-<span class="sourceLineNo">207</span>    addGroup("bar", 3);<a name="line.207"></a>
-<span class="sourceLineNo">208</span>    TEST_UTIL.createTable(tableName, Bytes.toBytes("f"));<a name="line.208"></a>
-<span class="sourceLineNo">209</span>    ADMIN.setRSGroup(Sets.newHashSet(tableName), "bar");<a name="line.209"></a>
-<span class="sourceLineNo">210</span>    RSGroupInfo barGroup = ADMIN.getRSGroup("bar");<a name="line.210"></a>
-<span class="sourceLineNo">211</span>    // group is not empty therefore it should fail<a name="line.211"></a>
-<span class="sourceLineNo">212</span>    try {<a name="line.212"></a>
-<span class="sourceLineNo">213</span>      ADMIN.removeRSGroup(barGroup.getName());<a name="line.213"></a>
-<span class="sourceLineNo">214</span>      fail("Expected remove group to fail");<a name="line.214"></a>
-<span class="sourceLineNo">215</span>    } catch (IOException e) {<a name="line.215"></a>
-<span class="sourceLineNo">216</span>    }<a name="line.216"></a>
-<span class="sourceLineNo">217</span>    // group cannot lose all it's servers therefore it should fail<a name="line.217"></a>
-<span class="sourceLineNo">218</span>    try {<a name="line.218"></a>
-<span class="sourceLineNo">219</span>      ADMIN.moveServersToRSGroup(barGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);<a name="line.219"></a>
-<span class="sourceLineNo">220</span>      fail("Expected move servers to fail");<a name="line.220"></a>
-<span class="sourceLineNo">221</span>    } catch (IOException e) {<a name="line.221"></a>
-<span class="sourceLineNo">222</span>    }<a name="line.222"></a>
-<span class="sourceLineNo">223</span><a name="line.223"></a>
-<span class="sourceLineNo">224</span>    ADMIN.setRSGroup(Sets.newHashSet(ADMIN.listTablesInRSGroup("bar")), RSGroupInfo.DEFAULT_GROUP);<a name="line.224"></a>
-<span class="sourceLineNo">225</span>    try {<a name="line.225"></a>
-<span class="sourceLineNo">226</span>      ADMIN.removeRSGroup(barGroup.getName());<a name="line.226"></a>
-<span class="sourceLineNo">227</span>      fail("Expected move servers to fail");<a name="line.227"></a>
-<span class="sourceLineNo">228</span>    } catch (IOException e) {<a name="line.228"></a>
-<span class="sourceLineNo">229</span>    }<a name="line.229"></a>
-<span class="sourceLineNo">230</span><a name="line.230"></a>
-<span class="sourceLineNo">231</span>    ADMIN.moveServersToRSGroup(barGroup.getServers(), RSGroupInfo.DEFAULT_GROUP);<a name="line.231"></a>
-<span class="sourceLineNo">232</span>    ADMIN.removeRSGroup(barGroup.getName());<a name="line.232"></a>
-<span class="sourceLineNo">233</span><a name="line.233"></a>
-<span class="sourceLineNo">234</span>    assertEquals(initNumGroups, ADMIN.listRSGroups().size());<a name="line.234"></a>
-<span class="sourceLineNo">235</span>  }<a name="line.235"></a>
-<span class="sourceLineNo">236</span><a name="line.236"></a>
-<span class="sourceLineNo">237</span>  @Test<a name="line.237"></a>
-<span class="sourceLineNo">238</span>  public void testMultiTableMove() throws Exception {<a name="line.238"></a>
-<span class="sourceLineNo">239</span>    final TableName tableNameA =<a name="line.239"></a>
-<span class="sourceLineNo">240</span>      TableName.valueOf(TABLE_PREFIX + getNameWithoutIndex(name.getMethodName()) + "A");<a name="line.240"></a>
-<span class="sourceLineNo">241</span>    final TableName tableNameB =<a name="line.241"></a>
-<span class="sourceLineNo">242</span>      TableName.valueOf(TABLE_PREFIX + getNameWithoutIndex(name.getMethodName()) + "B");<a name="line.242"></a>
-<span class="sourceLineNo">243</span>    final byte[] familyNameBytes = Bytes.toBytes("f");<a name="line.243"></a>
-<span class="sourceLineNo">244</span>    String newGroupName = getGroupName(getNameWithoutIndex(name.getMethodName()));<a name="line.244"></a>
-<span class="sourceLineNo">245</span>    final RSGroupInfo newGroup = addGroup(newGroupName, 1);<a name="line.245"></a>
-<span class="sourceLineNo">246</span><a name="line.246"></a>
-<span class="sourceLineNo">247</span>    TEST_UTIL.createTable(tableNameA, familyNameBytes);<a name="line.247"></a>
-<span class="sourceLineNo">248</span>    TEST_UTIL.createTable(tableNameB, familyNameBytes);<a name="line.248"></a>
-<span class="sourceLineNo">249</span>    TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate&lt;Exception&gt;() {<a name="line.249"></a>
-<span class="sourceLineNo">250</span>      @Override<a name="line.250"></a>
-<span class="sourceLineNo">251</span>      public boolean evaluate() throws Exception {<a name="line.251"></a>
-<span class="sourceLineNo">252</span>        List&lt;String&gt; regionsA = getTableRegionMap().get(tableNameA);<a name="line.252"></a>
-<span class="sourceLineNo">253</span>        if (regionsA == null) {<a name="line.253"></a>
-<span class="sourceLineNo">254</span>          return false;<a name="line.254"></a>
-<span class="sourceLineNo">255</span>        }<a name="line.255"></a>
-<span class="sourceLineNo">256</span>        List&lt;String&gt; regionsB = getTableRegionMap().get(tableNameB);<a name="line.256"></a>
-<span class="sourceLineNo">257</span>        if (regionsB == null) {<a name="line.257"></a>
-<span class="sourceLineNo">258</span>          return false;<a name="line.258"></a>
-<span class="sourceLineNo">259</span>        }<a name="line.259"></a>
-<span class="sourceLineNo">260</span>        return getTableRegionMap().get(tableNameA).size() &gt;= 1 &amp;&amp;<a name="line.260"></a>
-<span class="sourceLineNo">261</span>          getTableRegionMap().get(tableNameB).size() &gt;= 1;<a name="line.261"></a>
-<span class="sourceLineNo">262</span>      }<a name="line.262"></a>
-<span class="sourceLineNo">263</span>    });<a name="line.263"></a>
-<span class="sourceLineNo">264</span><a name="line.264"></a>
-<span class="sourceLineNo">265</span>    RSGroupInfo tableGrpA = ADMIN.getRSGroup(tableNameA);<a name="line.265"></a>
-<span class="sourceLineNo">266</span>    assertTrue(tableGrpA.getName().equals(RSGroupInfo.DEFAULT_GROUP));<a name="line.266"></a>
-<span class="sourceLineNo">267</span><a name="line.267"></a>
-<span class="sourceLineNo">268</span>    RSGroupInfo tableGrpB = ADMIN.getRSGroup(tableNameB);<a name="line.268"></a>
-<span class="sourceLineNo">269</span>    assertTrue(tableGrpB.getName().equals(RSGroupInfo.DEFAULT_GROUP));<a name="line.269"></a>
-<span class="sourceLineNo">270</span>    // change table's group<a name="line.270"></a>
-<span class="sourceLineNo">271</span>    LOG.info("Moving table [" + tableNameA + "," + tableNameB + "] to " + newGroup.getName());<a name="line.271"></a>
-<span class="sourceLineNo">272</span>    ADMIN.setRSGroup(Sets.newHashSet(tableNameA, tableNameB), newGroup.getName());<a name="line.272"></a>
-<span class="sourceLineNo">273</span><a name="line.273"></a>
-<span class="sourceLineNo">274</span>    // verify group change<a name="line.274"></a>
-<span class="sourceLineNo">275</span>    assertEquals(newGroup.getName(), ADMIN.getRSGroup(tableNameA).getName());<a name="line.275"></a>
-<span class="sourceLineNo">276</span><a name="line.276"></a>
-<span class="sourceLineNo">277</span>    assertEquals(newGroup.getName(), ADMIN.getRSGroup(tableNameB).getName());<a name="line.277"></a>
-<span class="sourceLineNo">278</span><a name="line.278"></a>
-<span class="sourceLineNo">279</span>    // verify tables' not exist in old group<a name="line.279"></a>
-<span class="sourceLineNo">280</span>    Set&lt;TableName&gt; defaultTables =<a name="line.280"></a>
-<span class="sourceLineNo">281</span>      Sets.newHashSet(ADMIN.listTablesInRSGroup(RSGroupInfo.DEFAULT_GROUP));<a name="line.281"></a>
-<span class="sourceLineNo">282</span>    assertFalse(defaultTables.contains(tableNameA));<a name="line.282"></a>
-<span class="sourceLineNo">283</span>    assertFalse(defaultTables.contains(tableNameB));<a name="line.283"></a>
-<span class="sourceLineNo">284</span><a name="line.284"></a>
-<span class="sourceLineNo">285</span>    // verify tables' exist in new group<a name="line.285"></a>
-<span class="sourceLineNo">286</span>    Set&lt;TableName&gt; newGroupTables = Sets.newHashSet(ADMIN.listTablesInRSGroup(newGroupName));<a name="line.286"></a>
-<span class="sourceLineNo">287</span>    assertTrue(newGroupTables.contains(tableNameA));<a name="line.287"></a>
-<span class="sourceLineNo">288</span>    assertTrue(newGroupTables.contains(tableNameB));<a name="line.288"></a>
-<span class="sourceLineNo">289</span>  }<a name="line.289"></a>
-<span class="sourceLineNo">290</span><a name="line.290"></a>
-<span class="sourceLineNo">291</span>  @Test<a name="line.291"></a>
-<span class="sourceLineNo">292</span>  public void testTableMoveTruncateAndDrop() throws Exception {<a name="line.292"></a>
-<span class="sourceLineNo">293</span>    final byte[] familyNameBytes = Bytes.toBytes("f");<a name="line.293"></a>
-<span class="sourceLineNo">294</span>    String newGroupName = getGroupName(getNameWithoutIndex(name.getMethodName()));<a name="line.294"></a>
-<span class="sourceLineNo">295</span>    final RSGroupInfo newGroup = addGroup(newGroupName, 2);<a name="line.295"></a>
-<span class="sourceLineNo">296</span><a name="line.296"></a>
-<span class="sourceLineNo">297</span>    TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 5);<a name="line.297"></a>
-<span class="sourceLineNo">298</span>    TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate&lt;Exception&gt;() {<a name="line.298"></a>
-<span class="sourceLineNo">299</span>      @Override<a name="line.299"></a>
-<span class="sourceLineNo">300</span>      public boolean evaluate() throws Exception {<a name="line.300"></a>
-<span class="sourceLineNo">301</span>        List&lt;String&gt; regions = getTableRegionMap().get(tableName);<a name="line.301"></a>
-<span class="sourceLineNo">302</span>        if (regions == null) {<a name="line.302"></a>
-<span class="sourceLineNo">303</span>          return false;<a name="line.303"></a>
-<span class="sourceLineNo">304</span>        }<a name="line.304"></a>
-<span class="sourceLineNo">305</span><a name="line.305"></a>
-<span class="sourceLineNo">306</span>        return getTableRegionMap().get(tableName).size() &gt;= 5;<a name="line.306"></a>
-<span class="sourceLineNo">307</span>      }<a name="line.307"></a>
-<span class="sourceLineNo">308</span>    });<a name="line.308"></a>
-<span class="sourceLineNo">309</span><a name="line.309"></a>
-<span class="sourceLineNo">310</span>    RSGroupInfo tableGrp = ADMIN.getRSGroup(tableName);<a name="line.310"></a>
-<span class="sourceLineNo">311</span>    LOG.info("got table group info is {}", tableGrp);<a name="line.311"></a>
-<span class="sourceLineNo">312</span>    assertTrue(tableGrp.getName().equals(RSGroupInfo.DEFAULT_GROUP));<a name="line.312"></a>
-<span class="sourceLineNo">313</span><a name="line.313"></a>
-<span class="sourceLineNo">314</span>    // change table's group<a name="line.314"></a>
-<span class="sourceLineNo">315</span>    LOG.info("Moving table " + tableName + " to " + newGroup.getName());<a name="line.315"></a>
-<span class="sourceLineNo">316</span>    ADMIN.setRSGroup(Sets.newHashSet(tableName), newGroup.getName());<a name="line.316"></a>
-<span class="sourceLineNo">317</span><a name="line.317"></a>
-<span class="sourceLineNo">318</span>    // verify group change<a name="line.318"></a>
-<span class="sourceLineNo">319</span>    assertEquals(newGroup.getName(), ADMIN.getRSGroup(tableName).getName());<a name="line.319"></a>
-<span class="sourceLineNo">320</span><a name="line.320"></a>
-<span class="sourceLineNo">321</span>    TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate&lt;Exception&gt;() {<a name="line.321"></a>
-<span class="sourceLineNo">322</span>      @Override<a name="line.322"></a>
-<span class="sourceLineNo">323</span>      public boolean evaluate() throws Exception {<a name="line.323"></a>
-<span class="sourceLineNo">324</span>        Map&lt;ServerName, List&lt;String&gt;&gt; serverMap = getTableServerRegionMap().get(tableName);<a name="line.324"></a>
-<span class="sourceLineNo">325</span>        int count = 0;<a name="line.325"></a>
-<span class="sourceLineNo">326</span>        if (serverMap != null) {<a name="line.326"></a>
-<span class="sourceLineNo">327</span>          for (ServerName rs : serverMap.keySet()) {<a name="line.327"></a>
-<span class="sourceLineNo">328</span>            if (newGroup.containsServer(rs.getAddress())) {<a name="line.328"></a>
-<span class="sourceLineNo">329</span>              count += serverMap.get(rs).size();<a name="line.329"></a>
-<span class="sourceLineNo">330</span>            }<a name="line.330"></a>
-<span class="sourceLineNo">331</span>          }<a name="line.331"></a>
-<span class="sourceLineNo">332</span>        }<a name="line.332"></a>
-<span class="sourceLineNo">333</span>        return count == 5;<a name="line.333"></a>
-<span class="sourceLineNo">334</span>      }<a name="line.334"></a>
-<span class="sourceLineNo">335</span>    });<a name="line.335"></a>
-<span class="sourceLineNo">336</span><a name="line.336"></a>
-<span class="sourceLineNo">337</span>    // test truncate<a name="line.337"></a>
-<span class="sourceLineNo">338</span>    ADMIN.disableTable(tableName);<a name="line.338"></a>
-<span class="sourceLineNo">339</span>    ADMIN.truncateTable(tableName, true);<a name="line.339"></a>
-<span class="sourceLineNo">340</span>    List&lt;TableName&gt; tablesInGroup = ADMIN.listTablesInRSGroup(newGroup.getName());<a name="line.340"></a>
-<span class="sourceLineNo">341</span>    assertEquals(1, tablesInGroup.size());<a name="line.341"></a>
-<span class="sourceLineNo">342</span>    assertEquals(tableName, tablesInGroup.get(0));<a name="line.342"></a>
-<span class="sourceLineNo">343</span><a name="line.343"></a>
-<span class="sourceLineNo">344</span>    // verify removed table is removed from group<a name="line.344"></a>
-<span class="sourceLineNo">345</span>    TEST_UTIL.deleteTable(tableName);<a name="line.345"></a>
-<span class="sourceLineNo">346</span>    assertEquals(0, ADMIN.listTablesInRSGroup(newGroup.getName()).size());<a name="line.346"></a>
-<span class="sourceLineNo">347</span>  }<a name="line.347"></a>
-<span class="sourceLineNo">348</span><a name="line.348"></a>
-<span class="sourceLineNo">349</span>  @Test<a name="line.349"></a>
-<span class="sourceLineNo">350</span>  public void testDisabledTableMove() throws Exception {<a name="line.350"></a>
-<span class="sourceLineNo">351</span>    final byte[] familyNameBytes = Bytes.toBytes("f");<a name="line.351"></a>
-<span class="sourceLineNo">352</span>    String newGroupName = getGroupName(getNameWithoutIndex(name.getMethodName()));<a name="line.352"></a>
-<span class="sourceLineNo">353</span>    final RSGroupInfo newGroup = addGroup(newGroupName, 2);<a name="line.353"></a>
-<span class="sourceLineNo">354</span><a name="line.354"></a>
-<span class="sourceLineNo">355</span>    TEST_UTIL.createMultiRegionTable(tableName, familyNameBytes, 5);<a name="line.355"></a>
-<span class="sourceLineNo">356</span>    TEST_UTIL.waitFor(WAIT_TIMEOUT, new Waiter.Predicate&lt;Exception&gt;() {<a name="line.356"></a>
-<span class="sourceLineNo">357</span>      @Override<a name="line.357"></a>
-<span class="sourceLineNo">358</span>      public boolean evaluate() throws Exception {<a name="line.358"></a>
-<span class="sourceLineNo">359</span>        List&lt;String&gt; regions = getTableRegionMap().get(tableName);<a name="line.359"></a>
-<span class="sourceLineNo">360</span>        if (regions == null) {<a name="line.360"></a>
-<span class="sourceLineNo">361</span>          return false;<a name="line.361"></a>
-<span class="sourceLineNo">362</span>        }<a name="line.362"></a>
-<span class="sourceLineNo">363</span>        return getTableRegionMap().get(tableName).size() &gt;= 5;<a name="line.363"></a>
-<span class="sourceLineNo">364</span>      }<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    });<a name="line.365"></a>
-<span class="sourceLineNo">366</span><a name="line.366"></a>
-<span class="sourceLineNo">367</span>    RSGroupInfo tableGrp = ADMIN.getRSGroup(tableName);<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    assertTrue(tableGrp.getName().equals(RSGroupInfo.DEFAULT_GROUP));<a name="line.368"></a>
-<span class="sourceLineNo">369</span><a name="line.369"></a>
-<span class="sourceLineNo">370</span>    // test disable table<a name="line.370"></a>
-<span class="sourceLineNo">371</span>    ADMIN.disableTable(tableName);<a name="line.371"></a>
-<span class="sourceLineNo">372</span><a name="line.372"></a>
-<span class="sourceLineNo">373</span>    // change table's group<a name="line.373"></a>
-<span class="sourceLineNo">374</span>    LOG.info("Moving table " + tableName + " to " + newGroup.getName());<a name="line.374"></a>
-<span class="sourceLineNo">375</span>    ADMIN.setRSGroup(Sets.newHashSet(tableName), newGroup.getName());<a name="line.375"></a>
-<span class="sourceLineNo">376</span><a name="line.376"></a>
-<span class="sourceLineNo">377</span>    // verify group change<a name="line.377"></a>
-<span class="sourceLineNo">378</span>    assertEquals(newGroup.getName(), ADMIN.getRSGroup(tableName).getName());<a name="line.378"></a>
-<span class="sourceLineNo">379</span>  }<a name="line.379"></a>
-<span class="sourceLineNo">380</span><a name="line.380"></a>
-<span class="sourceLineNo">381</span>  @Test<a name="line.381"></a>
-<span class="sourceLineNo">382</span>  public void testNonExistentTableMove() throws Exception {<a name="line.382"></a>
-<span class="sourceLineNo">383</span>    TableName tableName =<a name="line.383"></a>
-<span class="sourceLineNo">384</span>      TableName.valueOf(TABLE_PREFIX + getNameWithoutIndex(name.getMethodName()));<a name="line.384"></a>
-<span class="sourceLineNo">385</span>    RSGroupInfo tableGrp = ADMIN.getRSGroup(tableName);<a name="line.385"></a>
-<span class="sourceLineNo">386</span>    assertNull(tableGrp);<a name="line.386"></a>
-<span class="sourceLineNo">387</span><a name="line.387"></a>
-<span class="sourceLineNo">388</span>    // test if table exists already.<a name="line.388"></a>
-<span class="sourceLineNo">389</span>    boolean exist = ADMIN.tableExists(tableName);<a name="line.389"></a>
-<span class="sourceLineNo">390</span>    assertFalse(exist);<a name="line.390"></a>
-<span class="sourceLineNo">391</span><a name="line.391"></a>
-<span class="sourceLineNo">392</span>    LOG.info("Moving table " + tableName + " to " + RSGroupInfo.DEFAULT_GROUP);<a name="line.392"></a>
-<span class="sourceLineNo">393</span>    try {<a name="line.393"></a>
-<span class="sourceLineNo">394</span>      ADMIN.setRSGroup(Sets.newHashSet(tableName), RSGroupInfo.DEFAULT_GROUP);<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      fail("Table " + tableName + " shouldn't have been successfully moved.");<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    } catch (IOException ex) {<a name="line.396"></a>
-<span class="sourceLineNo">397</span>      assertTrue(ex instanceof TableNotFoundException);<a name="line.397"></a>
-<span class="sourceLineNo">398</span>    }<a name="line.398"></a>
-<span class="sourceLineNo">399</span><a name="line.399"></a>
-<span class="sourceLineNo">400</span>    try {<a name="line.400"></a>
-<span class="sourceLineNo">401</span>      ADMIN.setRSGroup(Sets.newHashSet(tableName), RSGroupInfo.DEFAULT_GROUP);<a name="line.401"></a>
-<span class="sourceLineNo">402</span>      ADMIN.moveServersToRSGroup(Sets.newHashSet(Address.fromParts("bogus", 123)),<a name="line.402"></a>
-<span class="sourceLineNo">403</span>        RSGroupInfo.DEFAULT_GROUP);<a name="line.403"></a>
-<span class="sourceLineNo">404</span>      fail("Table " + tableName + " shouldn't have been successfully moved.");<a name="line.404"></a>
-<span class="sourceLineNo">405</span>    } catch (IOException ex) {<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      assertTrue(ex instanceof TableNotFoundException);<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    }<a name="line.407"></a>
-<span class="sourceLineNo">408</span>    // verify group change<a name="line.408"></a>
-<span class="sourceLineNo">409</span>    assertNull(ADMIN.getRSGroup(tableName));<a name="line.409"></a>
-<span class="sourceLineNo">410</span>  }<a name="line.410"></a>
-<span class="sourceLineNo">411</span><a name="line.411"></a>
-<span class="sourceLineNo">412</span>  @Test<a name="line.412"></a>
-<span class="sourceLineNo">413</span>  public void testRSGroupListDoesNotContainFailedTableCreation() throws Exception {<a name="line.413"></a>
-<span class="sourceLineNo">414</span>    toggleQuotaCheckAndRestartMiniCluster(true);<a name="line.414"></a>
-<span class="sourceLineNo">415</span>    String nsp = "np1";<a name="line.415"></a>
-<span class="sourceLineNo">416</span>    NamespaceDescriptor nspDesc =<a name="line.416"></a>
-<span class="sourceLineNo">417</span>      NamespaceDescriptor.create(nsp).addConfiguration(TableNamespaceManager.KEY_MAX_REGIONS, "5")<a name="line.417"></a>
-<span class="sourceLineNo">418</span>        .addConfiguration(TableNamespaceManager.KEY_MAX_TABLES, "2").build();<a name="line.418"></a>
-<span class="sourceLineNo">419</span>    ADMIN.createNamespace(nspDesc);<a name="line.419"></a>
-<span class="sourceLineNo">420</span>    assertEquals(3, ADMIN.listNamespaceDescriptors().length);<a name="line.420"></a>
-<span class="sourceLineNo">421</span>    ColumnFamilyDescriptor fam1 = ColumnFamilyDescriptorBuilder.of("fam1");<a name="line.421"></a>
-<span class="sourceLineNo">422</span>    TableDescriptor tableDescOne = TableDescriptorBuilder<a name="line.422"></a>
-<span class="sourceLineNo">423</span>      .newBuilder(TableName.valueOf(nsp + TableName.NAMESPACE_DELIM + "table1"))<a name="line.423"></a>
-<span class="sourceLineNo">424</span>      .setColumnFamily(fam1).build();<a name="line.424"></a>
-<span class="sourceLineNo">425</span>    ADMIN.createTable(tableDescOne);<a name="line.425"></a>
-<span class="sourceLineNo">426</span><a name="line.426"></a>
-<span class="sourceLineNo">427</span>    TableDescriptor tableDescTwo = TableDescriptorBuilder<a name="line.427"></a>
-<span class="sourceLineNo">428</span>      .newBuilder(TableName.valueOf(nsp + TableName.NAMESPACE_DELIM + "table2"))<a name="line.428"></a>
-<span class="sourceLineNo">429</span>      .setColumnFamily(fam1).build();<a name="line.429"></a>
-<span class="sourceLineNo">430</span>    boolean constraintViolated = false;<a name="line.430"></a>
-<span class="sourceLineNo">431</span><a name="line.431"></a>
-<span class="sourceLineNo">432</span>    try {<a name="line.432"></a>
-<span class="sourceLineNo">433</span>      ADMIN.createTable(tableDescTwo, Bytes.toBytes("AAA"), Bytes.toBytes("ZZZ"), 6);<a name="line.433"></a>
-<span class="sourceLineNo">434</span>      fail("Creation table should fail because of quota violation.");<a name="line.434"></a>
-<span class="sourceLineNo">435</span>    } catch (Exception exp) {<a name="line.435"></a>
-<span class="sourceLineNo">436</span>      assertTrue(exp instanceof IOException);<a name="line.436"></a>
-<span class="sourceLineNo">437</span>      constraintViolated = true;<a name="line.437"></a>
-<span class="sourceLineNo">438</span>    } finally {<a name="line.438"></a>
-<span class="sourceLineNo">439</span>      assertTrue("Constraint not violated for table " + tableDescTwo.getTableName(),<a name="line.439"></a>
-<span class="sourceLineNo">440</span>        constraintViolated);<a name="line.440"></a>
-<span class="sourceLineNo">441</span>    }<a name="line.441"></a>
-<span class="sourceLineNo">442</span>    List&lt;RSGroupInfo&gt; rsGroupInfoList = ADMIN.listRSGroups();<a name="line.442"></a>
-<span class="sourceLineNo">443</span>    boolean foundTable2 = false;<a name="line.443"></a>
-<span class="sourceLineNo">444</span>    boolean foundTable1 = false;<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    for (int i = 0; i &lt; rsGroupInfoList.size(); i++) {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      Set&lt;TableName&gt; tables =<a name="line.446"></a>
-<span class="sourceLineNo">447</span>        Sets.newHashSet(ADMIN.listTablesInRSGroup(rsGroupInfoList.get(i).getName()));<a name="line.447"></a>
-<span class="sourceLineNo">448</span>      if (tables.contains(tableDescTwo.getTableName())) {<a name="line.448"></a>
-<span class="sourceLineNo">449</span>        foundTable2 = true;<a name="line.449"></a>
-<span class="sourceLineNo">450</span>      }<a name="line.450"></a>
-<span class="sourceLineNo">451</span>      if (tables.contains(tableDescOne.getTableName())) {<a name="line.451"></a>
-<span class="sourceLineNo">452</span>        foundTable1 = true;<a name="line.452"></a>
-<span class="sourceLineNo">453</span>      }<a name="line.453"></a>
-<span class="sourceLineNo">454</span>    }<a name="line.454"></a>
-<span class="sourceLineNo">455</span>    assertFalse("Found table2 in rsgroup list.", foundTable2);<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    assertTrue("Did not find table1 in rsgroup list", foundTable1);<a name="line.456"></a>
-<span class="sourceLineNo">457</span><a name="line.457"></a>
-<span class="sourceLineNo">458</span>    TEST_UTIL.deleteTable(tableDescOne.getTableName());<a name="line.458"></a>
-<span class="sourceLineNo">459</span>    ADMIN.deleteNamespace(nspDesc.getName());<a name="line.459"></a>
-<span class="sourceLineNo">460</span>    toggleQuotaCheckAndRestartMiniCluster(false);<a name="line.460"></a>
-<span class="sourceLineNo">461</span><a name="line.461"></a>
-<span class="sourceLineNo">462</span>  }<a name="line.462"></a>
-<span class="sourceLineNo">463</span><a name="line.463"></a>
-<span class="sourceLineNo">464</span>  @Test<a name="line.464"></a>
-<span class="sourceLineNo">465</span>  public void testNotMoveTableToNullRSGroupWhenCreatingExistingTable() throws Exception {<a name="line.465"></a>
-<span class="sourceLineNo">466</span>    // Trigger<a name="line.466"></a>
-<span class="sourceLineNo">467</span>    TableName tn1 = TableName.valueOf("t1");<a name="line.467"></a>
-<span class="sourceLineNo">468</span>    TEST_UTIL.createTable(tn1, "cf1");<a name="line.468"></a>
-<span class="sourceLineNo">469</span>    try {<a name="line.469"></a>
-<span class="sourceLineNo">470</span>      // Create an existing table to trigger HBASE-21866<a name="line.470"></a>
-<span class="sourceLineNo">471</span>      TEST_UTIL.createTable(tn1, "cf1");<a name="line.471"></a>
-<span class="sourceLineNo">472</span>    } catch (TableExistsException teex) {<a name="line.472"></a>
-<span class="sourceLineNo">473</span>      // Ignore<a name="line.473"></a>
-<span class="sourceLineNo">474</span>    }<a name="line.474"></a>
-<span class="sourceLineNo">475</span><a name="line.475"></a>
-<span class="sourceLineNo">476</span>    // Wait then verify<a name="line.476"></a>
-<span class="sourceLineNo">477</span>    // Could not verify until the rollback of CreateTableProcedure is done<a name="line.477"></a>
-<span class="sourceLineNo">478</span>    // (that is, the coprocessor finishes its work),<a name="line.478"></a>
-<span class="sourceLineNo">479</span>    // or the table is still in the "default" rsgroup even though HBASE-21866<a name="line.479"></a>
-<span class="sourceLineNo">480</span>    // is not fixed.<a name="line.480"></a>
-<span class="sourceLineNo">481</span>    TEST_UTIL.waitFor(5000, new Waiter.Predicate&lt;Exception&gt;() {<a name="line.481"></a>
-<span class="sourceLineNo">482</span>      @Override<a name="line.482"></a>
-<span class="sourceLineNo">483</span>      public boolean evaluate() throws Exception {<a name="line.483"></a>
-<span class="sourceLineNo">484</span>        return MASTER.getMasterProcedureExecutor().getActiveExecutorCount() == 0;<a name="line.484"></a>
-<span class="sourceLineNo">485</span>      }<a name="line.485"></a>
-<span class="sourceLineNo">486</span>    });<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    Set&lt;TableName&gt; tables = Sets.newHashSet(ADMIN.listTablesInRSGroup(RSGroupInfo.DEFAULT_GROUP));<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    assertTrue("Table 't1' must be in 'default' rsgroup", tables.contains(tn1));<a name="line.488"></a>
-<span class="sourceLineNo">489</span><a name="line.489"></a>
-<span class="sourceLineNo">490</span>    // Cleanup<a name="line.490"></a>
-<span class="sourceLineNo">491</span>    TEST_UTIL.deleteTable(tn1);<a name="line.491"></a>
-<span class="sourceLineNo">492</span>  }<a name="line.492"></a>
-<span class="sourceLineNo">493</span><a name="line.493"></a>
-<span class="sourceLineNo">494</span>  @Test<a name="line.494"></a>
-<span class="sourceLineNo">495</span>  public void testRenameRSGroup() throws Exception {<a name="line.495"></a>
-<span class="sourceLineNo">496</span>    // Add rsgroup, and assign 2 servers and a table to it.<a name="line.496"></a>
-<span class="sourceLineNo">497</span>    RSGroupInfo oldgroup = addGroup("oldgroup", 2);<a name="line.497"></a>
-<span class="sourceLineNo">498</span>    TableName tb1 = TableName.valueOf("testRename");<a name="line.498"></a>
-<span class="sourceLineNo">499</span>    TEST_UTIL.createTable(tb1, "tr");<a name="line.499"></a>
-<span class="sourceLineNo">500</span>    ADMIN.setRSGroup(Sets.newHashSet(tb1), oldgroup.getName());<a name="line.500"></a>
-<span class="sourceLineNo">501</span>    TEST_UTIL.waitFor(1000,<a name="line.501"></a>
-<span class="sourceLineNo">502</span>      (Waiter.Predicate&lt;Exception&gt;) () -&gt;<a name="line.502"></a>
-<span class="sourceLineNo">503</span>        ADMIN.getRSGroup(tb1).getServers().size() == 2);<a name="line.503"></a>
-<span class="sourceLineNo">504</span>    oldgroup = ADMIN.getRSGroup(oldgroup.getName());<a name="line.504"></a>
-<span class="sourceLineNo">505</span>    assertEquals(2, oldgroup.getServers().size());<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    assertEquals(oldgroup.getName(), ADMIN.getRSGroup(tb1).getName());<a name="line.506"></a>
-<span class="sourceLineNo">507</span><a name="line.507"></a>
-<span class="sourceLineNo">508</span>    // Another rsgroup and table for verification<a name="line.508"></a>
-<span class="sourceLineNo">509</span>    // that they are unchanged during we're renaming oldgroup.<a name="line.509"></a>
-<span class="sourceLineNo">510</span>    RSGroupInfo normal = addGroup("normal", 1);<a name="line.510"></a>
-<span class="sourceLineNo">511</span>    TableName tb2 = TableName.valueOf("unmovedTable");<a name="line.511"></a>
-<span class="sourceLineNo">512</span>    TEST_UTIL.createTable(tb2, "ut");<a name="line.512"></a>
-<span class="sourceLineNo">513</span>    ADMIN.setRSGroup(Sets.newHashSet(tb2), normal.getName());<a name="line.513"></a>
-<span class="sourceLineNo">514</span>    TEST_UTIL.waitFor(1000,<a name="line.514"></a>
-<span class="sourceLineNo">515</span>      (Waiter.Predicate&lt;Exception&gt;) () -&gt;<a name="line.515"></a>
-<span class="sourceLineNo">516</span>        ADMIN.getRSGroup(tb2).getServers().size() == 1);<a name="line.516"></a>
-<span class="sourceLineNo">517</span>    normal = ADMIN.getRSGroup(normal.getName());<a name="line.517"></a>
-<span class="sourceLineNo">518</span>    assertEquals(1, normal.getServers().size());<a name="line.518"></a>
-<span class="sourceLineNo">519</span>    assertEquals(normal.getName(), ADMIN.getRSGroup(tb2).getName());<a name="line.519"></a>
-<span class="sourceLineNo">520</span><a name="line.520"></a>
+<span class="sourceLineNo">022</span>import static org.junit.Assert.assertNotNull;<a name="line.22"></a>
+<span class="sourceLineNo">023</span>import static org.junit.Assert.assertNull;<a name="line.23"></a>
+<span class="sourceLineNo">024</span>import static org.junit.Assert.assertTrue;<a name="line.24"></a>
+<span class="sourceLineNo">025</span>import static org.junit.Assert.fail;<a name="line.25"></a>
+<span class="sourceLineNo">026</span><a name="line.26"></a>
+<span class="sourceLineNo">027</span>import java.io.IOException;<a name="line.27"></a>
+<span class="sourceLineNo">028</span>import java.util.List;<a name="line.28"></a>
+<span class="sourceLineNo">029</span>import java.util.Map;<a name="line.29"></a>
+<span class="sourceLineNo">030</span>import java.util.Set;<a name="line.30"></a>
+<span class="sourceLineNo">031</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.31"></a>
+<span class="sourceLineNo">032</span>import org.apache.hadoop.hbase.NamespaceDescriptor;<a name="line.32"></a>
+<span class="sourceLineNo">033</span>import org.apache.hadoop.hbase.ServerName;<a name="line.33"></a>
+<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.TableExistsException;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.TableName;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.TableNotFoundException;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.Waiter;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.client.TableDescriptor;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.client.TableDescriptorBuilder;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.constraint.ConstraintException;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.master.TableNamespaceManager;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.net.Address;<a name="line.44"></a>
+<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.testclassification.MediumTests;<a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.testclassification.RSGroupTests;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.junit.After;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.junit.AfterClass;<a name="line.49"></a>
+<span class="sourceLineNo">050</span>import org.junit.Before;<a name="line.50"></a>
... 558 lines suppressed ...