You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by gi...@apache.org on 2026/07/20 23:56:57 UTC
(hbase-site) branch asf-site updated: Published site at 872616e4b45bf2994a63092b272987187bf3e161.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/hbase-site.git
The following commit(s) were added to refs/heads/asf-site by this push:
new 3fde55a6901 Published site at 872616e4b45bf2994a63092b272987187bf3e161.
3fde55a6901 is described below
commit 3fde55a6901e1121c84384490004e91c3f32064c
Author: HBase <de...@hbase.apache.org>
AuthorDate: Mon Jul 20 23:53:36 2026 +0000
Published site at 872616e4b45bf2994a63092b272987187bf3e161.
---
books/apache-hbase-reference-guide-dark-mode.pdf | Bin 38943794 -> 38943795 bytes
books/apache-hbase-reference-guide.pdf | Bin 38833623 -> 38833623 bytes
checkstyle-aggregate.html | 2 +-
dependency-convergence.html | 2 +-
dependency-info.html | 2 +-
dependency-management.html | 2 +-
hbase-website/dependency-convergence.html | 2 +-
hbase-website/dependency-info.html | 2 +-
hbase-website/dependency-management.html | 2 +-
hbase-website/index.html | 2 +-
hbase-website/issue-management.html | 2 +-
hbase-website/licenses.html | 2 +-
hbase-website/mailing-lists.html | 2 +-
hbase-website/plugin-management.html | 2 +-
hbase-website/plugins.html | 2 +-
hbase-website/project-info.html | 2 +-
hbase-website/scm.html | 2 +-
hbase-website/summary.html | 2 +-
hbase-website/team.html | 2 +-
issue-management.html | 2 +-
licenses.html | 2 +-
mailing-lists.html | 2 +-
plugin-management.html | 2 +-
plugins.html | 2 +-
project-info.html | 2 +-
project-reports.html | 2 +-
scm.html | 2 +-
summary.html | 2 +-
team.html | 2 +-
testapidocs/index-all.html | 2 +
testapidocs/member-search-index.js | 2 +-
.../apache/hadoop/hbase/util/RSProcDispatcher.html | 242 ++++++++++++-------
.../hadoop/hbase/util/TestProcDispatcher.html | 257 +++++++++++----------
testdevapidocs/constant-values.html | 11 +
testdevapidocs/index-all.html | 33 ++-
testdevapidocs/member-search-index.js | 2 +-
.../util/RSProcDispatcher.DeadRSRemoteCall.html | 6 +-
...Dispatcher.TestExecuteProceduresRemoteCall.html | 50 +++-
.../apache/hadoop/hbase/util/RSProcDispatcher.html | 119 ++++++++--
.../hadoop/hbase/util/TestProcDispatcher.html | 40 ++--
.../util/RSProcDispatcher.DeadRSRemoteCall.html | 242 ++++++++++++-------
...Dispatcher.TestExecuteProceduresRemoteCall.html | 242 ++++++++++++-------
.../apache/hadoop/hbase/util/RSProcDispatcher.html | 242 ++++++++++++-------
.../hadoop/hbase/util/TestProcDispatcher.html | 257 +++++++++++----------
44 files changed, 1133 insertions(+), 668 deletions(-)
diff --git a/books/apache-hbase-reference-guide-dark-mode.pdf b/books/apache-hbase-reference-guide-dark-mode.pdf
index 4418db99d0c..162886d8d28 100644
Binary files a/books/apache-hbase-reference-guide-dark-mode.pdf and b/books/apache-hbase-reference-guide-dark-mode.pdf differ
diff --git a/books/apache-hbase-reference-guide.pdf b/books/apache-hbase-reference-guide.pdf
index 072da602b11..f436519d7a2 100644
Binary files a/books/apache-hbase-reference-guide.pdf and b/books/apache-hbase-reference-guide.pdf differ
diff --git a/checkstyle-aggregate.html b/checkstyle-aggregate.html
index 7ef7e3727b8..357a34338fc 100644
--- a/checkstyle-aggregate.html
+++ b/checkstyle-aggregate.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-checkstyle-plugin:3.6.0:checkstyle-aggregate at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-checkstyle-plugin:3.6.0:checkstyle-aggregate at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/dependency-convergence.html b/dependency-convergence.html
index f7efa987004..c404354e6ed 100644
--- a/dependency-convergence.html
+++ b/dependency-convergence.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-convergence at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-convergence at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/dependency-info.html b/dependency-info.html
index c88a7cc9023..cb587635235 100644
--- a/dependency-info.html
+++ b/dependency-info.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-info at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-info at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/dependency-management.html b/dependency-management.html
index d397d519ec7..15d4d23d29b 100644
--- a/dependency-management.html
+++ b/dependency-management.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-management at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-management at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/hbase-website/dependency-convergence.html b/hbase-website/dependency-convergence.html
index 47fbe71a046..058a32f2a77 100644
--- a/hbase-website/dependency-convergence.html
+++ b/hbase-website/dependency-convergence.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-convergence at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-convergence at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/hbase-website/dependency-info.html b/hbase-website/dependency-info.html
index bfe91ac9be5..3733b3cc1e4 100644
--- a/hbase-website/dependency-info.html
+++ b/hbase-website/dependency-info.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-info at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-info at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/hbase-website/dependency-management.html b/hbase-website/dependency-management.html
index 33910217e4f..d0577c5c2d0 100644
--- a/hbase-website/dependency-management.html
+++ b/hbase-website/dependency-management.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-management at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:dependency-management at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/hbase-website/index.html b/hbase-website/index.html
index 4ebaeed16be..fa304e721ea 100644
--- a/hbase-website/index.html
+++ b/hbase-website/index.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:index at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:index at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/hbase-website/issue-management.html b/hbase-website/issue-management.html
index 5723038fe46..aabed9a9f52 100644
--- a/hbase-website/issue-management.html
+++ b/hbase-website/issue-management.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:issue-management at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:issue-management at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/hbase-website/licenses.html b/hbase-website/licenses.html
index 4446bd92f23..ac00ed72d27 100644
--- a/hbase-website/licenses.html
+++ b/hbase-website/licenses.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:licenses at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:licenses at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/hbase-website/mailing-lists.html b/hbase-website/mailing-lists.html
index 3d88a1867da..808c896637a 100644
--- a/hbase-website/mailing-lists.html
+++ b/hbase-website/mailing-lists.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:mailing-lists at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:mailing-lists at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/hbase-website/plugin-management.html b/hbase-website/plugin-management.html
index 6eebac8189c..703b6cc6b22 100644
--- a/hbase-website/plugin-management.html
+++ b/hbase-website/plugin-management.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:plugin-management at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:plugin-management at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/hbase-website/plugins.html b/hbase-website/plugins.html
index 015f854a73f..f6576a6dd87 100644
--- a/hbase-website/plugins.html
+++ b/hbase-website/plugins.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:plugins at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:plugins at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/hbase-website/project-info.html b/hbase-website/project-info.html
index 872208ca225..9e207665607 100644
--- a/hbase-website/project-info.html
+++ b/hbase-website/project-info.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-site-plugin:3.21.0:project-info at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-site-plugin:3.21.0:project-info at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/hbase-website/scm.html b/hbase-website/scm.html
index cfcfe45beda..48f4b96d8e8 100644
--- a/hbase-website/scm.html
+++ b/hbase-website/scm.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:scm at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:scm at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/hbase-website/summary.html b/hbase-website/summary.html
index 20437b5c93b..081998e324b 100644
--- a/hbase-website/summary.html
+++ b/hbase-website/summary.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:summary at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:summary at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/hbase-website/team.html b/hbase-website/team.html
index 3c762eaae3d..98b7d0afc6a 100644
--- a/hbase-website/team.html
+++ b/hbase-website/team.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:team at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:team at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/issue-management.html b/issue-management.html
index 8cf10c24eb4..6b0ec4bdb59 100644
--- a/issue-management.html
+++ b/issue-management.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:issue-management at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:issue-management at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/licenses.html b/licenses.html
index a76386ad96d..c97a724ce47 100644
--- a/licenses.html
+++ b/licenses.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:licenses at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:licenses at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/mailing-lists.html b/mailing-lists.html
index 1cc8fab2e48..8c2ed1c9054 100644
--- a/mailing-lists.html
+++ b/mailing-lists.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:mailing-lists at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:mailing-lists at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/plugin-management.html b/plugin-management.html
index 671e8c82417..fe320cb83fd 100644
--- a/plugin-management.html
+++ b/plugin-management.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:plugin-management at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:plugin-management at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/plugins.html b/plugins.html
index b5e18d9119a..f4aefd06407 100644
--- a/plugins.html
+++ b/plugins.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:plugins at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:plugins at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/project-info.html b/project-info.html
index ab40aff925c..33dee26cbce 100644
--- a/project-info.html
+++ b/project-info.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-site-plugin:3.21.0:project-info at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-site-plugin:3.21.0:project-info at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/project-reports.html b/project-reports.html
index 5cb53341059..e3b447ab831 100644
--- a/project-reports.html
+++ b/project-reports.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-site-plugin:3.21.0:project-reports at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-site-plugin:3.21.0:project-reports at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/scm.html b/scm.html
index e5ba5b756c5..071d5a927b8 100644
--- a/scm.html
+++ b/scm.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:scm at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:scm at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/summary.html b/summary.html
index 5fcaec77fce..f8b4d9d5842 100644
--- a/summary.html
+++ b/summary.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:summary at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:summary at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/team.html b/team.html
index f18d663275d..0875ca929b4 100644
--- a/team.html
+++ b/team.html
@@ -2,7 +2,7 @@
<!--
- | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:team at 2026-07-16
+ | Generated by Apache Maven Doxia Site Renderer 2.0.0 from org.apache.maven.plugins:maven-project-info-reports-plugin:3.9.0:team at 2026-07-20
| Rendered using Apache Maven Fluido Skin 2.0.0-M9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
diff --git a/testapidocs/index-all.html b/testapidocs/index-all.html
index e3256861f23..a3df34b88d0 100644
--- a/testapidocs/index-all.html
+++ b/testapidocs/index-all.html
@@ -20672,6 +20672,8 @@ loadScripts(document, 'script');</script>
<dd> </dd>
<dt><a href="../apidocs/org/apache/hadoop/hbase/util/TestMiniClusterLoadSequential.html#tearDown()" class="member-name-link external-link" title="class or interface in org.apache.hadoop.hbase.util">tearDown()</a> - Method in class org.apache.hadoop.hbase.util.<a href="../apidocs/org/apache/hadoop/hbase/util/TestMiniClusterLoadSequential.html" title="class or interface in org.apache.hadoop.hbase.util" class="external-link">TestMiniClusterLoadSequential</a></dt>
<dd> </dd>
+<dt><a href="../apidocs/org/apache/hadoop/hbase/util/TestProcDispatcher.html#tearDown()" class="member-name-link external-link" title="class or interface in org.apache.hadoop.hbase.util">tearDown()</a> - Method in class org.apache.hadoop.hbase.util.<a href="../apidocs/org/apache/hadoop/hbase/util/TestProcDispatcher.html" title="class or interface in org.apache.hadoop.hbase.util" class="external-link">TestProcDispatcher</a></dt>
+<dd> </dd>
<dt><a href="../apidocs/org/apache/hadoop/hbase/util/TestRegionMover1.html#tearDown()" class="member-name-link external-link" title="class or interface in org.apache.hadoop.hbase.util">tearDown()</a> - Method in class org.apache.hadoop.hbase.util.<a href="../apidocs/org/apache/hadoop/hbase/util/TestRegionMover1.html" title="class or interface in org.apache.hadoop.hbase.util" class="external-link">TestRegionMover1</a></dt>
<dd> </dd>
<dt><a href="../apidocs/org/apache/hadoop/hbase/util/TestRegionMover2.html#tearDown()" class="member-name-link external-link" title="class or interface in org.apache.hadoop.hbase.util">tearDown()</a> - Method in class org.apache.hadoop.hbase.util.<a href="../apidocs/org/apache/hadoop/hbase/util/TestRegionMover2.html" title="class or interface in org.apache.hadoop.hbase.util" class="external-link">TestRegionMover2</a></dt>
diff --git a/testapidocs/member-search-index.js b/testapidocs/member-search-index.js
index f1c8c7915a5..f64e6dca3ce 100644
--- a/testapidocs/member-search-index.js
+++ b/testapidocs/member-search-index.js
@@ -1 +1 @@
-memberSearchIndex = [{"p":"org.apache.hadoop.hbase.backup","c":"TestSystemTableSnapshot","l":"_testBackupRestoreSystemTable()"},{"p":"org.apache.hadoop.hbase.coprocessor","c":"TestRegionObserverInterface","l":"A"},{"p":"org.apache.hadoop.hbase.client","c":"TestGetProcedureResult.DummyProcedure","l":"abort(MasterProcedureEnv)","u":"abort(org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv)"},{"p":"org.apache.hadoop.hbase.master","c":"TestMigrateNamespaceTable.SuspendProcedure","l" [...]
\ No newline at end of file
+memberSearchIndex = [{"p":"org.apache.hadoop.hbase.backup","c":"TestSystemTableSnapshot","l":"_testBackupRestoreSystemTable()"},{"p":"org.apache.hadoop.hbase.coprocessor","c":"TestRegionObserverInterface","l":"A"},{"p":"org.apache.hadoop.hbase.client","c":"TestGetProcedureResult.DummyProcedure","l":"abort(MasterProcedureEnv)","u":"abort(org.apache.hadoop.hbase.master.procedure.MasterProcedureEnv)"},{"p":"org.apache.hadoop.hbase.master","c":"TestMigrateNamespaceTable.SuspendProcedure","l" [...]
\ No newline at end of file
diff --git a/testapidocs/src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html b/testapidocs/src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html
index b676f94e16b..fcca06ad2ba 100644
--- a/testapidocs/src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html
+++ b/testapidocs/src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html
@@ -36,97 +36,165 @@
<span class="source-line-no">023</span><span id="line-23">import java.util.Arrays;</span>
<span class="source-line-no">024</span><span id="line-24">import java.util.List;</span>
<span class="source-line-no">025</span><span id="line-25">import java.util.Set;</span>
-<span class="source-line-no">026</span><span id="line-26">import java.util.concurrent.atomic.AtomicInteger;</span>
-<span class="source-line-no">027</span><span id="line-27">import org.apache.hadoop.hbase.ServerName;</span>
-<span class="source-line-no">028</span><span id="line-28">import org.apache.hadoop.hbase.client.AsyncRegionServerAdmin;</span>
-<span class="source-line-no">029</span><span id="line-29">import org.apache.hadoop.hbase.exceptions.ConnectionClosedException;</span>
-<span class="source-line-no">030</span><span id="line-30">import org.apache.hadoop.hbase.master.MasterServices;</span>
-<span class="source-line-no">031</span><span id="line-31">import org.apache.hadoop.hbase.master.procedure.RSProcedureDispatcher;</span>
-<span class="source-line-no">032</span><span id="line-32">import org.apache.hadoop.hbase.regionserver.RegionServerStoppedException;</span>
-<span class="source-line-no">033</span><span id="line-33">import org.slf4j.Logger;</span>
-<span class="source-line-no">034</span><span id="line-34">import org.slf4j.LoggerFactory;</span>
-<span class="source-line-no">035</span><span id="line-35"></span>
-<span class="source-line-no">036</span><span id="line-36">import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos;</span>
-<span class="source-line-no">037</span><span id="line-37"></span>
-<span class="source-line-no">038</span><span id="line-38">/**</span>
-<span class="source-line-no">039</span><span id="line-39"> * Test implementation of RSProcedureDispatcher that throws desired errors for testing purpose.</span>
-<span class="source-line-no">040</span><span id="line-40"> */</span>
-<span class="source-line-no">041</span><span id="line-41">public class RSProcDispatcher extends RSProcedureDispatcher {</span>
+<span class="source-line-no">026</span><span id="line-26">import java.util.concurrent.atomic.AtomicBoolean;</span>
+<span class="source-line-no">027</span><span id="line-27">import java.util.concurrent.atomic.AtomicInteger;</span>
+<span class="source-line-no">028</span><span id="line-28">import org.apache.hadoop.hbase.ServerName;</span>
+<span class="source-line-no">029</span><span id="line-29">import org.apache.hadoop.hbase.TableName;</span>
+<span class="source-line-no">030</span><span id="line-30">import org.apache.hadoop.hbase.client.AsyncRegionServerAdmin;</span>
+<span class="source-line-no">031</span><span id="line-31">import org.apache.hadoop.hbase.client.RegionInfo;</span>
+<span class="source-line-no">032</span><span id="line-32">import org.apache.hadoop.hbase.exceptions.ConnectionClosedException;</span>
+<span class="source-line-no">033</span><span id="line-33">import org.apache.hadoop.hbase.master.MasterServices;</span>
+<span class="source-line-no">034</span><span id="line-34">import org.apache.hadoop.hbase.master.procedure.RSProcedureDispatcher;</span>
+<span class="source-line-no">035</span><span id="line-35">import org.apache.hadoop.hbase.regionserver.RegionServerStoppedException;</span>
+<span class="source-line-no">036</span><span id="line-36">import org.slf4j.Logger;</span>
+<span class="source-line-no">037</span><span id="line-37">import org.slf4j.LoggerFactory;</span>
+<span class="source-line-no">038</span><span id="line-38"></span>
+<span class="source-line-no">039</span><span id="line-39">import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;</span>
+<span class="source-line-no">040</span><span id="line-40">import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos;</span>
+<span class="source-line-no">041</span><span id="line-41">import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;</span>
<span class="source-line-no">042</span><span id="line-42"></span>
-<span class="source-line-no">043</span><span id="line-43"> private static final Logger LOG = LoggerFactory.getLogger(RSProcDispatcher.class);</span>
-<span class="source-line-no">044</span><span id="line-44"></span>
-<span class="source-line-no">045</span><span id="line-45"> private static final AtomicInteger I = new AtomicInteger();</span>
-<span class="source-line-no">046</span><span id="line-46"></span>
-<span class="source-line-no">047</span><span id="line-47"> private static final List<IOException> ERRORS =</span>
-<span class="source-line-no">048</span><span id="line-48"> Arrays.asList(new ConnectionClosedException("test connection closed error..."),</span>
-<span class="source-line-no">049</span><span id="line-49"> new UnknownHostException("test unknown host error..."),</span>
-<span class="source-line-no">050</span><span id="line-50"> new ConnectException("test connect error..."));</span>
-<span class="source-line-no">051</span><span id="line-51"></span>
-<span class="source-line-no">052</span><span id="line-52"> private static final AtomicInteger ERROR_IDX = new AtomicInteger();</span>
-<span class="source-line-no">053</span><span id="line-53"></span>
-<span class="source-line-no">054</span><span id="line-54"> public RSProcDispatcher(MasterServices master) {</span>
-<span class="source-line-no">055</span><span id="line-55"> super(master);</span>
-<span class="source-line-no">056</span><span id="line-56"> }</span>
+<span class="source-line-no">043</span><span id="line-43">/**</span>
+<span class="source-line-no">044</span><span id="line-44"> * Test implementation of RSProcedureDispatcher that throws desired errors for testing purpose.</span>
+<span class="source-line-no">045</span><span id="line-45"> */</span>
+<span class="source-line-no">046</span><span id="line-46">public class RSProcDispatcher extends RSProcedureDispatcher {</span>
+<span class="source-line-no">047</span><span id="line-47"></span>
+<span class="source-line-no">048</span><span id="line-48"> private static final Logger LOG = LoggerFactory.getLogger(RSProcDispatcher.class);</span>
+<span class="source-line-no">049</span><span id="line-49"></span>
+<span class="source-line-no">050</span><span id="line-50"> /** Config key for the fail-fast retry limit, shared with the test so the two cannot drift. */</span>
+<span class="source-line-no">051</span><span id="line-51"> static final String FAIL_FAST_LIMIT_KEY = "hbase.master.rs.remote.proc.fail.fast.limit";</span>
+<span class="source-line-no">052</span><span id="line-52"></span>
+<span class="source-line-no">053</span><span id="line-53"> private static final List<IOException> ERRORS =</span>
+<span class="source-line-no">054</span><span id="line-54"> Arrays.asList(new ConnectionClosedException("test connection closed error..."),</span>
+<span class="source-line-no">055</span><span id="line-55"> new UnknownHostException("test unknown host error..."),</span>
+<span class="source-line-no">056</span><span id="line-56"> new ConnectException("test connect error..."));</span>
<span class="source-line-no">057</span><span id="line-57"></span>
-<span class="source-line-no">058</span><span id="line-58"> @Override</span>
-<span class="source-line-no">059</span><span id="line-59"> protected void remoteDispatch(final ServerName serverName,</span>
-<span class="source-line-no">060</span><span id="line-60"> final Set<RemoteProcedure> remoteProcedures) {</span>
-<span class="source-line-no">061</span><span id="line-61"> if (!master.getServerManager().isServerOnline(serverName)) {</span>
-<span class="source-line-no">062</span><span id="line-62"> // fail fast</span>
-<span class="source-line-no">063</span><span id="line-63"> submitTask(new DeadRSRemoteCall(serverName, remoteProcedures));</span>
-<span class="source-line-no">064</span><span id="line-64"> } else {</span>
-<span class="source-line-no">065</span><span id="line-65"> submitTask(new TestExecuteProceduresRemoteCall(serverName, remoteProcedures));</span>
-<span class="source-line-no">066</span><span id="line-66"> }</span>
-<span class="source-line-no">067</span><span id="line-67"> }</span>
-<span class="source-line-no">068</span><span id="line-68"></span>
-<span class="source-line-no">069</span><span id="line-69"> class TestExecuteProceduresRemoteCall extends ExecuteProceduresRemoteCall {</span>
-<span class="source-line-no">070</span><span id="line-70"></span>
-<span class="source-line-no">071</span><span id="line-71"> public TestExecuteProceduresRemoteCall(ServerName serverName,</span>
-<span class="source-line-no">072</span><span id="line-72"> Set<RemoteProcedure> remoteProcedures) {</span>
-<span class="source-line-no">073</span><span id="line-73"> super(serverName, remoteProcedures);</span>
-<span class="source-line-no">074</span><span id="line-74"> }</span>
-<span class="source-line-no">075</span><span id="line-75"></span>
-<span class="source-line-no">076</span><span id="line-76"> @Override</span>
-<span class="source-line-no">077</span><span id="line-77"> public AdminProtos.ExecuteProceduresResponse sendRequest(final ServerName serverName,</span>
-<span class="source-line-no">078</span><span id="line-78"> final AdminProtos.ExecuteProceduresRequest request) throws IOException {</span>
-<span class="source-line-no">079</span><span id="line-79"> int j = I.addAndGet(1);</span>
-<span class="source-line-no">080</span><span id="line-80"> LOG.info("sendRequest() req: {} , j: {}", request, j);</span>
-<span class="source-line-no">081</span><span id="line-81"> if (j == 12 || j == 22) {</span>
-<span class="source-line-no">082</span><span id="line-82"> // Execute the remote close and open region requests in the last (5th) retry before</span>
-<span class="source-line-no">083</span><span id="line-83"> // throwing ConnectionClosedException. This is to ensure even if the region open/close</span>
-<span class="source-line-no">084</span><span id="line-84"> // is successfully completed by regionserver, master still schedules SCP because</span>
-<span class="source-line-no">085</span><span id="line-85"> // sendRequest() throws error which has retry-limit exhausted.</span>
-<span class="source-line-no">086</span><span id="line-86"> FutureUtils.get(getRsAdmin().executeProcedures(request));</span>
-<span class="source-line-no">087</span><span id="line-87"> }</span>
-<span class="source-line-no">088</span><span id="line-88"> // For one of the close region requests and one of the open region requests,</span>
-<span class="source-line-no">089</span><span id="line-89"> // throw ConnectionClosedException until retry limit is exhausted and master</span>
-<span class="source-line-no">090</span><span id="line-90"> // schedules recoveries for the server.</span>
-<span class="source-line-no">091</span><span id="line-91"> // We will have ABNORMALLY_CLOSED regions, and they are expected to recover on their own.</span>
-<span class="source-line-no">092</span><span id="line-92"> if (j >= 8 && j <= 13 || j >= 18 && j <= 23) {</span>
-<span class="source-line-no">093</span><span id="line-93"> throw ERRORS.get(ERROR_IDX.getAndIncrement() % ERRORS.size());</span>
-<span class="source-line-no">094</span><span id="line-94"> }</span>
-<span class="source-line-no">095</span><span id="line-95"> return FutureUtils.get(getRsAdmin().executeProcedures(request));</span>
-<span class="source-line-no">096</span><span id="line-96"> }</span>
-<span class="source-line-no">097</span><span id="line-97"></span>
-<span class="source-line-no">098</span><span id="line-98"> private AsyncRegionServerAdmin getRsAdmin() {</span>
-<span class="source-line-no">099</span><span id="line-99"> return master.getAsyncClusterConnection().getRegionServerAdmin(getServerName());</span>
-<span class="source-line-no">100</span><span id="line-100"> }</span>
-<span class="source-line-no">101</span><span id="line-101"> }</span>
-<span class="source-line-no">102</span><span id="line-102"></span>
-<span class="source-line-no">103</span><span id="line-103"> private class DeadRSRemoteCall extends ExecuteProceduresRemoteCall {</span>
+<span class="source-line-no">058</span><span id="line-58"> private static final AtomicInteger ERROR_IDX = new AtomicInteger();</span>
+<span class="source-line-no">059</span><span id="line-59"></span>
+<span class="source-line-no">060</span><span id="line-60"> // Injection is driven by the test and bound to a target table, not a global call count:</span>
+<span class="source-line-no">061</span><span id="line-61"> // remoteDispatch() fires for every remote procedure in the cluster (startup, table creation,</span>
+<span class="source-line-no">062</span><span id="line-62"> // chores, background assignments), so counting calls drifts and misses the operations under test.</span>
+<span class="source-line-no">063</span><span id="line-63"> private static final AtomicBoolean INJECT = new AtomicBoolean(false);</span>
+<span class="source-line-no">064</span><span id="line-64"> private static final AtomicInteger VICTIMS_REMAINING = new AtomicInteger(0);</span>
+<span class="source-line-no">065</span><span id="line-65"> private static volatile TableName targetTable;</span>
+<span class="source-line-no">066</span><span id="line-66"></span>
+<span class="source-line-no">067</span><span id="line-67"> // Fail-fast retry limit after which the master schedules an SCP; read from conf to match test.</span>
+<span class="source-line-no">068</span><span id="line-68"> private final int failFastLimit;</span>
+<span class="source-line-no">069</span><span id="line-69"></span>
+<span class="source-line-no">070</span><span id="line-70"> /**</span>
+<span class="source-line-no">071</span><span id="line-71"> * Fails the next {@code n} open/close-region requests for {@code table} with connection errors</span>
+<span class="source-line-no">072</span><span id="line-72"> * until the fail-fast retry limit is exhausted, so the master schedules an SCP. Call right before</span>
+<span class="source-line-no">073</span><span id="line-73"> * the operations under test.</span>
+<span class="source-line-no">074</span><span id="line-74"> */</span>
+<span class="source-line-no">075</span><span id="line-75"> static void injectErrorsForNextRequests(TableName table, int n) {</span>
+<span class="source-line-no">076</span><span id="line-76"> ERROR_IDX.set(0);</span>
+<span class="source-line-no">077</span><span id="line-77"> targetTable = table;</span>
+<span class="source-line-no">078</span><span id="line-78"> VICTIMS_REMAINING.set(n);</span>
+<span class="source-line-no">079</span><span id="line-79"> INJECT.set(true);</span>
+<span class="source-line-no">080</span><span id="line-80"> }</span>
+<span class="source-line-no">081</span><span id="line-81"></span>
+<span class="source-line-no">082</span><span id="line-82"> /** Stops error injection. Safe to call unconditionally, e.g. from test teardown. */</span>
+<span class="source-line-no">083</span><span id="line-83"> static void stopInjecting() {</span>
+<span class="source-line-no">084</span><span id="line-84"> INJECT.set(false);</span>
+<span class="source-line-no">085</span><span id="line-85"> VICTIMS_REMAINING.set(0);</span>
+<span class="source-line-no">086</span><span id="line-86"> targetTable = null;</span>
+<span class="source-line-no">087</span><span id="line-87"> }</span>
+<span class="source-line-no">088</span><span id="line-88"></span>
+<span class="source-line-no">089</span><span id="line-89"> public RSProcDispatcher(MasterServices master) {</span>
+<span class="source-line-no">090</span><span id="line-90"> super(master);</span>
+<span class="source-line-no">091</span><span id="line-91"> this.failFastLimit = master.getConfiguration().getInt(FAIL_FAST_LIMIT_KEY, 10);</span>
+<span class="source-line-no">092</span><span id="line-92"> }</span>
+<span class="source-line-no">093</span><span id="line-93"></span>
+<span class="source-line-no">094</span><span id="line-94"> @Override</span>
+<span class="source-line-no">095</span><span id="line-95"> protected void remoteDispatch(final ServerName serverName,</span>
+<span class="source-line-no">096</span><span id="line-96"> final Set<RemoteProcedure> remoteProcedures) {</span>
+<span class="source-line-no">097</span><span id="line-97"> if (!master.getServerManager().isServerOnline(serverName)) {</span>
+<span class="source-line-no">098</span><span id="line-98"> // fail fast</span>
+<span class="source-line-no">099</span><span id="line-99"> submitTask(new DeadRSRemoteCall(serverName, remoteProcedures));</span>
+<span class="source-line-no">100</span><span id="line-100"> } else {</span>
+<span class="source-line-no">101</span><span id="line-101"> submitTask(new TestExecuteProceduresRemoteCall(serverName, remoteProcedures));</span>
+<span class="source-line-no">102</span><span id="line-102"> }</span>
+<span class="source-line-no">103</span><span id="line-103"> }</span>
<span class="source-line-no">104</span><span id="line-104"></span>
-<span class="source-line-no">105</span><span id="line-105"> public DeadRSRemoteCall(ServerName serverName, Set<RemoteProcedure> remoteProcedures) {</span>
-<span class="source-line-no">106</span><span id="line-106"> super(serverName, remoteProcedures);</span>
-<span class="source-line-no">107</span><span id="line-107"> }</span>
-<span class="source-line-no">108</span><span id="line-108"></span>
-<span class="source-line-no">109</span><span id="line-109"> @Override</span>
-<span class="source-line-no">110</span><span id="line-110"> public void run() {</span>
-<span class="source-line-no">111</span><span id="line-111"> remoteCallFailed(master.getMasterProcedureExecutor().getEnvironment(),</span>
-<span class="source-line-no">112</span><span id="line-112"> new RegionServerStoppedException("Server " + getServerName() + " is not online"));</span>
+<span class="source-line-no">105</span><span id="line-105"> /**</span>
+<span class="source-line-no">106</span><span id="line-106"> * True if the request opens or closes a region of the injection target table. Open requests carry</span>
+<span class="source-line-no">107</span><span id="line-107"> * a full RegionInfo; close requests carry a REGION_NAME specifier the table is parsed from.</span>
+<span class="source-line-no">108</span><span id="line-108"> */</span>
+<span class="source-line-no">109</span><span id="line-109"> private static boolean targetsInjectionTable(AdminProtos.ExecuteProceduresRequest request) {</span>
+<span class="source-line-no">110</span><span id="line-110"> TableName table = targetTable;</span>
+<span class="source-line-no">111</span><span id="line-111"> if (table == null) {</span>
+<span class="source-line-no">112</span><span id="line-112"> return false;</span>
<span class="source-line-no">113</span><span id="line-113"> }</span>
-<span class="source-line-no">114</span><span id="line-114"> }</span>
-<span class="source-line-no">115</span><span id="line-115"></span>
-<span class="source-line-no">116</span><span id="line-116">}</span>
+<span class="source-line-no">114</span><span id="line-114"> for (AdminProtos.OpenRegionRequest open : request.getOpenRegionList()) {</span>
+<span class="source-line-no">115</span><span id="line-115"> for (AdminProtos.OpenRegionRequest.RegionOpenInfo info : open.getOpenInfoList()) {</span>
+<span class="source-line-no">116</span><span id="line-116"> if (table.equals(ProtobufUtil.toTableName(info.getRegion().getTableName()))) {</span>
+<span class="source-line-no">117</span><span id="line-117"> return true;</span>
+<span class="source-line-no">118</span><span id="line-118"> }</span>
+<span class="source-line-no">119</span><span id="line-119"> }</span>
+<span class="source-line-no">120</span><span id="line-120"> }</span>
+<span class="source-line-no">121</span><span id="line-121"> for (AdminProtos.CloseRegionRequest close : request.getCloseRegionList()) {</span>
+<span class="source-line-no">122</span><span id="line-122"> HBaseProtos.RegionSpecifier region = close.getRegion();</span>
+<span class="source-line-no">123</span><span id="line-123"> if (</span>
+<span class="source-line-no">124</span><span id="line-124"> region.getType() == HBaseProtos.RegionSpecifier.RegionSpecifierType.REGION_NAME</span>
+<span class="source-line-no">125</span><span id="line-125"> && table.equals(RegionInfo.getTable(region.getValue().toByteArray()))</span>
+<span class="source-line-no">126</span><span id="line-126"> ) {</span>
+<span class="source-line-no">127</span><span id="line-127"> return true;</span>
+<span class="source-line-no">128</span><span id="line-128"> }</span>
+<span class="source-line-no">129</span><span id="line-129"> }</span>
+<span class="source-line-no">130</span><span id="line-130"> return false;</span>
+<span class="source-line-no">131</span><span id="line-131"> }</span>
+<span class="source-line-no">132</span><span id="line-132"></span>
+<span class="source-line-no">133</span><span id="line-133"> class TestExecuteProceduresRemoteCall extends ExecuteProceduresRemoteCall {</span>
+<span class="source-line-no">134</span><span id="line-134"></span>
+<span class="source-line-no">135</span><span id="line-135"> // attempts: retries of this single request instance (mirrors the dispatcher's</span>
+<span class="source-line-no">136</span><span id="line-136"> // numberOfAttemptsSoFar). injectErrors: whether this instance is failed with injected errors,</span>
+<span class="source-line-no">137</span><span id="line-137"> // decided once on the first call and kept across its retries.</span>
+<span class="source-line-no">138</span><span id="line-138"> private int attempts = 0;</span>
+<span class="source-line-no">139</span><span id="line-139"> private Boolean injectErrors = null;</span>
+<span class="source-line-no">140</span><span id="line-140"></span>
+<span class="source-line-no">141</span><span id="line-141"> public TestExecuteProceduresRemoteCall(ServerName serverName,</span>
+<span class="source-line-no">142</span><span id="line-142"> Set<RemoteProcedure> remoteProcedures) {</span>
+<span class="source-line-no">143</span><span id="line-143"> super(serverName, remoteProcedures);</span>
+<span class="source-line-no">144</span><span id="line-144"> }</span>
+<span class="source-line-no">145</span><span id="line-145"></span>
+<span class="source-line-no">146</span><span id="line-146"> @Override</span>
+<span class="source-line-no">147</span><span id="line-147"> public AdminProtos.ExecuteProceduresResponse sendRequest(final ServerName serverName,</span>
+<span class="source-line-no">148</span><span id="line-148"> final AdminProtos.ExecuteProceduresRequest request) throws IOException {</span>
+<span class="source-line-no">149</span><span id="line-149"> if (injectErrors == null) {</span>
+<span class="source-line-no">150</span><span id="line-150"> // Claim a slot only for a target-table open/close request, once per instance.</span>
+<span class="source-line-no">151</span><span id="line-151"> injectErrors =</span>
+<span class="source-line-no">152</span><span id="line-152"> INJECT.get() && targetsInjectionTable(request) && VICTIMS_REMAINING.getAndDecrement() > 0;</span>
+<span class="source-line-no">153</span><span id="line-153"> }</span>
+<span class="source-line-no">154</span><span id="line-154"> LOG.info("sendRequest() req: {}, attempts: {}, injectErrors: {}", request, attempts,</span>
+<span class="source-line-no">155</span><span id="line-155"> injectErrors);</span>
+<span class="source-line-no">156</span><span id="line-156"> if (!injectErrors) {</span>
+<span class="source-line-no">157</span><span id="line-157"> return FutureUtils.get(getRsAdmin().executeProcedures(request));</span>
+<span class="source-line-no">158</span><span id="line-158"> }</span>
+<span class="source-line-no">159</span><span id="line-159"> // Throw a connection error each attempt until the retry limit is exhausted (-> SCP). On the</span>
+<span class="source-line-no">160</span><span id="line-160"> // last attempt run the real open/close first so the region still recovers.</span>
+<span class="source-line-no">161</span><span id="line-161"> if (attempts++ >= failFastLimit - 1) {</span>
+<span class="source-line-no">162</span><span id="line-162"> FutureUtils.get(getRsAdmin().executeProcedures(request));</span>
+<span class="source-line-no">163</span><span id="line-163"> }</span>
+<span class="source-line-no">164</span><span id="line-164"> throw ERRORS.get(ERROR_IDX.getAndIncrement() % ERRORS.size());</span>
+<span class="source-line-no">165</span><span id="line-165"> }</span>
+<span class="source-line-no">166</span><span id="line-166"></span>
+<span class="source-line-no">167</span><span id="line-167"> private AsyncRegionServerAdmin getRsAdmin() {</span>
+<span class="source-line-no">168</span><span id="line-168"> return master.getAsyncClusterConnection().getRegionServerAdmin(getServerName());</span>
+<span class="source-line-no">169</span><span id="line-169"> }</span>
+<span class="source-line-no">170</span><span id="line-170"> }</span>
+<span class="source-line-no">171</span><span id="line-171"></span>
+<span class="source-line-no">172</span><span id="line-172"> private class DeadRSRemoteCall extends ExecuteProceduresRemoteCall {</span>
+<span class="source-line-no">173</span><span id="line-173"></span>
+<span class="source-line-no">174</span><span id="line-174"> public DeadRSRemoteCall(ServerName serverName, Set<RemoteProcedure> remoteProcedures) {</span>
+<span class="source-line-no">175</span><span id="line-175"> super(serverName, remoteProcedures);</span>
+<span class="source-line-no">176</span><span id="line-176"> }</span>
+<span class="source-line-no">177</span><span id="line-177"></span>
+<span class="source-line-no">178</span><span id="line-178"> @Override</span>
+<span class="source-line-no">179</span><span id="line-179"> public void run() {</span>
+<span class="source-line-no">180</span><span id="line-180"> remoteCallFailed(master.getMasterProcedureExecutor().getEnvironment(),</span>
+<span class="source-line-no">181</span><span id="line-181"> new RegionServerStoppedException("Server " + getServerName() + " is not online"));</span>
+<span class="source-line-no">182</span><span id="line-182"> }</span>
+<span class="source-line-no">183</span><span id="line-183"> }</span>
+<span class="source-line-no">184</span><span id="line-184">}</span>
diff --git a/testapidocs/src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html b/testapidocs/src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html
index 9316d77f071..151ac524f28 100644
--- a/testapidocs/src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html
+++ b/testapidocs/src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html
@@ -55,131 +55,138 @@
<span class="source-line-no">042</span><span id="line-42">import org.apache.hadoop.hbase.testclassification.LargeTests;</span>
<span class="source-line-no">043</span><span id="line-43">import org.apache.hadoop.hbase.testclassification.MiscTests;</span>
<span class="source-line-no">044</span><span id="line-44">import org.junit.jupiter.api.AfterAll;</span>
-<span class="source-line-no">045</span><span id="line-45">import org.junit.jupiter.api.BeforeAll;</span>
-<span class="source-line-no">046</span><span id="line-46">import org.junit.jupiter.api.BeforeEach;</span>
-<span class="source-line-no">047</span><span id="line-47">import org.junit.jupiter.api.Tag;</span>
-<span class="source-line-no">048</span><span id="line-48">import org.junit.jupiter.api.Test;</span>
-<span class="source-line-no">049</span><span id="line-49">import org.junit.jupiter.api.TestInfo;</span>
-<span class="source-line-no">050</span><span id="line-50">import org.slf4j.Logger;</span>
-<span class="source-line-no">051</span><span id="line-51">import org.slf4j.LoggerFactory;</span>
-<span class="source-line-no">052</span><span id="line-52"></span>
-<span class="source-line-no">053</span><span id="line-53">import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos;</span>
-<span class="source-line-no">054</span><span id="line-54"></span>
-<span class="source-line-no">055</span><span id="line-55">/**</span>
-<span class="source-line-no">056</span><span id="line-56"> * Testing custom RSProcedureDispatcher to ensure retry limit can be imposed on certain errors.</span>
-<span class="source-line-no">057</span><span id="line-57"> */</span>
-<span class="source-line-no">058</span><span id="line-58">@Tag(MiscTests.TAG)</span>
-<span class="source-line-no">059</span><span id="line-59">@Tag(LargeTests.TAG)</span>
-<span class="source-line-no">060</span><span id="line-60">public class TestProcDispatcher {</span>
-<span class="source-line-no">061</span><span id="line-61"></span>
-<span class="source-line-no">062</span><span id="line-62"> private static final Logger LOG = LoggerFactory.getLogger(TestProcDispatcher.class);</span>
-<span class="source-line-no">063</span><span id="line-63"></span>
-<span class="source-line-no">064</span><span id="line-64"> private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();</span>
-<span class="source-line-no">065</span><span id="line-65"> private static ServerName rs0;</span>
-<span class="source-line-no">066</span><span id="line-66"></span>
-<span class="source-line-no">067</span><span id="line-67"> @BeforeAll</span>
-<span class="source-line-no">068</span><span id="line-68"> public static void setUpBeforeClass() throws Exception {</span>
-<span class="source-line-no">069</span><span id="line-69"> TEST_UTIL.getConfiguration().set(HBASE_MASTER_RSPROC_DISPATCHER_CLASS,</span>
-<span class="source-line-no">070</span><span id="line-70"> RSProcDispatcher.class.getName());</span>
-<span class="source-line-no">071</span><span id="line-71"> TEST_UTIL.getConfiguration().setInt("hbase.master.rs.remote.proc.fail.fast.limit", 5);</span>
-<span class="source-line-no">072</span><span id="line-72"> TEST_UTIL.startMiniCluster(3);</span>
-<span class="source-line-no">073</span><span id="line-73"> SingleProcessHBaseCluster cluster = TEST_UTIL.getHBaseCluster();</span>
-<span class="source-line-no">074</span><span id="line-74"> rs0 = cluster.getRegionServer(0).getServerName();</span>
-<span class="source-line-no">075</span><span id="line-75"> TEST_UTIL.getAdmin().balancerSwitch(false, true);</span>
-<span class="source-line-no">076</span><span id="line-76"> }</span>
-<span class="source-line-no">077</span><span id="line-77"></span>
-<span class="source-line-no">078</span><span id="line-78"> @AfterAll</span>
-<span class="source-line-no">079</span><span id="line-79"> public static void tearDownAfterClass() throws Exception {</span>
-<span class="source-line-no">080</span><span id="line-80"> TEST_UTIL.shutdownMiniCluster();</span>
-<span class="source-line-no">081</span><span id="line-81"> }</span>
-<span class="source-line-no">082</span><span id="line-82"></span>
-<span class="source-line-no">083</span><span id="line-83"> @BeforeEach</span>
-<span class="source-line-no">084</span><span id="line-84"> public void setUp(TestInfo testInfo) throws Exception {</span>
-<span class="source-line-no">085</span><span id="line-85"> final TableName tableName = TableName.valueOf(testInfo.getTestMethod().get().getName());</span>
-<span class="source-line-no">086</span><span id="line-86"> TableDescriptor tableDesc = TableDescriptorBuilder.newBuilder(tableName)</span>
-<span class="source-line-no">087</span><span id="line-87"> .setColumnFamily(ColumnFamilyDescriptorBuilder.of("fam1")).build();</span>
-<span class="source-line-no">088</span><span id="line-88"> int startKey = 0;</span>
-<span class="source-line-no">089</span><span id="line-89"> int endKey = 80000;</span>
-<span class="source-line-no">090</span><span id="line-90"> TEST_UTIL.getAdmin().createTable(tableDesc, Bytes.toBytes(startKey), Bytes.toBytes(endKey), 9);</span>
-<span class="source-line-no">091</span><span id="line-91"> }</span>
-<span class="source-line-no">092</span><span id="line-92"></span>
-<span class="source-line-no">093</span><span id="line-93"> @Test</span>
-<span class="source-line-no">094</span><span id="line-94"> public void testRetryLimitOnConnClosedErrors(TestInfo testInfo) throws Exception {</span>
-<span class="source-line-no">095</span><span id="line-95"> HbckChore hbckChore = new HbckChore(TEST_UTIL.getHBaseCluster().getMaster());</span>
-<span class="source-line-no">096</span><span id="line-96"> final TableName tableName = TableName.valueOf(testInfo.getTestMethod().get().getName());</span>
-<span class="source-line-no">097</span><span id="line-97"> SingleProcessHBaseCluster cluster = TEST_UTIL.getHBaseCluster();</span>
-<span class="source-line-no">098</span><span id="line-98"> Admin admin = TEST_UTIL.getAdmin();</span>
-<span class="source-line-no">099</span><span id="line-99"> Table table = TEST_UTIL.getConnection().getTable(tableName);</span>
-<span class="source-line-no">100</span><span id="line-100"> List<Put> puts = IntStream.range(10, 50000).mapToObj(i -> new Put(Bytes.toBytes(i))</span>
-<span class="source-line-no">101</span><span id="line-101"> .addColumn(Bytes.toBytes("fam1"), Bytes.toBytes("q1"), Bytes.toBytes("val_" + i)))</span>
-<span class="source-line-no">102</span><span id="line-102"> .collect(Collectors.toList());</span>
-<span class="source-line-no">103</span><span id="line-103"> table.put(puts);</span>
-<span class="source-line-no">104</span><span id="line-104"> admin.flush(tableName);</span>
-<span class="source-line-no">105</span><span id="line-105"> admin.compact(tableName);</span>
-<span class="source-line-no">106</span><span id="line-106"> Thread.sleep(3000);</span>
-<span class="source-line-no">107</span><span id="line-107"> HRegionServer hRegionServer0 = cluster.getRegionServer(0);</span>
-<span class="source-line-no">108</span><span id="line-108"> HRegionServer hRegionServer1 = cluster.getRegionServer(1);</span>
-<span class="source-line-no">109</span><span id="line-109"> HRegionServer hRegionServer2 = cluster.getRegionServer(2);</span>
-<span class="source-line-no">110</span><span id="line-110"> int numRegions0 = hRegionServer0.getNumberOfOnlineRegions();</span>
-<span class="source-line-no">111</span><span id="line-111"> int numRegions1 = hRegionServer1.getNumberOfOnlineRegions();</span>
-<span class="source-line-no">112</span><span id="line-112"> int numRegions2 = hRegionServer2.getNumberOfOnlineRegions();</span>
-<span class="source-line-no">113</span><span id="line-113"></span>
-<span class="source-line-no">114</span><span id="line-114"> hbckChore.choreForTesting();</span>
-<span class="source-line-no">115</span><span id="line-115"> HbckReport hbckReport = hbckChore.getLastReport();</span>
-<span class="source-line-no">116</span><span id="line-116"> assertEquals(0, hbckReport.getInconsistentRegions().size());</span>
-<span class="source-line-no">117</span><span id="line-117"> assertEquals(0, hbckReport.getOrphanRegionsOnFS().size());</span>
-<span class="source-line-no">118</span><span id="line-118"> assertEquals(0, hbckReport.getOrphanRegionsOnRS().size());</span>
-<span class="source-line-no">119</span><span id="line-119"></span>
-<span class="source-line-no">120</span><span id="line-120"> HRegion region0 = hRegionServer0.getRegions().get(0);</span>
-<span class="source-line-no">121</span><span id="line-121"> // move all regions from server1 to server0</span>
-<span class="source-line-no">122</span><span id="line-122"> for (HRegion region : hRegionServer1.getRegions()) {</span>
-<span class="source-line-no">123</span><span id="line-123"> TEST_UTIL.getAdmin().move(region.getRegionInfo().getEncodedNameAsBytes(), rs0);</span>
-<span class="source-line-no">124</span><span id="line-124"> }</span>
-<span class="source-line-no">125</span><span id="line-125"> TEST_UTIL.getAdmin().move(region0.getRegionInfo().getEncodedNameAsBytes());</span>
-<span class="source-line-no">126</span><span id="line-126"> HMaster master = TEST_UTIL.getHBaseCluster().getMaster();</span>
-<span class="source-line-no">127</span><span id="line-127"></span>
-<span class="source-line-no">128</span><span id="line-128"> // Ensure:</span>
-<span class="source-line-no">129</span><span id="line-129"> // 1. num of regions before and after scheduling SCP remain same</span>
-<span class="source-line-no">130</span><span id="line-130"> // 2. all procedures including SCPs are successfully completed</span>
-<span class="source-line-no">131</span><span id="line-131"> // 3. two servers have SCPs scheduled</span>
-<span class="source-line-no">132</span><span id="line-132"> TEST_UTIL.waitFor(5000, 1000, () -> {</span>
-<span class="source-line-no">133</span><span id="line-133"> LOG.info("numRegions0: {} , numRegions1: {} , numRegions2: {}", numRegions0, numRegions1,</span>
-<span class="source-line-no">134</span><span id="line-134"> numRegions2);</span>
-<span class="source-line-no">135</span><span id="line-135"> LOG.info("Online regions - server0 : {} , server1: {} , server2: {}",</span>
-<span class="source-line-no">136</span><span id="line-136"> cluster.getRegionServer(0).getNumberOfOnlineRegions(),</span>
-<span class="source-line-no">137</span><span id="line-137"> cluster.getRegionServer(1).getNumberOfOnlineRegions(),</span>
-<span class="source-line-no">138</span><span id="line-138"> cluster.getRegionServer(2).getNumberOfOnlineRegions());</span>
-<span class="source-line-no">139</span><span id="line-139"> LOG.info("Num of successfully completed procedures: {} , num of all procedures: {}",</span>
-<span class="source-line-no">140</span><span id="line-140"> master.getMasterProcedureExecutor().getProcedures().stream()</span>
-<span class="source-line-no">141</span><span id="line-141"> .filter(masterProcedureEnvProcedure -> masterProcedureEnvProcedure.getState()</span>
-<span class="source-line-no">142</span><span id="line-142"> == ProcedureProtos.ProcedureState.SUCCESS)</span>
-<span class="source-line-no">143</span><span id="line-143"> .count(),</span>
-<span class="source-line-no">144</span><span id="line-144"> master.getMasterProcedureExecutor().getProcedures().size());</span>
-<span class="source-line-no">145</span><span id="line-145"> LOG.info("Num of SCPs: " + master.getMasterProcedureExecutor().getProcedures().stream()</span>
-<span class="source-line-no">146</span><span id="line-146"> .filter(proc -> proc instanceof ServerCrashProcedure).count());</span>
-<span class="source-line-no">147</span><span id="line-147"> return (numRegions0 + numRegions1 + numRegions2)</span>
-<span class="source-line-no">148</span><span id="line-148"> == (cluster.getRegionServer(0).getNumberOfOnlineRegions()</span>
-<span class="source-line-no">149</span><span id="line-149"> + cluster.getRegionServer(1).getNumberOfOnlineRegions()</span>
-<span class="source-line-no">150</span><span id="line-150"> + cluster.getRegionServer(2).getNumberOfOnlineRegions())</span>
-<span class="source-line-no">151</span><span id="line-151"> && master.getMasterProcedureExecutor().getProcedures().stream()</span>
-<span class="source-line-no">152</span><span id="line-152"> .filter(masterProcedureEnvProcedure -> masterProcedureEnvProcedure.getState()</span>
-<span class="source-line-no">153</span><span id="line-153"> == ProcedureProtos.ProcedureState.SUCCESS)</span>
-<span class="source-line-no">154</span><span id="line-154"> .count() == master.getMasterProcedureExecutor().getProcedures().size()</span>
-<span class="source-line-no">155</span><span id="line-155"> && master.getMasterProcedureExecutor().getProcedures().stream()</span>
-<span class="source-line-no">156</span><span id="line-156"> .anyMatch(proc -> proc instanceof ServerCrashProcedure);</span>
-<span class="source-line-no">157</span><span id="line-157"> });</span>
-<span class="source-line-no">158</span><span id="line-158"></span>
-<span class="source-line-no">159</span><span id="line-159"> // Ensure we have no inconsistent regions</span>
-<span class="source-line-no">160</span><span id="line-160"> TEST_UTIL.waitFor(5000, 1000, () -> {</span>
-<span class="source-line-no">161</span><span id="line-161"> hbckChore.choreForTesting();</span>
-<span class="source-line-no">162</span><span id="line-162"> HbckReport report = hbckChore.getLastReport();</span>
-<span class="source-line-no">163</span><span id="line-163"> return report.getInconsistentRegions().isEmpty() && report.getOrphanRegionsOnFS().isEmpty()</span>
-<span class="source-line-no">164</span><span id="line-164"> && report.getOrphanRegionsOnRS().isEmpty();</span>
-<span class="source-line-no">165</span><span id="line-165"> });</span>
-<span class="source-line-no">166</span><span id="line-166"></span>
-<span class="source-line-no">167</span><span id="line-167"> }</span>
-<span class="source-line-no">168</span><span id="line-168"></span>
-<span class="source-line-no">169</span><span id="line-169">}</span>
+<span class="source-line-no">045</span><span id="line-45">import org.junit.jupiter.api.AfterEach;</span>
+<span class="source-line-no">046</span><span id="line-46">import org.junit.jupiter.api.BeforeAll;</span>
+<span class="source-line-no">047</span><span id="line-47">import org.junit.jupiter.api.BeforeEach;</span>
+<span class="source-line-no">048</span><span id="line-48">import org.junit.jupiter.api.Tag;</span>
+<span class="source-line-no">049</span><span id="line-49">import org.junit.jupiter.api.Test;</span>
+<span class="source-line-no">050</span><span id="line-50">import org.junit.jupiter.api.TestInfo;</span>
+<span class="source-line-no">051</span><span id="line-51">import org.slf4j.Logger;</span>
+<span class="source-line-no">052</span><span id="line-52">import org.slf4j.LoggerFactory;</span>
+<span class="source-line-no">053</span><span id="line-53"></span>
+<span class="source-line-no">054</span><span id="line-54">import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos;</span>
+<span class="source-line-no">055</span><span id="line-55"></span>
+<span class="source-line-no">056</span><span id="line-56">/**</span>
+<span class="source-line-no">057</span><span id="line-57"> * Testing custom RSProcedureDispatcher to ensure retry limit can be imposed on certain errors.</span>
+<span class="source-line-no">058</span><span id="line-58"> */</span>
+<span class="source-line-no">059</span><span id="line-59">@Tag(MiscTests.TAG)</span>
+<span class="source-line-no">060</span><span id="line-60">@Tag(LargeTests.TAG)</span>
+<span class="source-line-no">061</span><span id="line-61">public class TestProcDispatcher {</span>
+<span class="source-line-no">062</span><span id="line-62"></span>
+<span class="source-line-no">063</span><span id="line-63"> private static final Logger LOG = LoggerFactory.getLogger(TestProcDispatcher.class);</span>
+<span class="source-line-no">064</span><span id="line-64"></span>
+<span class="source-line-no">065</span><span id="line-65"> private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();</span>
+<span class="source-line-no">066</span><span id="line-66"> private static ServerName rs0;</span>
+<span class="source-line-no">067</span><span id="line-67"></span>
+<span class="source-line-no">068</span><span id="line-68"> @BeforeAll</span>
+<span class="source-line-no">069</span><span id="line-69"> public static void setUpBeforeClass() throws Exception {</span>
+<span class="source-line-no">070</span><span id="line-70"> TEST_UTIL.getConfiguration().set(HBASE_MASTER_RSPROC_DISPATCHER_CLASS,</span>
+<span class="source-line-no">071</span><span id="line-71"> RSProcDispatcher.class.getName());</span>
+<span class="source-line-no">072</span><span id="line-72"> TEST_UTIL.getConfiguration().setInt(RSProcDispatcher.FAIL_FAST_LIMIT_KEY, 5);</span>
+<span class="source-line-no">073</span><span id="line-73"> TEST_UTIL.startMiniCluster(3);</span>
+<span class="source-line-no">074</span><span id="line-74"> SingleProcessHBaseCluster cluster = TEST_UTIL.getHBaseCluster();</span>
+<span class="source-line-no">075</span><span id="line-75"> rs0 = cluster.getRegionServer(0).getServerName();</span>
+<span class="source-line-no">076</span><span id="line-76"> TEST_UTIL.getAdmin().balancerSwitch(false, true);</span>
+<span class="source-line-no">077</span><span id="line-77"> }</span>
+<span class="source-line-no">078</span><span id="line-78"></span>
+<span class="source-line-no">079</span><span id="line-79"> @AfterAll</span>
+<span class="source-line-no">080</span><span id="line-80"> public static void tearDownAfterClass() throws Exception {</span>
+<span class="source-line-no">081</span><span id="line-81"> TEST_UTIL.shutdownMiniCluster();</span>
+<span class="source-line-no">082</span><span id="line-82"> }</span>
+<span class="source-line-no">083</span><span id="line-83"></span>
+<span class="source-line-no">084</span><span id="line-84"> @BeforeEach</span>
+<span class="source-line-no">085</span><span id="line-85"> public void setUp(TestInfo testInfo) throws Exception {</span>
+<span class="source-line-no">086</span><span id="line-86"> final TableName tableName = TableName.valueOf(testInfo.getTestMethod().get().getName());</span>
+<span class="source-line-no">087</span><span id="line-87"> TableDescriptor tableDesc = TableDescriptorBuilder.newBuilder(tableName)</span>
+<span class="source-line-no">088</span><span id="line-88"> .setColumnFamily(ColumnFamilyDescriptorBuilder.of("fam1")).build();</span>
+<span class="source-line-no">089</span><span id="line-89"> int startKey = 0;</span>
+<span class="source-line-no">090</span><span id="line-90"> int endKey = 80000;</span>
+<span class="source-line-no">091</span><span id="line-91"> TEST_UTIL.getAdmin().createTable(tableDesc, Bytes.toBytes(startKey), Bytes.toBytes(endKey), 9);</span>
+<span class="source-line-no">092</span><span id="line-92"> }</span>
+<span class="source-line-no">093</span><span id="line-93"></span>
+<span class="source-line-no">094</span><span id="line-94"> @AfterEach</span>
+<span class="source-line-no">095</span><span id="line-95"> public void tearDown() {</span>
+<span class="source-line-no">096</span><span id="line-96"> RSProcDispatcher.stopInjecting();</span>
+<span class="source-line-no">097</span><span id="line-97"> }</span>
+<span class="source-line-no">098</span><span id="line-98"></span>
+<span class="source-line-no">099</span><span id="line-99"> @Test</span>
+<span class="source-line-no">100</span><span id="line-100"> public void testRetryLimitOnConnClosedErrors(TestInfo testInfo) throws Exception {</span>
+<span class="source-line-no">101</span><span id="line-101"> HbckChore hbckChore = new HbckChore(TEST_UTIL.getHBaseCluster().getMaster());</span>
+<span class="source-line-no">102</span><span id="line-102"> final TableName tableName = TableName.valueOf(testInfo.getTestMethod().get().getName());</span>
+<span class="source-line-no">103</span><span id="line-103"> SingleProcessHBaseCluster cluster = TEST_UTIL.getHBaseCluster();</span>
+<span class="source-line-no">104</span><span id="line-104"> Admin admin = TEST_UTIL.getAdmin();</span>
+<span class="source-line-no">105</span><span id="line-105"> List<Put> puts = IntStream.range(10, 50000).mapToObj(i -> new Put(Bytes.toBytes(i))</span>
+<span class="source-line-no">106</span><span id="line-106"> .addColumn(Bytes.toBytes("fam1"), Bytes.toBytes("q1"), Bytes.toBytes("val_" + i)))</span>
+<span class="source-line-no">107</span><span id="line-107"> .collect(Collectors.toList());</span>
+<span class="source-line-no">108</span><span id="line-108"> try (Table table = TEST_UTIL.getConnection().getTable(tableName)) {</span>
+<span class="source-line-no">109</span><span id="line-109"> table.put(puts);</span>
+<span class="source-line-no">110</span><span id="line-110"> }</span>
+<span class="source-line-no">111</span><span id="line-111"> admin.flush(tableName);</span>
+<span class="source-line-no">112</span><span id="line-112"> admin.compact(tableName);</span>
+<span class="source-line-no">113</span><span id="line-113"> Thread.sleep(3000);</span>
+<span class="source-line-no">114</span><span id="line-114"> HRegionServer hRegionServer0 = cluster.getRegionServer(0);</span>
+<span class="source-line-no">115</span><span id="line-115"> HRegionServer hRegionServer1 = cluster.getRegionServer(1);</span>
+<span class="source-line-no">116</span><span id="line-116"> HRegionServer hRegionServer2 = cluster.getRegionServer(2);</span>
+<span class="source-line-no">117</span><span id="line-117"> int numRegions0 = hRegionServer0.getNumberOfOnlineRegions();</span>
+<span class="source-line-no">118</span><span id="line-118"> int numRegions1 = hRegionServer1.getNumberOfOnlineRegions();</span>
+<span class="source-line-no">119</span><span id="line-119"> int numRegions2 = hRegionServer2.getNumberOfOnlineRegions();</span>
+<span class="source-line-no">120</span><span id="line-120"></span>
+<span class="source-line-no">121</span><span id="line-121"> hbckChore.choreForTesting();</span>
+<span class="source-line-no">122</span><span id="line-122"> HbckReport hbckReport = hbckChore.getLastReport();</span>
+<span class="source-line-no">123</span><span id="line-123"> assertEquals(0, hbckReport.getInconsistentRegions().size());</span>
+<span class="source-line-no">124</span><span id="line-124"> assertEquals(0, hbckReport.getOrphanRegionsOnFS().size());</span>
+<span class="source-line-no">125</span><span id="line-125"> assertEquals(0, hbckReport.getOrphanRegionsOnRS().size());</span>
+<span class="source-line-no">126</span><span id="line-126"></span>
+<span class="source-line-no">127</span><span id="line-127"> HRegion region0 = hRegionServer0.getRegions().get(0);</span>
+<span class="source-line-no">128</span><span id="line-128"> // Fail the next two open/close-region requests for this table so the moves trigger SCP(s).</span>
+<span class="source-line-no">129</span><span id="line-129"> RSProcDispatcher.injectErrorsForNextRequests(tableName, 2);</span>
+<span class="source-line-no">130</span><span id="line-130"> // move all regions from server1 to server0</span>
+<span class="source-line-no">131</span><span id="line-131"> for (HRegion region : hRegionServer1.getRegions()) {</span>
+<span class="source-line-no">132</span><span id="line-132"> TEST_UTIL.getAdmin().move(region.getRegionInfo().getEncodedNameAsBytes(), rs0);</span>
+<span class="source-line-no">133</span><span id="line-133"> }</span>
+<span class="source-line-no">134</span><span id="line-134"> TEST_UTIL.getAdmin().move(region0.getRegionInfo().getEncodedNameAsBytes());</span>
+<span class="source-line-no">135</span><span id="line-135"> HMaster master = TEST_UTIL.getHBaseCluster().getMaster();</span>
+<span class="source-line-no">136</span><span id="line-136"></span>
+<span class="source-line-no">137</span><span id="line-137"> // Ensure, after the injected connection errors:</span>
+<span class="source-line-no">138</span><span id="line-138"> // 1. the total number of regions is unchanged before and after the SCP(s)</span>
+<span class="source-line-no">139</span><span id="line-139"> // 2. all procedures (including the SCP(s)) complete successfully</span>
+<span class="source-line-no">140</span><span id="line-140"> // 3. at least one ServerCrashProcedure was scheduled</span>
+<span class="source-line-no">141</span><span id="line-141"> TEST_UTIL.waitFor(60000, 1000, () -> {</span>
+<span class="source-line-no">142</span><span id="line-142"> LOG.info("numRegions0: {} , numRegions1: {} , numRegions2: {}", numRegions0, numRegions1,</span>
+<span class="source-line-no">143</span><span id="line-143"> numRegions2);</span>
+<span class="source-line-no">144</span><span id="line-144"> LOG.info("Online regions - server0 : {} , server1: {} , server2: {}",</span>
+<span class="source-line-no">145</span><span id="line-145"> cluster.getRegionServer(0).getNumberOfOnlineRegions(),</span>
+<span class="source-line-no">146</span><span id="line-146"> cluster.getRegionServer(1).getNumberOfOnlineRegions(),</span>
+<span class="source-line-no">147</span><span id="line-147"> cluster.getRegionServer(2).getNumberOfOnlineRegions());</span>
+<span class="source-line-no">148</span><span id="line-148"> LOG.info("Num of successfully completed procedures: {} , num of all procedures: {}",</span>
+<span class="source-line-no">149</span><span id="line-149"> master.getMasterProcedureExecutor().getProcedures().stream()</span>
+<span class="source-line-no">150</span><span id="line-150"> .filter(masterProcedureEnvProcedure -> masterProcedureEnvProcedure.getState()</span>
+<span class="source-line-no">151</span><span id="line-151"> == ProcedureProtos.ProcedureState.SUCCESS)</span>
+<span class="source-line-no">152</span><span id="line-152"> .count(),</span>
+<span class="source-line-no">153</span><span id="line-153"> master.getMasterProcedureExecutor().getProcedures().size());</span>
+<span class="source-line-no">154</span><span id="line-154"> LOG.info("Num of SCPs: {}", master.getMasterProcedureExecutor().getProcedures().stream()</span>
+<span class="source-line-no">155</span><span id="line-155"> .filter(proc -> proc instanceof ServerCrashProcedure).count());</span>
+<span class="source-line-no">156</span><span id="line-156"> return (numRegions0 + numRegions1 + numRegions2)</span>
+<span class="source-line-no">157</span><span id="line-157"> == (cluster.getRegionServer(0).getNumberOfOnlineRegions()</span>
+<span class="source-line-no">158</span><span id="line-158"> + cluster.getRegionServer(1).getNumberOfOnlineRegions()</span>
+<span class="source-line-no">159</span><span id="line-159"> + cluster.getRegionServer(2).getNumberOfOnlineRegions())</span>
+<span class="source-line-no">160</span><span id="line-160"> && master.getMasterProcedureExecutor().getProcedures().stream()</span>
+<span class="source-line-no">161</span><span id="line-161"> .filter(masterProcedureEnvProcedure -> masterProcedureEnvProcedure.getState()</span>
+<span class="source-line-no">162</span><span id="line-162"> == ProcedureProtos.ProcedureState.SUCCESS)</span>
+<span class="source-line-no">163</span><span id="line-163"> .count() == master.getMasterProcedureExecutor().getProcedures().size()</span>
+<span class="source-line-no">164</span><span id="line-164"> && master.getMasterProcedureExecutor().getProcedures().stream()</span>
+<span class="source-line-no">165</span><span id="line-165"> .anyMatch(proc -> proc instanceof ServerCrashProcedure);</span>
+<span class="source-line-no">166</span><span id="line-166"> });</span>
+<span class="source-line-no">167</span><span id="line-167"></span>
+<span class="source-line-no">168</span><span id="line-168"> // Ensure we have no inconsistent regions</span>
+<span class="source-line-no">169</span><span id="line-169"> TEST_UTIL.waitFor(60000, 1000, () -> {</span>
+<span class="source-line-no">170</span><span id="line-170"> hbckChore.choreForTesting();</span>
+<span class="source-line-no">171</span><span id="line-171"> HbckReport report = hbckChore.getLastReport();</span>
+<span class="source-line-no">172</span><span id="line-172"> return report.getInconsistentRegions().isEmpty() && report.getOrphanRegionsOnFS().isEmpty()</span>
+<span class="source-line-no">173</span><span id="line-173"> && report.getOrphanRegionsOnRS().isEmpty();</span>
+<span class="source-line-no">174</span><span id="line-174"> });</span>
+<span class="source-line-no">175</span><span id="line-175"> }</span>
+<span class="source-line-no">176</span><span id="line-176">}</span>
diff --git a/testdevapidocs/constant-values.html b/testdevapidocs/constant-values.html
index 9450e353dfe..7cf15e1c8b5 100644
--- a/testdevapidocs/constant-values.html
+++ b/testdevapidocs/constant-values.html
@@ -10654,6 +10654,17 @@ loadScripts(document, 'script');</script>
</div>
</li>
<li>
+<div class="caption"><span>org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html" title="class in org.apache.hadoop.hbase.util">RSProcDispatcher</a></span></div>
+<div class="summary-table three-column-summary">
+<div class="table-header col-first">Modifier and Type</div>
+<div class="table-header col-second">Constant Field</div>
+<div class="table-header col-last">Value</div>
+<div class="col-first even-row-color"><code id="org.apache.hadoop.hbase.util.RSProcDispatcher.FAIL_FAST_LIMIT_KEY">static final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></code></div>
+<div class="col-second even-row-color"><code><a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html#FAIL_FAST_LIMIT_KEY">FAIL_FAST_LIMIT_KEY</a></code></div>
+<div class="col-last even-row-color"><code>"hbase.master.rs.remote.proc.fail.fast.limit"</code></div>
+</div>
+</li>
+<li>
<div class="caption"><span>org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/TestBoundedPriorityBlockingQueue.html" title="class in org.apache.hadoop.hbase.util">TestBoundedPriorityBlockingQueue</a></span></div>
<div class="summary-table three-column-summary">
<div class="table-header col-first">Modifier and Type</div>
diff --git a/testdevapidocs/index-all.html b/testdevapidocs/index-all.html
index 5be01da18c5..5e01ac29607 100644
--- a/testdevapidocs/index-all.html
+++ b/testdevapidocs/index-all.html
@@ -2877,6 +2877,8 @@ loadScripts(document, 'script');</script>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/replication/TestReplicationWithWALExtendedAttributes.TestReplicationSinkRegionServerEndpoint.html#attachWALExtendedAttributesToMutation(org.apache.hadoop.hbase.client.Mutation,java.util.List)" class="member-name-link">attachWALExtendedAttributesToMutation(Mutation, List<WALProtos.Attribute>)</a> - Method in class org.apache.hadoop.hbase.replication.<a href="org/apache/hadoop/hbase/replication/TestReplicationWithWALExtendedAttributes.TestReplicat [...]
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html#attempts" class="member-name-link">attempts</a> - Variable in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html" title="class in org.apache.hadoop.hbase.util">RSProcDispatcher.TestExecuteProceduresRemoteCall</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/client/TestConnectionAttributes.AttributesCoprocessor.html#%3Cinit%3E()" class="member-name-link">AttributesCoprocessor()</a> - Constructor for class org.apache.hadoop.hbase.client.<a href="org/apache/hadoop/hbase/client/TestConnectionAttributes.AttributesCoprocessor.html" title="class in org.apache.hadoop.hbase.client">TestConnectionAttributes.AttributesCoprocessor</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/client/TestRequestAttributes.AttributesCoprocessor.html#%3Cinit%3E()" class="member-name-link">AttributesCoprocessor()</a> - Constructor for class org.apache.hadoop.hbase.client.<a href="org/apache/hadoop/hbase/client/TestRequestAttributes.AttributesCoprocessor.html" title="class in org.apache.hadoop.hbase.client">TestRequestAttributes.AttributesCoprocessor</a></dt>
@@ -15768,6 +15770,10 @@ loadScripts(document, 'script');</script>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/master/replication/TestTransitPeerSyncReplicationStateProcedureBackoff.html#FAIL" class="member-name-link">FAIL</a> - Static variable in class org.apache.hadoop.hbase.master.replication.<a href="org/apache/hadoop/hbase/master/replication/TestTransitPeerSyncReplicationStateProcedureBackoff.html" title="class in org.apache.hadoop.hbase.master.replication">TestTransitPeerSyncReplicationStateProcedureBackoff</a></dt>
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html#FAIL_FAST_LIMIT_KEY" class="member-name-link">FAIL_FAST_LIMIT_KEY</a> - Static variable in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html" title="class in org.apache.hadoop.hbase.util">RSProcDispatcher</a></dt>
+<dd>
+<div class="block">Config key for the fail-fast retry limit, shared with the test so the two cannot drift.</div>
+</dd>
<dt><a href="org/apache/hadoop/hbase/master/TestLoadProcedureError.html#FAIL_LOAD" class="member-name-link">FAIL_LOAD</a> - Static variable in class org.apache.hadoop.hbase.master.<a href="org/apache/hadoop/hbase/master/TestLoadProcedureError.html" title="class in org.apache.hadoop.hbase.master">TestLoadProcedureError</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/client/AbstractTestAsyncTableRegionReplicasRead.html#FAIL_PRIMARY_GET" class="member-name-link">FAIL_PRIMARY_GET</a> - Static variable in class org.apache.hadoop.hbase.client.<a href="org/apache/hadoop/hbase/client/AbstractTestAsyncTableRegionReplicasRead.html" title="class in org.apache.hadoop.hbase.client">AbstractTestAsyncTableRegionReplicasRead</a></dt>
@@ -15796,6 +15802,8 @@ loadScripts(document, 'script');</script>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/replication/ReplicationEndpointTestBase.InterClusterReplicationEndpointForTest.html#failedOnce" class="member-name-link">failedOnce</a> - Static variable in class org.apache.hadoop.hbase.replication.<a href="org/apache/hadoop/hbase/replication/ReplicationEndpointTestBase.InterClusterReplicationEndpointForTest.html" title="class in org.apache.hadoop.hbase.replication">ReplicationEndpointTestBase.InterClusterReplicationEndpointForTest</a></dt>
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html#failFastLimit" class="member-name-link">failFastLimit</a> - Variable in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html" title="class in org.apache.hadoop.hbase.util">RSProcDispatcher</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/replication/regionserver/TestReplicationSource.BadReplicationEndpoint.html#failing" class="member-name-link">failing</a> - Static variable in class org.apache.hadoop.hbase.replication.regionserver.<a href="org/apache/hadoop/hbase/replication/regionserver/TestReplicationSource.BadReplicationEndpoint.html" title="class in org.apache.hadoop.hbase.replication.regionserver">TestReplicationSource.BadReplicationEndpoint</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/util/TestEncryptionTest.FailingCipherProvider.html#%3Cinit%3E()" class="member-name-link">FailingCipherProvider()</a> - Constructor for class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/TestEncryptionTest.FailingCipherProvider.html" title="class in org.apache.hadoop.hbase.util">TestEncryptionTest.FailingCipherProvider</a></dt>
@@ -25013,8 +25021,6 @@ loadScripts(document, 'script');</script>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/HBaseTestingUtil.SeenRowTracker.html#i(byte)" class="member-name-link">i(byte)</a> - Method in class org.apache.hadoop.hbase.<a href="org/apache/hadoop/hbase/HBaseTestingUtil.SeenRowTracker.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtil.SeenRowTracker</a></dt>
<dd> </dd>
-<dt><a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html#I" class="member-name-link">I</a> - Static variable in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html" title="class in org.apache.hadoop.hbase.util">RSProcDispatcher</a></dt>
-<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/util/TestOrderedBytes.html#I_LENGTHS" class="member-name-link">I_LENGTHS</a> - Static variable in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/TestOrderedBytes.html" title="class in org.apache.hadoop.hbase.util">TestOrderedBytes</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/util/TestOrderedBytes.html#I_VALS" class="member-name-link">I_VALS</a> - Static variable in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/TestOrderedBytes.html" title="class in org.apache.hadoop.hbase.util">TestOrderedBytes</a></dt>
@@ -25730,6 +25736,8 @@ loadScripts(document, 'script');</script>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/client/FromClientSideScanExcpetionTestBase.html#inject()" class="member-name-link">inject()</a> - Static method in class org.apache.hadoop.hbase.client.<a href="org/apache/hadoop/hbase/client/FromClientSideScanExcpetionTestBase.html" title="class in org.apache.hadoop.hbase.client">FromClientSideScanExcpetionTestBase</a></dt>
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html#INJECT" class="member-name-link">INJECT</a> - Static variable in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html" title="class in org.apache.hadoop.hbase.util">RSProcDispatcher</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.InjectAbortOnLoadListener.html#%3Cinit%3E(org.apache.hadoop.hbase.procedure2.ProcedureExecutor)" class="member-name-link">InjectAbortOnLoadListener(ProcedureExecutor<MasterProcedureEnv>)</a> - Constructor for class org.apache.hadoop.hbase.master.procedure.<a href="org/apache/hadoop/hbase/master/procedure/MasterProcedureTestingUtility.InjectAbortOnLoadListener.html" title="class in org.apache.hadoop. [...]
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/master/assignment/TestTRSPPersistUninitializedSubProc.TRSPForTest.html#injected" class="member-name-link">injected</a> - Variable in class org.apache.hadoop.hbase.master.assignment.<a href="org/apache/hadoop/hbase/master/assignment/TestTRSPPersistUninitializedSubProc.TRSPForTest.html" title="class in org.apache.hadoop.hbase.master.assignment">TestTRSPPersistUninitializedSubProc.TRSPForTest</a></dt>
@@ -25747,6 +25755,13 @@ loadScripts(document, 'script');</script>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/replication/TestReplicationEmptyWALRecovery.html#injectEmptyWAL(int,java.util.List)" class="member-name-link">injectEmptyWAL(int, List<Path>)</a> - Method in class org.apache.hadoop.hbase.replication.<a href="org/apache/hadoop/hbase/replication/TestReplicationEmptyWALRecovery.html" title="class in org.apache.hadoop.hbase.replication">TestReplicationEmptyWALRecovery</a></dt>
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html#injectErrors" class="member-name-link">injectErrors</a> - Variable in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html" title="class in org.apache.hadoop.hbase.util">RSProcDispatcher.TestExecuteProceduresRemoteCall</a></dt>
+<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html#injectErrorsForNextRequests(org.apache.hadoop.hbase.TableName,int)" class="member-name-link">injectErrorsForNextRequests(TableName, int)</a> - Static method in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html" title="class in org.apache.hadoop.hbase.util">RSProcDispatcher</a></dt>
+<dd>
+<div class="block">Fails the next <code>n</code> open/close-region requests for <code>table</code> with connection errors
+ until the fail-fast retry limit is exhausted, so the master schedules an SCP.</div>
+</dd>
<dt><a href="org/apache/hadoop/hbase/regionserver/TestFSErrorsExposed.FaultyInputStream.html#injectFault()" class="member-name-link">injectFault()</a> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestFSErrorsExposed.FaultyInputStream.html" title="class in org.apache.hadoop.hbase.regionserver">TestFSErrorsExposed.FaultyInputStream</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/regionserver/TestHStore.FaultyOutputStream.html#injectFault()" class="member-name-link">injectFault()</a> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestHStore.FaultyOutputStream.html" title="class in org.apache.hadoop.hbase.regionserver">TestHStore.FaultyOutputStream</a></dt>
@@ -51535,6 +51550,10 @@ loadScripts(document, 'script');</script>
</dd>
<dt><a href="org/apache/hadoop/hbase/SingleProcessHBaseCluster.html#stopDataNode(org.apache.hadoop.hbase.ServerName)" class="member-name-link">stopDataNode(ServerName)</a> - Method in class org.apache.hadoop.hbase.<a href="org/apache/hadoop/hbase/SingleProcessHBaseCluster.html" title="class in org.apache.hadoop.hbase">SingleProcessHBaseCluster</a></dt>
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html#stopInjecting()" class="member-name-link">stopInjecting()</a> - Static method in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html" title="class in org.apache.hadoop.hbase.util">RSProcDispatcher</a></dt>
+<dd>
+<div class="block">Stops error injection.</div>
+</dd>
<dt><a href="org/apache/hadoop/hbase/DistributedHBaseCluster.html#stopJournalNode(org.apache.hadoop.hbase.ServerName)" class="member-name-link">stopJournalNode(ServerName)</a> - Method in class org.apache.hadoop.hbase.<a href="org/apache/hadoop/hbase/DistributedHBaseCluster.html" title="class in org.apache.hadoop.hbase">DistributedHBaseCluster</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/HBaseClusterInterface.html#stopJournalNode(org.apache.hadoop.hbase.ServerName)" class="member-name-link">stopJournalNode(ServerName)</a> - Method in class org.apache.hadoop.hbase.<a href="org/apache/hadoop/hbase/HBaseClusterInterface.html" title="class in org.apache.hadoop.hbase">HBaseClusterInterface</a></dt>
@@ -53798,12 +53817,18 @@ loadScripts(document, 'script');</script>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/AcidGuaranteesTestTool.AtomicityWriter.html#targetRows" class="member-name-link">targetRows</a> - Variable in class org.apache.hadoop.hbase.<a href="org/apache/hadoop/hbase/AcidGuaranteesTestTool.AtomicityWriter.html" title="class in org.apache.hadoop.hbase">AcidGuaranteesTestTool.AtomicityWriter</a></dt>
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html#targetsInjectionTable(org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ExecuteProceduresRequest)" class="member-name-link">targetsInjectionTable(AdminProtos.ExecuteProceduresRequest)</a> - Static method in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html" title="class in org.apache.hadoop.hbase.util">RSProcDispatcher</a></dt>
+<dd>
+<div class="block">True if the request opens or closes a region of the injection target table.</div>
+</dd>
<dt><a href="org/apache/hadoop/hbase/backup/TestBackupRestoreOnEmptyEnvironment.html#targetTable" class="member-name-link">targetTable</a> - Variable in class org.apache.hadoop.hbase.backup.<a href="org/apache/hadoop/hbase/backup/TestBackupRestoreOnEmptyEnvironment.html" title="class in org.apache.hadoop.hbase.backup">TestBackupRestoreOnEmptyEnvironment</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/backup/TestBackupRestoreWithModifications.html#targetTable" class="member-name-link">targetTable</a> - Variable in class org.apache.hadoop.hbase.backup.<a href="org/apache/hadoop/hbase/backup/TestBackupRestoreWithModifications.html" title="class in org.apache.hadoop.hbase.backup">TestBackupRestoreWithModifications</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/backup/TestIncrementalBackupMergeWithBulkLoad.html#targetTable" class="member-name-link">targetTable</a> - Variable in class org.apache.hadoop.hbase.backup.<a href="org/apache/hadoop/hbase/backup/TestIncrementalBackupMergeWithBulkLoad.html" title="class in org.apache.hadoop.hbase.backup">TestIncrementalBackupMergeWithBulkLoad</a></dt>
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html#targetTable" class="member-name-link">targetTable</a> - Static variable in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html" title="class in org.apache.hadoop.hbase.util">RSProcDispatcher</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/procedure/TestProcedureCoordinator.html#task" class="member-name-link">task</a> - Variable in class org.apache.hadoop.hbase.procedure.<a href="org/apache/hadoop/hbase/procedure/TestProcedureCoordinator.html" title="class in org.apache.hadoop.hbase.procedure">TestProcedureCoordinator</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/ChaosZKClient.html#TASK_BOOLEAN_FALSE" class="member-name-link">TASK_BOOLEAN_FALSE</a> - Static variable in class org.apache.hadoop.hbase.<a href="org/apache/hadoop/hbase/ChaosZKClient.html" title="class in org.apache.hadoop.hbase">ChaosZKClient</a></dt>
@@ -55006,6 +55031,8 @@ loadScripts(document, 'script');</script>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/util/TestMiniClusterLoadSequential.html#tearDown()" class="member-name-link">tearDown()</a> - Method in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/TestMiniClusterLoadSequential.html" title="class in org.apache.hadoop.hbase.util">TestMiniClusterLoadSequential</a></dt>
<dd> </dd>
+<dt><a href="org/apache/hadoop/hbase/util/TestProcDispatcher.html#tearDown()" class="member-name-link">tearDown()</a> - Method in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/TestProcDispatcher.html" title="class in org.apache.hadoop.hbase.util">TestProcDispatcher</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/util/TestRegionMover1.html#tearDown()" class="member-name-link">tearDown()</a> - Method in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/TestRegionMover1.html" title="class in org.apache.hadoop.hbase.util">TestRegionMover1</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/util/TestRegionMover2.html#tearDown()" class="member-name-link">tearDown()</a> - Method in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/TestRegionMover2.html" title="class in org.apache.hadoop.hbase.util">TestRegionMover2</a></dt>
@@ -93070,6 +93097,8 @@ the order they are declared.</div>
<div class="block">Tag a test as region tests which takes longer than 5 minutes to run on public build
infrastructure.</div>
</dd>
+<dt><a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html#VICTIMS_REMAINING" class="member-name-link">VICTIMS_REMAINING</a> - Static variable in class org.apache.hadoop.hbase.util.<a href="org/apache/hadoop/hbase/util/RSProcDispatcher.html" title="class in org.apache.hadoop.hbase.util">RSProcDispatcher</a></dt>
+<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/IntegrationTestIngestWithVisibilityLabels.html#VISIBILITY_EXPS" class="member-name-link">VISIBILITY_EXPS</a> - Static variable in class org.apache.hadoop.hbase.<a href="org/apache/hadoop/hbase/IntegrationTestIngestWithVisibilityLabels.html" title="class in org.apache.hadoop.hbase">IntegrationTestIngestWithVisibilityLabels</a></dt>
<dd> </dd>
<dt><a href="org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.html#VISIBILITY_EXPS" class="member-name-link">VISIBILITY_EXPS</a> - Static variable in class org.apache.hadoop.hbase.test.<a href="org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.html" title="class in org.apache.hadoop.hbase.test">IntegrationTestWithCellVisibilityLoadAndVerify</a></dt>
diff --git a/testdevapidocs/member-search-index.js b/testdevapidocs/member-search-index.js
index 860921bc043..436682cd229 100644
--- a/testdevapidocs/member-search-index.js
+++ b/testdevapidocs/member-search-index.js
@@ -1 +1 @@
-memberSearchIndex = [{"p":"org.apache.hadoop.hbase.master.janitor","c":"TestMetaFixerNoCluster","l":"_ARI"},{"p":"org.apache.hadoop.hbase.io","c":"TestHalfStoreFileReader","l":"_b(String)","u":"_b(java.lang.String)"},{"p":"org.apache.hadoop.hbase.master.janitor","c":"TestMetaFixerNoCluster","l":"_BRI"},{"p":"org.apache.hadoop.hbase.backup","c":"TestSystemTableSnapshot","l":"_testBackupRestoreSystemTable()"},{"p":"org.apache.hadoop.hbase.regionserver","c":"TestBlocksScanned","l":"_testBlo [...]
\ No newline at end of file
+memberSearchIndex = [{"p":"org.apache.hadoop.hbase.master.janitor","c":"TestMetaFixerNoCluster","l":"_ARI"},{"p":"org.apache.hadoop.hbase.io","c":"TestHalfStoreFileReader","l":"_b(String)","u":"_b(java.lang.String)"},{"p":"org.apache.hadoop.hbase.master.janitor","c":"TestMetaFixerNoCluster","l":"_BRI"},{"p":"org.apache.hadoop.hbase.backup","c":"TestSystemTableSnapshot","l":"_testBackupRestoreSystemTable()"},{"p":"org.apache.hadoop.hbase.regionserver","c":"TestBlocksScanned","l":"_testBlo [...]
\ No newline at end of file
diff --git a/testdevapidocs/org/apache/hadoop/hbase/util/RSProcDispatcher.DeadRSRemoteCall.html b/testdevapidocs/org/apache/hadoop/hbase/util/RSProcDispatcher.DeadRSRemoteCall.html
index 65f3c8abe89..d9623540754 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/util/RSProcDispatcher.DeadRSRemoteCall.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/util/RSProcDispatcher.DeadRSRemoteCall.html
@@ -85,7 +85,7 @@ loadScripts(document, 'script');</script>
<dd><a href="RSProcDispatcher.html" title="class in org.apache.hadoop.hbase.util">RSProcDispatcher</a></dd>
</dl>
<hr>
-<div class="type-signature"><span class="modifiers">private class </span><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-103">RSProcDispatcher.DeadRSRemoteCall</a></span>
+<div class="type-signature"><span class="modifiers">private class </span><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-172">RSProcDispatcher.DeadRSRemoteCall</a></span>
<span class="extends-implements">extends <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html" title="class or interface in java.lang" class="external-link">Object</a></span></div>
</section>
<section class="summary">
@@ -138,7 +138,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="<init>(org.apache.hadoop.hbase.ServerName,java.util.Set)">
<h3>DeadRSRemoteCall</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.DeadRSRemoteCall.html#line-105">DeadRSRemoteCall</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.ServerName serverName,
+<div class="member-signature"><span class="modifiers">public</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.DeadRSRemoteCall.html#line-174">DeadRSRemoteCall</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.ServerName serverName,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Set.html" title="class or interface in java.util" class="external-link">Set</a><org.apache.hadoop.hbase.procedure2.RemoteProcedureDispatcher.RemoteProcedure> remoteProcedures)</span></div>
</section>
</li>
@@ -153,7 +153,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="run()">
<h3>run</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.DeadRSRemoteCall.html#line-109">run</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.DeadRSRemoteCall.html#line-178">run</a></span>()</div>
<dl class="notes">
<dt>Specified by:</dt>
<dd><code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Runnable.html#run()" title="class or interface in java.lang" class="external-link">run</a></code> in interface <code><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Runnable.html" title="class or interface in java.lang" class="external-link">Runnable</a></code></dd>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html b/testdevapidocs/org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html
index 03c5421c1eb..5e3422d58e4 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html
@@ -46,13 +46,13 @@ loadScripts(document, 'script');</script>
<ul class="sub-nav-list">
<li>Summary: </li>
<li>Nested | </li>
-<li>Field | </li>
+<li><a href="#field-summary">Field</a> | </li>
<li><a href="#constructor-summary">Constr</a> | </li>
<li><a href="#method-summary">Method</a></li>
</ul>
<ul class="sub-nav-list">
<li>Detail: </li>
-<li>Field | </li>
+<li><a href="#field-detail">Field</a> | </li>
<li><a href="#constructor-detail">Constr</a> | </li>
<li><a href="#method-detail">Method</a></li>
</ul>
@@ -85,11 +85,29 @@ loadScripts(document, 'script');</script>
<dd><a href="RSProcDispatcher.html" title="class in org.apache.hadoop.hbase.util">RSProcDispatcher</a></dd>
</dl>
<hr>
-<div class="type-signature"><span class="modifiers">class </span><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-69">RSProcDispatcher.TestExecuteProceduresRemoteCall</a></span>
+<div class="type-signature"><span class="modifiers">class </span><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-133">RSProcDispatcher.TestExecuteProceduresRemoteCall</a></span>
<span class="extends-implements">extends <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html" title="class or interface in java.lang" class="external-link">Object</a></span></div>
</section>
<section class="summary">
<ul class="summary-list">
+<!-- =========== FIELD SUMMARY =========== -->
+<li>
+<section class="field-summary" id="field-summary">
+<h2>Field Summary</h2>
+<div class="caption"><span>Fields</span></div>
+<div class="summary-table three-column-summary">
+<div class="table-header col-first">Modifier and Type</div>
+<div class="table-header col-second">Field</div>
+<div class="table-header col-last">Description</div>
+<div class="col-first even-row-color"><code>private int</code></div>
+<div class="col-second even-row-color"><code><a href="#attempts" class="member-name-link">attempts</a></code></div>
+<div class="col-last even-row-color"> </div>
+<div class="col-first odd-row-color"><code>private <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Boolean.html" title="class or interface in java.lang" class="external-link">Boolean</a></code></div>
+<div class="col-second odd-row-color"><code><a href="#injectErrors" class="member-name-link">injectErrors</a></code></div>
+<div class="col-last odd-row-color"> </div>
+</div>
+</section>
+</li>
<!-- ======== CONSTRUCTOR SUMMARY ======== -->
<li>
<section class="constructor-summary" id="constructor-summary">
@@ -134,6 +152,26 @@ loadScripts(document, 'script');</script>
</section>
<section class="details">
<ul class="details-list">
+<!-- ============ FIELD DETAIL =========== -->
+<li>
+<section class="field-details" id="field-detail">
+<h2>Field Details</h2>
+<ul class="member-list">
+<li>
+<section class="detail" id="attempts">
+<h3>attempts</h3>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html#line-138">attempts</a></span></div>
+</section>
+</li>
+<li>
+<section class="detail" id="injectErrors">
+<h3>injectErrors</h3>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Boolean.html" title="class or interface in java.lang" class="external-link">Boolean</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html#line-139">injectErrors</a></span></div>
+</section>
+</li>
+</ul>
+</section>
+</li>
<!-- ========= CONSTRUCTOR DETAIL ======== -->
<li>
<section class="constructor-details" id="constructor-detail">
@@ -142,7 +180,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="<init>(org.apache.hadoop.hbase.ServerName,java.util.Set)">
<h3>TestExecuteProceduresRemoteCall</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html#line-71">TestExecuteProceduresRemoteCall</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.ServerName serverName,
+<div class="member-signature"><span class="modifiers">public</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html#line-141">TestExecuteProceduresRemoteCall</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.ServerName serverName,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Set.html" title="class or interface in java.util" class="external-link">Set</a><org.apache.hadoop.hbase.procedure2.RemoteProcedureDispatcher.RemoteProcedure> remoteProcedures)</span></div>
</section>
</li>
@@ -157,7 +195,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="sendRequest(org.apache.hadoop.hbase.ServerName,org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ExecuteProceduresRequest)">
<h3>sendRequest</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ExecuteProceduresResponse</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html#line-76">sendRequest</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.ServerName serverName,
+<div class="member-signature"><span class="modifiers">public</span> <span class="return-type">org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ExecuteProceduresResponse</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html#line-146">sendRequest</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.ServerName serverName,
org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ExecuteProceduresRequest request)</span>
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a></span></div>
<dl class="notes">
@@ -169,7 +207,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="getRsAdmin()">
<h3>getRsAdmin</h3>
-<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">org.apache.hadoop.hbase.client.AsyncRegionServerAdmin</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html#line-98">getRsAdmin</a></span>()</div>
+<div class="member-signature"><span class="modifiers">private</span> <span class="return-type">org.apache.hadoop.hbase.client.AsyncRegionServerAdmin</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html#line-167">getRsAdmin</a></span>()</div>
</section>
</li>
</ul>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/util/RSProcDispatcher.html b/testdevapidocs/org/apache/hadoop/hbase/util/RSProcDispatcher.html
index fd898abe03c..9f14ae013a4 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/util/RSProcDispatcher.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/util/RSProcDispatcher.html
@@ -85,7 +85,7 @@ loadScripts(document, 'script');</script>
<dd><code>org.apache.hadoop.hbase.master.ServerListener</code></dd>
</dl>
<hr>
-<div class="type-signature"><span class="modifiers">public class </span><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-41">RSProcDispatcher</a></span>
+<div class="type-signature"><span class="modifiers">public class </span><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-46">RSProcDispatcher</a></span>
<span class="extends-implements">extends org.apache.hadoop.hbase.master.procedure.RSProcedureDispatcher</span></div>
<div class="block">Test implementation of RSProcedureDispatcher that throws desired errors for testing purpose.</div>
</section>
@@ -130,12 +130,26 @@ loadScripts(document, 'script');</script>
<div class="col-first odd-row-color"><code>private static final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/List.html" title="class or interface in java.util" class="external-link">List</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a>></code></div>
<div class="col-second odd-row-color"><code><a href="#ERRORS" class="member-name-link">ERRORS</a></code></div>
<div class="col-last odd-row-color"> </div>
-<div class="col-first even-row-color"><code>private static final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></code></div>
-<div class="col-second even-row-color"><code><a href="#I" class="member-name-link">I</a></code></div>
+<div class="col-first even-row-color"><code>(package private) static final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></code></div>
+<div class="col-second even-row-color"><code><a href="#FAIL_FAST_LIMIT_KEY" class="member-name-link">FAIL_FAST_LIMIT_KEY</a></code></div>
+<div class="col-last even-row-color">
+<div class="block">Config key for the fail-fast retry limit, shared with the test so the two cannot drift.</div>
+</div>
+<div class="col-first odd-row-color"><code>private final int</code></div>
+<div class="col-second odd-row-color"><code><a href="#failFastLimit" class="member-name-link">failFastLimit</a></code></div>
+<div class="col-last odd-row-color"> </div>
+<div class="col-first even-row-color"><code>private static final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicBoolean.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicBoolean</a></code></div>
+<div class="col-second even-row-color"><code><a href="#INJECT" class="member-name-link">INJECT</a></code></div>
<div class="col-last even-row-color"> </div>
<div class="col-first odd-row-color"><code>private static final org.slf4j.Logger</code></div>
<div class="col-second odd-row-color"><code><a href="#LOG" class="member-name-link">LOG</a></code></div>
<div class="col-last odd-row-color"> </div>
+<div class="col-first even-row-color"><code>private static org.apache.hadoop.hbase.TableName</code></div>
+<div class="col-second even-row-color"><code><a href="#targetTable" class="member-name-link">targetTable</a></code></div>
+<div class="col-last even-row-color"> </div>
+<div class="col-first odd-row-color"><code>private static final <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></code></div>
+<div class="col-second odd-row-color"><code><a href="#VICTIMS_REMAINING" class="member-name-link">VICTIMS_REMAINING</a></code></div>
+<div class="col-last odd-row-color"> </div>
</div>
<div class="inherited-list">
<h3 id="fields-inherited-from-class-org.apache.hadoop.hbase.master.procedure.RSProcedureDispatcher">Fields inherited from class org.apache.hadoop.hbase.master.procedure.RSProcedureDispatcher</h3>
@@ -163,16 +177,33 @@ loadScripts(document, 'script');</script>
<section class="method-summary" id="method-summary">
<h2>Method Summary</h2>
<div id="method-summary-table">
-<div class="table-tabs" role="tablist" aria-orientation="horizontal"><button id="method-summary-table-tab0" role="tab" aria-selected="true" aria-controls="method-summary-table.tabpanel" tabindex="0" onkeydown="switchTab(event)" onclick="show('method-summary-table', 'method-summary-table', 3)" class="active-table-tab">All Methods</button><button id="method-summary-table-tab2" role="tab" aria-selected="false" aria-controls="method-summary-table.tabpanel" tabindex="-1" onkeydown="switchTab( [...]
+<div class="table-tabs" role="tablist" aria-orientation="horizontal"><button id="method-summary-table-tab0" role="tab" aria-selected="true" aria-controls="method-summary-table.tabpanel" tabindex="0" onkeydown="switchTab(event)" onclick="show('method-summary-table', 'method-summary-table', 3)" class="active-table-tab">All Methods</button><button id="method-summary-table-tab1" role="tab" aria-selected="false" aria-controls="method-summary-table.tabpanel" tabindex="-1" onkeydown="switchTab( [...]
<div id="method-summary-table.tabpanel" role="tabpanel">
<div class="summary-table three-column-summary" aria-labelledby="method-summary-table-tab0">
<div class="table-header col-first">Modifier and Type</div>
<div class="table-header col-second">Method</div>
<div class="table-header col-last">Description</div>
-<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>protected void</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#remoteDispatch(org.apache.hadoop.hbase.ServerName,java.util.Set)" class="member-name-link">remoteDispatch</a><wbr>(org.apache.hadoop.hbase.ServerName serverName,
+<div class="col-first even-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4"><code>(package private) static void</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4"><code><a href="#injectErrorsForNextRequests(org.apache.hadoop.hbase.TableName,int)" class="member-name-link">injectErrorsForNextRequests</a><wbr>(org.apache.hadoop.hbase.TableName table,
+ int n)</code></div>
+<div class="col-last even-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4">
+<div class="block">Fails the next <code>n</code> open/close-region requests for <code>table</code> with connection errors
+ until the fail-fast retry limit is exhausted, so the master schedules an SCP.</div>
+</div>
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>protected void</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#remoteDispatch(org.apache.hadoop.hbase.ServerName,java.util.Set)" class="member-name-link">remoteDispatch</a><wbr>(org.apache.hadoop.hbase.ServerName serverName,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Set.html" title="class or interface in java.util" class="external-link">Set</a><org.apache.hadoop.hbase.procedure2.RemoteProcedureDispatcher.RemoteProcedure> remoteProcedures)</code></div>
-<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
+<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4"><code>(package private) static void</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4"><code><a href="#stopInjecting()" class="member-name-link">stopInjecting</a>()</code></div>
+<div class="col-last even-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4">
+<div class="block">Stops error injection.</div>
+</div>
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4"><code>private static boolean</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4"><code><a href="#targetsInjectionTable(org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ExecuteProceduresRequest)" class="member-name-link">targetsInjectionTable</a><wbr>(org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ExecuteProceduresRequest request)</code></div>
+<div class="col-last odd-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4">
+<div class="block">True if the request opens or closes a region of the injection target table.</div>
+</div>
</div>
</div>
</div>
@@ -202,25 +233,58 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="LOG">
<h3>LOG</h3>
-<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type">org.slf4j.Logger</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-43">LOG</a></span></div>
+<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type">org.slf4j.Logger</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-48">LOG</a></span></div>
</section>
</li>
<li>
-<section class="detail" id="I">
-<h3>I</h3>
-<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-45">I</a></span></div>
+<section class="detail" id="FAIL_FAST_LIMIT_KEY">
+<h3>FAIL_FAST_LIMIT_KEY</h3>
+<div class="member-signature"><span class="modifiers">static final</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/String.html" title="class or interface in java.lang" class="external-link">String</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-51">FAIL_FAST_LIMIT_KEY</a></span></div>
+<div class="block">Config key for the fail-fast retry limit, shared with the test so the two cannot drift.</div>
+<dl class="notes">
+<dt>See Also:</dt>
+<dd>
+<ul class="see-list">
+<li><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.util.RSProcDispatcher.FAIL_FAST_LIMIT_KEY">Constant Field Values</a></li>
+</ul>
+</dd>
+</dl>
</section>
</li>
<li>
<section class="detail" id="ERRORS">
<h3>ERRORS</h3>
-<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/List.html" title="class or interface in java.util" class="external-link">List</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a>></span> <span class="element-name" [...]
+<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/List.html" title="class or interface in java.util" class="external-link">List</a><<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/io/IOException.html" title="class or interface in java.io" class="external-link">IOException</a>></span> <span class="element-name" [...]
</section>
</li>
<li>
<section class="detail" id="ERROR_IDX">
<h3>ERROR_IDX</h3>
-<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-52">ERROR_IDX</a></span></div>
+<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-58">ERROR_IDX</a></span></div>
+</section>
+</li>
+<li>
+<section class="detail" id="INJECT">
+<h3>INJECT</h3>
+<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicBoolean.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicBoolean</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-63">INJECT</a></span></div>
+</section>
+</li>
+<li>
+<section class="detail" id="VICTIMS_REMAINING">
+<h3>VICTIMS_REMAINING</h3>
+<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/concurrent/atomic/AtomicInteger.html" title="class or interface in java.util.concurrent.atomic" class="external-link">AtomicInteger</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-64">VICTIMS_REMAINING</a></span></div>
+</section>
+</li>
+<li>
+<section class="detail" id="targetTable">
+<h3>targetTable</h3>
+<div class="member-signature"><span class="modifiers">private static volatile</span> <span class="return-type">org.apache.hadoop.hbase.TableName</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-65">targetTable</a></span></div>
+</section>
+</li>
+<li>
+<section class="detail" id="failFastLimit">
+<h3>failFastLimit</h3>
+<div class="member-signature"><span class="modifiers">private final</span> <span class="return-type">int</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-68">failFastLimit</a></span></div>
</section>
</li>
</ul>
@@ -234,7 +298,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="<init>(org.apache.hadoop.hbase.master.MasterServices)">
<h3>RSProcDispatcher</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-54">RSProcDispatcher</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.master.MasterServices master)</span></div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-89">RSProcDispatcher</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.master.MasterServices master)</span></div>
</section>
</li>
</ul>
@@ -246,9 +310,26 @@ loadScripts(document, 'script');</script>
<h2>Method Details</h2>
<ul class="member-list">
<li>
+<section class="detail" id="injectErrorsForNextRequests(org.apache.hadoop.hbase.TableName,int)">
+<h3>injectErrorsForNextRequests</h3>
+<div class="member-signature"><span class="modifiers">static</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-75">injectErrorsForNextRequests</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.TableName table,
+ int n)</span></div>
+<div class="block">Fails the next <code>n</code> open/close-region requests for <code>table</code> with connection errors
+ until the fail-fast retry limit is exhausted, so the master schedules an SCP. Call right before
+ the operations under test.</div>
+</section>
+</li>
+<li>
+<section class="detail" id="stopInjecting()">
+<h3>stopInjecting</h3>
+<div class="member-signature"><span class="modifiers">static</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-83">stopInjecting</a></span>()</div>
+<div class="block">Stops error injection. Safe to call unconditionally, e.g. from test teardown.</div>
+</section>
+</li>
+<li>
<section class="detail" id="remoteDispatch(org.apache.hadoop.hbase.ServerName,java.util.Set)">
<h3>remoteDispatch</h3>
-<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-58">remoteDispatch</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.ServerName serverName,
+<div class="member-signature"><span class="modifiers">protected</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-94">remoteDispatch</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.ServerName serverName,
<a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Set.html" title="class or interface in java.util" class="external-link">Set</a><org.apache.hadoop.hbase.procedure2.RemoteProcedureDispatcher.RemoteProcedure> remoteProcedures)</span></div>
<dl class="notes">
<dt>Overrides:</dt>
@@ -256,6 +337,14 @@ loadScripts(document, 'script');</script>
</dl>
</section>
</li>
+<li>
+<section class="detail" id="targetsInjectionTable(org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ExecuteProceduresRequest)">
+<h3>targetsInjectionTable</h3>
+<div class="member-signature"><span class="modifiers">private static</span> <span class="return-type">boolean</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html#line-109">targetsInjectionTable</a></span><wbr><span class="parameters">(org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos.ExecuteProceduresRequest request)</span></div>
+<div class="block">True if the request opens or closes a region of the injection target table. Open requests carry
+ a full RegionInfo; close requests carry a REGION_NAME specifier the table is parsed from.</div>
+</section>
+</li>
</ul>
</section>
</li>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/util/TestProcDispatcher.html b/testdevapidocs/org/apache/hadoop/hbase/util/TestProcDispatcher.html
index 35af0a1533a..067e9cb1186 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/util/TestProcDispatcher.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/util/TestProcDispatcher.html
@@ -78,7 +78,7 @@ loadScripts(document, 'script');</script>
<section class="class-description" id="class-description">
<hr>
<div class="type-signature"><span class="annotations">@Tag("org.apache.hadoop.hbase.testclassification.MiscTests") @Tag("org.apache.hadoop.hbase.testclassification.LargeTests")
-</span><span class="modifiers">public class </span><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-58">TestProcDispatcher</a></span>
+</span><span class="modifiers">public class </span><span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-59">TestProcDispatcher</a></span>
<span class="extends-implements">extends <a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Object.html" title="class or interface in java.lang" class="external-link">Object</a></span></div>
<div class="block">Testing custom RSProcedureDispatcher to ensure retry limit can be imposed on certain errors.</div>
</section>
@@ -135,12 +135,15 @@ loadScripts(document, 'script');</script>
<div class="col-first odd-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4"><code>static void</code></div>
<div class="col-second odd-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4"><code><a href="#setUpBeforeClass()" class="member-name-link">setUpBeforeClass</a>()</code></div>
<div class="col-last odd-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4"> </div>
-<div class="col-first even-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4"><code>static void</code></div>
-<div class="col-second even-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4"><code><a href="#tearDownAfterClass()" class="member-name-link">tearDownAfterClass</a>()</code></div>
-<div class="col-last even-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4"> </div>
-<div class="col-first odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>void</code></div>
-<div class="col-second odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#testRetryLimitOnConnClosedErrors(org.junit.jupiter.api.TestInfo)" class="member-name-link">testRetryLimitOnConnClosedErrors</a><wbr>(org.junit.jupiter.api.TestInfo testInfo)</code></div>
-<div class="col-last odd-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>void</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#tearDown()" class="member-name-link">tearDown</a>()</code></div>
+<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
+<div class="col-first odd-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4"><code>static void</code></div>
+<div class="col-second odd-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4"><code><a href="#tearDownAfterClass()" class="member-name-link">tearDownAfterClass</a>()</code></div>
+<div class="col-last odd-row-color method-summary-table method-summary-table-tab1 method-summary-table-tab4"> </div>
+<div class="col-first even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code>void</code></div>
+<div class="col-second even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"><code><a href="#testRetryLimitOnConnClosedErrors(org.junit.jupiter.api.TestInfo)" class="member-name-link">testRetryLimitOnConnClosedErrors</a><wbr>(org.junit.jupiter.api.TestInfo testInfo)</code></div>
+<div class="col-last even-row-color method-summary-table method-summary-table-tab2 method-summary-table-tab4"> </div>
</div>
</div>
</div>
@@ -161,19 +164,19 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="LOG">
<h3>LOG</h3>
-<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type">org.slf4j.Logger</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-62">LOG</a></span></div>
+<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type">org.slf4j.Logger</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-63">LOG</a></span></div>
</section>
</li>
<li>
<section class="detail" id="TEST_UTIL">
<h3>TEST_UTIL</h3>
-<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type"><a href="../HBaseTestingUtil.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtil</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-64">TEST_UTIL</a></span></div>
+<div class="member-signature"><span class="modifiers">private static final</span> <span class="return-type"><a href="../HBaseTestingUtil.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtil</a></span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-65">TEST_UTIL</a></span></div>
</section>
</li>
<li>
<section class="detail" id="rs0">
<h3>rs0</h3>
-<div class="member-signature"><span class="modifiers">private static</span> <span class="return-type">org.apache.hadoop.hbase.ServerName</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-65">rs0</a></span></div>
+<div class="member-signature"><span class="modifiers">private static</span> <span class="return-type">org.apache.hadoop.hbase.ServerName</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-66">rs0</a></span></div>
</section>
</li>
</ul>
@@ -187,7 +190,7 @@ loadScripts(document, 'script');</script>
<li>
<section class="detail" id="<init>()">
<h3>TestProcDispatcher</h3>
-<div class="member-signature"><span class="modifiers">public</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-60">TestProcDispatcher</a></span>()</div>
+<div class="member-signature"><span class="modifiers">public</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-61">TestProcDispatcher</a></span>()</div>
</section>
</li>
</ul>
@@ -202,7 +205,7 @@ loadScripts(document, 'script');</script>
<section class="detail" id="setUpBeforeClass()">
<h3>setUpBeforeClass</h3>
<div class="member-signature"><span class="annotations">@BeforeAll
-</span><span class="modifiers">public static</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-67">setUpBeforeClass</a></span>()
+</span><span class="modifiers">public static</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-68">setUpBeforeClass</a></span>()
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Exception.html" title="class or interface in java.lang" class="external-link">Exception</a></span></div>
<dl class="notes">
<dt>Throws:</dt>
@@ -214,7 +217,7 @@ loadScripts(document, 'script');</script>
<section class="detail" id="tearDownAfterClass()">
<h3>tearDownAfterClass</h3>
<div class="member-signature"><span class="annotations">@AfterAll
-</span><span class="modifiers">public static</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-78">tearDownAfterClass</a></span>()
+</span><span class="modifiers">public static</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-79">tearDownAfterClass</a></span>()
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Exception.html" title="class or interface in java.lang" class="external-link">Exception</a></span></div>
<dl class="notes">
<dt>Throws:</dt>
@@ -226,7 +229,7 @@ loadScripts(document, 'script');</script>
<section class="detail" id="setUp(org.junit.jupiter.api.TestInfo)">
<h3>setUp</h3>
<div class="member-signature"><span class="annotations">@BeforeEach
-</span><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-83">setUp</a></span><wbr><span class="parameters">(org.junit.jupiter.api.TestInfo testInfo)</span>
+</span><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-84">setUp</a></span><wbr><span class="parameters">(org.junit.jupiter.api.TestInfo testInfo)</span>
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Exception.html" title="class or interface in java.lang" class="external-link">Exception</a></span></div>
<dl class="notes">
<dt>Throws:</dt>
@@ -235,10 +238,17 @@ loadScripts(document, 'script');</script>
</section>
</li>
<li>
+<section class="detail" id="tearDown()">
+<h3>tearDown</h3>
+<div class="member-signature"><span class="annotations">@AfterEach
+</span><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-94">tearDown</a></span>()</div>
+</section>
+</li>
+<li>
<section class="detail" id="testRetryLimitOnConnClosedErrors(org.junit.jupiter.api.TestInfo)">
<h3>testRetryLimitOnConnClosedErrors</h3>
<div class="member-signature"><span class="annotations">@Test
-</span><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-93">testRetryLimitOnConnClosedErrors</a></span><wbr><span class="parameters">(org.junit.jupiter.api.TestInfo testInfo)</span>
+</span><span class="modifiers">public</span> <span class="return-type">void</span> <span class="element-name"><a href="../../../../../src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html#line-99">testRetryLimitOnConnClosedErrors</a></span><wbr><span class="parameters">(org.junit.jupiter.api.TestInfo testInfo)</span>
throws <span class="exceptions"><a href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Exception.html" title="class or interface in java.lang" class="external-link">Exception</a></span></div>
<dl class="notes">
<dt>Throws:</dt>
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.DeadRSRemoteCall.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.DeadRSRemoteCall.html
index 5baa2fe87d7..9b63bfdaa12 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.DeadRSRemoteCall.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.DeadRSRemoteCall.html
@@ -36,97 +36,165 @@
<span class="source-line-no">023</span><span id="line-23">import java.util.Arrays;</span>
<span class="source-line-no">024</span><span id="line-24">import java.util.List;</span>
<span class="source-line-no">025</span><span id="line-25">import java.util.Set;</span>
-<span class="source-line-no">026</span><span id="line-26">import java.util.concurrent.atomic.AtomicInteger;</span>
-<span class="source-line-no">027</span><span id="line-27">import org.apache.hadoop.hbase.ServerName;</span>
-<span class="source-line-no">028</span><span id="line-28">import org.apache.hadoop.hbase.client.AsyncRegionServerAdmin;</span>
-<span class="source-line-no">029</span><span id="line-29">import org.apache.hadoop.hbase.exceptions.ConnectionClosedException;</span>
-<span class="source-line-no">030</span><span id="line-30">import org.apache.hadoop.hbase.master.MasterServices;</span>
-<span class="source-line-no">031</span><span id="line-31">import org.apache.hadoop.hbase.master.procedure.RSProcedureDispatcher;</span>
-<span class="source-line-no">032</span><span id="line-32">import org.apache.hadoop.hbase.regionserver.RegionServerStoppedException;</span>
-<span class="source-line-no">033</span><span id="line-33">import org.slf4j.Logger;</span>
-<span class="source-line-no">034</span><span id="line-34">import org.slf4j.LoggerFactory;</span>
-<span class="source-line-no">035</span><span id="line-35"></span>
-<span class="source-line-no">036</span><span id="line-36">import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos;</span>
-<span class="source-line-no">037</span><span id="line-37"></span>
-<span class="source-line-no">038</span><span id="line-38">/**</span>
-<span class="source-line-no">039</span><span id="line-39"> * Test implementation of RSProcedureDispatcher that throws desired errors for testing purpose.</span>
-<span class="source-line-no">040</span><span id="line-40"> */</span>
-<span class="source-line-no">041</span><span id="line-41">public class RSProcDispatcher extends RSProcedureDispatcher {</span>
+<span class="source-line-no">026</span><span id="line-26">import java.util.concurrent.atomic.AtomicBoolean;</span>
+<span class="source-line-no">027</span><span id="line-27">import java.util.concurrent.atomic.AtomicInteger;</span>
+<span class="source-line-no">028</span><span id="line-28">import org.apache.hadoop.hbase.ServerName;</span>
+<span class="source-line-no">029</span><span id="line-29">import org.apache.hadoop.hbase.TableName;</span>
+<span class="source-line-no">030</span><span id="line-30">import org.apache.hadoop.hbase.client.AsyncRegionServerAdmin;</span>
+<span class="source-line-no">031</span><span id="line-31">import org.apache.hadoop.hbase.client.RegionInfo;</span>
+<span class="source-line-no">032</span><span id="line-32">import org.apache.hadoop.hbase.exceptions.ConnectionClosedException;</span>
+<span class="source-line-no">033</span><span id="line-33">import org.apache.hadoop.hbase.master.MasterServices;</span>
+<span class="source-line-no">034</span><span id="line-34">import org.apache.hadoop.hbase.master.procedure.RSProcedureDispatcher;</span>
+<span class="source-line-no">035</span><span id="line-35">import org.apache.hadoop.hbase.regionserver.RegionServerStoppedException;</span>
+<span class="source-line-no">036</span><span id="line-36">import org.slf4j.Logger;</span>
+<span class="source-line-no">037</span><span id="line-37">import org.slf4j.LoggerFactory;</span>
+<span class="source-line-no">038</span><span id="line-38"></span>
+<span class="source-line-no">039</span><span id="line-39">import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;</span>
+<span class="source-line-no">040</span><span id="line-40">import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos;</span>
+<span class="source-line-no">041</span><span id="line-41">import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;</span>
<span class="source-line-no">042</span><span id="line-42"></span>
-<span class="source-line-no">043</span><span id="line-43"> private static final Logger LOG = LoggerFactory.getLogger(RSProcDispatcher.class);</span>
-<span class="source-line-no">044</span><span id="line-44"></span>
-<span class="source-line-no">045</span><span id="line-45"> private static final AtomicInteger I = new AtomicInteger();</span>
-<span class="source-line-no">046</span><span id="line-46"></span>
-<span class="source-line-no">047</span><span id="line-47"> private static final List<IOException> ERRORS =</span>
-<span class="source-line-no">048</span><span id="line-48"> Arrays.asList(new ConnectionClosedException("test connection closed error..."),</span>
-<span class="source-line-no">049</span><span id="line-49"> new UnknownHostException("test unknown host error..."),</span>
-<span class="source-line-no">050</span><span id="line-50"> new ConnectException("test connect error..."));</span>
-<span class="source-line-no">051</span><span id="line-51"></span>
-<span class="source-line-no">052</span><span id="line-52"> private static final AtomicInteger ERROR_IDX = new AtomicInteger();</span>
-<span class="source-line-no">053</span><span id="line-53"></span>
-<span class="source-line-no">054</span><span id="line-54"> public RSProcDispatcher(MasterServices master) {</span>
-<span class="source-line-no">055</span><span id="line-55"> super(master);</span>
-<span class="source-line-no">056</span><span id="line-56"> }</span>
+<span class="source-line-no">043</span><span id="line-43">/**</span>
+<span class="source-line-no">044</span><span id="line-44"> * Test implementation of RSProcedureDispatcher that throws desired errors for testing purpose.</span>
+<span class="source-line-no">045</span><span id="line-45"> */</span>
+<span class="source-line-no">046</span><span id="line-46">public class RSProcDispatcher extends RSProcedureDispatcher {</span>
+<span class="source-line-no">047</span><span id="line-47"></span>
+<span class="source-line-no">048</span><span id="line-48"> private static final Logger LOG = LoggerFactory.getLogger(RSProcDispatcher.class);</span>
+<span class="source-line-no">049</span><span id="line-49"></span>
+<span class="source-line-no">050</span><span id="line-50"> /** Config key for the fail-fast retry limit, shared with the test so the two cannot drift. */</span>
+<span class="source-line-no">051</span><span id="line-51"> static final String FAIL_FAST_LIMIT_KEY = "hbase.master.rs.remote.proc.fail.fast.limit";</span>
+<span class="source-line-no">052</span><span id="line-52"></span>
+<span class="source-line-no">053</span><span id="line-53"> private static final List<IOException> ERRORS =</span>
+<span class="source-line-no">054</span><span id="line-54"> Arrays.asList(new ConnectionClosedException("test connection closed error..."),</span>
+<span class="source-line-no">055</span><span id="line-55"> new UnknownHostException("test unknown host error..."),</span>
+<span class="source-line-no">056</span><span id="line-56"> new ConnectException("test connect error..."));</span>
<span class="source-line-no">057</span><span id="line-57"></span>
-<span class="source-line-no">058</span><span id="line-58"> @Override</span>
-<span class="source-line-no">059</span><span id="line-59"> protected void remoteDispatch(final ServerName serverName,</span>
-<span class="source-line-no">060</span><span id="line-60"> final Set<RemoteProcedure> remoteProcedures) {</span>
-<span class="source-line-no">061</span><span id="line-61"> if (!master.getServerManager().isServerOnline(serverName)) {</span>
-<span class="source-line-no">062</span><span id="line-62"> // fail fast</span>
-<span class="source-line-no">063</span><span id="line-63"> submitTask(new DeadRSRemoteCall(serverName, remoteProcedures));</span>
-<span class="source-line-no">064</span><span id="line-64"> } else {</span>
-<span class="source-line-no">065</span><span id="line-65"> submitTask(new TestExecuteProceduresRemoteCall(serverName, remoteProcedures));</span>
-<span class="source-line-no">066</span><span id="line-66"> }</span>
-<span class="source-line-no">067</span><span id="line-67"> }</span>
-<span class="source-line-no">068</span><span id="line-68"></span>
-<span class="source-line-no">069</span><span id="line-69"> class TestExecuteProceduresRemoteCall extends ExecuteProceduresRemoteCall {</span>
-<span class="source-line-no">070</span><span id="line-70"></span>
-<span class="source-line-no">071</span><span id="line-71"> public TestExecuteProceduresRemoteCall(ServerName serverName,</span>
-<span class="source-line-no">072</span><span id="line-72"> Set<RemoteProcedure> remoteProcedures) {</span>
-<span class="source-line-no">073</span><span id="line-73"> super(serverName, remoteProcedures);</span>
-<span class="source-line-no">074</span><span id="line-74"> }</span>
-<span class="source-line-no">075</span><span id="line-75"></span>
-<span class="source-line-no">076</span><span id="line-76"> @Override</span>
-<span class="source-line-no">077</span><span id="line-77"> public AdminProtos.ExecuteProceduresResponse sendRequest(final ServerName serverName,</span>
-<span class="source-line-no">078</span><span id="line-78"> final AdminProtos.ExecuteProceduresRequest request) throws IOException {</span>
-<span class="source-line-no">079</span><span id="line-79"> int j = I.addAndGet(1);</span>
-<span class="source-line-no">080</span><span id="line-80"> LOG.info("sendRequest() req: {} , j: {}", request, j);</span>
-<span class="source-line-no">081</span><span id="line-81"> if (j == 12 || j == 22) {</span>
-<span class="source-line-no">082</span><span id="line-82"> // Execute the remote close and open region requests in the last (5th) retry before</span>
-<span class="source-line-no">083</span><span id="line-83"> // throwing ConnectionClosedException. This is to ensure even if the region open/close</span>
-<span class="source-line-no">084</span><span id="line-84"> // is successfully completed by regionserver, master still schedules SCP because</span>
-<span class="source-line-no">085</span><span id="line-85"> // sendRequest() throws error which has retry-limit exhausted.</span>
-<span class="source-line-no">086</span><span id="line-86"> FutureUtils.get(getRsAdmin().executeProcedures(request));</span>
-<span class="source-line-no">087</span><span id="line-87"> }</span>
-<span class="source-line-no">088</span><span id="line-88"> // For one of the close region requests and one of the open region requests,</span>
-<span class="source-line-no">089</span><span id="line-89"> // throw ConnectionClosedException until retry limit is exhausted and master</span>
-<span class="source-line-no">090</span><span id="line-90"> // schedules recoveries for the server.</span>
-<span class="source-line-no">091</span><span id="line-91"> // We will have ABNORMALLY_CLOSED regions, and they are expected to recover on their own.</span>
-<span class="source-line-no">092</span><span id="line-92"> if (j >= 8 && j <= 13 || j >= 18 && j <= 23) {</span>
-<span class="source-line-no">093</span><span id="line-93"> throw ERRORS.get(ERROR_IDX.getAndIncrement() % ERRORS.size());</span>
-<span class="source-line-no">094</span><span id="line-94"> }</span>
-<span class="source-line-no">095</span><span id="line-95"> return FutureUtils.get(getRsAdmin().executeProcedures(request));</span>
-<span class="source-line-no">096</span><span id="line-96"> }</span>
-<span class="source-line-no">097</span><span id="line-97"></span>
-<span class="source-line-no">098</span><span id="line-98"> private AsyncRegionServerAdmin getRsAdmin() {</span>
-<span class="source-line-no">099</span><span id="line-99"> return master.getAsyncClusterConnection().getRegionServerAdmin(getServerName());</span>
-<span class="source-line-no">100</span><span id="line-100"> }</span>
-<span class="source-line-no">101</span><span id="line-101"> }</span>
-<span class="source-line-no">102</span><span id="line-102"></span>
-<span class="source-line-no">103</span><span id="line-103"> private class DeadRSRemoteCall extends ExecuteProceduresRemoteCall {</span>
+<span class="source-line-no">058</span><span id="line-58"> private static final AtomicInteger ERROR_IDX = new AtomicInteger();</span>
+<span class="source-line-no">059</span><span id="line-59"></span>
+<span class="source-line-no">060</span><span id="line-60"> // Injection is driven by the test and bound to a target table, not a global call count:</span>
+<span class="source-line-no">061</span><span id="line-61"> // remoteDispatch() fires for every remote procedure in the cluster (startup, table creation,</span>
+<span class="source-line-no">062</span><span id="line-62"> // chores, background assignments), so counting calls drifts and misses the operations under test.</span>
+<span class="source-line-no">063</span><span id="line-63"> private static final AtomicBoolean INJECT = new AtomicBoolean(false);</span>
+<span class="source-line-no">064</span><span id="line-64"> private static final AtomicInteger VICTIMS_REMAINING = new AtomicInteger(0);</span>
+<span class="source-line-no">065</span><span id="line-65"> private static volatile TableName targetTable;</span>
+<span class="source-line-no">066</span><span id="line-66"></span>
+<span class="source-line-no">067</span><span id="line-67"> // Fail-fast retry limit after which the master schedules an SCP; read from conf to match test.</span>
+<span class="source-line-no">068</span><span id="line-68"> private final int failFastLimit;</span>
+<span class="source-line-no">069</span><span id="line-69"></span>
+<span class="source-line-no">070</span><span id="line-70"> /**</span>
+<span class="source-line-no">071</span><span id="line-71"> * Fails the next {@code n} open/close-region requests for {@code table} with connection errors</span>
+<span class="source-line-no">072</span><span id="line-72"> * until the fail-fast retry limit is exhausted, so the master schedules an SCP. Call right before</span>
+<span class="source-line-no">073</span><span id="line-73"> * the operations under test.</span>
+<span class="source-line-no">074</span><span id="line-74"> */</span>
+<span class="source-line-no">075</span><span id="line-75"> static void injectErrorsForNextRequests(TableName table, int n) {</span>
+<span class="source-line-no">076</span><span id="line-76"> ERROR_IDX.set(0);</span>
+<span class="source-line-no">077</span><span id="line-77"> targetTable = table;</span>
+<span class="source-line-no">078</span><span id="line-78"> VICTIMS_REMAINING.set(n);</span>
+<span class="source-line-no">079</span><span id="line-79"> INJECT.set(true);</span>
+<span class="source-line-no">080</span><span id="line-80"> }</span>
+<span class="source-line-no">081</span><span id="line-81"></span>
+<span class="source-line-no">082</span><span id="line-82"> /** Stops error injection. Safe to call unconditionally, e.g. from test teardown. */</span>
+<span class="source-line-no">083</span><span id="line-83"> static void stopInjecting() {</span>
+<span class="source-line-no">084</span><span id="line-84"> INJECT.set(false);</span>
+<span class="source-line-no">085</span><span id="line-85"> VICTIMS_REMAINING.set(0);</span>
+<span class="source-line-no">086</span><span id="line-86"> targetTable = null;</span>
+<span class="source-line-no">087</span><span id="line-87"> }</span>
+<span class="source-line-no">088</span><span id="line-88"></span>
+<span class="source-line-no">089</span><span id="line-89"> public RSProcDispatcher(MasterServices master) {</span>
+<span class="source-line-no">090</span><span id="line-90"> super(master);</span>
+<span class="source-line-no">091</span><span id="line-91"> this.failFastLimit = master.getConfiguration().getInt(FAIL_FAST_LIMIT_KEY, 10);</span>
+<span class="source-line-no">092</span><span id="line-92"> }</span>
+<span class="source-line-no">093</span><span id="line-93"></span>
+<span class="source-line-no">094</span><span id="line-94"> @Override</span>
+<span class="source-line-no">095</span><span id="line-95"> protected void remoteDispatch(final ServerName serverName,</span>
+<span class="source-line-no">096</span><span id="line-96"> final Set<RemoteProcedure> remoteProcedures) {</span>
+<span class="source-line-no">097</span><span id="line-97"> if (!master.getServerManager().isServerOnline(serverName)) {</span>
+<span class="source-line-no">098</span><span id="line-98"> // fail fast</span>
+<span class="source-line-no">099</span><span id="line-99"> submitTask(new DeadRSRemoteCall(serverName, remoteProcedures));</span>
+<span class="source-line-no">100</span><span id="line-100"> } else {</span>
+<span class="source-line-no">101</span><span id="line-101"> submitTask(new TestExecuteProceduresRemoteCall(serverName, remoteProcedures));</span>
+<span class="source-line-no">102</span><span id="line-102"> }</span>
+<span class="source-line-no">103</span><span id="line-103"> }</span>
<span class="source-line-no">104</span><span id="line-104"></span>
-<span class="source-line-no">105</span><span id="line-105"> public DeadRSRemoteCall(ServerName serverName, Set<RemoteProcedure> remoteProcedures) {</span>
-<span class="source-line-no">106</span><span id="line-106"> super(serverName, remoteProcedures);</span>
-<span class="source-line-no">107</span><span id="line-107"> }</span>
-<span class="source-line-no">108</span><span id="line-108"></span>
-<span class="source-line-no">109</span><span id="line-109"> @Override</span>
-<span class="source-line-no">110</span><span id="line-110"> public void run() {</span>
-<span class="source-line-no">111</span><span id="line-111"> remoteCallFailed(master.getMasterProcedureExecutor().getEnvironment(),</span>
-<span class="source-line-no">112</span><span id="line-112"> new RegionServerStoppedException("Server " + getServerName() + " is not online"));</span>
+<span class="source-line-no">105</span><span id="line-105"> /**</span>
+<span class="source-line-no">106</span><span id="line-106"> * True if the request opens or closes a region of the injection target table. Open requests carry</span>
+<span class="source-line-no">107</span><span id="line-107"> * a full RegionInfo; close requests carry a REGION_NAME specifier the table is parsed from.</span>
+<span class="source-line-no">108</span><span id="line-108"> */</span>
+<span class="source-line-no">109</span><span id="line-109"> private static boolean targetsInjectionTable(AdminProtos.ExecuteProceduresRequest request) {</span>
+<span class="source-line-no">110</span><span id="line-110"> TableName table = targetTable;</span>
+<span class="source-line-no">111</span><span id="line-111"> if (table == null) {</span>
+<span class="source-line-no">112</span><span id="line-112"> return false;</span>
<span class="source-line-no">113</span><span id="line-113"> }</span>
-<span class="source-line-no">114</span><span id="line-114"> }</span>
-<span class="source-line-no">115</span><span id="line-115"></span>
-<span class="source-line-no">116</span><span id="line-116">}</span>
+<span class="source-line-no">114</span><span id="line-114"> for (AdminProtos.OpenRegionRequest open : request.getOpenRegionList()) {</span>
+<span class="source-line-no">115</span><span id="line-115"> for (AdminProtos.OpenRegionRequest.RegionOpenInfo info : open.getOpenInfoList()) {</span>
+<span class="source-line-no">116</span><span id="line-116"> if (table.equals(ProtobufUtil.toTableName(info.getRegion().getTableName()))) {</span>
+<span class="source-line-no">117</span><span id="line-117"> return true;</span>
+<span class="source-line-no">118</span><span id="line-118"> }</span>
+<span class="source-line-no">119</span><span id="line-119"> }</span>
+<span class="source-line-no">120</span><span id="line-120"> }</span>
+<span class="source-line-no">121</span><span id="line-121"> for (AdminProtos.CloseRegionRequest close : request.getCloseRegionList()) {</span>
+<span class="source-line-no">122</span><span id="line-122"> HBaseProtos.RegionSpecifier region = close.getRegion();</span>
+<span class="source-line-no">123</span><span id="line-123"> if (</span>
+<span class="source-line-no">124</span><span id="line-124"> region.getType() == HBaseProtos.RegionSpecifier.RegionSpecifierType.REGION_NAME</span>
+<span class="source-line-no">125</span><span id="line-125"> && table.equals(RegionInfo.getTable(region.getValue().toByteArray()))</span>
+<span class="source-line-no">126</span><span id="line-126"> ) {</span>
+<span class="source-line-no">127</span><span id="line-127"> return true;</span>
+<span class="source-line-no">128</span><span id="line-128"> }</span>
+<span class="source-line-no">129</span><span id="line-129"> }</span>
+<span class="source-line-no">130</span><span id="line-130"> return false;</span>
+<span class="source-line-no">131</span><span id="line-131"> }</span>
+<span class="source-line-no">132</span><span id="line-132"></span>
+<span class="source-line-no">133</span><span id="line-133"> class TestExecuteProceduresRemoteCall extends ExecuteProceduresRemoteCall {</span>
+<span class="source-line-no">134</span><span id="line-134"></span>
+<span class="source-line-no">135</span><span id="line-135"> // attempts: retries of this single request instance (mirrors the dispatcher's</span>
+<span class="source-line-no">136</span><span id="line-136"> // numberOfAttemptsSoFar). injectErrors: whether this instance is failed with injected errors,</span>
+<span class="source-line-no">137</span><span id="line-137"> // decided once on the first call and kept across its retries.</span>
+<span class="source-line-no">138</span><span id="line-138"> private int attempts = 0;</span>
+<span class="source-line-no">139</span><span id="line-139"> private Boolean injectErrors = null;</span>
+<span class="source-line-no">140</span><span id="line-140"></span>
+<span class="source-line-no">141</span><span id="line-141"> public TestExecuteProceduresRemoteCall(ServerName serverName,</span>
+<span class="source-line-no">142</span><span id="line-142"> Set<RemoteProcedure> remoteProcedures) {</span>
+<span class="source-line-no">143</span><span id="line-143"> super(serverName, remoteProcedures);</span>
+<span class="source-line-no">144</span><span id="line-144"> }</span>
+<span class="source-line-no">145</span><span id="line-145"></span>
+<span class="source-line-no">146</span><span id="line-146"> @Override</span>
+<span class="source-line-no">147</span><span id="line-147"> public AdminProtos.ExecuteProceduresResponse sendRequest(final ServerName serverName,</span>
+<span class="source-line-no">148</span><span id="line-148"> final AdminProtos.ExecuteProceduresRequest request) throws IOException {</span>
+<span class="source-line-no">149</span><span id="line-149"> if (injectErrors == null) {</span>
+<span class="source-line-no">150</span><span id="line-150"> // Claim a slot only for a target-table open/close request, once per instance.</span>
+<span class="source-line-no">151</span><span id="line-151"> injectErrors =</span>
+<span class="source-line-no">152</span><span id="line-152"> INJECT.get() && targetsInjectionTable(request) && VICTIMS_REMAINING.getAndDecrement() > 0;</span>
+<span class="source-line-no">153</span><span id="line-153"> }</span>
+<span class="source-line-no">154</span><span id="line-154"> LOG.info("sendRequest() req: {}, attempts: {}, injectErrors: {}", request, attempts,</span>
+<span class="source-line-no">155</span><span id="line-155"> injectErrors);</span>
+<span class="source-line-no">156</span><span id="line-156"> if (!injectErrors) {</span>
+<span class="source-line-no">157</span><span id="line-157"> return FutureUtils.get(getRsAdmin().executeProcedures(request));</span>
+<span class="source-line-no">158</span><span id="line-158"> }</span>
+<span class="source-line-no">159</span><span id="line-159"> // Throw a connection error each attempt until the retry limit is exhausted (-> SCP). On the</span>
+<span class="source-line-no">160</span><span id="line-160"> // last attempt run the real open/close first so the region still recovers.</span>
+<span class="source-line-no">161</span><span id="line-161"> if (attempts++ >= failFastLimit - 1) {</span>
+<span class="source-line-no">162</span><span id="line-162"> FutureUtils.get(getRsAdmin().executeProcedures(request));</span>
+<span class="source-line-no">163</span><span id="line-163"> }</span>
+<span class="source-line-no">164</span><span id="line-164"> throw ERRORS.get(ERROR_IDX.getAndIncrement() % ERRORS.size());</span>
+<span class="source-line-no">165</span><span id="line-165"> }</span>
+<span class="source-line-no">166</span><span id="line-166"></span>
+<span class="source-line-no">167</span><span id="line-167"> private AsyncRegionServerAdmin getRsAdmin() {</span>
+<span class="source-line-no">168</span><span id="line-168"> return master.getAsyncClusterConnection().getRegionServerAdmin(getServerName());</span>
+<span class="source-line-no">169</span><span id="line-169"> }</span>
+<span class="source-line-no">170</span><span id="line-170"> }</span>
+<span class="source-line-no">171</span><span id="line-171"></span>
+<span class="source-line-no">172</span><span id="line-172"> private class DeadRSRemoteCall extends ExecuteProceduresRemoteCall {</span>
+<span class="source-line-no">173</span><span id="line-173"></span>
+<span class="source-line-no">174</span><span id="line-174"> public DeadRSRemoteCall(ServerName serverName, Set<RemoteProcedure> remoteProcedures) {</span>
+<span class="source-line-no">175</span><span id="line-175"> super(serverName, remoteProcedures);</span>
+<span class="source-line-no">176</span><span id="line-176"> }</span>
+<span class="source-line-no">177</span><span id="line-177"></span>
+<span class="source-line-no">178</span><span id="line-178"> @Override</span>
+<span class="source-line-no">179</span><span id="line-179"> public void run() {</span>
+<span class="source-line-no">180</span><span id="line-180"> remoteCallFailed(master.getMasterProcedureExecutor().getEnvironment(),</span>
+<span class="source-line-no">181</span><span id="line-181"> new RegionServerStoppedException("Server " + getServerName() + " is not online"));</span>
+<span class="source-line-no">182</span><span id="line-182"> }</span>
+<span class="source-line-no">183</span><span id="line-183"> }</span>
+<span class="source-line-no">184</span><span id="line-184">}</span>
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html
index f746d603faa..08180d7a118 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.TestExecuteProceduresRemoteCall.html
@@ -36,97 +36,165 @@
<span class="source-line-no">023</span><span id="line-23">import java.util.Arrays;</span>
<span class="source-line-no">024</span><span id="line-24">import java.util.List;</span>
<span class="source-line-no">025</span><span id="line-25">import java.util.Set;</span>
-<span class="source-line-no">026</span><span id="line-26">import java.util.concurrent.atomic.AtomicInteger;</span>
-<span class="source-line-no">027</span><span id="line-27">import org.apache.hadoop.hbase.ServerName;</span>
-<span class="source-line-no">028</span><span id="line-28">import org.apache.hadoop.hbase.client.AsyncRegionServerAdmin;</span>
-<span class="source-line-no">029</span><span id="line-29">import org.apache.hadoop.hbase.exceptions.ConnectionClosedException;</span>
-<span class="source-line-no">030</span><span id="line-30">import org.apache.hadoop.hbase.master.MasterServices;</span>
-<span class="source-line-no">031</span><span id="line-31">import org.apache.hadoop.hbase.master.procedure.RSProcedureDispatcher;</span>
-<span class="source-line-no">032</span><span id="line-32">import org.apache.hadoop.hbase.regionserver.RegionServerStoppedException;</span>
-<span class="source-line-no">033</span><span id="line-33">import org.slf4j.Logger;</span>
-<span class="source-line-no">034</span><span id="line-34">import org.slf4j.LoggerFactory;</span>
-<span class="source-line-no">035</span><span id="line-35"></span>
-<span class="source-line-no">036</span><span id="line-36">import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos;</span>
-<span class="source-line-no">037</span><span id="line-37"></span>
-<span class="source-line-no">038</span><span id="line-38">/**</span>
-<span class="source-line-no">039</span><span id="line-39"> * Test implementation of RSProcedureDispatcher that throws desired errors for testing purpose.</span>
-<span class="source-line-no">040</span><span id="line-40"> */</span>
-<span class="source-line-no">041</span><span id="line-41">public class RSProcDispatcher extends RSProcedureDispatcher {</span>
+<span class="source-line-no">026</span><span id="line-26">import java.util.concurrent.atomic.AtomicBoolean;</span>
+<span class="source-line-no">027</span><span id="line-27">import java.util.concurrent.atomic.AtomicInteger;</span>
+<span class="source-line-no">028</span><span id="line-28">import org.apache.hadoop.hbase.ServerName;</span>
+<span class="source-line-no">029</span><span id="line-29">import org.apache.hadoop.hbase.TableName;</span>
+<span class="source-line-no">030</span><span id="line-30">import org.apache.hadoop.hbase.client.AsyncRegionServerAdmin;</span>
+<span class="source-line-no">031</span><span id="line-31">import org.apache.hadoop.hbase.client.RegionInfo;</span>
+<span class="source-line-no">032</span><span id="line-32">import org.apache.hadoop.hbase.exceptions.ConnectionClosedException;</span>
+<span class="source-line-no">033</span><span id="line-33">import org.apache.hadoop.hbase.master.MasterServices;</span>
+<span class="source-line-no">034</span><span id="line-34">import org.apache.hadoop.hbase.master.procedure.RSProcedureDispatcher;</span>
+<span class="source-line-no">035</span><span id="line-35">import org.apache.hadoop.hbase.regionserver.RegionServerStoppedException;</span>
+<span class="source-line-no">036</span><span id="line-36">import org.slf4j.Logger;</span>
+<span class="source-line-no">037</span><span id="line-37">import org.slf4j.LoggerFactory;</span>
+<span class="source-line-no">038</span><span id="line-38"></span>
+<span class="source-line-no">039</span><span id="line-39">import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;</span>
+<span class="source-line-no">040</span><span id="line-40">import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos;</span>
+<span class="source-line-no">041</span><span id="line-41">import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;</span>
<span class="source-line-no">042</span><span id="line-42"></span>
-<span class="source-line-no">043</span><span id="line-43"> private static final Logger LOG = LoggerFactory.getLogger(RSProcDispatcher.class);</span>
-<span class="source-line-no">044</span><span id="line-44"></span>
-<span class="source-line-no">045</span><span id="line-45"> private static final AtomicInteger I = new AtomicInteger();</span>
-<span class="source-line-no">046</span><span id="line-46"></span>
-<span class="source-line-no">047</span><span id="line-47"> private static final List<IOException> ERRORS =</span>
-<span class="source-line-no">048</span><span id="line-48"> Arrays.asList(new ConnectionClosedException("test connection closed error..."),</span>
-<span class="source-line-no">049</span><span id="line-49"> new UnknownHostException("test unknown host error..."),</span>
-<span class="source-line-no">050</span><span id="line-50"> new ConnectException("test connect error..."));</span>
-<span class="source-line-no">051</span><span id="line-51"></span>
-<span class="source-line-no">052</span><span id="line-52"> private static final AtomicInteger ERROR_IDX = new AtomicInteger();</span>
-<span class="source-line-no">053</span><span id="line-53"></span>
-<span class="source-line-no">054</span><span id="line-54"> public RSProcDispatcher(MasterServices master) {</span>
-<span class="source-line-no">055</span><span id="line-55"> super(master);</span>
-<span class="source-line-no">056</span><span id="line-56"> }</span>
+<span class="source-line-no">043</span><span id="line-43">/**</span>
+<span class="source-line-no">044</span><span id="line-44"> * Test implementation of RSProcedureDispatcher that throws desired errors for testing purpose.</span>
+<span class="source-line-no">045</span><span id="line-45"> */</span>
+<span class="source-line-no">046</span><span id="line-46">public class RSProcDispatcher extends RSProcedureDispatcher {</span>
+<span class="source-line-no">047</span><span id="line-47"></span>
+<span class="source-line-no">048</span><span id="line-48"> private static final Logger LOG = LoggerFactory.getLogger(RSProcDispatcher.class);</span>
+<span class="source-line-no">049</span><span id="line-49"></span>
+<span class="source-line-no">050</span><span id="line-50"> /** Config key for the fail-fast retry limit, shared with the test so the two cannot drift. */</span>
+<span class="source-line-no">051</span><span id="line-51"> static final String FAIL_FAST_LIMIT_KEY = "hbase.master.rs.remote.proc.fail.fast.limit";</span>
+<span class="source-line-no">052</span><span id="line-52"></span>
+<span class="source-line-no">053</span><span id="line-53"> private static final List<IOException> ERRORS =</span>
+<span class="source-line-no">054</span><span id="line-54"> Arrays.asList(new ConnectionClosedException("test connection closed error..."),</span>
+<span class="source-line-no">055</span><span id="line-55"> new UnknownHostException("test unknown host error..."),</span>
+<span class="source-line-no">056</span><span id="line-56"> new ConnectException("test connect error..."));</span>
<span class="source-line-no">057</span><span id="line-57"></span>
-<span class="source-line-no">058</span><span id="line-58"> @Override</span>
-<span class="source-line-no">059</span><span id="line-59"> protected void remoteDispatch(final ServerName serverName,</span>
-<span class="source-line-no">060</span><span id="line-60"> final Set<RemoteProcedure> remoteProcedures) {</span>
-<span class="source-line-no">061</span><span id="line-61"> if (!master.getServerManager().isServerOnline(serverName)) {</span>
-<span class="source-line-no">062</span><span id="line-62"> // fail fast</span>
-<span class="source-line-no">063</span><span id="line-63"> submitTask(new DeadRSRemoteCall(serverName, remoteProcedures));</span>
-<span class="source-line-no">064</span><span id="line-64"> } else {</span>
-<span class="source-line-no">065</span><span id="line-65"> submitTask(new TestExecuteProceduresRemoteCall(serverName, remoteProcedures));</span>
-<span class="source-line-no">066</span><span id="line-66"> }</span>
-<span class="source-line-no">067</span><span id="line-67"> }</span>
-<span class="source-line-no">068</span><span id="line-68"></span>
-<span class="source-line-no">069</span><span id="line-69"> class TestExecuteProceduresRemoteCall extends ExecuteProceduresRemoteCall {</span>
-<span class="source-line-no">070</span><span id="line-70"></span>
-<span class="source-line-no">071</span><span id="line-71"> public TestExecuteProceduresRemoteCall(ServerName serverName,</span>
-<span class="source-line-no">072</span><span id="line-72"> Set<RemoteProcedure> remoteProcedures) {</span>
-<span class="source-line-no">073</span><span id="line-73"> super(serverName, remoteProcedures);</span>
-<span class="source-line-no">074</span><span id="line-74"> }</span>
-<span class="source-line-no">075</span><span id="line-75"></span>
-<span class="source-line-no">076</span><span id="line-76"> @Override</span>
-<span class="source-line-no">077</span><span id="line-77"> public AdminProtos.ExecuteProceduresResponse sendRequest(final ServerName serverName,</span>
-<span class="source-line-no">078</span><span id="line-78"> final AdminProtos.ExecuteProceduresRequest request) throws IOException {</span>
-<span class="source-line-no">079</span><span id="line-79"> int j = I.addAndGet(1);</span>
-<span class="source-line-no">080</span><span id="line-80"> LOG.info("sendRequest() req: {} , j: {}", request, j);</span>
-<span class="source-line-no">081</span><span id="line-81"> if (j == 12 || j == 22) {</span>
-<span class="source-line-no">082</span><span id="line-82"> // Execute the remote close and open region requests in the last (5th) retry before</span>
-<span class="source-line-no">083</span><span id="line-83"> // throwing ConnectionClosedException. This is to ensure even if the region open/close</span>
-<span class="source-line-no">084</span><span id="line-84"> // is successfully completed by regionserver, master still schedules SCP because</span>
-<span class="source-line-no">085</span><span id="line-85"> // sendRequest() throws error which has retry-limit exhausted.</span>
-<span class="source-line-no">086</span><span id="line-86"> FutureUtils.get(getRsAdmin().executeProcedures(request));</span>
-<span class="source-line-no">087</span><span id="line-87"> }</span>
-<span class="source-line-no">088</span><span id="line-88"> // For one of the close region requests and one of the open region requests,</span>
-<span class="source-line-no">089</span><span id="line-89"> // throw ConnectionClosedException until retry limit is exhausted and master</span>
-<span class="source-line-no">090</span><span id="line-90"> // schedules recoveries for the server.</span>
-<span class="source-line-no">091</span><span id="line-91"> // We will have ABNORMALLY_CLOSED regions, and they are expected to recover on their own.</span>
-<span class="source-line-no">092</span><span id="line-92"> if (j >= 8 && j <= 13 || j >= 18 && j <= 23) {</span>
-<span class="source-line-no">093</span><span id="line-93"> throw ERRORS.get(ERROR_IDX.getAndIncrement() % ERRORS.size());</span>
-<span class="source-line-no">094</span><span id="line-94"> }</span>
-<span class="source-line-no">095</span><span id="line-95"> return FutureUtils.get(getRsAdmin().executeProcedures(request));</span>
-<span class="source-line-no">096</span><span id="line-96"> }</span>
-<span class="source-line-no">097</span><span id="line-97"></span>
-<span class="source-line-no">098</span><span id="line-98"> private AsyncRegionServerAdmin getRsAdmin() {</span>
-<span class="source-line-no">099</span><span id="line-99"> return master.getAsyncClusterConnection().getRegionServerAdmin(getServerName());</span>
-<span class="source-line-no">100</span><span id="line-100"> }</span>
-<span class="source-line-no">101</span><span id="line-101"> }</span>
-<span class="source-line-no">102</span><span id="line-102"></span>
-<span class="source-line-no">103</span><span id="line-103"> private class DeadRSRemoteCall extends ExecuteProceduresRemoteCall {</span>
+<span class="source-line-no">058</span><span id="line-58"> private static final AtomicInteger ERROR_IDX = new AtomicInteger();</span>
+<span class="source-line-no">059</span><span id="line-59"></span>
+<span class="source-line-no">060</span><span id="line-60"> // Injection is driven by the test and bound to a target table, not a global call count:</span>
+<span class="source-line-no">061</span><span id="line-61"> // remoteDispatch() fires for every remote procedure in the cluster (startup, table creation,</span>
+<span class="source-line-no">062</span><span id="line-62"> // chores, background assignments), so counting calls drifts and misses the operations under test.</span>
+<span class="source-line-no">063</span><span id="line-63"> private static final AtomicBoolean INJECT = new AtomicBoolean(false);</span>
+<span class="source-line-no">064</span><span id="line-64"> private static final AtomicInteger VICTIMS_REMAINING = new AtomicInteger(0);</span>
+<span class="source-line-no">065</span><span id="line-65"> private static volatile TableName targetTable;</span>
+<span class="source-line-no">066</span><span id="line-66"></span>
+<span class="source-line-no">067</span><span id="line-67"> // Fail-fast retry limit after which the master schedules an SCP; read from conf to match test.</span>
+<span class="source-line-no">068</span><span id="line-68"> private final int failFastLimit;</span>
+<span class="source-line-no">069</span><span id="line-69"></span>
+<span class="source-line-no">070</span><span id="line-70"> /**</span>
+<span class="source-line-no">071</span><span id="line-71"> * Fails the next {@code n} open/close-region requests for {@code table} with connection errors</span>
+<span class="source-line-no">072</span><span id="line-72"> * until the fail-fast retry limit is exhausted, so the master schedules an SCP. Call right before</span>
+<span class="source-line-no">073</span><span id="line-73"> * the operations under test.</span>
+<span class="source-line-no">074</span><span id="line-74"> */</span>
+<span class="source-line-no">075</span><span id="line-75"> static void injectErrorsForNextRequests(TableName table, int n) {</span>
+<span class="source-line-no">076</span><span id="line-76"> ERROR_IDX.set(0);</span>
+<span class="source-line-no">077</span><span id="line-77"> targetTable = table;</span>
+<span class="source-line-no">078</span><span id="line-78"> VICTIMS_REMAINING.set(n);</span>
+<span class="source-line-no">079</span><span id="line-79"> INJECT.set(true);</span>
+<span class="source-line-no">080</span><span id="line-80"> }</span>
+<span class="source-line-no">081</span><span id="line-81"></span>
+<span class="source-line-no">082</span><span id="line-82"> /** Stops error injection. Safe to call unconditionally, e.g. from test teardown. */</span>
+<span class="source-line-no">083</span><span id="line-83"> static void stopInjecting() {</span>
+<span class="source-line-no">084</span><span id="line-84"> INJECT.set(false);</span>
+<span class="source-line-no">085</span><span id="line-85"> VICTIMS_REMAINING.set(0);</span>
+<span class="source-line-no">086</span><span id="line-86"> targetTable = null;</span>
+<span class="source-line-no">087</span><span id="line-87"> }</span>
+<span class="source-line-no">088</span><span id="line-88"></span>
+<span class="source-line-no">089</span><span id="line-89"> public RSProcDispatcher(MasterServices master) {</span>
+<span class="source-line-no">090</span><span id="line-90"> super(master);</span>
+<span class="source-line-no">091</span><span id="line-91"> this.failFastLimit = master.getConfiguration().getInt(FAIL_FAST_LIMIT_KEY, 10);</span>
+<span class="source-line-no">092</span><span id="line-92"> }</span>
+<span class="source-line-no">093</span><span id="line-93"></span>
+<span class="source-line-no">094</span><span id="line-94"> @Override</span>
+<span class="source-line-no">095</span><span id="line-95"> protected void remoteDispatch(final ServerName serverName,</span>
+<span class="source-line-no">096</span><span id="line-96"> final Set<RemoteProcedure> remoteProcedures) {</span>
+<span class="source-line-no">097</span><span id="line-97"> if (!master.getServerManager().isServerOnline(serverName)) {</span>
+<span class="source-line-no">098</span><span id="line-98"> // fail fast</span>
+<span class="source-line-no">099</span><span id="line-99"> submitTask(new DeadRSRemoteCall(serverName, remoteProcedures));</span>
+<span class="source-line-no">100</span><span id="line-100"> } else {</span>
+<span class="source-line-no">101</span><span id="line-101"> submitTask(new TestExecuteProceduresRemoteCall(serverName, remoteProcedures));</span>
+<span class="source-line-no">102</span><span id="line-102"> }</span>
+<span class="source-line-no">103</span><span id="line-103"> }</span>
<span class="source-line-no">104</span><span id="line-104"></span>
-<span class="source-line-no">105</span><span id="line-105"> public DeadRSRemoteCall(ServerName serverName, Set<RemoteProcedure> remoteProcedures) {</span>
-<span class="source-line-no">106</span><span id="line-106"> super(serverName, remoteProcedures);</span>
-<span class="source-line-no">107</span><span id="line-107"> }</span>
-<span class="source-line-no">108</span><span id="line-108"></span>
-<span class="source-line-no">109</span><span id="line-109"> @Override</span>
-<span class="source-line-no">110</span><span id="line-110"> public void run() {</span>
-<span class="source-line-no">111</span><span id="line-111"> remoteCallFailed(master.getMasterProcedureExecutor().getEnvironment(),</span>
-<span class="source-line-no">112</span><span id="line-112"> new RegionServerStoppedException("Server " + getServerName() + " is not online"));</span>
+<span class="source-line-no">105</span><span id="line-105"> /**</span>
+<span class="source-line-no">106</span><span id="line-106"> * True if the request opens or closes a region of the injection target table. Open requests carry</span>
+<span class="source-line-no">107</span><span id="line-107"> * a full RegionInfo; close requests carry a REGION_NAME specifier the table is parsed from.</span>
+<span class="source-line-no">108</span><span id="line-108"> */</span>
+<span class="source-line-no">109</span><span id="line-109"> private static boolean targetsInjectionTable(AdminProtos.ExecuteProceduresRequest request) {</span>
+<span class="source-line-no">110</span><span id="line-110"> TableName table = targetTable;</span>
+<span class="source-line-no">111</span><span id="line-111"> if (table == null) {</span>
+<span class="source-line-no">112</span><span id="line-112"> return false;</span>
<span class="source-line-no">113</span><span id="line-113"> }</span>
-<span class="source-line-no">114</span><span id="line-114"> }</span>
-<span class="source-line-no">115</span><span id="line-115"></span>
-<span class="source-line-no">116</span><span id="line-116">}</span>
+<span class="source-line-no">114</span><span id="line-114"> for (AdminProtos.OpenRegionRequest open : request.getOpenRegionList()) {</span>
+<span class="source-line-no">115</span><span id="line-115"> for (AdminProtos.OpenRegionRequest.RegionOpenInfo info : open.getOpenInfoList()) {</span>
+<span class="source-line-no">116</span><span id="line-116"> if (table.equals(ProtobufUtil.toTableName(info.getRegion().getTableName()))) {</span>
+<span class="source-line-no">117</span><span id="line-117"> return true;</span>
+<span class="source-line-no">118</span><span id="line-118"> }</span>
+<span class="source-line-no">119</span><span id="line-119"> }</span>
+<span class="source-line-no">120</span><span id="line-120"> }</span>
+<span class="source-line-no">121</span><span id="line-121"> for (AdminProtos.CloseRegionRequest close : request.getCloseRegionList()) {</span>
+<span class="source-line-no">122</span><span id="line-122"> HBaseProtos.RegionSpecifier region = close.getRegion();</span>
+<span class="source-line-no">123</span><span id="line-123"> if (</span>
+<span class="source-line-no">124</span><span id="line-124"> region.getType() == HBaseProtos.RegionSpecifier.RegionSpecifierType.REGION_NAME</span>
+<span class="source-line-no">125</span><span id="line-125"> && table.equals(RegionInfo.getTable(region.getValue().toByteArray()))</span>
+<span class="source-line-no">126</span><span id="line-126"> ) {</span>
+<span class="source-line-no">127</span><span id="line-127"> return true;</span>
+<span class="source-line-no">128</span><span id="line-128"> }</span>
+<span class="source-line-no">129</span><span id="line-129"> }</span>
+<span class="source-line-no">130</span><span id="line-130"> return false;</span>
+<span class="source-line-no">131</span><span id="line-131"> }</span>
+<span class="source-line-no">132</span><span id="line-132"></span>
+<span class="source-line-no">133</span><span id="line-133"> class TestExecuteProceduresRemoteCall extends ExecuteProceduresRemoteCall {</span>
+<span class="source-line-no">134</span><span id="line-134"></span>
+<span class="source-line-no">135</span><span id="line-135"> // attempts: retries of this single request instance (mirrors the dispatcher's</span>
+<span class="source-line-no">136</span><span id="line-136"> // numberOfAttemptsSoFar). injectErrors: whether this instance is failed with injected errors,</span>
+<span class="source-line-no">137</span><span id="line-137"> // decided once on the first call and kept across its retries.</span>
+<span class="source-line-no">138</span><span id="line-138"> private int attempts = 0;</span>
+<span class="source-line-no">139</span><span id="line-139"> private Boolean injectErrors = null;</span>
+<span class="source-line-no">140</span><span id="line-140"></span>
+<span class="source-line-no">141</span><span id="line-141"> public TestExecuteProceduresRemoteCall(ServerName serverName,</span>
+<span class="source-line-no">142</span><span id="line-142"> Set<RemoteProcedure> remoteProcedures) {</span>
+<span class="source-line-no">143</span><span id="line-143"> super(serverName, remoteProcedures);</span>
+<span class="source-line-no">144</span><span id="line-144"> }</span>
+<span class="source-line-no">145</span><span id="line-145"></span>
+<span class="source-line-no">146</span><span id="line-146"> @Override</span>
+<span class="source-line-no">147</span><span id="line-147"> public AdminProtos.ExecuteProceduresResponse sendRequest(final ServerName serverName,</span>
+<span class="source-line-no">148</span><span id="line-148"> final AdminProtos.ExecuteProceduresRequest request) throws IOException {</span>
+<span class="source-line-no">149</span><span id="line-149"> if (injectErrors == null) {</span>
+<span class="source-line-no">150</span><span id="line-150"> // Claim a slot only for a target-table open/close request, once per instance.</span>
+<span class="source-line-no">151</span><span id="line-151"> injectErrors =</span>
+<span class="source-line-no">152</span><span id="line-152"> INJECT.get() && targetsInjectionTable(request) && VICTIMS_REMAINING.getAndDecrement() > 0;</span>
+<span class="source-line-no">153</span><span id="line-153"> }</span>
+<span class="source-line-no">154</span><span id="line-154"> LOG.info("sendRequest() req: {}, attempts: {}, injectErrors: {}", request, attempts,</span>
+<span class="source-line-no">155</span><span id="line-155"> injectErrors);</span>
+<span class="source-line-no">156</span><span id="line-156"> if (!injectErrors) {</span>
+<span class="source-line-no">157</span><span id="line-157"> return FutureUtils.get(getRsAdmin().executeProcedures(request));</span>
+<span class="source-line-no">158</span><span id="line-158"> }</span>
+<span class="source-line-no">159</span><span id="line-159"> // Throw a connection error each attempt until the retry limit is exhausted (-> SCP). On the</span>
+<span class="source-line-no">160</span><span id="line-160"> // last attempt run the real open/close first so the region still recovers.</span>
+<span class="source-line-no">161</span><span id="line-161"> if (attempts++ >= failFastLimit - 1) {</span>
+<span class="source-line-no">162</span><span id="line-162"> FutureUtils.get(getRsAdmin().executeProcedures(request));</span>
+<span class="source-line-no">163</span><span id="line-163"> }</span>
+<span class="source-line-no">164</span><span id="line-164"> throw ERRORS.get(ERROR_IDX.getAndIncrement() % ERRORS.size());</span>
+<span class="source-line-no">165</span><span id="line-165"> }</span>
+<span class="source-line-no">166</span><span id="line-166"></span>
+<span class="source-line-no">167</span><span id="line-167"> private AsyncRegionServerAdmin getRsAdmin() {</span>
+<span class="source-line-no">168</span><span id="line-168"> return master.getAsyncClusterConnection().getRegionServerAdmin(getServerName());</span>
+<span class="source-line-no">169</span><span id="line-169"> }</span>
+<span class="source-line-no">170</span><span id="line-170"> }</span>
+<span class="source-line-no">171</span><span id="line-171"></span>
+<span class="source-line-no">172</span><span id="line-172"> private class DeadRSRemoteCall extends ExecuteProceduresRemoteCall {</span>
+<span class="source-line-no">173</span><span id="line-173"></span>
+<span class="source-line-no">174</span><span id="line-174"> public DeadRSRemoteCall(ServerName serverName, Set<RemoteProcedure> remoteProcedures) {</span>
+<span class="source-line-no">175</span><span id="line-175"> super(serverName, remoteProcedures);</span>
+<span class="source-line-no">176</span><span id="line-176"> }</span>
+<span class="source-line-no">177</span><span id="line-177"></span>
+<span class="source-line-no">178</span><span id="line-178"> @Override</span>
+<span class="source-line-no">179</span><span id="line-179"> public void run() {</span>
+<span class="source-line-no">180</span><span id="line-180"> remoteCallFailed(master.getMasterProcedureExecutor().getEnvironment(),</span>
+<span class="source-line-no">181</span><span id="line-181"> new RegionServerStoppedException("Server " + getServerName() + " is not online"));</span>
+<span class="source-line-no">182</span><span id="line-182"> }</span>
+<span class="source-line-no">183</span><span id="line-183"> }</span>
+<span class="source-line-no">184</span><span id="line-184">}</span>
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html
index b676f94e16b..fcca06ad2ba 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/util/RSProcDispatcher.html
@@ -36,97 +36,165 @@
<span class="source-line-no">023</span><span id="line-23">import java.util.Arrays;</span>
<span class="source-line-no">024</span><span id="line-24">import java.util.List;</span>
<span class="source-line-no">025</span><span id="line-25">import java.util.Set;</span>
-<span class="source-line-no">026</span><span id="line-26">import java.util.concurrent.atomic.AtomicInteger;</span>
-<span class="source-line-no">027</span><span id="line-27">import org.apache.hadoop.hbase.ServerName;</span>
-<span class="source-line-no">028</span><span id="line-28">import org.apache.hadoop.hbase.client.AsyncRegionServerAdmin;</span>
-<span class="source-line-no">029</span><span id="line-29">import org.apache.hadoop.hbase.exceptions.ConnectionClosedException;</span>
-<span class="source-line-no">030</span><span id="line-30">import org.apache.hadoop.hbase.master.MasterServices;</span>
-<span class="source-line-no">031</span><span id="line-31">import org.apache.hadoop.hbase.master.procedure.RSProcedureDispatcher;</span>
-<span class="source-line-no">032</span><span id="line-32">import org.apache.hadoop.hbase.regionserver.RegionServerStoppedException;</span>
-<span class="source-line-no">033</span><span id="line-33">import org.slf4j.Logger;</span>
-<span class="source-line-no">034</span><span id="line-34">import org.slf4j.LoggerFactory;</span>
-<span class="source-line-no">035</span><span id="line-35"></span>
-<span class="source-line-no">036</span><span id="line-36">import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos;</span>
-<span class="source-line-no">037</span><span id="line-37"></span>
-<span class="source-line-no">038</span><span id="line-38">/**</span>
-<span class="source-line-no">039</span><span id="line-39"> * Test implementation of RSProcedureDispatcher that throws desired errors for testing purpose.</span>
-<span class="source-line-no">040</span><span id="line-40"> */</span>
-<span class="source-line-no">041</span><span id="line-41">public class RSProcDispatcher extends RSProcedureDispatcher {</span>
+<span class="source-line-no">026</span><span id="line-26">import java.util.concurrent.atomic.AtomicBoolean;</span>
+<span class="source-line-no">027</span><span id="line-27">import java.util.concurrent.atomic.AtomicInteger;</span>
+<span class="source-line-no">028</span><span id="line-28">import org.apache.hadoop.hbase.ServerName;</span>
+<span class="source-line-no">029</span><span id="line-29">import org.apache.hadoop.hbase.TableName;</span>
+<span class="source-line-no">030</span><span id="line-30">import org.apache.hadoop.hbase.client.AsyncRegionServerAdmin;</span>
+<span class="source-line-no">031</span><span id="line-31">import org.apache.hadoop.hbase.client.RegionInfo;</span>
+<span class="source-line-no">032</span><span id="line-32">import org.apache.hadoop.hbase.exceptions.ConnectionClosedException;</span>
+<span class="source-line-no">033</span><span id="line-33">import org.apache.hadoop.hbase.master.MasterServices;</span>
+<span class="source-line-no">034</span><span id="line-34">import org.apache.hadoop.hbase.master.procedure.RSProcedureDispatcher;</span>
+<span class="source-line-no">035</span><span id="line-35">import org.apache.hadoop.hbase.regionserver.RegionServerStoppedException;</span>
+<span class="source-line-no">036</span><span id="line-36">import org.slf4j.Logger;</span>
+<span class="source-line-no">037</span><span id="line-37">import org.slf4j.LoggerFactory;</span>
+<span class="source-line-no">038</span><span id="line-38"></span>
+<span class="source-line-no">039</span><span id="line-39">import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;</span>
+<span class="source-line-no">040</span><span id="line-40">import org.apache.hadoop.hbase.shaded.protobuf.generated.AdminProtos;</span>
+<span class="source-line-no">041</span><span id="line-41">import org.apache.hadoop.hbase.shaded.protobuf.generated.HBaseProtos;</span>
<span class="source-line-no">042</span><span id="line-42"></span>
-<span class="source-line-no">043</span><span id="line-43"> private static final Logger LOG = LoggerFactory.getLogger(RSProcDispatcher.class);</span>
-<span class="source-line-no">044</span><span id="line-44"></span>
-<span class="source-line-no">045</span><span id="line-45"> private static final AtomicInteger I = new AtomicInteger();</span>
-<span class="source-line-no">046</span><span id="line-46"></span>
-<span class="source-line-no">047</span><span id="line-47"> private static final List<IOException> ERRORS =</span>
-<span class="source-line-no">048</span><span id="line-48"> Arrays.asList(new ConnectionClosedException("test connection closed error..."),</span>
-<span class="source-line-no">049</span><span id="line-49"> new UnknownHostException("test unknown host error..."),</span>
-<span class="source-line-no">050</span><span id="line-50"> new ConnectException("test connect error..."));</span>
-<span class="source-line-no">051</span><span id="line-51"></span>
-<span class="source-line-no">052</span><span id="line-52"> private static final AtomicInteger ERROR_IDX = new AtomicInteger();</span>
-<span class="source-line-no">053</span><span id="line-53"></span>
-<span class="source-line-no">054</span><span id="line-54"> public RSProcDispatcher(MasterServices master) {</span>
-<span class="source-line-no">055</span><span id="line-55"> super(master);</span>
-<span class="source-line-no">056</span><span id="line-56"> }</span>
+<span class="source-line-no">043</span><span id="line-43">/**</span>
+<span class="source-line-no">044</span><span id="line-44"> * Test implementation of RSProcedureDispatcher that throws desired errors for testing purpose.</span>
+<span class="source-line-no">045</span><span id="line-45"> */</span>
+<span class="source-line-no">046</span><span id="line-46">public class RSProcDispatcher extends RSProcedureDispatcher {</span>
+<span class="source-line-no">047</span><span id="line-47"></span>
+<span class="source-line-no">048</span><span id="line-48"> private static final Logger LOG = LoggerFactory.getLogger(RSProcDispatcher.class);</span>
+<span class="source-line-no">049</span><span id="line-49"></span>
+<span class="source-line-no">050</span><span id="line-50"> /** Config key for the fail-fast retry limit, shared with the test so the two cannot drift. */</span>
+<span class="source-line-no">051</span><span id="line-51"> static final String FAIL_FAST_LIMIT_KEY = "hbase.master.rs.remote.proc.fail.fast.limit";</span>
+<span class="source-line-no">052</span><span id="line-52"></span>
+<span class="source-line-no">053</span><span id="line-53"> private static final List<IOException> ERRORS =</span>
+<span class="source-line-no">054</span><span id="line-54"> Arrays.asList(new ConnectionClosedException("test connection closed error..."),</span>
+<span class="source-line-no">055</span><span id="line-55"> new UnknownHostException("test unknown host error..."),</span>
+<span class="source-line-no">056</span><span id="line-56"> new ConnectException("test connect error..."));</span>
<span class="source-line-no">057</span><span id="line-57"></span>
-<span class="source-line-no">058</span><span id="line-58"> @Override</span>
-<span class="source-line-no">059</span><span id="line-59"> protected void remoteDispatch(final ServerName serverName,</span>
-<span class="source-line-no">060</span><span id="line-60"> final Set<RemoteProcedure> remoteProcedures) {</span>
-<span class="source-line-no">061</span><span id="line-61"> if (!master.getServerManager().isServerOnline(serverName)) {</span>
-<span class="source-line-no">062</span><span id="line-62"> // fail fast</span>
-<span class="source-line-no">063</span><span id="line-63"> submitTask(new DeadRSRemoteCall(serverName, remoteProcedures));</span>
-<span class="source-line-no">064</span><span id="line-64"> } else {</span>
-<span class="source-line-no">065</span><span id="line-65"> submitTask(new TestExecuteProceduresRemoteCall(serverName, remoteProcedures));</span>
-<span class="source-line-no">066</span><span id="line-66"> }</span>
-<span class="source-line-no">067</span><span id="line-67"> }</span>
-<span class="source-line-no">068</span><span id="line-68"></span>
-<span class="source-line-no">069</span><span id="line-69"> class TestExecuteProceduresRemoteCall extends ExecuteProceduresRemoteCall {</span>
-<span class="source-line-no">070</span><span id="line-70"></span>
-<span class="source-line-no">071</span><span id="line-71"> public TestExecuteProceduresRemoteCall(ServerName serverName,</span>
-<span class="source-line-no">072</span><span id="line-72"> Set<RemoteProcedure> remoteProcedures) {</span>
-<span class="source-line-no">073</span><span id="line-73"> super(serverName, remoteProcedures);</span>
-<span class="source-line-no">074</span><span id="line-74"> }</span>
-<span class="source-line-no">075</span><span id="line-75"></span>
-<span class="source-line-no">076</span><span id="line-76"> @Override</span>
-<span class="source-line-no">077</span><span id="line-77"> public AdminProtos.ExecuteProceduresResponse sendRequest(final ServerName serverName,</span>
-<span class="source-line-no">078</span><span id="line-78"> final AdminProtos.ExecuteProceduresRequest request) throws IOException {</span>
-<span class="source-line-no">079</span><span id="line-79"> int j = I.addAndGet(1);</span>
-<span class="source-line-no">080</span><span id="line-80"> LOG.info("sendRequest() req: {} , j: {}", request, j);</span>
-<span class="source-line-no">081</span><span id="line-81"> if (j == 12 || j == 22) {</span>
-<span class="source-line-no">082</span><span id="line-82"> // Execute the remote close and open region requests in the last (5th) retry before</span>
-<span class="source-line-no">083</span><span id="line-83"> // throwing ConnectionClosedException. This is to ensure even if the region open/close</span>
-<span class="source-line-no">084</span><span id="line-84"> // is successfully completed by regionserver, master still schedules SCP because</span>
-<span class="source-line-no">085</span><span id="line-85"> // sendRequest() throws error which has retry-limit exhausted.</span>
-<span class="source-line-no">086</span><span id="line-86"> FutureUtils.get(getRsAdmin().executeProcedures(request));</span>
-<span class="source-line-no">087</span><span id="line-87"> }</span>
-<span class="source-line-no">088</span><span id="line-88"> // For one of the close region requests and one of the open region requests,</span>
-<span class="source-line-no">089</span><span id="line-89"> // throw ConnectionClosedException until retry limit is exhausted and master</span>
-<span class="source-line-no">090</span><span id="line-90"> // schedules recoveries for the server.</span>
-<span class="source-line-no">091</span><span id="line-91"> // We will have ABNORMALLY_CLOSED regions, and they are expected to recover on their own.</span>
-<span class="source-line-no">092</span><span id="line-92"> if (j >= 8 && j <= 13 || j >= 18 && j <= 23) {</span>
-<span class="source-line-no">093</span><span id="line-93"> throw ERRORS.get(ERROR_IDX.getAndIncrement() % ERRORS.size());</span>
-<span class="source-line-no">094</span><span id="line-94"> }</span>
-<span class="source-line-no">095</span><span id="line-95"> return FutureUtils.get(getRsAdmin().executeProcedures(request));</span>
-<span class="source-line-no">096</span><span id="line-96"> }</span>
-<span class="source-line-no">097</span><span id="line-97"></span>
-<span class="source-line-no">098</span><span id="line-98"> private AsyncRegionServerAdmin getRsAdmin() {</span>
-<span class="source-line-no">099</span><span id="line-99"> return master.getAsyncClusterConnection().getRegionServerAdmin(getServerName());</span>
-<span class="source-line-no">100</span><span id="line-100"> }</span>
-<span class="source-line-no">101</span><span id="line-101"> }</span>
-<span class="source-line-no">102</span><span id="line-102"></span>
-<span class="source-line-no">103</span><span id="line-103"> private class DeadRSRemoteCall extends ExecuteProceduresRemoteCall {</span>
+<span class="source-line-no">058</span><span id="line-58"> private static final AtomicInteger ERROR_IDX = new AtomicInteger();</span>
+<span class="source-line-no">059</span><span id="line-59"></span>
+<span class="source-line-no">060</span><span id="line-60"> // Injection is driven by the test and bound to a target table, not a global call count:</span>
+<span class="source-line-no">061</span><span id="line-61"> // remoteDispatch() fires for every remote procedure in the cluster (startup, table creation,</span>
+<span class="source-line-no">062</span><span id="line-62"> // chores, background assignments), so counting calls drifts and misses the operations under test.</span>
+<span class="source-line-no">063</span><span id="line-63"> private static final AtomicBoolean INJECT = new AtomicBoolean(false);</span>
+<span class="source-line-no">064</span><span id="line-64"> private static final AtomicInteger VICTIMS_REMAINING = new AtomicInteger(0);</span>
+<span class="source-line-no">065</span><span id="line-65"> private static volatile TableName targetTable;</span>
+<span class="source-line-no">066</span><span id="line-66"></span>
+<span class="source-line-no">067</span><span id="line-67"> // Fail-fast retry limit after which the master schedules an SCP; read from conf to match test.</span>
+<span class="source-line-no">068</span><span id="line-68"> private final int failFastLimit;</span>
+<span class="source-line-no">069</span><span id="line-69"></span>
+<span class="source-line-no">070</span><span id="line-70"> /**</span>
+<span class="source-line-no">071</span><span id="line-71"> * Fails the next {@code n} open/close-region requests for {@code table} with connection errors</span>
+<span class="source-line-no">072</span><span id="line-72"> * until the fail-fast retry limit is exhausted, so the master schedules an SCP. Call right before</span>
+<span class="source-line-no">073</span><span id="line-73"> * the operations under test.</span>
+<span class="source-line-no">074</span><span id="line-74"> */</span>
+<span class="source-line-no">075</span><span id="line-75"> static void injectErrorsForNextRequests(TableName table, int n) {</span>
+<span class="source-line-no">076</span><span id="line-76"> ERROR_IDX.set(0);</span>
+<span class="source-line-no">077</span><span id="line-77"> targetTable = table;</span>
+<span class="source-line-no">078</span><span id="line-78"> VICTIMS_REMAINING.set(n);</span>
+<span class="source-line-no">079</span><span id="line-79"> INJECT.set(true);</span>
+<span class="source-line-no">080</span><span id="line-80"> }</span>
+<span class="source-line-no">081</span><span id="line-81"></span>
+<span class="source-line-no">082</span><span id="line-82"> /** Stops error injection. Safe to call unconditionally, e.g. from test teardown. */</span>
+<span class="source-line-no">083</span><span id="line-83"> static void stopInjecting() {</span>
+<span class="source-line-no">084</span><span id="line-84"> INJECT.set(false);</span>
+<span class="source-line-no">085</span><span id="line-85"> VICTIMS_REMAINING.set(0);</span>
+<span class="source-line-no">086</span><span id="line-86"> targetTable = null;</span>
+<span class="source-line-no">087</span><span id="line-87"> }</span>
+<span class="source-line-no">088</span><span id="line-88"></span>
+<span class="source-line-no">089</span><span id="line-89"> public RSProcDispatcher(MasterServices master) {</span>
+<span class="source-line-no">090</span><span id="line-90"> super(master);</span>
+<span class="source-line-no">091</span><span id="line-91"> this.failFastLimit = master.getConfiguration().getInt(FAIL_FAST_LIMIT_KEY, 10);</span>
+<span class="source-line-no">092</span><span id="line-92"> }</span>
+<span class="source-line-no">093</span><span id="line-93"></span>
+<span class="source-line-no">094</span><span id="line-94"> @Override</span>
+<span class="source-line-no">095</span><span id="line-95"> protected void remoteDispatch(final ServerName serverName,</span>
+<span class="source-line-no">096</span><span id="line-96"> final Set<RemoteProcedure> remoteProcedures) {</span>
+<span class="source-line-no">097</span><span id="line-97"> if (!master.getServerManager().isServerOnline(serverName)) {</span>
+<span class="source-line-no">098</span><span id="line-98"> // fail fast</span>
+<span class="source-line-no">099</span><span id="line-99"> submitTask(new DeadRSRemoteCall(serverName, remoteProcedures));</span>
+<span class="source-line-no">100</span><span id="line-100"> } else {</span>
+<span class="source-line-no">101</span><span id="line-101"> submitTask(new TestExecuteProceduresRemoteCall(serverName, remoteProcedures));</span>
+<span class="source-line-no">102</span><span id="line-102"> }</span>
+<span class="source-line-no">103</span><span id="line-103"> }</span>
<span class="source-line-no">104</span><span id="line-104"></span>
-<span class="source-line-no">105</span><span id="line-105"> public DeadRSRemoteCall(ServerName serverName, Set<RemoteProcedure> remoteProcedures) {</span>
-<span class="source-line-no">106</span><span id="line-106"> super(serverName, remoteProcedures);</span>
-<span class="source-line-no">107</span><span id="line-107"> }</span>
-<span class="source-line-no">108</span><span id="line-108"></span>
-<span class="source-line-no">109</span><span id="line-109"> @Override</span>
-<span class="source-line-no">110</span><span id="line-110"> public void run() {</span>
-<span class="source-line-no">111</span><span id="line-111"> remoteCallFailed(master.getMasterProcedureExecutor().getEnvironment(),</span>
-<span class="source-line-no">112</span><span id="line-112"> new RegionServerStoppedException("Server " + getServerName() + " is not online"));</span>
+<span class="source-line-no">105</span><span id="line-105"> /**</span>
+<span class="source-line-no">106</span><span id="line-106"> * True if the request opens or closes a region of the injection target table. Open requests carry</span>
+<span class="source-line-no">107</span><span id="line-107"> * a full RegionInfo; close requests carry a REGION_NAME specifier the table is parsed from.</span>
+<span class="source-line-no">108</span><span id="line-108"> */</span>
+<span class="source-line-no">109</span><span id="line-109"> private static boolean targetsInjectionTable(AdminProtos.ExecuteProceduresRequest request) {</span>
+<span class="source-line-no">110</span><span id="line-110"> TableName table = targetTable;</span>
+<span class="source-line-no">111</span><span id="line-111"> if (table == null) {</span>
+<span class="source-line-no">112</span><span id="line-112"> return false;</span>
<span class="source-line-no">113</span><span id="line-113"> }</span>
-<span class="source-line-no">114</span><span id="line-114"> }</span>
-<span class="source-line-no">115</span><span id="line-115"></span>
-<span class="source-line-no">116</span><span id="line-116">}</span>
+<span class="source-line-no">114</span><span id="line-114"> for (AdminProtos.OpenRegionRequest open : request.getOpenRegionList()) {</span>
+<span class="source-line-no">115</span><span id="line-115"> for (AdminProtos.OpenRegionRequest.RegionOpenInfo info : open.getOpenInfoList()) {</span>
+<span class="source-line-no">116</span><span id="line-116"> if (table.equals(ProtobufUtil.toTableName(info.getRegion().getTableName()))) {</span>
+<span class="source-line-no">117</span><span id="line-117"> return true;</span>
+<span class="source-line-no">118</span><span id="line-118"> }</span>
+<span class="source-line-no">119</span><span id="line-119"> }</span>
+<span class="source-line-no">120</span><span id="line-120"> }</span>
+<span class="source-line-no">121</span><span id="line-121"> for (AdminProtos.CloseRegionRequest close : request.getCloseRegionList()) {</span>
+<span class="source-line-no">122</span><span id="line-122"> HBaseProtos.RegionSpecifier region = close.getRegion();</span>
+<span class="source-line-no">123</span><span id="line-123"> if (</span>
+<span class="source-line-no">124</span><span id="line-124"> region.getType() == HBaseProtos.RegionSpecifier.RegionSpecifierType.REGION_NAME</span>
+<span class="source-line-no">125</span><span id="line-125"> && table.equals(RegionInfo.getTable(region.getValue().toByteArray()))</span>
+<span class="source-line-no">126</span><span id="line-126"> ) {</span>
+<span class="source-line-no">127</span><span id="line-127"> return true;</span>
+<span class="source-line-no">128</span><span id="line-128"> }</span>
+<span class="source-line-no">129</span><span id="line-129"> }</span>
+<span class="source-line-no">130</span><span id="line-130"> return false;</span>
+<span class="source-line-no">131</span><span id="line-131"> }</span>
+<span class="source-line-no">132</span><span id="line-132"></span>
+<span class="source-line-no">133</span><span id="line-133"> class TestExecuteProceduresRemoteCall extends ExecuteProceduresRemoteCall {</span>
+<span class="source-line-no">134</span><span id="line-134"></span>
+<span class="source-line-no">135</span><span id="line-135"> // attempts: retries of this single request instance (mirrors the dispatcher's</span>
+<span class="source-line-no">136</span><span id="line-136"> // numberOfAttemptsSoFar). injectErrors: whether this instance is failed with injected errors,</span>
+<span class="source-line-no">137</span><span id="line-137"> // decided once on the first call and kept across its retries.</span>
+<span class="source-line-no">138</span><span id="line-138"> private int attempts = 0;</span>
+<span class="source-line-no">139</span><span id="line-139"> private Boolean injectErrors = null;</span>
+<span class="source-line-no">140</span><span id="line-140"></span>
+<span class="source-line-no">141</span><span id="line-141"> public TestExecuteProceduresRemoteCall(ServerName serverName,</span>
+<span class="source-line-no">142</span><span id="line-142"> Set<RemoteProcedure> remoteProcedures) {</span>
+<span class="source-line-no">143</span><span id="line-143"> super(serverName, remoteProcedures);</span>
+<span class="source-line-no">144</span><span id="line-144"> }</span>
+<span class="source-line-no">145</span><span id="line-145"></span>
+<span class="source-line-no">146</span><span id="line-146"> @Override</span>
+<span class="source-line-no">147</span><span id="line-147"> public AdminProtos.ExecuteProceduresResponse sendRequest(final ServerName serverName,</span>
+<span class="source-line-no">148</span><span id="line-148"> final AdminProtos.ExecuteProceduresRequest request) throws IOException {</span>
+<span class="source-line-no">149</span><span id="line-149"> if (injectErrors == null) {</span>
+<span class="source-line-no">150</span><span id="line-150"> // Claim a slot only for a target-table open/close request, once per instance.</span>
+<span class="source-line-no">151</span><span id="line-151"> injectErrors =</span>
+<span class="source-line-no">152</span><span id="line-152"> INJECT.get() && targetsInjectionTable(request) && VICTIMS_REMAINING.getAndDecrement() > 0;</span>
+<span class="source-line-no">153</span><span id="line-153"> }</span>
+<span class="source-line-no">154</span><span id="line-154"> LOG.info("sendRequest() req: {}, attempts: {}, injectErrors: {}", request, attempts,</span>
+<span class="source-line-no">155</span><span id="line-155"> injectErrors);</span>
+<span class="source-line-no">156</span><span id="line-156"> if (!injectErrors) {</span>
+<span class="source-line-no">157</span><span id="line-157"> return FutureUtils.get(getRsAdmin().executeProcedures(request));</span>
+<span class="source-line-no">158</span><span id="line-158"> }</span>
+<span class="source-line-no">159</span><span id="line-159"> // Throw a connection error each attempt until the retry limit is exhausted (-> SCP). On the</span>
+<span class="source-line-no">160</span><span id="line-160"> // last attempt run the real open/close first so the region still recovers.</span>
+<span class="source-line-no">161</span><span id="line-161"> if (attempts++ >= failFastLimit - 1) {</span>
+<span class="source-line-no">162</span><span id="line-162"> FutureUtils.get(getRsAdmin().executeProcedures(request));</span>
+<span class="source-line-no">163</span><span id="line-163"> }</span>
+<span class="source-line-no">164</span><span id="line-164"> throw ERRORS.get(ERROR_IDX.getAndIncrement() % ERRORS.size());</span>
+<span class="source-line-no">165</span><span id="line-165"> }</span>
+<span class="source-line-no">166</span><span id="line-166"></span>
+<span class="source-line-no">167</span><span id="line-167"> private AsyncRegionServerAdmin getRsAdmin() {</span>
+<span class="source-line-no">168</span><span id="line-168"> return master.getAsyncClusterConnection().getRegionServerAdmin(getServerName());</span>
+<span class="source-line-no">169</span><span id="line-169"> }</span>
+<span class="source-line-no">170</span><span id="line-170"> }</span>
+<span class="source-line-no">171</span><span id="line-171"></span>
+<span class="source-line-no">172</span><span id="line-172"> private class DeadRSRemoteCall extends ExecuteProceduresRemoteCall {</span>
+<span class="source-line-no">173</span><span id="line-173"></span>
+<span class="source-line-no">174</span><span id="line-174"> public DeadRSRemoteCall(ServerName serverName, Set<RemoteProcedure> remoteProcedures) {</span>
+<span class="source-line-no">175</span><span id="line-175"> super(serverName, remoteProcedures);</span>
+<span class="source-line-no">176</span><span id="line-176"> }</span>
+<span class="source-line-no">177</span><span id="line-177"></span>
+<span class="source-line-no">178</span><span id="line-178"> @Override</span>
+<span class="source-line-no">179</span><span id="line-179"> public void run() {</span>
+<span class="source-line-no">180</span><span id="line-180"> remoteCallFailed(master.getMasterProcedureExecutor().getEnvironment(),</span>
+<span class="source-line-no">181</span><span id="line-181"> new RegionServerStoppedException("Server " + getServerName() + " is not online"));</span>
+<span class="source-line-no">182</span><span id="line-182"> }</span>
+<span class="source-line-no">183</span><span id="line-183"> }</span>
+<span class="source-line-no">184</span><span id="line-184">}</span>
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html
index 9316d77f071..151ac524f28 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/util/TestProcDispatcher.html
@@ -55,131 +55,138 @@
<span class="source-line-no">042</span><span id="line-42">import org.apache.hadoop.hbase.testclassification.LargeTests;</span>
<span class="source-line-no">043</span><span id="line-43">import org.apache.hadoop.hbase.testclassification.MiscTests;</span>
<span class="source-line-no">044</span><span id="line-44">import org.junit.jupiter.api.AfterAll;</span>
-<span class="source-line-no">045</span><span id="line-45">import org.junit.jupiter.api.BeforeAll;</span>
-<span class="source-line-no">046</span><span id="line-46">import org.junit.jupiter.api.BeforeEach;</span>
-<span class="source-line-no">047</span><span id="line-47">import org.junit.jupiter.api.Tag;</span>
-<span class="source-line-no">048</span><span id="line-48">import org.junit.jupiter.api.Test;</span>
-<span class="source-line-no">049</span><span id="line-49">import org.junit.jupiter.api.TestInfo;</span>
-<span class="source-line-no">050</span><span id="line-50">import org.slf4j.Logger;</span>
-<span class="source-line-no">051</span><span id="line-51">import org.slf4j.LoggerFactory;</span>
-<span class="source-line-no">052</span><span id="line-52"></span>
-<span class="source-line-no">053</span><span id="line-53">import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos;</span>
-<span class="source-line-no">054</span><span id="line-54"></span>
-<span class="source-line-no">055</span><span id="line-55">/**</span>
-<span class="source-line-no">056</span><span id="line-56"> * Testing custom RSProcedureDispatcher to ensure retry limit can be imposed on certain errors.</span>
-<span class="source-line-no">057</span><span id="line-57"> */</span>
-<span class="source-line-no">058</span><span id="line-58">@Tag(MiscTests.TAG)</span>
-<span class="source-line-no">059</span><span id="line-59">@Tag(LargeTests.TAG)</span>
-<span class="source-line-no">060</span><span id="line-60">public class TestProcDispatcher {</span>
-<span class="source-line-no">061</span><span id="line-61"></span>
-<span class="source-line-no">062</span><span id="line-62"> private static final Logger LOG = LoggerFactory.getLogger(TestProcDispatcher.class);</span>
-<span class="source-line-no">063</span><span id="line-63"></span>
-<span class="source-line-no">064</span><span id="line-64"> private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();</span>
-<span class="source-line-no">065</span><span id="line-65"> private static ServerName rs0;</span>
-<span class="source-line-no">066</span><span id="line-66"></span>
-<span class="source-line-no">067</span><span id="line-67"> @BeforeAll</span>
-<span class="source-line-no">068</span><span id="line-68"> public static void setUpBeforeClass() throws Exception {</span>
-<span class="source-line-no">069</span><span id="line-69"> TEST_UTIL.getConfiguration().set(HBASE_MASTER_RSPROC_DISPATCHER_CLASS,</span>
-<span class="source-line-no">070</span><span id="line-70"> RSProcDispatcher.class.getName());</span>
-<span class="source-line-no">071</span><span id="line-71"> TEST_UTIL.getConfiguration().setInt("hbase.master.rs.remote.proc.fail.fast.limit", 5);</span>
-<span class="source-line-no">072</span><span id="line-72"> TEST_UTIL.startMiniCluster(3);</span>
-<span class="source-line-no">073</span><span id="line-73"> SingleProcessHBaseCluster cluster = TEST_UTIL.getHBaseCluster();</span>
-<span class="source-line-no">074</span><span id="line-74"> rs0 = cluster.getRegionServer(0).getServerName();</span>
-<span class="source-line-no">075</span><span id="line-75"> TEST_UTIL.getAdmin().balancerSwitch(false, true);</span>
-<span class="source-line-no">076</span><span id="line-76"> }</span>
-<span class="source-line-no">077</span><span id="line-77"></span>
-<span class="source-line-no">078</span><span id="line-78"> @AfterAll</span>
-<span class="source-line-no">079</span><span id="line-79"> public static void tearDownAfterClass() throws Exception {</span>
-<span class="source-line-no">080</span><span id="line-80"> TEST_UTIL.shutdownMiniCluster();</span>
-<span class="source-line-no">081</span><span id="line-81"> }</span>
-<span class="source-line-no">082</span><span id="line-82"></span>
-<span class="source-line-no">083</span><span id="line-83"> @BeforeEach</span>
-<span class="source-line-no">084</span><span id="line-84"> public void setUp(TestInfo testInfo) throws Exception {</span>
-<span class="source-line-no">085</span><span id="line-85"> final TableName tableName = TableName.valueOf(testInfo.getTestMethod().get().getName());</span>
-<span class="source-line-no">086</span><span id="line-86"> TableDescriptor tableDesc = TableDescriptorBuilder.newBuilder(tableName)</span>
-<span class="source-line-no">087</span><span id="line-87"> .setColumnFamily(ColumnFamilyDescriptorBuilder.of("fam1")).build();</span>
-<span class="source-line-no">088</span><span id="line-88"> int startKey = 0;</span>
-<span class="source-line-no">089</span><span id="line-89"> int endKey = 80000;</span>
-<span class="source-line-no">090</span><span id="line-90"> TEST_UTIL.getAdmin().createTable(tableDesc, Bytes.toBytes(startKey), Bytes.toBytes(endKey), 9);</span>
-<span class="source-line-no">091</span><span id="line-91"> }</span>
-<span class="source-line-no">092</span><span id="line-92"></span>
-<span class="source-line-no">093</span><span id="line-93"> @Test</span>
-<span class="source-line-no">094</span><span id="line-94"> public void testRetryLimitOnConnClosedErrors(TestInfo testInfo) throws Exception {</span>
-<span class="source-line-no">095</span><span id="line-95"> HbckChore hbckChore = new HbckChore(TEST_UTIL.getHBaseCluster().getMaster());</span>
-<span class="source-line-no">096</span><span id="line-96"> final TableName tableName = TableName.valueOf(testInfo.getTestMethod().get().getName());</span>
-<span class="source-line-no">097</span><span id="line-97"> SingleProcessHBaseCluster cluster = TEST_UTIL.getHBaseCluster();</span>
-<span class="source-line-no">098</span><span id="line-98"> Admin admin = TEST_UTIL.getAdmin();</span>
-<span class="source-line-no">099</span><span id="line-99"> Table table = TEST_UTIL.getConnection().getTable(tableName);</span>
-<span class="source-line-no">100</span><span id="line-100"> List<Put> puts = IntStream.range(10, 50000).mapToObj(i -> new Put(Bytes.toBytes(i))</span>
-<span class="source-line-no">101</span><span id="line-101"> .addColumn(Bytes.toBytes("fam1"), Bytes.toBytes("q1"), Bytes.toBytes("val_" + i)))</span>
-<span class="source-line-no">102</span><span id="line-102"> .collect(Collectors.toList());</span>
-<span class="source-line-no">103</span><span id="line-103"> table.put(puts);</span>
-<span class="source-line-no">104</span><span id="line-104"> admin.flush(tableName);</span>
-<span class="source-line-no">105</span><span id="line-105"> admin.compact(tableName);</span>
-<span class="source-line-no">106</span><span id="line-106"> Thread.sleep(3000);</span>
-<span class="source-line-no">107</span><span id="line-107"> HRegionServer hRegionServer0 = cluster.getRegionServer(0);</span>
-<span class="source-line-no">108</span><span id="line-108"> HRegionServer hRegionServer1 = cluster.getRegionServer(1);</span>
-<span class="source-line-no">109</span><span id="line-109"> HRegionServer hRegionServer2 = cluster.getRegionServer(2);</span>
-<span class="source-line-no">110</span><span id="line-110"> int numRegions0 = hRegionServer0.getNumberOfOnlineRegions();</span>
-<span class="source-line-no">111</span><span id="line-111"> int numRegions1 = hRegionServer1.getNumberOfOnlineRegions();</span>
-<span class="source-line-no">112</span><span id="line-112"> int numRegions2 = hRegionServer2.getNumberOfOnlineRegions();</span>
-<span class="source-line-no">113</span><span id="line-113"></span>
-<span class="source-line-no">114</span><span id="line-114"> hbckChore.choreForTesting();</span>
-<span class="source-line-no">115</span><span id="line-115"> HbckReport hbckReport = hbckChore.getLastReport();</span>
-<span class="source-line-no">116</span><span id="line-116"> assertEquals(0, hbckReport.getInconsistentRegions().size());</span>
-<span class="source-line-no">117</span><span id="line-117"> assertEquals(0, hbckReport.getOrphanRegionsOnFS().size());</span>
-<span class="source-line-no">118</span><span id="line-118"> assertEquals(0, hbckReport.getOrphanRegionsOnRS().size());</span>
-<span class="source-line-no">119</span><span id="line-119"></span>
-<span class="source-line-no">120</span><span id="line-120"> HRegion region0 = hRegionServer0.getRegions().get(0);</span>
-<span class="source-line-no">121</span><span id="line-121"> // move all regions from server1 to server0</span>
-<span class="source-line-no">122</span><span id="line-122"> for (HRegion region : hRegionServer1.getRegions()) {</span>
-<span class="source-line-no">123</span><span id="line-123"> TEST_UTIL.getAdmin().move(region.getRegionInfo().getEncodedNameAsBytes(), rs0);</span>
-<span class="source-line-no">124</span><span id="line-124"> }</span>
-<span class="source-line-no">125</span><span id="line-125"> TEST_UTIL.getAdmin().move(region0.getRegionInfo().getEncodedNameAsBytes());</span>
-<span class="source-line-no">126</span><span id="line-126"> HMaster master = TEST_UTIL.getHBaseCluster().getMaster();</span>
-<span class="source-line-no">127</span><span id="line-127"></span>
-<span class="source-line-no">128</span><span id="line-128"> // Ensure:</span>
-<span class="source-line-no">129</span><span id="line-129"> // 1. num of regions before and after scheduling SCP remain same</span>
-<span class="source-line-no">130</span><span id="line-130"> // 2. all procedures including SCPs are successfully completed</span>
-<span class="source-line-no">131</span><span id="line-131"> // 3. two servers have SCPs scheduled</span>
-<span class="source-line-no">132</span><span id="line-132"> TEST_UTIL.waitFor(5000, 1000, () -> {</span>
-<span class="source-line-no">133</span><span id="line-133"> LOG.info("numRegions0: {} , numRegions1: {} , numRegions2: {}", numRegions0, numRegions1,</span>
-<span class="source-line-no">134</span><span id="line-134"> numRegions2);</span>
-<span class="source-line-no">135</span><span id="line-135"> LOG.info("Online regions - server0 : {} , server1: {} , server2: {}",</span>
-<span class="source-line-no">136</span><span id="line-136"> cluster.getRegionServer(0).getNumberOfOnlineRegions(),</span>
-<span class="source-line-no">137</span><span id="line-137"> cluster.getRegionServer(1).getNumberOfOnlineRegions(),</span>
-<span class="source-line-no">138</span><span id="line-138"> cluster.getRegionServer(2).getNumberOfOnlineRegions());</span>
-<span class="source-line-no">139</span><span id="line-139"> LOG.info("Num of successfully completed procedures: {} , num of all procedures: {}",</span>
-<span class="source-line-no">140</span><span id="line-140"> master.getMasterProcedureExecutor().getProcedures().stream()</span>
-<span class="source-line-no">141</span><span id="line-141"> .filter(masterProcedureEnvProcedure -> masterProcedureEnvProcedure.getState()</span>
-<span class="source-line-no">142</span><span id="line-142"> == ProcedureProtos.ProcedureState.SUCCESS)</span>
-<span class="source-line-no">143</span><span id="line-143"> .count(),</span>
-<span class="source-line-no">144</span><span id="line-144"> master.getMasterProcedureExecutor().getProcedures().size());</span>
-<span class="source-line-no">145</span><span id="line-145"> LOG.info("Num of SCPs: " + master.getMasterProcedureExecutor().getProcedures().stream()</span>
-<span class="source-line-no">146</span><span id="line-146"> .filter(proc -> proc instanceof ServerCrashProcedure).count());</span>
-<span class="source-line-no">147</span><span id="line-147"> return (numRegions0 + numRegions1 + numRegions2)</span>
-<span class="source-line-no">148</span><span id="line-148"> == (cluster.getRegionServer(0).getNumberOfOnlineRegions()</span>
-<span class="source-line-no">149</span><span id="line-149"> + cluster.getRegionServer(1).getNumberOfOnlineRegions()</span>
-<span class="source-line-no">150</span><span id="line-150"> + cluster.getRegionServer(2).getNumberOfOnlineRegions())</span>
-<span class="source-line-no">151</span><span id="line-151"> && master.getMasterProcedureExecutor().getProcedures().stream()</span>
-<span class="source-line-no">152</span><span id="line-152"> .filter(masterProcedureEnvProcedure -> masterProcedureEnvProcedure.getState()</span>
-<span class="source-line-no">153</span><span id="line-153"> == ProcedureProtos.ProcedureState.SUCCESS)</span>
-<span class="source-line-no">154</span><span id="line-154"> .count() == master.getMasterProcedureExecutor().getProcedures().size()</span>
-<span class="source-line-no">155</span><span id="line-155"> && master.getMasterProcedureExecutor().getProcedures().stream()</span>
-<span class="source-line-no">156</span><span id="line-156"> .anyMatch(proc -> proc instanceof ServerCrashProcedure);</span>
-<span class="source-line-no">157</span><span id="line-157"> });</span>
-<span class="source-line-no">158</span><span id="line-158"></span>
-<span class="source-line-no">159</span><span id="line-159"> // Ensure we have no inconsistent regions</span>
-<span class="source-line-no">160</span><span id="line-160"> TEST_UTIL.waitFor(5000, 1000, () -> {</span>
-<span class="source-line-no">161</span><span id="line-161"> hbckChore.choreForTesting();</span>
-<span class="source-line-no">162</span><span id="line-162"> HbckReport report = hbckChore.getLastReport();</span>
-<span class="source-line-no">163</span><span id="line-163"> return report.getInconsistentRegions().isEmpty() && report.getOrphanRegionsOnFS().isEmpty()</span>
-<span class="source-line-no">164</span><span id="line-164"> && report.getOrphanRegionsOnRS().isEmpty();</span>
-<span class="source-line-no">165</span><span id="line-165"> });</span>
-<span class="source-line-no">166</span><span id="line-166"></span>
-<span class="source-line-no">167</span><span id="line-167"> }</span>
-<span class="source-line-no">168</span><span id="line-168"></span>
-<span class="source-line-no">169</span><span id="line-169">}</span>
+<span class="source-line-no">045</span><span id="line-45">import org.junit.jupiter.api.AfterEach;</span>
+<span class="source-line-no">046</span><span id="line-46">import org.junit.jupiter.api.BeforeAll;</span>
+<span class="source-line-no">047</span><span id="line-47">import org.junit.jupiter.api.BeforeEach;</span>
+<span class="source-line-no">048</span><span id="line-48">import org.junit.jupiter.api.Tag;</span>
+<span class="source-line-no">049</span><span id="line-49">import org.junit.jupiter.api.Test;</span>
+<span class="source-line-no">050</span><span id="line-50">import org.junit.jupiter.api.TestInfo;</span>
+<span class="source-line-no">051</span><span id="line-51">import org.slf4j.Logger;</span>
+<span class="source-line-no">052</span><span id="line-52">import org.slf4j.LoggerFactory;</span>
+<span class="source-line-no">053</span><span id="line-53"></span>
+<span class="source-line-no">054</span><span id="line-54">import org.apache.hadoop.hbase.shaded.protobuf.generated.ProcedureProtos;</span>
+<span class="source-line-no">055</span><span id="line-55"></span>
+<span class="source-line-no">056</span><span id="line-56">/**</span>
+<span class="source-line-no">057</span><span id="line-57"> * Testing custom RSProcedureDispatcher to ensure retry limit can be imposed on certain errors.</span>
+<span class="source-line-no">058</span><span id="line-58"> */</span>
+<span class="source-line-no">059</span><span id="line-59">@Tag(MiscTests.TAG)</span>
+<span class="source-line-no">060</span><span id="line-60">@Tag(LargeTests.TAG)</span>
+<span class="source-line-no">061</span><span id="line-61">public class TestProcDispatcher {</span>
+<span class="source-line-no">062</span><span id="line-62"></span>
+<span class="source-line-no">063</span><span id="line-63"> private static final Logger LOG = LoggerFactory.getLogger(TestProcDispatcher.class);</span>
+<span class="source-line-no">064</span><span id="line-64"></span>
+<span class="source-line-no">065</span><span id="line-65"> private static final HBaseTestingUtil TEST_UTIL = new HBaseTestingUtil();</span>
+<span class="source-line-no">066</span><span id="line-66"> private static ServerName rs0;</span>
+<span class="source-line-no">067</span><span id="line-67"></span>
+<span class="source-line-no">068</span><span id="line-68"> @BeforeAll</span>
+<span class="source-line-no">069</span><span id="line-69"> public static void setUpBeforeClass() throws Exception {</span>
+<span class="source-line-no">070</span><span id="line-70"> TEST_UTIL.getConfiguration().set(HBASE_MASTER_RSPROC_DISPATCHER_CLASS,</span>
+<span class="source-line-no">071</span><span id="line-71"> RSProcDispatcher.class.getName());</span>
+<span class="source-line-no">072</span><span id="line-72"> TEST_UTIL.getConfiguration().setInt(RSProcDispatcher.FAIL_FAST_LIMIT_KEY, 5);</span>
+<span class="source-line-no">073</span><span id="line-73"> TEST_UTIL.startMiniCluster(3);</span>
+<span class="source-line-no">074</span><span id="line-74"> SingleProcessHBaseCluster cluster = TEST_UTIL.getHBaseCluster();</span>
+<span class="source-line-no">075</span><span id="line-75"> rs0 = cluster.getRegionServer(0).getServerName();</span>
+<span class="source-line-no">076</span><span id="line-76"> TEST_UTIL.getAdmin().balancerSwitch(false, true);</span>
+<span class="source-line-no">077</span><span id="line-77"> }</span>
+<span class="source-line-no">078</span><span id="line-78"></span>
+<span class="source-line-no">079</span><span id="line-79"> @AfterAll</span>
+<span class="source-line-no">080</span><span id="line-80"> public static void tearDownAfterClass() throws Exception {</span>
+<span class="source-line-no">081</span><span id="line-81"> TEST_UTIL.shutdownMiniCluster();</span>
+<span class="source-line-no">082</span><span id="line-82"> }</span>
+<span class="source-line-no">083</span><span id="line-83"></span>
+<span class="source-line-no">084</span><span id="line-84"> @BeforeEach</span>
+<span class="source-line-no">085</span><span id="line-85"> public void setUp(TestInfo testInfo) throws Exception {</span>
+<span class="source-line-no">086</span><span id="line-86"> final TableName tableName = TableName.valueOf(testInfo.getTestMethod().get().getName());</span>
+<span class="source-line-no">087</span><span id="line-87"> TableDescriptor tableDesc = TableDescriptorBuilder.newBuilder(tableName)</span>
+<span class="source-line-no">088</span><span id="line-88"> .setColumnFamily(ColumnFamilyDescriptorBuilder.of("fam1")).build();</span>
+<span class="source-line-no">089</span><span id="line-89"> int startKey = 0;</span>
+<span class="source-line-no">090</span><span id="line-90"> int endKey = 80000;</span>
+<span class="source-line-no">091</span><span id="line-91"> TEST_UTIL.getAdmin().createTable(tableDesc, Bytes.toBytes(startKey), Bytes.toBytes(endKey), 9);</span>
+<span class="source-line-no">092</span><span id="line-92"> }</span>
+<span class="source-line-no">093</span><span id="line-93"></span>
+<span class="source-line-no">094</span><span id="line-94"> @AfterEach</span>
+<span class="source-line-no">095</span><span id="line-95"> public void tearDown() {</span>
+<span class="source-line-no">096</span><span id="line-96"> RSProcDispatcher.stopInjecting();</span>
+<span class="source-line-no">097</span><span id="line-97"> }</span>
+<span class="source-line-no">098</span><span id="line-98"></span>
+<span class="source-line-no">099</span><span id="line-99"> @Test</span>
+<span class="source-line-no">100</span><span id="line-100"> public void testRetryLimitOnConnClosedErrors(TestInfo testInfo) throws Exception {</span>
+<span class="source-line-no">101</span><span id="line-101"> HbckChore hbckChore = new HbckChore(TEST_UTIL.getHBaseCluster().getMaster());</span>
+<span class="source-line-no">102</span><span id="line-102"> final TableName tableName = TableName.valueOf(testInfo.getTestMethod().get().getName());</span>
+<span class="source-line-no">103</span><span id="line-103"> SingleProcessHBaseCluster cluster = TEST_UTIL.getHBaseCluster();</span>
+<span class="source-line-no">104</span><span id="line-104"> Admin admin = TEST_UTIL.getAdmin();</span>
+<span class="source-line-no">105</span><span id="line-105"> List<Put> puts = IntStream.range(10, 50000).mapToObj(i -> new Put(Bytes.toBytes(i))</span>
+<span class="source-line-no">106</span><span id="line-106"> .addColumn(Bytes.toBytes("fam1"), Bytes.toBytes("q1"), Bytes.toBytes("val_" + i)))</span>
+<span class="source-line-no">107</span><span id="line-107"> .collect(Collectors.toList());</span>
+<span class="source-line-no">108</span><span id="line-108"> try (Table table = TEST_UTIL.getConnection().getTable(tableName)) {</span>
+<span class="source-line-no">109</span><span id="line-109"> table.put(puts);</span>
+<span class="source-line-no">110</span><span id="line-110"> }</span>
+<span class="source-line-no">111</span><span id="line-111"> admin.flush(tableName);</span>
+<span class="source-line-no">112</span><span id="line-112"> admin.compact(tableName);</span>
+<span class="source-line-no">113</span><span id="line-113"> Thread.sleep(3000);</span>
+<span class="source-line-no">114</span><span id="line-114"> HRegionServer hRegionServer0 = cluster.getRegionServer(0);</span>
+<span class="source-line-no">115</span><span id="line-115"> HRegionServer hRegionServer1 = cluster.getRegionServer(1);</span>
+<span class="source-line-no">116</span><span id="line-116"> HRegionServer hRegionServer2 = cluster.getRegionServer(2);</span>
+<span class="source-line-no">117</span><span id="line-117"> int numRegions0 = hRegionServer0.getNumberOfOnlineRegions();</span>
+<span class="source-line-no">118</span><span id="line-118"> int numRegions1 = hRegionServer1.getNumberOfOnlineRegions();</span>
+<span class="source-line-no">119</span><span id="line-119"> int numRegions2 = hRegionServer2.getNumberOfOnlineRegions();</span>
+<span class="source-line-no">120</span><span id="line-120"></span>
+<span class="source-line-no">121</span><span id="line-121"> hbckChore.choreForTesting();</span>
+<span class="source-line-no">122</span><span id="line-122"> HbckReport hbckReport = hbckChore.getLastReport();</span>
+<span class="source-line-no">123</span><span id="line-123"> assertEquals(0, hbckReport.getInconsistentRegions().size());</span>
+<span class="source-line-no">124</span><span id="line-124"> assertEquals(0, hbckReport.getOrphanRegionsOnFS().size());</span>
+<span class="source-line-no">125</span><span id="line-125"> assertEquals(0, hbckReport.getOrphanRegionsOnRS().size());</span>
+<span class="source-line-no">126</span><span id="line-126"></span>
+<span class="source-line-no">127</span><span id="line-127"> HRegion region0 = hRegionServer0.getRegions().get(0);</span>
+<span class="source-line-no">128</span><span id="line-128"> // Fail the next two open/close-region requests for this table so the moves trigger SCP(s).</span>
+<span class="source-line-no">129</span><span id="line-129"> RSProcDispatcher.injectErrorsForNextRequests(tableName, 2);</span>
+<span class="source-line-no">130</span><span id="line-130"> // move all regions from server1 to server0</span>
+<span class="source-line-no">131</span><span id="line-131"> for (HRegion region : hRegionServer1.getRegions()) {</span>
+<span class="source-line-no">132</span><span id="line-132"> TEST_UTIL.getAdmin().move(region.getRegionInfo().getEncodedNameAsBytes(), rs0);</span>
+<span class="source-line-no">133</span><span id="line-133"> }</span>
+<span class="source-line-no">134</span><span id="line-134"> TEST_UTIL.getAdmin().move(region0.getRegionInfo().getEncodedNameAsBytes());</span>
+<span class="source-line-no">135</span><span id="line-135"> HMaster master = TEST_UTIL.getHBaseCluster().getMaster();</span>
+<span class="source-line-no">136</span><span id="line-136"></span>
+<span class="source-line-no">137</span><span id="line-137"> // Ensure, after the injected connection errors:</span>
+<span class="source-line-no">138</span><span id="line-138"> // 1. the total number of regions is unchanged before and after the SCP(s)</span>
+<span class="source-line-no">139</span><span id="line-139"> // 2. all procedures (including the SCP(s)) complete successfully</span>
+<span class="source-line-no">140</span><span id="line-140"> // 3. at least one ServerCrashProcedure was scheduled</span>
+<span class="source-line-no">141</span><span id="line-141"> TEST_UTIL.waitFor(60000, 1000, () -> {</span>
+<span class="source-line-no">142</span><span id="line-142"> LOG.info("numRegions0: {} , numRegions1: {} , numRegions2: {}", numRegions0, numRegions1,</span>
+<span class="source-line-no">143</span><span id="line-143"> numRegions2);</span>
+<span class="source-line-no">144</span><span id="line-144"> LOG.info("Online regions - server0 : {} , server1: {} , server2: {}",</span>
+<span class="source-line-no">145</span><span id="line-145"> cluster.getRegionServer(0).getNumberOfOnlineRegions(),</span>
+<span class="source-line-no">146</span><span id="line-146"> cluster.getRegionServer(1).getNumberOfOnlineRegions(),</span>
+<span class="source-line-no">147</span><span id="line-147"> cluster.getRegionServer(2).getNumberOfOnlineRegions());</span>
+<span class="source-line-no">148</span><span id="line-148"> LOG.info("Num of successfully completed procedures: {} , num of all procedures: {}",</span>
+<span class="source-line-no">149</span><span id="line-149"> master.getMasterProcedureExecutor().getProcedures().stream()</span>
+<span class="source-line-no">150</span><span id="line-150"> .filter(masterProcedureEnvProcedure -> masterProcedureEnvProcedure.getState()</span>
+<span class="source-line-no">151</span><span id="line-151"> == ProcedureProtos.ProcedureState.SUCCESS)</span>
+<span class="source-line-no">152</span><span id="line-152"> .count(),</span>
+<span class="source-line-no">153</span><span id="line-153"> master.getMasterProcedureExecutor().getProcedures().size());</span>
+<span class="source-line-no">154</span><span id="line-154"> LOG.info("Num of SCPs: {}", master.getMasterProcedureExecutor().getProcedures().stream()</span>
+<span class="source-line-no">155</span><span id="line-155"> .filter(proc -> proc instanceof ServerCrashProcedure).count());</span>
+<span class="source-line-no">156</span><span id="line-156"> return (numRegions0 + numRegions1 + numRegions2)</span>
+<span class="source-line-no">157</span><span id="line-157"> == (cluster.getRegionServer(0).getNumberOfOnlineRegions()</span>
+<span class="source-line-no">158</span><span id="line-158"> + cluster.getRegionServer(1).getNumberOfOnlineRegions()</span>
+<span class="source-line-no">159</span><span id="line-159"> + cluster.getRegionServer(2).getNumberOfOnlineRegions())</span>
+<span class="source-line-no">160</span><span id="line-160"> && master.getMasterProcedureExecutor().getProcedures().stream()</span>
+<span class="source-line-no">161</span><span id="line-161"> .filter(masterProcedureEnvProcedure -> masterProcedureEnvProcedure.getState()</span>
+<span class="source-line-no">162</span><span id="line-162"> == ProcedureProtos.ProcedureState.SUCCESS)</span>
+<span class="source-line-no">163</span><span id="line-163"> .count() == master.getMasterProcedureExecutor().getProcedures().size()</span>
+<span class="source-line-no">164</span><span id="line-164"> && master.getMasterProcedureExecutor().getProcedures().stream()</span>
+<span class="source-line-no">165</span><span id="line-165"> .anyMatch(proc -> proc instanceof ServerCrashProcedure);</span>
+<span class="source-line-no">166</span><span id="line-166"> });</span>
+<span class="source-line-no">167</span><span id="line-167"></span>
+<span class="source-line-no">168</span><span id="line-168"> // Ensure we have no inconsistent regions</span>
+<span class="source-line-no">169</span><span id="line-169"> TEST_UTIL.waitFor(60000, 1000, () -> {</span>
+<span class="source-line-no">170</span><span id="line-170"> hbckChore.choreForTesting();</span>
+<span class="source-line-no">171</span><span id="line-171"> HbckReport report = hbckChore.getLastReport();</span>
+<span class="source-line-no">172</span><span id="line-172"> return report.getInconsistentRegions().isEmpty() && report.getOrphanRegionsOnFS().isEmpty()</span>
+<span class="source-line-no">173</span><span id="line-173"> && report.getOrphanRegionsOnRS().isEmpty();</span>
+<span class="source-line-no">174</span><span id="line-174"> });</span>
+<span class="source-line-no">175</span><span id="line-175"> }</span>
+<span class="source-line-no">176</span><span id="line-176">}</span>