You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by gi...@apache.org on 2021/09/14 00:25:34 UTC

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

This is an automated email from the ASF dual-hosted git repository.

git-site-role pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/hbase-site.git


The following commit(s) were added to refs/heads/asf-site by this push:
     new 52fbc7b  Published site at c60adfd13a24f0256681bc0fd6e3a93fd8991280.
52fbc7b is described below

commit 52fbc7bbd83286f60caddeaad5ed994953568f62
Author: jenkins <bu...@apache.org>
AuthorDate: Tue Sep 14 00:24:57 2021 +0000

    Published site at c60adfd13a24f0256681bc0fd6e3a93fd8991280.
---
 acid-semantics.html                                |    2 +-
 apache_hbase_reference_guide.pdf                   |    4 +-
 book.html                                          |    2 +-
 bulk-loads.html                                    |    2 +-
 checkstyle-aggregate.html                          |    4 +-
 coc.html                                           |    2 +-
 dependencies.html                                  |    2 +-
 dependency-convergence.html                        |    2 +-
 dependency-info.html                               |    2 +-
 dependency-management.html                         |    2 +-
 devapidocs/constant-values.html                    |    9 +-
 devapidocs/index-all.html                          |    7 +
 .../apache/hadoop/hbase/backup/package-tree.html   |    4 +-
 .../hbase/client/class-use/Scan.ReadType.html      |   27 +-
 .../apache/hadoop/hbase/client/package-tree.html   |   24 +-
 .../apache/hadoop/hbase/client/package-use.html    |    5 +-
 .../apache/hadoop/hbase/filter/package-tree.html   |    6 +-
 .../hadoop/hbase/hbtop/terminal/package-tree.html  |    2 +-
 .../org/apache/hadoop/hbase/http/package-tree.html |    2 +-
 .../apache/hadoop/hbase/io/hfile/package-tree.html |    8 +-
 .../org/apache/hadoop/hbase/ipc/package-tree.html  |    2 +-
 .../TableSnapshotInputFormatImpl.InputSplit.html   |   34 +-
 .../TableSnapshotInputFormatImpl.RecordReader.html |   34 +-
 .../mapreduce/TableSnapshotInputFormatImpl.html    |   95 +-
 .../hadoop/hbase/mapreduce/package-tree.html       |    4 +-
 .../hbase/master/assignment/package-tree.html      |    2 +-
 .../apache/hadoop/hbase/master/package-tree.html   |    4 +-
 .../hbase/master/procedure/package-tree.html       |    4 +-
 .../hadoop/hbase/monitoring/package-tree.html      |    2 +-
 .../org/apache/hadoop/hbase/package-tree.html      |   16 +-
 .../hadoop/hbase/procedure2/package-tree.html      |    6 +-
 .../hbase/procedure2/store/wal/package-tree.html   |    2 +-
 .../apache/hadoop/hbase/quotas/package-tree.html   |    6 +-
 .../hadoop/hbase/regionserver/package-tree.html    |   12 +-
 .../hbase/regionserver/wal/package-tree.html       |    2 +-
 .../hadoop/hbase/replication/package-tree.html     |    2 +-
 .../replication/regionserver/package-tree.html     |    2 +-
 .../hadoop/hbase/rest/model/package-tree.html      |    2 +-
 .../hadoop/hbase/security/access/package-tree.html |    6 +-
 .../apache/hadoop/hbase/security/package-tree.html |    2 +-
 .../apache/hadoop/hbase/thrift/package-tree.html   |    2 +-
 .../org/apache/hadoop/hbase/util/package-tree.html |    6 +-
 .../org/apache/hadoop/hbase/wal/package-tree.html  |    2 +-
 .../TableSnapshotInputFormatImpl.InputSplit.html   | 1114 ++++++++++----------
 .../TableSnapshotInputFormatImpl.RecordReader.html | 1114 ++++++++++----------
 .../mapreduce/TableSnapshotInputFormatImpl.html    | 1114 ++++++++++----------
 downloads.html                                     |   18 +-
 export_control.html                                |    2 +-
 index.html                                         |    2 +-
 issue-tracking.html                                |    2 +-
 mail-lists.html                                    |    2 +-
 metrics.html                                       |    2 +-
 old_news.html                                      |    2 +-
 plugin-management.html                             |    2 +-
 plugins.html                                       |    2 +-
 poweredbyhbase.html                                |    2 +-
 project-info.html                                  |    2 +-
 project-reports.html                               |    2 +-
 project-summary.html                               |    2 +-
 pseudo-distributed.html                            |    2 +-
 replication.html                                   |    2 +-
 resources.html                                     |    2 +-
 source-repository.html                             |    2 +-
 sponsors.html                                      |    2 +-
 supportingprojects.html                            |    2 +-
 team-list.html                                     |    2 +-
 testdevapidocs/index-all.html                      |    7 +
 .../hadoop/hbase/chaos/actions/package-tree.html   |    2 +-
 ...pshotInputFormat.TestTableSnapshotCounters.html |    8 +-
 ...napshotInputFormat.TestTableSnapshotMapper.html |    6 +-
 ...apshotInputFormat.TestTableSnapshotReducer.html |   10 +-
 .../mapreduce/TestTableSnapshotInputFormat.html    |  115 +-
 .../org/apache/hadoop/hbase/package-tree.html      |   16 +-
 .../hadoop/hbase/procedure/package-tree.html       |    8 +-
 .../hadoop/hbase/procedure2/package-tree.html      |    4 +-
 .../hadoop/hbase/regionserver/package-tree.html    |    6 +-
 .../org/apache/hadoop/hbase/test/package-tree.html |    4 +-
 .../org/apache/hadoop/hbase/wal/package-tree.html  |    4 +-
 ...pshotInputFormat.TestTableSnapshotCounters.html | 1053 +++++++++---------
 ...napshotInputFormat.TestTableSnapshotMapper.html | 1053 +++++++++---------
 ...apshotInputFormat.TestTableSnapshotReducer.html | 1053 +++++++++---------
 .../mapreduce/TestTableSnapshotInputFormat.html    | 1053 +++++++++---------
 82 files changed, 4240 insertions(+), 3927 deletions(-)

diff --git a/acid-semantics.html b/acid-semantics.html
index b87393e..b0f0030 100644
--- a/acid-semantics.html
+++ b/acid-semantics.html
@@ -456,7 +456,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/apache_hbase_reference_guide.pdf b/apache_hbase_reference_guide.pdf
index 477a4b0..8201b90 100644
--- a/apache_hbase_reference_guide.pdf
+++ b/apache_hbase_reference_guide.pdf
@@ -5,8 +5,8 @@
 /Author (Apache HBase Team)
 /Creator (Asciidoctor PDF 1.5.3, based on Prawn 2.2.2)
 /Producer (Apache HBase Team)
-/ModDate (D:20210913200552+00'00')
-/CreationDate (D:20210913201711+00'00')
+/ModDate (D:20210914001312+00'00')
+/CreationDate (D:20210914002301+00'00')
 >>
 endobj
 2 0 obj
diff --git a/book.html b/book.html
index 0693c8f..2e6b9c7 100644
--- a/book.html
+++ b/book.html
@@ -46227,7 +46227,7 @@ org/apache/hadoop/hbase/security/access/AccessControlClient.revoke:(Lorg/apache/
 <div id="footer">
 <div id="footer-text">
 Version 3.0.0-alpha-2-SNAPSHOT<br>
-Last updated 2021-09-13 20:05:52 UTC
+Last updated 2021-09-14 00:13:12 UTC
 </div>
 </div>
 <link rel="stylesheet" href="./coderay-asciidoctor.css">
diff --git a/bulk-loads.html b/bulk-loads.html
index 837501c..5ca4aa5 100644
--- a/bulk-loads.html
+++ b/bulk-loads.html
@@ -161,7 +161,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/checkstyle-aggregate.html b/checkstyle-aggregate.html
index 011e2e4..1b3ddc4 100644
--- a/checkstyle-aggregate.html
+++ b/checkstyle-aggregate.html
@@ -36316,7 +36316,7 @@
 <td>design</td>
 <td>HideUtilityClassConstructor</td>
 <td>Utility classes should not have a public or default constructor.</td>
-<td>68</td></tr></table></div>
+<td>69</td></tr></table></div>
 <div class="section">
 <h3 id="org.apache.hadoop.hbase.mapreduce.TestGroupingTableMapper.java">org/apache/hadoop/hbase/mapreduce/TestGroupingTableMapper.java</h3>
 <table border="0" class="table table-striped">
@@ -73468,7 +73468,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/coc.html b/coc.html
index b3a62a4..2d13c47 100644
--- a/coc.html
+++ b/coc.html
@@ -230,7 +230,7 @@ email to <a class="externalLink" href="mailto:private@hbase.apache.org">the priv
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/dependencies.html b/dependencies.html
index f625809..43ebdfa 100644
--- a/dependencies.html
+++ b/dependencies.html
@@ -302,7 +302,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/dependency-convergence.html b/dependency-convergence.html
index 451d32b..4707990 100644
--- a/dependency-convergence.html
+++ b/dependency-convergence.html
@@ -866,7 +866,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/dependency-info.html b/dependency-info.html
index 46f8e27..ab02127 100644
--- a/dependency-info.html
+++ b/dependency-info.html
@@ -183,7 +183,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/dependency-management.html b/dependency-management.html
index f2d805f..539573b 100644
--- a/dependency-management.html
+++ b/dependency-management.html
@@ -1190,7 +1190,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/devapidocs/constant-values.html b/devapidocs/constant-values.html
index eec6e3a..68016c5 100644
--- a/devapidocs/constant-values.html
+++ b/devapidocs/constant-values.html
@@ -14457,13 +14457,20 @@
 <td class="colLast"><code>true</code></td>
 </tr>
 <tr class="rowColor">
+<td class="colFirst"><a name="org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE">
+<!--   -->
+</a><code>public&nbsp;static&nbsp;final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a></code></td>
+<td><code><a href="org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE">SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE</a></code></td>
+<td class="colLast"><code>"hbase.TableSnapshotInputFormat.scanner.readtype"</code></td>
+</tr>
+<tr class="altColor">
 <td class="colFirst"><a name="org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_NAME_KEY">
 <!--   -->
 </a><code>private&nbsp;static&nbsp;final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a></code></td>
 <td><code><a href="org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#SNAPSHOT_NAME_KEY">SNAPSHOT_NAME_KEY</a></code></td>
 <td class="colLast"><code>"hbase.TableSnapshotInputFormat.snapshot.name"</code></td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><a name="org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SPLIT_ALGO">
 <!--   -->
 </a><code>public&nbsp;static&nbsp;final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a></code></td>
diff --git a/devapidocs/index-all.html b/devapidocs/index-all.html
index 643eb64..8490e10 100644
--- a/devapidocs/index-all.html
+++ b/devapidocs/index-all.html
@@ -116668,6 +116668,13 @@ service.</div>
 </dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT">SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT</a></span> - Static variable in class org.apache.hadoop.hbase.mapreduce.<a href="org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html" title="class in org.apache.hadoop.hbase.mapreduce">TableSnapshotInputFormatImpl</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE">SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE</a></span> - Static variable in class org.apache.hadoop.hbase.mapreduce.<a href="org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html" title="class in org.apache.hadoop.hbase.mapreduce">TableSnapshotInputFormatImpl</a></dt>
+<dd>
+<div class="block">The <a href="org/apache/hadoop/hbase/client/Scan.ReadType.html" title="enum in org.apache.hadoop.hbase.client"><code>Scan.ReadType</code></a> which should be set on the <a href="org/apache/hadoop/hbase/client/Scan.html" title="class in org.apache.hadoop.hbase.client"><code>Scan</code></a> to read the HBase Snapshot,
+ default STREAM.</div>
+</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE_DEFAULT">SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE_DEFAULT</a></span> - Static variable in class org.apache.hadoop.hbase.mapreduce.<a href="org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html" title="class in org.apache.hadoop.hbase.mapreduce">TableSnapshotInputFormatImpl</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/snapshot/SnapshotDescriptionUtils.html#SNAPSHOT_LAYOUT_VERSION">SNAPSHOT_LAYOUT_VERSION</a></span> - Static variable in class org.apache.hadoop.hbase.snapshot.<a href="org/apache/hadoop/hbase/snapshot/SnapshotDescriptionUtils.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotDescriptionUtils</a></dt>
 <dd>
 <div class="block">Version of the fs layout for a snapshot.</div>
diff --git a/devapidocs/org/apache/hadoop/hbase/backup/package-tree.html b/devapidocs/org/apache/hadoop/hbase/backup/package-tree.html
index 233124d..644adb5 100644
--- a/devapidocs/org/apache/hadoop/hbase/backup/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/backup/package-tree.html
@@ -167,9 +167,9 @@
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
 <li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/BackupInfo.BackupState.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">BackupInfo.BackupState</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/BackupRestoreConstants.BackupCommand.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">BackupRestoreConstants.BackupCommand</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/BackupType.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">BackupType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/BackupInfo.BackupPhase.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">BackupInfo.BackupPhase</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/BackupType.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">BackupType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.backup.<a href="../../../../../org/apache/hadoop/hbase/backup/BackupRestoreConstants.BackupCommand.html" title="enum in org.apache.hadoop.hbase.backup"><span class="typeNameLink">BackupRestoreConstants.BackupCommand</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/client/class-use/Scan.ReadType.html b/devapidocs/org/apache/hadoop/hbase/client/class-use/Scan.ReadType.html
index 6223283..36bcbaf 100644
--- a/devapidocs/org/apache/hadoop/hbase/client/class-use/Scan.ReadType.html
+++ b/devapidocs/org/apache/hadoop/hbase/client/class-use/Scan.ReadType.html
@@ -89,10 +89,17 @@
 </td>
 </tr>
 <tr class="rowColor">
+<td class="colFirst"><a href="#org.apache.hadoop.hbase.mapreduce">org.apache.hadoop.hbase.mapreduce</a></td>
+<td class="colLast">
+<div class="block">Provides HBase <a href="https://cwiki.apache.org/confluence/display/HADOOP2/HadoopMapReduce">MapReduce</a>
+Input/OutputFormats, a table indexing MapReduce job, and utility methods.</div>
+</td>
+</tr>
+<tr class="altColor">
 <td class="colFirst"><a href="#org.apache.hadoop.hbase.regionserver">org.apache.hadoop.hbase.regionserver</a></td>
 <td class="colLast">&nbsp;</td>
 </tr>
-<tr class="altColor">
+<tr class="rowColor">
 <td class="colFirst"><a href="#org.apache.hadoop.hbase.thrift2">org.apache.hadoop.hbase.thrift2</a></td>
 <td class="colLast">
 <div class="block">Provides an HBase <a href="http://thrift.apache.org/">Thrift</a>
@@ -173,6 +180,24 @@ the order they are declared.</div>
 </tbody>
 </table>
 </li>
+<li class="blockList"><a name="org.apache.hadoop.hbase.mapreduce">
+<!--   -->
+</a>
+<h3>Uses of <a href="../../../../../../org/apache/hadoop/hbase/client/Scan.ReadType.html" title="enum in org.apache.hadoop.hbase.client">Scan.ReadType</a> in <a href="../../../../../../org/apache/hadoop/hbase/mapreduce/package-summary.html">org.apache.hadoop.hbase.mapreduce</a></h3>
+<table class="useSummary" border="0" cellpadding="3" cellspacing="0" summary="Use table, listing fields, and an explanation">
+<caption><span>Fields in <a href="../../../../../../org/apache/hadoop/hbase/mapreduce/package-summary.html">org.apache.hadoop.hbase.mapreduce</a> declared as <a href="../../../../../../org/apache/hadoop/hbase/client/Scan.ReadType.html" title="enum in org.apache.hadoop.hbase.client">Scan.ReadType</a></span><span class="tabEnd">&nbsp;</span></caption>
+<tr>
+<th class="colFirst" scope="col">Modifier and Type</th>
+<th class="colLast" scope="col">Field and Description</th>
+</tr>
+<tbody>
+<tr class="altColor">
+<td class="colFirst"><code>static <a href="../../../../../../org/apache/hadoop/hbase/client/Scan.ReadType.html" title="enum in org.apache.hadoop.hbase.client">Scan.ReadType</a></code></td>
+<td class="colLast"><span class="typeNameLabel">TableSnapshotInputFormatImpl.</span><code><span class="memberNameLink"><a href="../../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE_DEFAULT">SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE_DEFAULT</a></span></code>&nbsp;</td>
+</tr>
+</tbody>
+</table>
+</li>
 <li class="blockList"><a name="org.apache.hadoop.hbase.regionserver">
 <!--   -->
 </a>
diff --git a/devapidocs/org/apache/hadoop/hbase/client/package-tree.html b/devapidocs/org/apache/hadoop/hbase/client/package-tree.html
index 0f09395..25a82f2 100644
--- a/devapidocs/org/apache/hadoop/hbase/client/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/client/package-tree.html
@@ -466,25 +466,25 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/CompactType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">CompactType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/TableState.State.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">TableState.State</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/MasterSwitchType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">MasterSwitchType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/Durability.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">Durability</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/MobCompactPartitionPolicy.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">MobCompactPartitionPolicy</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/LogQueryFilter.FilterByOperator.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">LogQueryFilter.FilterByOperator</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/Scan.ReadType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">Scan.ReadType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/MasterSwitchType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">MasterSwitchType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/RegionLocateType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">RegionLocateType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/CompactionState.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">CompactionState</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/CatalogReplicaMode.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">CatalogReplicaMode</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/RequestController.ReturnCode.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">RequestController.ReturnCode</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/SnapshotType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">SnapshotType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/CompactType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">CompactType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/AsyncScanSingleRegionRpcRetryingCaller.ScanControllerState.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">AsyncScanSingleRegionRpcRetryingCaller.ScanControllerState</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/ServerType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">ServerType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/LogQueryFilter.Type.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">LogQueryFilter.Type</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/IsolationLevel.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">IsolationLevel</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/RequestController.ReturnCode.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">RequestController.ReturnCode</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/AsyncScanSingleRegionRpcRetryingCaller.ScanResumerState.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">AsyncScanSingleRegionRpcRetryingCaller.ScanResumerState</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/MobCompactPartitionPolicy.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">MobCompactPartitionPolicy</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/AsyncScanSingleRegionRpcRetryingCaller.ScanControllerState.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">AsyncScanSingleRegionRpcRetryingCaller.ScanControllerState</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/SnapshotType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">SnapshotType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/CompactionState.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">CompactionState</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/AbstractResponse.ResponseType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">AbstractResponse.ResponseType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/TableState.State.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">TableState.State</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/Consistency.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">Consistency</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/LogQueryFilter.Type.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">LogQueryFilter.Type</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/ServerType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">ServerType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/Scan.ReadType.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">Scan.ReadType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.client.<a href="../../../../../org/apache/hadoop/hbase/client/Durability.html" title="enum in org.apache.hadoop.hbase.client"><span class="typeNameLink">Durability</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/client/package-use.html b/devapidocs/org/apache/hadoop/hbase/client/package-use.html
index 041f9ca..f8a3d5e 100644
--- a/devapidocs/org/apache/hadoop/hbase/client/package-use.html
+++ b/devapidocs/org/apache/hadoop/hbase/client/package-use.html
@@ -2122,11 +2122,14 @@ service.</div>
 </td>
 </tr>
 <tr class="altColor">
+<td class="colOne"><a href="../../../../../org/apache/hadoop/hbase/client/class-use/Scan.ReadType.html#org.apache.hadoop.hbase.mapreduce">Scan.ReadType</a>&nbsp;</td>
+</tr>
+<tr class="rowColor">
 <td class="colOne"><a href="../../../../../org/apache/hadoop/hbase/client/class-use/Table.html#org.apache.hadoop.hbase.mapreduce">Table</a>
 <div class="block">Used to communicate with a single HBase table.</div>
 </td>
 </tr>
-<tr class="rowColor">
+<tr class="altColor">
 <td class="colOne"><a href="../../../../../org/apache/hadoop/hbase/client/class-use/TableDescriptor.html#org.apache.hadoop.hbase.mapreduce">TableDescriptor</a>
 <div class="block">TableDescriptor contains the details about an HBase table such as the descriptors of
  all the column families, is the table a catalog table, <code> hbase:meta </code>,
diff --git a/devapidocs/org/apache/hadoop/hbase/filter/package-tree.html b/devapidocs/org/apache/hadoop/hbase/filter/package-tree.html
index 338b2c6..1a1589c 100644
--- a/devapidocs/org/apache/hadoop/hbase/filter/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/filter/package-tree.html
@@ -190,13 +190,13 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/FuzzyRowFilter.SatisfiesCode.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">FuzzyRowFilter.SatisfiesCode</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/FuzzyRowFilter.Order.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">FuzzyRowFilter.Order</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/Filter.ReturnCode.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">Filter.ReturnCode</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/FilterWrapper.FilterRowRetCode.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">FilterWrapper.FilterRowRetCode</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/BitComparator.BitwiseOp.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">BitComparator.BitwiseOp</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/RegexStringComparator.EngineType.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">RegexStringComparator.EngineType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/FilterWrapper.FilterRowRetCode.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">FilterWrapper.FilterRowRetCode</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/Filter.ReturnCode.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">Filter.ReturnCode</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/FilterList.Operator.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">FilterList.Operator</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.filter.<a href="../../../../../org/apache/hadoop/hbase/filter/FuzzyRowFilter.SatisfiesCode.html" title="enum in org.apache.hadoop.hbase.filter"><span class="typeNameLink">FuzzyRowFilter.SatisfiesCode</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/hbtop/terminal/package-tree.html b/devapidocs/org/apache/hadoop/hbase/hbtop/terminal/package-tree.html
index 5a984ee..85ba9c8 100644
--- a/devapidocs/org/apache/hadoop/hbase/hbtop/terminal/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/hbtop/terminal/package-tree.html
@@ -107,8 +107,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.hbtop.terminal.<a href="../../../../../../org/apache/hadoop/hbase/hbtop/terminal/KeyPress.Type.html" title="enum in org.apache.hadoop.hbase.hbtop.terminal"><span class="typeNameLink">KeyPress.Type</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.hbtop.terminal.<a href="../../../../../../org/apache/hadoop/hbase/hbtop/terminal/Color.html" title="enum in org.apache.hadoop.hbase.hbtop.terminal"><span class="typeNameLink">Color</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.hbtop.terminal.<a href="../../../../../../org/apache/hadoop/hbase/hbtop/terminal/KeyPress.Type.html" title="enum in org.apache.hadoop.hbase.hbtop.terminal"><span class="typeNameLink">KeyPress.Type</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/http/package-tree.html b/devapidocs/org/apache/hadoop/hbase/http/package-tree.html
index f22d03f..30f215e 100644
--- a/devapidocs/org/apache/hadoop/hbase/http/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/http/package-tree.html
@@ -140,8 +140,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.http.<a href="../../../../../org/apache/hadoop/hbase/http/ProfileServlet.Event.html" title="enum in org.apache.hadoop.hbase.http"><span class="typeNameLink">ProfileServlet.Event</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.http.<a href="../../../../../org/apache/hadoop/hbase/http/HttpConfig.Policy.html" title="enum in org.apache.hadoop.hbase.http"><span class="typeNameLink">HttpConfig.Policy</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.http.<a href="../../../../../org/apache/hadoop/hbase/http/ProfileServlet.Event.html" title="enum in org.apache.hadoop.hbase.http"><span class="typeNameLink">ProfileServlet.Event</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.http.<a href="../../../../../org/apache/hadoop/hbase/http/ProfileServlet.Output.html" title="enum in org.apache.hadoop.hbase.http"><span class="typeNameLink">ProfileServlet.Output</span></a></li>
 </ul>
 </li>
diff --git a/devapidocs/org/apache/hadoop/hbase/io/hfile/package-tree.html b/devapidocs/org/apache/hadoop/hbase/io/hfile/package-tree.html
index 5b62f1c..632a5d9 100644
--- a/devapidocs/org/apache/hadoop/hbase/io/hfile/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/io/hfile/package-tree.html
@@ -305,12 +305,12 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.BlockCategory.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">BlockType.BlockCategory</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockPriority.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">BlockPriority</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">HFileBlock.Writer.State</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheFactory.ExternalBlockCaches.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">BlockCacheFactory.ExternalBlockCaches</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">BlockType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/ReaderContext.ReaderType.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">ReaderContext.ReaderType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockCacheFactory.ExternalBlockCaches.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">BlockCacheFactory.ExternalBlockCaches</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/HFileBlock.Writer.State.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">HFileBlock.Writer.State</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockPriority.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">BlockPriority</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.io.hfile.<a href="../../../../../../org/apache/hadoop/hbase/io/hfile/BlockType.BlockCategory.html" title="enum in org.apache.hadoop.hbase.io.hfile"><span class="typeNameLink">BlockType.BlockCategory</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/ipc/package-tree.html b/devapidocs/org/apache/hadoop/hbase/ipc/package-tree.html
index b0d179f..a6b11eb 100644
--- a/devapidocs/org/apache/hadoop/hbase/ipc/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/ipc/package-tree.html
@@ -363,9 +363,9 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.ipc.<a href="../../../../../org/apache/hadoop/hbase/ipc/CallEvent.Type.html" title="enum in org.apache.hadoop.hbase.ipc"><span class="typeNameLink">CallEvent.Type</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.ipc.<a href="../../../../../org/apache/hadoop/hbase/ipc/MetricsHBaseServerSourceFactoryImpl.SourceStorage.html" title="enum in org.apache.hadoop.hbase.ipc"><span class="typeNameLink">MetricsHBaseServerSourceFactoryImpl.SourceStorage</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.ipc.<a href="../../../../../org/apache/hadoop/hbase/ipc/BufferCallBeforeInitHandler.BufferCallAction.html" title="enum in org.apache.hadoop.hbase.ipc"><span class="typeNameLink">BufferCallBeforeInitHandler.BufferCallAction</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.ipc.<a href="../../../../../org/apache/hadoop/hbase/ipc/CallEvent.Type.html" title="enum in org.apache.hadoop.hbase.ipc"><span class="typeNameLink">CallEvent.Type</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html b/devapidocs/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html
index 65615d2..27ae391 100644
--- a/devapidocs/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html
+++ b/devapidocs/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html
@@ -117,7 +117,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>public static class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.134">TableSnapshotInputFormatImpl.InputSplit</a>
+<pre>public static class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.143">TableSnapshotInputFormatImpl.InputSplit</a>
 extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a>
 implements org.apache.hadoop.io.Writable</pre>
 <div class="block">Implementation class for InputSplit logic common between mapred and mapreduce.</div>
@@ -262,7 +262,7 @@ implements org.apache.hadoop.io.Writable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>htd</h4>
-<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client">TableDescriptor</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.136">htd</a></pre>
+<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client">TableDescriptor</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.145">htd</a></pre>
 </li>
 </ul>
 <a name="regionInfo">
@@ -271,7 +271,7 @@ implements org.apache.hadoop.io.Writable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>regionInfo</h4>
-<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.137">regionInfo</a></pre>
+<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.146">regionInfo</a></pre>
 </li>
 </ul>
 <a name="locations">
@@ -280,7 +280,7 @@ implements org.apache.hadoop.io.Writable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>locations</h4>
-<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>[] <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.138">locations</a></pre>
+<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>[] <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.147">locations</a></pre>
 </li>
 </ul>
 <a name="scan">
@@ -289,7 +289,7 @@ implements org.apache.hadoop.io.Writable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>scan</h4>
-<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.139">scan</a></pre>
+<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.148">scan</a></pre>
 </li>
 </ul>
 <a name="restoreDir">
@@ -298,7 +298,7 @@ implements org.apache.hadoop.io.Writable</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>restoreDir</h4>
-<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.140">restoreDir</a></pre>
+<pre>private&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.149">restoreDir</a></pre>
 </li>
 </ul>
 </li>
@@ -315,7 +315,7 @@ implements org.apache.hadoop.io.Writable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>InputSplit</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.143">InputSplit</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.152">InputSplit</a>()</pre>
 </li>
 </ul>
 <a name="InputSplit-org.apache.hadoop.hbase.client.TableDescriptor-org.apache.hadoop.hbase.client.RegionInfo-java.util.List-org.apache.hadoop.hbase.client.Scan-org.apache.hadoop.fs.Path-">
@@ -324,7 +324,7 @@ implements org.apache.hadoop.io.Writable</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>InputSplit</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.145">InputSplit</a>(<a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client">TableDescriptor</a>&nbsp;htd,
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.154">InputSplit</a>(<a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client">TableDescriptor</a>&nbsp;htd,
                   <a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>&nbsp;regionInfo,
                   <a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&gt;&nbsp;locations,
                   <a href="../../../../../org/apache/hadoop/hbase/client/Scan.html" title="class in org.apache.hadoop.hbase.client">Scan</a>&nbsp;scan,
@@ -345,7 +345,7 @@ implements org.apache.hadoop.io.Writable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>getHtd</h4>
-<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client">TableDescriptor</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.163">getHtd</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client">TableDescriptor</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.172">getHtd</a>()</pre>
 </li>
 </ul>
 <a name="getScan--">
@@ -354,7 +354,7 @@ implements org.apache.hadoop.io.Writable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>getScan</h4>
-<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.167">getScan</a>()</pre>
+<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.176">getScan</a>()</pre>
 </li>
 </ul>
 <a name="getRestoreDir--">
@@ -363,7 +363,7 @@ implements org.apache.hadoop.io.Writable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>getRestoreDir</h4>
-<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.171">getRestoreDir</a>()</pre>
+<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.180">getRestoreDir</a>()</pre>
 </li>
 </ul>
 <a name="getLength--">
@@ -372,7 +372,7 @@ implements org.apache.hadoop.io.Writable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>getLength</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.175">getLength</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.184">getLength</a>()</pre>
 </li>
 </ul>
 <a name="getLocations--">
@@ -381,7 +381,7 @@ implements org.apache.hadoop.io.Writable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>getLocations</h4>
-<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>[]&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.180">getLocations</a>()</pre>
+<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>[]&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.189">getLocations</a>()</pre>
 </li>
 </ul>
 <a name="getTableDescriptor--">
@@ -390,7 +390,7 @@ implements org.apache.hadoop.io.Writable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>getTableDescriptor</h4>
-<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client">TableDescriptor</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.184">getTableDescriptor</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client">TableDescriptor</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.193">getTableDescriptor</a>()</pre>
 </li>
 </ul>
 <a name="getRegionInfo--">
@@ -399,7 +399,7 @@ implements org.apache.hadoop.io.Writable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>getRegionInfo</h4>
-<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.188">getRegionInfo</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.197">getRegionInfo</a>()</pre>
 </li>
 </ul>
 <a name="write-java.io.DataOutput-">
@@ -408,7 +408,7 @@ implements org.apache.hadoop.io.Writable</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>write</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.195">write</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataOutput.html?is-external=true" title="class or interface in java.io">DataOutput</a>&nbsp;out)
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.204">write</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataOutput.html?is-external=true" title="class or interface in java.io">DataOutput</a>&nbsp;out)
            throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
@@ -424,7 +424,7 @@ implements org.apache.hadoop.io.Writable</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>readFields</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.219">readFields</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataInput.html?is-external=true" title="class or interface in java.io">DataInput</a>&nbsp;in)
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html#line.228">readFields</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/io/DataInput.html?is-external=true" title="class or interface in java.io">DataInput</a>&nbsp;in)
                 throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
diff --git a/devapidocs/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html b/devapidocs/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html
index 2a3f26b..384ecfc 100644
--- a/devapidocs/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html
+++ b/devapidocs/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html
@@ -113,7 +113,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>public static class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.237">TableSnapshotInputFormatImpl.RecordReader</a>
+<pre>public static class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.246">TableSnapshotInputFormatImpl.RecordReader</a>
 extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a></pre>
 <div class="block">Implementation class for RecordReader logic common between mapred and mapreduce.</div>
 </li>
@@ -255,7 +255,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>split</h4>
-<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html" title="class in org.apache.hadoop.hbase.mapreduce">TableSnapshotInputFormatImpl.InputSplit</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.238">split</a></pre>
+<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html" title="class in org.apache.hadoop.hbase.mapreduce">TableSnapshotInputFormatImpl.InputSplit</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.247">split</a></pre>
 </li>
 </ul>
 <a name="scan">
@@ -264,7 +264,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>scan</h4>
-<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/Scan.html" title="class in org.apache.hadoop.hbase.client">Scan</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.239">scan</a></pre>
+<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/Scan.html" title="class in org.apache.hadoop.hbase.client">Scan</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.248">scan</a></pre>
 </li>
 </ul>
 <a name="result">
@@ -273,7 +273,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>result</h4>
-<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/Result.html" title="class in org.apache.hadoop.hbase.client">Result</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.240">result</a></pre>
+<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/Result.html" title="class in org.apache.hadoop.hbase.client">Result</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.249">result</a></pre>
 </li>
 </ul>
 <a name="row">
@@ -282,7 +282,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>row</h4>
-<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/io/ImmutableBytesWritable.html" title="class in org.apache.hadoop.hbase.io">ImmutableBytesWritable</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.241">row</a></pre>
+<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/io/ImmutableBytesWritable.html" title="class in org.apache.hadoop.hbase.io">ImmutableBytesWritable</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.250">row</a></pre>
 </li>
 </ul>
 <a name="scanner">
@@ -291,7 +291,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>scanner</h4>
-<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/ClientSideRegionScanner.html" title="class in org.apache.hadoop.hbase.client">ClientSideRegionScanner</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.242">scanner</a></pre>
+<pre>private&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/ClientSideRegionScanner.html" title="class in org.apache.hadoop.hbase.client">ClientSideRegionScanner</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.251">scanner</a></pre>
 </li>
 </ul>
 <a name="numOfCompleteRows">
@@ -300,7 +300,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>numOfCompleteRows</h4>
-<pre>private&nbsp;int <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.243">numOfCompleteRows</a></pre>
+<pre>private&nbsp;int <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.252">numOfCompleteRows</a></pre>
 </li>
 </ul>
 <a name="rowLimitPerSplit">
@@ -309,7 +309,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>rowLimitPerSplit</h4>
-<pre>private&nbsp;int <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.244">rowLimitPerSplit</a></pre>
+<pre>private&nbsp;int <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.253">rowLimitPerSplit</a></pre>
 </li>
 </ul>
 </li>
@@ -326,7 +326,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>RecordReader</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.237">RecordReader</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.246">RecordReader</a>()</pre>
 </li>
 </ul>
 </li>
@@ -343,7 +343,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getScanner</h4>
-<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/ClientSideRegionScanner.html" title="class in org.apache.hadoop.hbase.client">ClientSideRegionScanner</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.246">getScanner</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/ClientSideRegionScanner.html" title="class in org.apache.hadoop.hbase.client">ClientSideRegionScanner</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.255">getScanner</a>()</pre>
 </li>
 </ul>
 <a name="initialize-org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.InputSplit-org.apache.hadoop.conf.Configuration-">
@@ -352,7 +352,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>initialize</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.250">initialize</a>(<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html" title="class in org.apache.hadoop.hbase.mapreduce">TableSnapshotInputFormatImpl.InputSplit</a>&nbsp;split,
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.259">initialize</a>(<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html" title="class in org.apache.hadoop.hbase.mapreduce">TableSnapshotInputFormatImpl.InputSplit</a>&nbsp;split,
                        org.apache.hadoop.conf.Configuration&nbsp;conf)
                 throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <dl>
@@ -367,7 +367,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>nextKeyValue</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.269">nextKeyValue</a>()
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.278">nextKeyValue</a>()
                      throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -381,7 +381,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getCurrentKey</h4>
-<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/io/ImmutableBytesWritable.html" title="class in org.apache.hadoop.hbase.io">ImmutableBytesWritable</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.286">getCurrentKey</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/io/ImmutableBytesWritable.html" title="class in org.apache.hadoop.hbase.io">ImmutableBytesWritable</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.295">getCurrentKey</a>()</pre>
 </li>
 </ul>
 <a name="getCurrentValue--">
@@ -390,7 +390,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getCurrentValue</h4>
-<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/Result.html" title="class in org.apache.hadoop.hbase.client">Result</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.290">getCurrentValue</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/Result.html" title="class in org.apache.hadoop.hbase.client">Result</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.299">getCurrentValue</a>()</pre>
 </li>
 </ul>
 <a name="getPos--">
@@ -399,7 +399,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getPos</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.294">getPos</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.303">getPos</a>()</pre>
 </li>
 </ul>
 <a name="getProgress--">
@@ -408,7 +408,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getProgress</h4>
-<pre>public&nbsp;float&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.298">getProgress</a>()</pre>
+<pre>public&nbsp;float&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.307">getProgress</a>()</pre>
 </li>
 </ul>
 <a name="close--">
@@ -417,7 +417,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>close</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.302">close</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html#line.311">close</a>()</pre>
 </li>
 </ul>
 </li>
diff --git a/devapidocs/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html b/devapidocs/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html
index c4345c7..95d79ca 100644
--- a/devapidocs/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html
+++ b/devapidocs/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html
@@ -110,7 +110,7 @@ var activeTableTab = "activeTableTab";
 <hr>
 <br>
 <pre>@InterfaceAudience.Private
-public class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.69">TableSnapshotInputFormatImpl</a>
+public class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.70">TableSnapshotInputFormatImpl</a>
 extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a></pre>
 <div class="block">Hadoop MR API-agnostic implementation for mapreduce over table snapshots.</div>
 </li>
@@ -220,6 +220,17 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT">SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT</a></span></code>&nbsp;</td>
 </tr>
 <tr class="altColor">
+<td class="colFirst"><code>static <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a></code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE">SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE</a></span></code>
+<div class="block">The <a href="../../../../../org/apache/hadoop/hbase/client/Scan.ReadType.html" title="enum in org.apache.hadoop.hbase.client"><code>Scan.ReadType</code></a> which should be set on the <a href="../../../../../org/apache/hadoop/hbase/client/Scan.html" title="class in org.apache.hadoop.hbase.client"><code>Scan</code></a> to read the HBase Snapshot,
+ default STREAM.</div>
+</td>
+</tr>
+<tr class="rowColor">
+<td class="colFirst"><code>static <a href="../../../../../org/apache/hadoop/hbase/client/Scan.ReadType.html" title="enum in org.apache.hadoop.hbase.client">Scan.ReadType</a></code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE_DEFAULT">SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE_DEFAULT</a></span></code>&nbsp;</td>
+</tr>
+<tr class="altColor">
 <td class="colFirst"><code>private static <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a></code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#SNAPSHOT_NAME_KEY">SNAPSHOT_NAME_KEY</a></span></code>&nbsp;</td>
 </tr>
@@ -376,7 +387,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>LOG</h4>
-<pre>public static final&nbsp;org.slf4j.Logger <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.73">LOG</a></pre>
+<pre>public static final&nbsp;org.slf4j.Logger <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.74">LOG</a></pre>
 </li>
 </ul>
 <a name="SNAPSHOT_NAME_KEY">
@@ -385,7 +396,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>SNAPSHOT_NAME_KEY</h4>
-<pre>private static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.75">SNAPSHOT_NAME_KEY</a></pre>
+<pre>private static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.76">SNAPSHOT_NAME_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_NAME_KEY">Constant Field Values</a></dd>
@@ -398,7 +409,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>RESTORE_DIR_KEY</h4>
-<pre>protected static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.77">RESTORE_DIR_KEY</a></pre>
+<pre>protected static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.78">RESTORE_DIR_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.RESTORE_DIR_KEY">Constant Field Values</a></dd>
@@ -411,7 +422,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>LOCALITY_CUTOFF_MULTIPLIER</h4>
-<pre>private static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.80">LOCALITY_CUTOFF_MULTIPLIER</a></pre>
+<pre>private static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.81">LOCALITY_CUTOFF_MULTIPLIER</a></pre>
 <div class="block">See <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#getBestLocations-org.apache.hadoop.conf.Configuration-org.apache.hadoop.hbase.HDFSBlocksDistribution-int-"><code>getBestLocations(Configuration, HDFSBlocksDistribution, int)</code></a></div>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
@@ -425,7 +436,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>DEFAULT_LOCALITY_CUTOFF_MULTIPLIER</h4>
-<pre>private static final&nbsp;float <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.82">DEFAULT_LOCALITY_CUTOFF_MULTIPLIER</a></pre>
+<pre>private static final&nbsp;float <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.83">DEFAULT_LOCALITY_CUTOFF_MULTIPLIER</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.DEFAULT_LOCALITY_CUTOFF_MULTIPLIER">Constant Field Values</a></dd>
@@ -438,7 +449,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>SPLIT_ALGO</h4>
-<pre>public static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.88">SPLIT_ALGO</a></pre>
+<pre>public static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.89">SPLIT_ALGO</a></pre>
 <div class="block">For MapReduce jobs running multiple mappers per region, determines
  what split algorithm we should be using to find split points for scanners.</div>
 <dl>
@@ -453,7 +464,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>NUM_SPLITS_PER_REGION</h4>
-<pre>public static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.93">NUM_SPLITS_PER_REGION</a></pre>
+<pre>public static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.94">NUM_SPLITS_PER_REGION</a></pre>
 <div class="block">For MapReduce jobs running multiple mappers per region, determines
  number of splits to generate per region.</div>
 <dl>
@@ -468,7 +479,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY</h4>
-<pre>public static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.104">SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY</a></pre>
+<pre>public static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.105">SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY</a></pre>
 <div class="block">Whether to calculate the block location for splits. Default to true.
  If the computing layer runs outside of HBase cluster, the block locality does not master.
  Setting this value to false could skip the calculation and save some time.
@@ -488,7 +499,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT</h4>
-<pre>public static final&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.106">SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT</a></pre>
+<pre>public static final&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.107">SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT">Constant Field Values</a></dd>
@@ -501,7 +512,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION</h4>
-<pre>public static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.112">SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION</a></pre>
+<pre>public static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.113">SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION</a></pre>
 <div class="block">Whether to calculate the Snapshot region location by region location from meta.
  It is much faster than computing block locations for splits.</div>
 <dl>
@@ -516,7 +527,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT</h4>
-<pre>public static final&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.115">SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT</a></pre>
+<pre>public static final&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.116">SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT">Constant Field Values</a></dd>
@@ -529,7 +540,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT</h4>
-<pre>public static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.120">SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT</a></pre>
+<pre>public static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.121">SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT</a></pre>
 <div class="block">In some scenario, scan limited rows on each InputSplit for sampling data extraction</div>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
@@ -543,7 +554,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED</h4>
-<pre>public static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.126">SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED</a></pre>
+<pre>public static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.127">SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED</a></pre>
 <div class="block">Whether to enable scan metrics on Scan, default to true</div>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
@@ -554,16 +565,40 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <a name="SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT">
 <!--   -->
 </a>
-<ul class="blockListLast">
+<ul class="blockList">
 <li class="blockList">
 <h4>SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT</h4>
-<pre>public static final&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.129">SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT</a></pre>
+<pre>public static final&nbsp;boolean <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.130">SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT">Constant Field Values</a></dd>
 </dl>
 </li>
 </ul>
+<a name="SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE</h4>
+<pre>public static final&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.136">SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE</a></pre>
+<div class="block">The <a href="../../../../../org/apache/hadoop/hbase/client/Scan.ReadType.html" title="enum in org.apache.hadoop.hbase.client"><code>Scan.ReadType</code></a> which should be set on the <a href="../../../../../org/apache/hadoop/hbase/client/Scan.html" title="class in org.apache.hadoop.hbase.client"><code>Scan</code></a> to read the HBase Snapshot,
+ default STREAM.</div>
+<dl>
+<dt><span class="seeLabel">See Also:</span></dt>
+<dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE">Constant Field Values</a></dd>
+</dl>
+</li>
+</ul>
+<a name="SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE_DEFAULT">
+<!--   -->
+</a>
+<ul class="blockListLast">
+<li class="blockList">
+<h4>SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE_DEFAULT</h4>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/Scan.ReadType.html" title="enum in org.apache.hadoop.hbase.client">Scan.ReadType</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.138">SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE_DEFAULT</a></pre>
+</li>
+</ul>
 </li>
 </ul>
 <!-- ========= CONSTRUCTOR DETAIL ======== -->
@@ -578,7 +613,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>TableSnapshotInputFormatImpl</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.69">TableSnapshotInputFormatImpl</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.70">TableSnapshotInputFormatImpl</a>()</pre>
 </li>
 </ul>
 </li>
@@ -595,7 +630,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getSplits</h4>
-<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html" title="class in org.apache.hadoop.hbase.mapreduce">TableSnapshotInputFormatImpl.InputSplit</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.309">getSplit [...]
+<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html" title="class in org.apache.hadoop.hbase.mapreduce">TableSnapshotInputFormatImpl.InputSplit</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.318">getSplit [...]
                                                                throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -609,7 +644,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getSplitAlgo</h4>
-<pre>public static&nbsp;<a href="../../../../../org/apache/hadoop/hbase/util/RegionSplitter.SplitAlgorithm.html" title="interface in org.apache.hadoop.hbase.util">RegionSplitter.SplitAlgorithm</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.331">getSplitAlgo</a>(org.apache.hadoop.conf.Configuration&nbsp;conf)
+<pre>public static&nbsp;<a href="../../../../../org/apache/hadoop/hbase/util/RegionSplitter.SplitAlgorithm.html" title="interface in org.apache.hadoop.hbase.util">RegionSplitter.SplitAlgorithm</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.340">getSplitAlgo</a>(org.apache.hadoop.conf.Configuration&nbsp;conf)
                                                   throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -623,7 +658,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getRegionInfosFromManifest</h4>
-<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.346">getRegionInfosFromManifest</a>(<a href="../../../../../org/apache/ha [...]
+<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.355">getRegionInfosFromManifest</a>(<a href="../../../../../org/apache/ha [...]
 </li>
 </ul>
 <a name="getSnapshotManifest-org.apache.hadoop.conf.Configuration-java.lang.String-org.apache.hadoop.fs.Path-org.apache.hadoop.fs.FileSystem-">
@@ -632,7 +667,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getSnapshotManifest</h4>
-<pre>public static&nbsp;<a href="../../../../../org/apache/hadoop/hbase/snapshot/SnapshotManifest.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotManifest</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.364">getSnapshotManifest</a>(org.apache.hadoop.conf.Configuration&nbsp;conf,
+<pre>public static&nbsp;<a href="../../../../../org/apache/hadoop/hbase/snapshot/SnapshotManifest.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotManifest</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.373">getSnapshotManifest</a>(org.apache.hadoop.conf.Configuration&nbsp;conf,
                                                    <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;snapshotName,
                                                    org.apache.hadoop.fs.Path&nbsp;rootDir,
                                                    org.apache.hadoop.fs.FileSystem&nbsp;fs)
@@ -649,7 +684,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>extractScanFromConf</h4>
-<pre>public static&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/Scan.html" title="class in org.apache.hadoop.hbase.client">Scan</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.371">extractScanFromConf</a>(org.apache.hadoop.conf.Configuration&nbsp;conf)
+<pre>public static&nbsp;<a href="../../../../../org/apache/hadoop/hbase/client/Scan.html" title="class in org.apache.hadoop.hbase.client">Scan</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.380">extractScanFromConf</a>(org.apache.hadoop.conf.Configuration&nbsp;conf)
                                 throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -663,7 +698,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getSplits</h4>
-<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html" title="class in org.apache.hadoop.hbase.mapreduce">TableSnapshotInputFormatImpl.InputSplit</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.388">getSplit [...]
+<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html" title="class in org.apache.hadoop.hbase.mapreduce">TableSnapshotInputFormatImpl.InputSplit</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.406">getSplit [...]
                                                                       <a href="../../../../../org/apache/hadoop/hbase/snapshot/SnapshotManifest.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotManifest</a>&nbsp;manifest,
                                                                       <a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>&gt;&nbsp;regionManifests,
                                                                       org.apache.hadoop.fs.Path&nbsp;restoreDir,
@@ -681,7 +716,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getSplits</h4>
-<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html" title="class in org.apache.hadoop.hbase.mapreduce">TableSnapshotInputFormatImpl.InputSplit</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.393">getSplit [...]
+<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html" title="class in org.apache.hadoop.hbase.mapreduce">TableSnapshotInputFormatImpl.InputSplit</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.411">getSplit [...]
                                                                       <a href="../../../../../org/apache/hadoop/hbase/snapshot/SnapshotManifest.html" title="class in org.apache.hadoop.hbase.snapshot">SnapshotManifest</a>&nbsp;manifest,
                                                                       <a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>&gt;&nbsp;regionManifests,
                                                                       org.apache.hadoop.fs.Path&nbsp;restoreDir,
@@ -701,7 +736,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>calculateLocationsForInputSplit</h4>
-<pre>private static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.486">calculateLocationsForInputSplit</a>(org.apache.hadoop.conf.Confi [...]
+<pre>private static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.504">calculateLocationsForInputSplit</a>(org.apache.hadoop.conf.Confi [...]
                                                             <a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client">TableDescriptor</a>&nbsp;htd,
                                                             <a href="../../../../../org/apache/hadoop/hbase/client/RegionInfo.html" title="interface in org.apache.hadoop.hbase.client">RegionInfo</a>&nbsp;hri,
                                                             org.apache.hadoop.fs.Path&nbsp;tableDir)
@@ -720,7 +755,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getBestLocations</h4>
-<pre>private static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.505">getBestLocations</a>(org.apache.hadoop.conf.Configuration&nbsp;conf,
+<pre>private static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.523">getBestLocations</a>(org.apache.hadoop.conf.Configuration&nbsp;conf,
                                              <a href="../../../../../org/apache/hadoop/hbase/HDFSBlocksDistribution.html" title="class in org.apache.hadoop.hbase">HDFSBlocksDistribution</a>&nbsp;blockDistribution,
                                              int&nbsp;numTopsAtMost)</pre>
 <div class="block">This computes the locations to be passed from the InputSplit. MR/Yarn schedulers does not take
@@ -742,7 +777,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getBestLocations</h4>
-<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.545">getBestLocations</a>(org.apache.hadoop.conf.Configuration&nbsp;conf,
+<pre>public static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/List.html?is-external=true" title="class or interface in java.util">List</a>&lt;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&gt;&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.563">getBestLocations</a>(org.apache.hadoop.conf.Configuration&nbsp;conf,
                                             <a href="../../../../../org/apache/hadoop/hbase/HDFSBlocksDistribution.html" title="class in org.apache.hadoop.hbase">HDFSBlocksDistribution</a>&nbsp;blockDistribution)</pre>
 </li>
 </ul>
@@ -752,7 +787,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getSnapshotName</h4>
-<pre>private static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.551">getSnapshotName</a>(org.apache.hadoop.conf.Configuration&nbsp;conf)</pre>
+<pre>private static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.569">getSnapshotName</a>(org.apache.hadoop.conf.Configuration&nbsp;conf)</pre>
 </li>
 </ul>
 <a name="setInput-org.apache.hadoop.conf.Configuration-java.lang.String-org.apache.hadoop.fs.Path-">
@@ -761,7 +796,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setInput</h4>
-<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.568">setInput</a>(org.apache.hadoop.conf.Configuration&nbsp;conf,
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.586">setInput</a>(org.apache.hadoop.conf.Configuration&nbsp;conf,
                             <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;snapshotName,
                             org.apache.hadoop.fs.Path&nbsp;restoreDir)
                      throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
@@ -784,7 +819,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>setInput</h4>
-<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.584">setInput</a>(org.apache.hadoop.conf.Configuration&nbsp;conf,
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html#line.602">setInput</a>(org.apache.hadoop.conf.Configuration&nbsp;conf,
                             <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;snapshotName,
                             org.apache.hadoop.fs.Path&nbsp;restoreDir,
                             <a href="../../../../../org/apache/hadoop/hbase/util/RegionSplitter.SplitAlgorithm.html" title="interface in org.apache.hadoop.hbase.util">RegionSplitter.SplitAlgorithm</a>&nbsp;splitAlgo,
diff --git a/devapidocs/org/apache/hadoop/hbase/mapreduce/package-tree.html b/devapidocs/org/apache/hadoop/hbase/mapreduce/package-tree.html
index 0ac1c12..a3b4520 100644
--- a/devapidocs/org/apache/hadoop/hbase/mapreduce/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/mapreduce/package-tree.html
@@ -300,10 +300,10 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.mapreduce.<a href="../../../../../org/apache/hadoop/hbase/mapreduce/RowCounter.RowCounterMapper.Counters.html" title="enum in org.apache.hadoop.hbase.mapreduce"><span class="typeNameLink">RowCounter.RowCounterMapper.Counters</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.mapreduce.<a href="../../../../../org/apache/hadoop/hbase/mapreduce/CellCounter.CellCounterMapper.Counters.html" title="enum in org.apache.hadoop.hbase.mapreduce"><span class="typeNameLink">CellCounter.CellCounterMapper.Counters</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.mapreduce.<a href="../../../../../org/apache/hadoop/hbase/mapreduce/WALPlayer.Counter.html" title="enum in org.apache.hadoop.hbase.mapreduce"><span class="typeNameLink">WALPlayer.Counter</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.mapreduce.<a href="../../../../../org/apache/hadoop/hbase/mapreduce/RowCounter.RowCounterMapper.Counters.html" title="enum in org.apache.hadoop.hbase.mapreduce"><span class="typeNameLink">RowCounter.RowCounterMapper.Counters</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.mapreduce.<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSplit.Version.html" title="enum in org.apache.hadoop.hbase.mapreduce"><span class="typeNameLink">TableSplit.Version</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.mapreduce.<a href="../../../../../org/apache/hadoop/hbase/mapreduce/CellCounter.CellCounterMapper.Counters.html" title="enum in org.apache.hadoop.hbase.mapreduce"><span class="typeNameLink">CellCounter.CellCounterMapper.Counters</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.mapreduce.<a href="../../../../../org/apache/hadoop/hbase/mapreduce/SyncTable.SyncMapper.Counter.html" title="enum in org.apache.hadoop.hbase.mapreduce"><span class="typeNameLink">SyncTable.SyncMapper.Counter</span></a></li>
 </ul>
 </li>
diff --git a/devapidocs/org/apache/hadoop/hbase/master/assignment/package-tree.html b/devapidocs/org/apache/hadoop/hbase/master/assignment/package-tree.html
index 8bede26..ba98778 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/assignment/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/assignment/package-tree.html
@@ -151,8 +151,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.master.assignment.<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment"><span class="typeNameLink">TransitRegionStateProcedure.TransitionType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.master.assignment.<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/ServerState.html" title="enum in org.apache.hadoop.hbase.master.assignment"><span class="typeNameLink">ServerState</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.master.assignment.<a href="../../../../../../org/apache/hadoop/hbase/master/assignment/TransitRegionStateProcedure.TransitionType.html" title="enum in org.apache.hadoop.hbase.master.assignment"><span class="typeNameLink">TransitRegionStateProcedure.TransitionType</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/master/package-tree.html b/devapidocs/org/apache/hadoop/hbase/master/package-tree.html
index 11a881c..5e6a78d 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/package-tree.html
@@ -317,11 +317,11 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.master.<a href="../../../../../org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html" title="enum in org.apache.hadoop.hbase.master"><span class="typeNameLink">ServerManager.ServerLiveState</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.master.<a href="../../../../../org/apache/hadoop/hbase/master/MasterRpcServices.BalanceSwitchMode.html" title="enum in org.apache.hadoop.hbase.master"><span class="typeNameLink">MasterRpcServices.BalanceSwitchMode</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.master.<a href="../../../../../org/apache/hadoop/hbase/master/SplitLogManager.TerminationStatus.html" title="enum in org.apache.hadoop.hbase.master"><span class="typeNameLink">SplitLogManager.TerminationStatus</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.master.<a href="../../../../../org/apache/hadoop/hbase/master/SplitLogManager.ResubmitDirective.html" title="enum in org.apache.hadoop.hbase.master"><span class="typeNameLink">SplitLogManager.ResubmitDirective</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.master.<a href="../../../../../org/apache/hadoop/hbase/master/MetricsMasterSourceFactoryImpl.FactoryStorage.html" title="enum in org.apache.hadoop.hbase.master"><span class="typeNameLink">MetricsMasterSourceFactoryImpl.FactoryStorage</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.master.<a href="../../../../../org/apache/hadoop/hbase/master/ServerManager.ServerLiveState.html" title="enum in org.apache.hadoop.hbase.master"><span class="typeNameLink">ServerManager.ServerLiveState</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.master.<a href="../../../../../org/apache/hadoop/hbase/master/SplitLogManager.TerminationStatus.html" title="enum in org.apache.hadoop.hbase.master"><span class="typeNameLink">SplitLogManager.TerminationStatus</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.master.<a href="../../../../../org/apache/hadoop/hbase/master/RegionState.State.html" title="enum in org.apache.hadoop.hbase.master"><span class="typeNameLink">RegionState.State</span></a></li>
 </ul>
 </li>
diff --git a/devapidocs/org/apache/hadoop/hbase/master/procedure/package-tree.html b/devapidocs/org/apache/hadoop/hbase/master/procedure/package-tree.html
index a31bbbc..9e99291 100644
--- a/devapidocs/org/apache/hadoop/hbase/master/procedure/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/master/procedure/package-tree.html
@@ -222,10 +222,10 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.master.procedure.<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/ServerProcedureInterface.ServerOperationType.html" title="enum in org.apache.hadoop.hbase.master.procedure"><span class="typeNameLink">ServerProcedureInterface.ServerOperationType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.master.procedure.<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MetaProcedureInterface.MetaOperationType.html" title="enum in org.apache.hadoop.hbase.master.procedure"><span class="typeNameLink">MetaProcedureInterface.MetaOperationType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.master.procedure.<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/TableProcedureInterface.TableOperationType.html" title="enum in org.apache.hadoop.hbase.master.procedure"><span class="typeNameLink">TableProcedureInterface.TableOperationType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.master.procedure.<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/ServerProcedureInterface.ServerOperationType.html" title="enum in org.apache.hadoop.hbase.master.procedure"><span class="typeNameLink">ServerProcedureInterface.ServerOperationType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.master.procedure.<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/PeerProcedureInterface.PeerOperationType.html" title="enum in org.apache.hadoop.hbase.master.procedure"><span class="typeNameLink">PeerProcedureInterface.PeerOperationType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.master.procedure.<a href="../../../../../../org/apache/hadoop/hbase/master/procedure/MetaProcedureInterface.MetaOperationType.html" title="enum in org.apache.hadoop.hbase.master.procedure"><span class="typeNameLink">MetaProcedureInterface.MetaOperationType</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/monitoring/package-tree.html b/devapidocs/org/apache/hadoop/hbase/monitoring/package-tree.html
index 8e1184b..c9ca896 100644
--- a/devapidocs/org/apache/hadoop/hbase/monitoring/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/monitoring/package-tree.html
@@ -126,8 +126,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.monitoring.<a href="../../../../../org/apache/hadoop/hbase/monitoring/MonitoredTask.State.html" title="enum in org.apache.hadoop.hbase.monitoring"><span class="typeNameLink">MonitoredTask.State</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.monitoring.<a href="../../../../../org/apache/hadoop/hbase/monitoring/TaskMonitor.TaskFilter.TaskType.html" title="enum in org.apache.hadoop.hbase.monitoring"><span class="typeNameLink">TaskMonitor.TaskFilter.TaskType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.monitoring.<a href="../../../../../org/apache/hadoop/hbase/monitoring/MonitoredTask.State.html" title="enum in org.apache.hadoop.hbase.monitoring"><span class="typeNameLink">MonitoredTask.State</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/package-tree.html b/devapidocs/org/apache/hadoop/hbase/package-tree.html
index 443e174..6e9f011 100644
--- a/devapidocs/org/apache/hadoop/hbase/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/package-tree.html
@@ -464,20 +464,20 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/KeyValue.Type.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">KeyValue.Type</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/MetaRegionLocationCache.ZNodeOpType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">MetaRegionLocationCache.ZNodeOpType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/CompareOperator.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">CompareOperator</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HealthChecker.HealthCheckerExitStatus.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HealthChecker.HealthCheckerExitStatus</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/Size.Unit.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">Size.Unit</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/CellBuilderType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">CellBuilderType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HConstants.OperationStatusCode.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HConstants.OperationStatusCode</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/KeepDeletedCells.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">KeepDeletedCells</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/CompatibilitySingletonFactory.SingletonStorage.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">CompatibilitySingletonFactory.SingletonStorage</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/Size.Unit.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">Size.Unit</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/MemoryCompactionPolicy.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">MemoryCompactionPolicy</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ClientMetaTableAccessor.QueryType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ClientMetaTableAccessor.QueryType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/Cell.Type.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">Cell.Type</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/KeyValue.Type.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">KeyValue.Type</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/Coprocessor.State.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">Coprocessor.State</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ClusterMetrics.Option.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ClusterMetrics.Option</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/KeepDeletedCells.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">KeepDeletedCells</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/Cell.Type.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">Cell.Type</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/MetaRegionLocationCache.ZNodeOpType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">MetaRegionLocationCache.ZNodeOpType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ClientMetaTableAccessor.QueryType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ClientMetaTableAccessor.QueryType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HConstants.OperationStatusCode.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HConstants.OperationStatusCode</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/MemoryCompactionPolicy.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">MemoryCompactionPolicy</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html b/devapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
index bfff6cb..8fd4ff6 100644
--- a/devapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
@@ -217,11 +217,11 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/StateMachineProcedure.Flow.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">StateMachineProcedure.Flow</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/Procedure.LockState.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">Procedure.LockState</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/LockType.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">LockType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/LockedResourceType.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">LockedResourceType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/RootProcedureState.State.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">RootProcedureState.State</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/StateMachineProcedure.Flow.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">StateMachineProcedure.Flow</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/LockedResourceType.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">LockedResourceType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/LockType.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">LockType</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/procedure2/store/wal/package-tree.html b/devapidocs/org/apache/hadoop/hbase/procedure2/store/wal/package-tree.html
index d094b12..a402ab9 100644
--- a/devapidocs/org/apache/hadoop/hbase/procedure2/store/wal/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/procedure2/store/wal/package-tree.html
@@ -133,8 +133,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.procedure2.store.wal.<a href="../../../../../../../org/apache/hadoop/hbase/procedure2/store/wal/WALProcedureStore.PushType.html" title="enum in org.apache.hadoop.hbase.procedure2.store.wal"><span class="typeNameLink">WALProcedureStore.PushType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.procedure2.store.wal.<a href="../../../../../../../org/apache/hadoop/hbase/procedure2/store/wal/ProcedureStoreTracker.DeleteState.html" title="enum in org.apache.hadoop.hbase.procedure2.store.wal"><span class="typeNameLink">ProcedureStoreTracker.DeleteState</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure2.store.wal.<a href="../../../../../../../org/apache/hadoop/hbase/procedure2/store/wal/WALProcedureStore.PushType.html" title="enum in org.apache.hadoop.hbase.procedure2.store.wal"><span class="typeNameLink">WALProcedureStore.PushType</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/quotas/package-tree.html b/devapidocs/org/apache/hadoop/hbase/quotas/package-tree.html
index 93004b8..ef8cfb4 100644
--- a/devapidocs/org/apache/hadoop/hbase/quotas/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/quotas/package-tree.html
@@ -240,11 +240,11 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/SpaceViolationPolicy.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">SpaceViolationPolicy</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/RpcThrottlingException.Type.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">RpcThrottlingException.Type</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/QuotaType.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">QuotaType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/OperationQuota.OperationType.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">OperationQuota.OperationType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/SpaceViolationPolicy.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">SpaceViolationPolicy</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/ThrottleType.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">ThrottleType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/QuotaType.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">QuotaType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/RpcThrottlingException.Type.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">RpcThrottlingException.Type</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.quotas.<a href="../../../../../org/apache/hadoop/hbase/quotas/QuotaScope.html" title="enum in org.apache.hadoop.hbase.quotas"><span class="typeNameLink">QuotaScope</span></a></li>
 </ul>
 </li>
diff --git a/devapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html b/devapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
index 93ad485..401bc25 100644
--- a/devapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
@@ -741,20 +741,20 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/CompactingMemStore.IndexType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">CompactingMemStore.IndexType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/BloomType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">BloomType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/FlushType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">FlushType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.NextState.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">ScannerContext.NextState</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/HRegion.FlushResult.Result.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">HRegion.FlushResult.Result</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/MetricsRegionServerSourceFactoryImpl.FactoryStorage.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">MetricsRegionServerSourceFactoryImpl.FactoryStorage</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/SplitLogWorker.TaskExecutor.Status.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">SplitLogWorker.TaskExecutor.Status</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TimeRangeTracker.Type.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TimeRangeTracker.Type</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">ScannerContext.LimitScope</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/ChunkCreator.ChunkType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">ChunkCreator.ChunkType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/CompactingMemStore.IndexType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">CompactingMemStore.IndexType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/MemStoreCompactionStrategy.Action.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">MemStoreCompactionStrategy.Action</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScannerContext.LimitScope.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">ScannerContext.LimitScope</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/BloomType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">BloomType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/DefaultHeapMemoryTuner.StepDirection.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">DefaultHeapMemoryTuner.StepDirection</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/Region.Operation.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Region.Operation</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/ChunkCreator.ChunkType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">ChunkCreator.ChunkType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/ScanType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">ScanType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/Region.Operation.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">Region.Operation</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/FlushType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">FlushType</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/regionserver/wal/package-tree.html b/devapidocs/org/apache/hadoop/hbase/regionserver/wal/package-tree.html
index 61f3f12..ba199ad 100644
--- a/devapidocs/org/apache/hadoop/hbase/regionserver/wal/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/regionserver/wal/package-tree.html
@@ -250,8 +250,8 @@
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
 <li type="circle">org.apache.hadoop.hbase.regionserver.wal.<a href="../../../../../../org/apache/hadoop/hbase/regionserver/wal/RingBufferTruck.Type.html" title="enum in org.apache.hadoop.hbase.regionserver.wal"><span class="typeNameLink">RingBufferTruck.Type</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.wal.<a href="../../../../../../org/apache/hadoop/hbase/regionserver/wal/CompressionContext.DictionaryIndex.html" title="enum in org.apache.hadoop.hbase.regionserver.wal"><span class="typeNameLink">CompressionContext.DictionaryIndex</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.wal.<a href="../../../../../../org/apache/hadoop/hbase/regionserver/wal/ProtobufLogReader.WALHdrResult.html" title="enum in org.apache.hadoop.hbase.regionserver.wal"><span class="typeNameLink">ProtobufLogReader.WALHdrResult</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.wal.<a href="../../../../../../org/apache/hadoop/hbase/regionserver/wal/CompressionContext.DictionaryIndex.html" title="enum in org.apache.hadoop.hbase.regionserver.wal"><span class="typeNameLink">CompressionContext.DictionaryIndex</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.wal.<a href="../../../../../../org/apache/hadoop/hbase/regionserver/wal/WALActionsListener.RollRequestReason.html" title="enum in org.apache.hadoop.hbase.regionserver.wal"><span class="typeNameLink">WALActionsListener.RollRequestReason</span></a></li>
 </ul>
 </li>
diff --git a/devapidocs/org/apache/hadoop/hbase/replication/package-tree.html b/devapidocs/org/apache/hadoop/hbase/replication/package-tree.html
index 14f1f73..c0fbff3 100644
--- a/devapidocs/org/apache/hadoop/hbase/replication/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/replication/package-tree.html
@@ -172,8 +172,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.replication.<a href="../../../../../org/apache/hadoop/hbase/replication/ReplicationPeer.PeerState.html" title="enum in org.apache.hadoop.hbase.replication"><span class="typeNameLink">ReplicationPeer.PeerState</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.replication.<a href="../../../../../org/apache/hadoop/hbase/replication/SyncReplicationState.html" title="enum in org.apache.hadoop.hbase.replication"><span class="typeNameLink">SyncReplicationState</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.replication.<a href="../../../../../org/apache/hadoop/hbase/replication/ReplicationPeer.PeerState.html" title="enum in org.apache.hadoop.hbase.replication"><span class="typeNameLink">ReplicationPeer.PeerState</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/package-tree.html b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/package-tree.html
index cdee00f..069bc9b 100644
--- a/devapidocs/org/apache/hadoop/hbase/replication/regionserver/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/replication/regionserver/package-tree.html
@@ -224,8 +224,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.replication.regionserver.<a href="../../../../../../org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.WorkerState.html" title="enum in org.apache.hadoop.hbase.replication.regionserver"><span class="typeNameLink">ReplicationSourceShipper.WorkerState</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.replication.regionserver.<a href="../../../../../../org/apache/hadoop/hbase/replication/regionserver/MetricsReplicationSourceFactoryImpl.SourceHolder.html" title="enum in org.apache.hadoop.hbase.replication.regionserver"><span class="typeNameLink">MetricsReplicationSourceFactoryImpl.SourceHolder</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.replication.regionserver.<a href="../../../../../../org/apache/hadoop/hbase/replication/regionserver/ReplicationSourceShipper.WorkerState.html" title="enum in org.apache.hadoop.hbase.replication.regionserver"><span class="typeNameLink">ReplicationSourceShipper.WorkerState</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/rest/model/package-tree.html b/devapidocs/org/apache/hadoop/hbase/rest/model/package-tree.html
index 8703f65..90989fc 100644
--- a/devapidocs/org/apache/hadoop/hbase/rest/model/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/rest/model/package-tree.html
@@ -110,8 +110,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.rest.model.<a href="../../../../../../org/apache/hadoop/hbase/rest/model/ScannerModel.FilterModel.FilterType.html" title="enum in org.apache.hadoop.hbase.rest.model"><span class="typeNameLink">ScannerModel.FilterModel.FilterType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.rest.model.<a href="../../../../../../org/apache/hadoop/hbase/rest/model/ScannerModel.FilterModel.ByteArrayComparableModel.ComparatorType.html" title="enum in org.apache.hadoop.hbase.rest.model"><span class="typeNameLink">ScannerModel.FilterModel.ByteArrayComparableModel.ComparatorType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.rest.model.<a href="../../../../../../org/apache/hadoop/hbase/rest/model/ScannerModel.FilterModel.FilterType.html" title="enum in org.apache.hadoop.hbase.rest.model"><span class="typeNameLink">ScannerModel.FilterModel.FilterType</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/security/access/package-tree.html b/devapidocs/org/apache/hadoop/hbase/security/access/package-tree.html
index 21c4d8a..cfd3e10 100644
--- a/devapidocs/org/apache/hadoop/hbase/security/access/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/security/access/package-tree.html
@@ -162,12 +162,12 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
+<li type="circle">org.apache.hadoop.hbase.security.access.<a href="../../../../../../org/apache/hadoop/hbase/security/access/Permission.Scope.html" title="enum in org.apache.hadoop.hbase.security.access"><span class="typeNameLink">Permission.Scope</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.security.access.<a href="../../../../../../org/apache/hadoop/hbase/security/access/SnapshotScannerHDFSAclHelper.HDFSAclOperation.AclType.html" title="enum in org.apache.hadoop.hbase.security.access"><span class="typeNameLink">SnapshotScannerHDFSAclHelper.HDFSAclOperation.AclType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.security.access.<a href="../../../../../../org/apache/hadoop/hbase/security/access/SnapshotScannerHDFSAclHelper.HDFSAclOperation.OperationType.html" title="enum in org.apache.hadoop.hbase.security.access"><span class="typeNameLink">SnapshotScannerHDFSAclHelper.HDFSAclOperation.OperationType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.security.access.<a href="../../../../../../org/apache/hadoop/hbase/security/access/AccessControlFilter.Strategy.html" title="enum in org.apache.hadoop.hbase.security.access"><span class="typeNameLink">AccessControlFilter.Strategy</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.security.access.<a href="../../../../../../org/apache/hadoop/hbase/security/access/AccessController.OpType.html" title="enum in org.apache.hadoop.hbase.security.access"><span class="typeNameLink">AccessController.OpType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.security.access.<a href="../../../../../../org/apache/hadoop/hbase/security/access/AccessControlFilter.Strategy.html" title="enum in org.apache.hadoop.hbase.security.access"><span class="typeNameLink">AccessControlFilter.Strategy</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.security.access.<a href="../../../../../../org/apache/hadoop/hbase/security/access/Permission.Action.html" title="enum in org.apache.hadoop.hbase.security.access"><span class="typeNameLink">Permission.Action</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.security.access.<a href="../../../../../../org/apache/hadoop/hbase/security/access/Permission.Scope.html" title="enum in org.apache.hadoop.hbase.security.access"><span class="typeNameLink">Permission.Scope</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.security.access.<a href="../../../../../../org/apache/hadoop/hbase/security/access/SnapshotScannerHDFSAclHelper.HDFSAclOperation.AclType.html" title="enum in org.apache.hadoop.hbase.security.access"><span class="typeNameLink">SnapshotScannerHDFSAclHelper.HDFSAclOperation.AclType</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/security/package-tree.html b/devapidocs/org/apache/hadoop/hbase/security/package-tree.html
index 0b85236..c56a992 100644
--- a/devapidocs/org/apache/hadoop/hbase/security/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/security/package-tree.html
@@ -190,8 +190,8 @@
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
 <li type="circle">org.apache.hadoop.hbase.security.<a href="../../../../../org/apache/hadoop/hbase/security/SaslStatus.html" title="enum in org.apache.hadoop.hbase.security"><span class="typeNameLink">SaslStatus</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.security.<a href="../../../../../org/apache/hadoop/hbase/security/AuthMethod.html" title="enum in org.apache.hadoop.hbase.security"><span class="typeNameLink">AuthMethod</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.security.<a href="../../../../../org/apache/hadoop/hbase/security/SaslUtil.QualityOfProtection.html" title="enum in org.apache.hadoop.hbase.security"><span class="typeNameLink">SaslUtil.QualityOfProtection</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.security.<a href="../../../../../org/apache/hadoop/hbase/security/AuthMethod.html" title="enum in org.apache.hadoop.hbase.security"><span class="typeNameLink">AuthMethod</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/thrift/package-tree.html b/devapidocs/org/apache/hadoop/hbase/thrift/package-tree.html
index fba9877..68b114e 100644
--- a/devapidocs/org/apache/hadoop/hbase/thrift/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/thrift/package-tree.html
@@ -211,9 +211,9 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
+<li type="circle">org.apache.hadoop.hbase.thrift.<a href="../../../../../org/apache/hadoop/hbase/thrift/MetricsThriftServerSourceFactoryImpl.FactoryStorage.html" title="enum in org.apache.hadoop.hbase.thrift"><span class="typeNameLink">MetricsThriftServerSourceFactoryImpl.FactoryStorage</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.thrift.<a href="../../../../../org/apache/hadoop/hbase/thrift/ThriftMetrics.ThriftServerType.html" title="enum in org.apache.hadoop.hbase.thrift"><span class="typeNameLink">ThriftMetrics.ThriftServerType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.thrift.<a href="../../../../../org/apache/hadoop/hbase/thrift/ImplType.html" title="enum in org.apache.hadoop.hbase.thrift"><span class="typeNameLink">ImplType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.thrift.<a href="../../../../../org/apache/hadoop/hbase/thrift/MetricsThriftServerSourceFactoryImpl.FactoryStorage.html" title="enum in org.apache.hadoop.hbase.thrift"><span class="typeNameLink">MetricsThriftServerSourceFactoryImpl.FactoryStorage</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/org/apache/hadoop/hbase/util/package-tree.html b/devapidocs/org/apache/hadoop/hbase/util/package-tree.html
index 9c19231..34c0d45 100644
--- a/devapidocs/org/apache/hadoop/hbase/util/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/util/package-tree.html
@@ -532,14 +532,14 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
+<li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/PrettyPrinter.Unit.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">PrettyPrinter.Unit</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/Bytes.LexicographicalComparerHolder.PureJavaComparer.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">Bytes.LexicographicalComparerHolder.PureJavaComparer</span></a> (implements org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/Bytes.Comparer.html" title="interface in org.apache.hadoop.hbase.util">Bytes.Comparer</a>&lt;T&gt;)</li>
 <li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/PoolMap.PoolType.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">PoolMap.PoolType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/PrettyPrinter.Unit.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">PrettyPrinter.Unit</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/DNS.ServerType.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">DNS.ServerType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/Bytes.LexicographicalComparerHolder.UnsafeComparer.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">Bytes.LexicographicalComparerHolder.UnsafeComparer</span></a> (implements org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/Bytes.Comparer.html" title="interface in org.apache.hadoop.hbase.util">Bytes.Comparer</a>&lt;T&gt;)</li>
 <li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/IdReadWriteLockWithObjectPool.ReferenceType.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">IdReadWriteLockWithObjectPool.ReferenceType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/Order.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">Order</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/Bytes.LexicographicalComparerHolder.UnsafeComparer.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">Bytes.LexicographicalComparerHolder.UnsafeComparer</span></a> (implements org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/Bytes.Comparer.html" title="interface in org.apache.hadoop.hbase.util">Bytes.Comparer</a>&lt;T&gt;)</li>
 <li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/ChecksumType.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">ChecksumType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/DNS.ServerType.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">DNS.ServerType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.util.<a href="../../../../../org/apache/hadoop/hbase/util/HbckErrorReporter.ERROR_CODE.html" title="enum in org.apache.hadoop.hbase.util"><span class="typeNameLink">HbckErrorReporter.ERROR_CODE</span></a></li>
 </ul>
 </li>
diff --git a/devapidocs/org/apache/hadoop/hbase/wal/package-tree.html b/devapidocs/org/apache/hadoop/hbase/wal/package-tree.html
index 61f35f9..5921874 100644
--- a/devapidocs/org/apache/hadoop/hbase/wal/package-tree.html
+++ b/devapidocs/org/apache/hadoop/hbase/wal/package-tree.html
@@ -198,8 +198,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/RegionGroupingProvider.Strategies.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">RegionGroupingProvider.Strategies</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/WALFactory.Providers.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">WALFactory.Providers</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/RegionGroupingProvider.Strategies.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">RegionGroupingProvider.Strategies</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html b/devapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html
index b614563..2f3d5ca 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.InputSplit.html
@@ -49,570 +49,588 @@
 <span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.client.RegionLocator;<a name="line.41"></a>
 <span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.client.Result;<a name="line.42"></a>
 <span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.client.Scan;<a name="line.43"></a>
-<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.client.TableDescriptor;<a name="line.44"></a>
-<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<a name="line.45"></a>
-<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.regionserver.HRegion;<a name="line.46"></a>
-<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.snapshot.RestoreSnapshotHelper;<a name="line.47"></a>
-<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;<a name="line.48"></a>
-<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.snapshot.SnapshotManifest;<a name="line.49"></a>
-<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.50"></a>
-<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.51"></a>
-<span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.util.RegionSplitter;<a name="line.52"></a>
-<span class="sourceLineNo">053</span>import org.apache.hadoop.io.Writable;<a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.54"></a>
-<span class="sourceLineNo">055</span>import org.slf4j.Logger;<a name="line.55"></a>
-<span class="sourceLineNo">056</span>import org.slf4j.LoggerFactory;<a name="line.56"></a>
-<span class="sourceLineNo">057</span><a name="line.57"></a>
-<span class="sourceLineNo">058</span>import org.apache.hbase.thirdparty.com.google.common.collect.Lists;<a name="line.58"></a>
-<span class="sourceLineNo">059</span><a name="line.59"></a>
-<span class="sourceLineNo">060</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.60"></a>
-<span class="sourceLineNo">061</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MapReduceProtos.TableSnapshotRegionSplit;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription;<a name="line.62"></a>
-<span class="sourceLineNo">063</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;<a name="line.63"></a>
-<span class="sourceLineNo">064</span><a name="line.64"></a>
-<span class="sourceLineNo">065</span>/**<a name="line.65"></a>
-<span class="sourceLineNo">066</span> * Hadoop MR API-agnostic implementation for mapreduce over table snapshots.<a name="line.66"></a>
-<span class="sourceLineNo">067</span> */<a name="line.67"></a>
-<span class="sourceLineNo">068</span>@InterfaceAudience.Private<a name="line.68"></a>
-<span class="sourceLineNo">069</span>public class TableSnapshotInputFormatImpl {<a name="line.69"></a>
-<span class="sourceLineNo">070</span>  // TODO: Snapshots files are owned in fs by the hbase user. There is no<a name="line.70"></a>
-<span class="sourceLineNo">071</span>  // easy way to delegate access.<a name="line.71"></a>
-<span class="sourceLineNo">072</span><a name="line.72"></a>
-<span class="sourceLineNo">073</span>  public static final Logger LOG = LoggerFactory.getLogger(TableSnapshotInputFormatImpl.class);<a name="line.73"></a>
-<span class="sourceLineNo">074</span><a name="line.74"></a>
-<span class="sourceLineNo">075</span>  private static final String SNAPSHOT_NAME_KEY = "hbase.TableSnapshotInputFormat.snapshot.name";<a name="line.75"></a>
-<span class="sourceLineNo">076</span>  // key for specifying the root dir of the restored snapshot<a name="line.76"></a>
-<span class="sourceLineNo">077</span>  protected static final String RESTORE_DIR_KEY = "hbase.TableSnapshotInputFormat.restore.dir";<a name="line.77"></a>
-<span class="sourceLineNo">078</span><a name="line.78"></a>
-<span class="sourceLineNo">079</span>  /** See {@link #getBestLocations(Configuration, HDFSBlocksDistribution, int)} */<a name="line.79"></a>
-<span class="sourceLineNo">080</span>  private static final String LOCALITY_CUTOFF_MULTIPLIER =<a name="line.80"></a>
-<span class="sourceLineNo">081</span>    "hbase.tablesnapshotinputformat.locality.cutoff.multiplier";<a name="line.81"></a>
-<span class="sourceLineNo">082</span>  private static final float DEFAULT_LOCALITY_CUTOFF_MULTIPLIER = 0.8f;<a name="line.82"></a>
-<span class="sourceLineNo">083</span><a name="line.83"></a>
-<span class="sourceLineNo">084</span>  /**<a name="line.84"></a>
-<span class="sourceLineNo">085</span>   * For MapReduce jobs running multiple mappers per region, determines<a name="line.85"></a>
-<span class="sourceLineNo">086</span>   * what split algorithm we should be using to find split points for scanners.<a name="line.86"></a>
-<span class="sourceLineNo">087</span>   */<a name="line.87"></a>
-<span class="sourceLineNo">088</span>  public static final String SPLIT_ALGO = "hbase.mapreduce.split.algorithm";<a name="line.88"></a>
-<span class="sourceLineNo">089</span>  /**<a name="line.89"></a>
-<span class="sourceLineNo">090</span>   * For MapReduce jobs running multiple mappers per region, determines<a name="line.90"></a>
-<span class="sourceLineNo">091</span>   * number of splits to generate per region.<a name="line.91"></a>
-<span class="sourceLineNo">092</span>   */<a name="line.92"></a>
-<span class="sourceLineNo">093</span>  public static final String NUM_SPLITS_PER_REGION = "hbase.mapreduce.splits.per.region";<a name="line.93"></a>
-<span class="sourceLineNo">094</span><a name="line.94"></a>
-<span class="sourceLineNo">095</span>  /**<a name="line.95"></a>
-<span class="sourceLineNo">096</span>   * Whether to calculate the block location for splits. Default to true.<a name="line.96"></a>
-<span class="sourceLineNo">097</span>   * If the computing layer runs outside of HBase cluster, the block locality does not master.<a name="line.97"></a>
-<span class="sourceLineNo">098</span>   * Setting this value to false could skip the calculation and save some time.<a name="line.98"></a>
-<span class="sourceLineNo">099</span>   *<a name="line.99"></a>
-<span class="sourceLineNo">100</span>   * Set access modifier to "public" so that these could be accessed by test classes of<a name="line.100"></a>
-<span class="sourceLineNo">101</span>   * both org.apache.hadoop.hbase.mapred<a name="line.101"></a>
-<span class="sourceLineNo">102</span>   * and  org.apache.hadoop.hbase.mapreduce.<a name="line.102"></a>
-<span class="sourceLineNo">103</span>   */<a name="line.103"></a>
-<span class="sourceLineNo">104</span>  public static final String  SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY =<a name="line.104"></a>
-<span class="sourceLineNo">105</span>      "hbase.TableSnapshotInputFormat.locality.enabled";<a name="line.105"></a>
-<span class="sourceLineNo">106</span>  public static final boolean SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT = true;<a name="line.106"></a>
-<span class="sourceLineNo">107</span><a name="line.107"></a>
-<span class="sourceLineNo">108</span>  /**<a name="line.108"></a>
-<span class="sourceLineNo">109</span>   * Whether to calculate the Snapshot region location by region location from meta.<a name="line.109"></a>
-<span class="sourceLineNo">110</span>   * It is much faster than computing block locations for splits.<a name="line.110"></a>
-<span class="sourceLineNo">111</span>   */<a name="line.111"></a>
-<span class="sourceLineNo">112</span>  public static final String  SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION =<a name="line.112"></a>
-<span class="sourceLineNo">113</span>    "hbase.TableSnapshotInputFormat.locality.by.region.location";<a name="line.113"></a>
-<span class="sourceLineNo">114</span><a name="line.114"></a>
-<span class="sourceLineNo">115</span>  public static final boolean SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT = false;<a name="line.115"></a>
-<span class="sourceLineNo">116</span><a name="line.116"></a>
-<span class="sourceLineNo">117</span>  /**<a name="line.117"></a>
-<span class="sourceLineNo">118</span>   * In some scenario, scan limited rows on each InputSplit for sampling data extraction<a name="line.118"></a>
-<span class="sourceLineNo">119</span>   */<a name="line.119"></a>
-<span class="sourceLineNo">120</span>  public static final String SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT =<a name="line.120"></a>
-<span class="sourceLineNo">121</span>      "hbase.TableSnapshotInputFormat.row.limit.per.inputsplit";<a name="line.121"></a>
-<span class="sourceLineNo">122</span><a name="line.122"></a>
-<span class="sourceLineNo">123</span>  /**<a name="line.123"></a>
-<span class="sourceLineNo">124</span>   * Whether to enable scan metrics on Scan, default to true<a name="line.124"></a>
-<span class="sourceLineNo">125</span>   */<a name="line.125"></a>
-<span class="sourceLineNo">126</span>  public static final String  SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED =<a name="line.126"></a>
-<span class="sourceLineNo">127</span>    "hbase.TableSnapshotInputFormat.scan_metrics.enabled";<a name="line.127"></a>
-<span class="sourceLineNo">128</span><a name="line.128"></a>
-<span class="sourceLineNo">129</span>  public static final boolean SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT = true;<a name="line.129"></a>
-<span class="sourceLineNo">130</span><a name="line.130"></a>
-<span class="sourceLineNo">131</span>  /**<a name="line.131"></a>
-<span class="sourceLineNo">132</span>   * Implementation class for InputSplit logic common between mapred and mapreduce.<a name="line.132"></a>
-<span class="sourceLineNo">133</span>   */<a name="line.133"></a>
-<span class="sourceLineNo">134</span>  public static class InputSplit implements Writable {<a name="line.134"></a>
-<span class="sourceLineNo">135</span><a name="line.135"></a>
-<span class="sourceLineNo">136</span>    private TableDescriptor htd;<a name="line.136"></a>
-<span class="sourceLineNo">137</span>    private RegionInfo regionInfo;<a name="line.137"></a>
-<span class="sourceLineNo">138</span>    private String[] locations;<a name="line.138"></a>
-<span class="sourceLineNo">139</span>    private String scan;<a name="line.139"></a>
-<span class="sourceLineNo">140</span>    private String restoreDir;<a name="line.140"></a>
-<span class="sourceLineNo">141</span><a name="line.141"></a>
-<span class="sourceLineNo">142</span>    // constructor for mapreduce framework / Writable<a name="line.142"></a>
-<span class="sourceLineNo">143</span>    public InputSplit() {}<a name="line.143"></a>
+<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.client.Scan.ReadType;<a name="line.44"></a>
+<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.client.TableDescriptor;<a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.regionserver.HRegion;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.snapshot.RestoreSnapshotHelper;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;<a name="line.49"></a>
+<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.snapshot.SnapshotManifest;<a name="line.50"></a>
+<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.51"></a>
+<span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.52"></a>
+<span class="sourceLineNo">053</span>import org.apache.hadoop.hbase.util.RegionSplitter;<a name="line.53"></a>
+<span class="sourceLineNo">054</span>import org.apache.hadoop.io.Writable;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>import org.slf4j.Logger;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>import org.slf4j.LoggerFactory;<a name="line.57"></a>
+<span class="sourceLineNo">058</span><a name="line.58"></a>
+<span class="sourceLineNo">059</span>import org.apache.hbase.thirdparty.com.google.common.collect.Lists;<a name="line.59"></a>
+<span class="sourceLineNo">060</span><a name="line.60"></a>
+<span class="sourceLineNo">061</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.61"></a>
+<span class="sourceLineNo">062</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MapReduceProtos.TableSnapshotRegionSplit;<a name="line.62"></a>
+<span class="sourceLineNo">063</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription;<a name="line.63"></a>
+<span class="sourceLineNo">064</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;<a name="line.64"></a>
+<span class="sourceLineNo">065</span><a name="line.65"></a>
+<span class="sourceLineNo">066</span>/**<a name="line.66"></a>
+<span class="sourceLineNo">067</span> * Hadoop MR API-agnostic implementation for mapreduce over table snapshots.<a name="line.67"></a>
+<span class="sourceLineNo">068</span> */<a name="line.68"></a>
+<span class="sourceLineNo">069</span>@InterfaceAudience.Private<a name="line.69"></a>
+<span class="sourceLineNo">070</span>public class TableSnapshotInputFormatImpl {<a name="line.70"></a>
+<span class="sourceLineNo">071</span>  // TODO: Snapshots files are owned in fs by the hbase user. There is no<a name="line.71"></a>
+<span class="sourceLineNo">072</span>  // easy way to delegate access.<a name="line.72"></a>
+<span class="sourceLineNo">073</span><a name="line.73"></a>
+<span class="sourceLineNo">074</span>  public static final Logger LOG = LoggerFactory.getLogger(TableSnapshotInputFormatImpl.class);<a name="line.74"></a>
+<span class="sourceLineNo">075</span><a name="line.75"></a>
+<span class="sourceLineNo">076</span>  private static final String SNAPSHOT_NAME_KEY = "hbase.TableSnapshotInputFormat.snapshot.name";<a name="line.76"></a>
+<span class="sourceLineNo">077</span>  // key for specifying the root dir of the restored snapshot<a name="line.77"></a>
+<span class="sourceLineNo">078</span>  protected static final String RESTORE_DIR_KEY = "hbase.TableSnapshotInputFormat.restore.dir";<a name="line.78"></a>
+<span class="sourceLineNo">079</span><a name="line.79"></a>
+<span class="sourceLineNo">080</span>  /** See {@link #getBestLocations(Configuration, HDFSBlocksDistribution, int)} */<a name="line.80"></a>
+<span class="sourceLineNo">081</span>  private static final String LOCALITY_CUTOFF_MULTIPLIER =<a name="line.81"></a>
+<span class="sourceLineNo">082</span>    "hbase.tablesnapshotinputformat.locality.cutoff.multiplier";<a name="line.82"></a>
+<span class="sourceLineNo">083</span>  private static final float DEFAULT_LOCALITY_CUTOFF_MULTIPLIER = 0.8f;<a name="line.83"></a>
+<span class="sourceLineNo">084</span><a name="line.84"></a>
+<span class="sourceLineNo">085</span>  /**<a name="line.85"></a>
+<span class="sourceLineNo">086</span>   * For MapReduce jobs running multiple mappers per region, determines<a name="line.86"></a>
+<span class="sourceLineNo">087</span>   * what split algorithm we should be using to find split points for scanners.<a name="line.87"></a>
+<span class="sourceLineNo">088</span>   */<a name="line.88"></a>
+<span class="sourceLineNo">089</span>  public static final String SPLIT_ALGO = "hbase.mapreduce.split.algorithm";<a name="line.89"></a>
+<span class="sourceLineNo">090</span>  /**<a name="line.90"></a>
+<span class="sourceLineNo">091</span>   * For MapReduce jobs running multiple mappers per region, determines<a name="line.91"></a>
+<span class="sourceLineNo">092</span>   * number of splits to generate per region.<a name="line.92"></a>
+<span class="sourceLineNo">093</span>   */<a name="line.93"></a>
+<span class="sourceLineNo">094</span>  public static final String NUM_SPLITS_PER_REGION = "hbase.mapreduce.splits.per.region";<a name="line.94"></a>
+<span class="sourceLineNo">095</span><a name="line.95"></a>
+<span class="sourceLineNo">096</span>  /**<a name="line.96"></a>
+<span class="sourceLineNo">097</span>   * Whether to calculate the block location for splits. Default to true.<a name="line.97"></a>
+<span class="sourceLineNo">098</span>   * If the computing layer runs outside of HBase cluster, the block locality does not master.<a name="line.98"></a>
+<span class="sourceLineNo">099</span>   * Setting this value to false could skip the calculation and save some time.<a name="line.99"></a>
+<span class="sourceLineNo">100</span>   *<a name="line.100"></a>
+<span class="sourceLineNo">101</span>   * Set access modifier to "public" so that these could be accessed by test classes of<a name="line.101"></a>
+<span class="sourceLineNo">102</span>   * both org.apache.hadoop.hbase.mapred<a name="line.102"></a>
+<span class="sourceLineNo">103</span>   * and  org.apache.hadoop.hbase.mapreduce.<a name="line.103"></a>
+<span class="sourceLineNo">104</span>   */<a name="line.104"></a>
+<span class="sourceLineNo">105</span>  public static final String  SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY =<a name="line.105"></a>
+<span class="sourceLineNo">106</span>      "hbase.TableSnapshotInputFormat.locality.enabled";<a name="line.106"></a>
+<span class="sourceLineNo">107</span>  public static final boolean SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT = true;<a name="line.107"></a>
+<span class="sourceLineNo">108</span><a name="line.108"></a>
+<span class="sourceLineNo">109</span>  /**<a name="line.109"></a>
+<span class="sourceLineNo">110</span>   * Whether to calculate the Snapshot region location by region location from meta.<a name="line.110"></a>
+<span class="sourceLineNo">111</span>   * It is much faster than computing block locations for splits.<a name="line.111"></a>
+<span class="sourceLineNo">112</span>   */<a name="line.112"></a>
+<span class="sourceLineNo">113</span>  public static final String  SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION =<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    "hbase.TableSnapshotInputFormat.locality.by.region.location";<a name="line.114"></a>
+<span class="sourceLineNo">115</span><a name="line.115"></a>
+<span class="sourceLineNo">116</span>  public static final boolean SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT = false;<a name="line.116"></a>
+<span class="sourceLineNo">117</span><a name="line.117"></a>
+<span class="sourceLineNo">118</span>  /**<a name="line.118"></a>
+<span class="sourceLineNo">119</span>   * In some scenario, scan limited rows on each InputSplit for sampling data extraction<a name="line.119"></a>
+<span class="sourceLineNo">120</span>   */<a name="line.120"></a>
+<span class="sourceLineNo">121</span>  public static final String SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT =<a name="line.121"></a>
+<span class="sourceLineNo">122</span>      "hbase.TableSnapshotInputFormat.row.limit.per.inputsplit";<a name="line.122"></a>
+<span class="sourceLineNo">123</span><a name="line.123"></a>
+<span class="sourceLineNo">124</span>  /**<a name="line.124"></a>
+<span class="sourceLineNo">125</span>   * Whether to enable scan metrics on Scan, default to true<a name="line.125"></a>
+<span class="sourceLineNo">126</span>   */<a name="line.126"></a>
+<span class="sourceLineNo">127</span>  public static final String  SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED =<a name="line.127"></a>
+<span class="sourceLineNo">128</span>    "hbase.TableSnapshotInputFormat.scan_metrics.enabled";<a name="line.128"></a>
+<span class="sourceLineNo">129</span><a name="line.129"></a>
+<span class="sourceLineNo">130</span>  public static final boolean SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT = true;<a name="line.130"></a>
+<span class="sourceLineNo">131</span><a name="line.131"></a>
+<span class="sourceLineNo">132</span>  /**<a name="line.132"></a>
+<span class="sourceLineNo">133</span>   * The {@link ReadType} which should be set on the {@link Scan} to read the HBase Snapshot,<a name="line.133"></a>
+<span class="sourceLineNo">134</span>   * default STREAM.<a name="line.134"></a>
+<span class="sourceLineNo">135</span>   */<a name="line.135"></a>
+<span class="sourceLineNo">136</span>  public static final String SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE =<a name="line.136"></a>
+<span class="sourceLineNo">137</span>      "hbase.TableSnapshotInputFormat.scanner.readtype";<a name="line.137"></a>
+<span class="sourceLineNo">138</span>  public static final ReadType SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE_DEFAULT = ReadType.STREAM;<a name="line.138"></a>
+<span class="sourceLineNo">139</span><a name="line.139"></a>
+<span class="sourceLineNo">140</span>  /**<a name="line.140"></a>
+<span class="sourceLineNo">141</span>   * Implementation class for InputSplit logic common between mapred and mapreduce.<a name="line.141"></a>
+<span class="sourceLineNo">142</span>   */<a name="line.142"></a>
+<span class="sourceLineNo">143</span>  public static class InputSplit implements Writable {<a name="line.143"></a>
 <span class="sourceLineNo">144</span><a name="line.144"></a>
-<span class="sourceLineNo">145</span>    public InputSplit(TableDescriptor htd, RegionInfo regionInfo, List&lt;String&gt; locations,<a name="line.145"></a>
-<span class="sourceLineNo">146</span>        Scan scan, Path restoreDir) {<a name="line.146"></a>
-<span class="sourceLineNo">147</span>      this.htd = htd;<a name="line.147"></a>
-<span class="sourceLineNo">148</span>      this.regionInfo = regionInfo;<a name="line.148"></a>
-<span class="sourceLineNo">149</span>      if (locations == null || locations.isEmpty()) {<a name="line.149"></a>
-<span class="sourceLineNo">150</span>        this.locations = new String[0];<a name="line.150"></a>
-<span class="sourceLineNo">151</span>      } else {<a name="line.151"></a>
-<span class="sourceLineNo">152</span>        this.locations = locations.toArray(new String[locations.size()]);<a name="line.152"></a>
-<span class="sourceLineNo">153</span>      }<a name="line.153"></a>
-<span class="sourceLineNo">154</span>      try {<a name="line.154"></a>
-<span class="sourceLineNo">155</span>        this.scan = scan != null ? TableMapReduceUtil.convertScanToString(scan) : "";<a name="line.155"></a>
-<span class="sourceLineNo">156</span>      } catch (IOException e) {<a name="line.156"></a>
-<span class="sourceLineNo">157</span>        LOG.warn("Failed to convert Scan to String", e);<a name="line.157"></a>
-<span class="sourceLineNo">158</span>      }<a name="line.158"></a>
-<span class="sourceLineNo">159</span><a name="line.159"></a>
-<span class="sourceLineNo">160</span>      this.restoreDir = restoreDir.toString();<a name="line.160"></a>
-<span class="sourceLineNo">161</span>    }<a name="line.161"></a>
-<span class="sourceLineNo">162</span><a name="line.162"></a>
-<span class="sourceLineNo">163</span>    public TableDescriptor getHtd() {<a name="line.163"></a>
-<span class="sourceLineNo">164</span>      return htd;<a name="line.164"></a>
-<span class="sourceLineNo">165</span>    }<a name="line.165"></a>
-<span class="sourceLineNo">166</span><a name="line.166"></a>
-<span class="sourceLineNo">167</span>    public String getScan() {<a name="line.167"></a>
-<span class="sourceLineNo">168</span>      return scan;<a name="line.168"></a>
-<span class="sourceLineNo">169</span>    }<a name="line.169"></a>
-<span class="sourceLineNo">170</span><a name="line.170"></a>
-<span class="sourceLineNo">171</span>    public String getRestoreDir() {<a name="line.171"></a>
-<span class="sourceLineNo">172</span>      return restoreDir;<a name="line.172"></a>
-<span class="sourceLineNo">173</span>    }<a name="line.173"></a>
-<span class="sourceLineNo">174</span><a name="line.174"></a>
-<span class="sourceLineNo">175</span>    public long getLength() {<a name="line.175"></a>
-<span class="sourceLineNo">176</span>      //TODO: We can obtain the file sizes of the snapshot here.<a name="line.176"></a>
-<span class="sourceLineNo">177</span>      return 0;<a name="line.177"></a>
+<span class="sourceLineNo">145</span>    private TableDescriptor htd;<a name="line.145"></a>
+<span class="sourceLineNo">146</span>    private RegionInfo regionInfo;<a name="line.146"></a>
+<span class="sourceLineNo">147</span>    private String[] locations;<a name="line.147"></a>
+<span class="sourceLineNo">148</span>    private String scan;<a name="line.148"></a>
+<span class="sourceLineNo">149</span>    private String restoreDir;<a name="line.149"></a>
+<span class="sourceLineNo">150</span><a name="line.150"></a>
+<span class="sourceLineNo">151</span>    // constructor for mapreduce framework / Writable<a name="line.151"></a>
+<span class="sourceLineNo">152</span>    public InputSplit() {}<a name="line.152"></a>
+<span class="sourceLineNo">153</span><a name="line.153"></a>
+<span class="sourceLineNo">154</span>    public InputSplit(TableDescriptor htd, RegionInfo regionInfo, List&lt;String&gt; locations,<a name="line.154"></a>
+<span class="sourceLineNo">155</span>        Scan scan, Path restoreDir) {<a name="line.155"></a>
+<span class="sourceLineNo">156</span>      this.htd = htd;<a name="line.156"></a>
+<span class="sourceLineNo">157</span>      this.regionInfo = regionInfo;<a name="line.157"></a>
+<span class="sourceLineNo">158</span>      if (locations == null || locations.isEmpty()) {<a name="line.158"></a>
+<span class="sourceLineNo">159</span>        this.locations = new String[0];<a name="line.159"></a>
+<span class="sourceLineNo">160</span>      } else {<a name="line.160"></a>
+<span class="sourceLineNo">161</span>        this.locations = locations.toArray(new String[locations.size()]);<a name="line.161"></a>
+<span class="sourceLineNo">162</span>      }<a name="line.162"></a>
+<span class="sourceLineNo">163</span>      try {<a name="line.163"></a>
+<span class="sourceLineNo">164</span>        this.scan = scan != null ? TableMapReduceUtil.convertScanToString(scan) : "";<a name="line.164"></a>
+<span class="sourceLineNo">165</span>      } catch (IOException e) {<a name="line.165"></a>
+<span class="sourceLineNo">166</span>        LOG.warn("Failed to convert Scan to String", e);<a name="line.166"></a>
+<span class="sourceLineNo">167</span>      }<a name="line.167"></a>
+<span class="sourceLineNo">168</span><a name="line.168"></a>
+<span class="sourceLineNo">169</span>      this.restoreDir = restoreDir.toString();<a name="line.169"></a>
+<span class="sourceLineNo">170</span>    }<a name="line.170"></a>
+<span class="sourceLineNo">171</span><a name="line.171"></a>
+<span class="sourceLineNo">172</span>    public TableDescriptor getHtd() {<a name="line.172"></a>
+<span class="sourceLineNo">173</span>      return htd;<a name="line.173"></a>
+<span class="sourceLineNo">174</span>    }<a name="line.174"></a>
+<span class="sourceLineNo">175</span><a name="line.175"></a>
+<span class="sourceLineNo">176</span>    public String getScan() {<a name="line.176"></a>
+<span class="sourceLineNo">177</span>      return scan;<a name="line.177"></a>
 <span class="sourceLineNo">178</span>    }<a name="line.178"></a>
 <span class="sourceLineNo">179</span><a name="line.179"></a>
-<span class="sourceLineNo">180</span>    public String[] getLocations() {<a name="line.180"></a>
-<span class="sourceLineNo">181</span>      return locations;<a name="line.181"></a>
+<span class="sourceLineNo">180</span>    public String getRestoreDir() {<a name="line.180"></a>
+<span class="sourceLineNo">181</span>      return restoreDir;<a name="line.181"></a>
 <span class="sourceLineNo">182</span>    }<a name="line.182"></a>
 <span class="sourceLineNo">183</span><a name="line.183"></a>
-<span class="sourceLineNo">184</span>    public TableDescriptor getTableDescriptor() {<a name="line.184"></a>
-<span class="sourceLineNo">185</span>      return htd;<a name="line.185"></a>
-<span class="sourceLineNo">186</span>    }<a name="line.186"></a>
-<span class="sourceLineNo">187</span><a name="line.187"></a>
-<span class="sourceLineNo">188</span>    public RegionInfo getRegionInfo() {<a name="line.188"></a>
-<span class="sourceLineNo">189</span>      return regionInfo;<a name="line.189"></a>
-<span class="sourceLineNo">190</span>    }<a name="line.190"></a>
-<span class="sourceLineNo">191</span><a name="line.191"></a>
-<span class="sourceLineNo">192</span>    // TODO: We should have ProtobufSerialization in Hadoop, and directly use PB objects instead of<a name="line.192"></a>
-<span class="sourceLineNo">193</span>    // doing this wrapping with Writables.<a name="line.193"></a>
-<span class="sourceLineNo">194</span>    @Override<a name="line.194"></a>
-<span class="sourceLineNo">195</span>    public void write(DataOutput out) throws IOException {<a name="line.195"></a>
-<span class="sourceLineNo">196</span>      TableSnapshotRegionSplit.Builder builder = TableSnapshotRegionSplit.newBuilder()<a name="line.196"></a>
-<span class="sourceLineNo">197</span>          .setTable(ProtobufUtil.toTableSchema(htd))<a name="line.197"></a>
-<span class="sourceLineNo">198</span>          .setRegion(ProtobufUtil.toRegionInfo(regionInfo));<a name="line.198"></a>
-<span class="sourceLineNo">199</span><a name="line.199"></a>
-<span class="sourceLineNo">200</span>      for (String location : locations) {<a name="line.200"></a>
-<span class="sourceLineNo">201</span>        builder.addLocations(location);<a name="line.201"></a>
-<span class="sourceLineNo">202</span>      }<a name="line.202"></a>
-<span class="sourceLineNo">203</span><a name="line.203"></a>
-<span class="sourceLineNo">204</span>      TableSnapshotRegionSplit split = builder.build();<a name="line.204"></a>
-<span class="sourceLineNo">205</span><a name="line.205"></a>
-<span class="sourceLineNo">206</span>      ByteArrayOutputStream baos = new ByteArrayOutputStream();<a name="line.206"></a>
-<span class="sourceLineNo">207</span>      split.writeTo(baos);<a name="line.207"></a>
-<span class="sourceLineNo">208</span>      baos.close();<a name="line.208"></a>
-<span class="sourceLineNo">209</span>      byte[] buf = baos.toByteArray();<a name="line.209"></a>
-<span class="sourceLineNo">210</span>      out.writeInt(buf.length);<a name="line.210"></a>
-<span class="sourceLineNo">211</span>      out.write(buf);<a name="line.211"></a>
+<span class="sourceLineNo">184</span>    public long getLength() {<a name="line.184"></a>
+<span class="sourceLineNo">185</span>      //TODO: We can obtain the file sizes of the snapshot here.<a name="line.185"></a>
+<span class="sourceLineNo">186</span>      return 0;<a name="line.186"></a>
+<span class="sourceLineNo">187</span>    }<a name="line.187"></a>
+<span class="sourceLineNo">188</span><a name="line.188"></a>
+<span class="sourceLineNo">189</span>    public String[] getLocations() {<a name="line.189"></a>
+<span class="sourceLineNo">190</span>      return locations;<a name="line.190"></a>
+<span class="sourceLineNo">191</span>    }<a name="line.191"></a>
+<span class="sourceLineNo">192</span><a name="line.192"></a>
+<span class="sourceLineNo">193</span>    public TableDescriptor getTableDescriptor() {<a name="line.193"></a>
+<span class="sourceLineNo">194</span>      return htd;<a name="line.194"></a>
+<span class="sourceLineNo">195</span>    }<a name="line.195"></a>
+<span class="sourceLineNo">196</span><a name="line.196"></a>
+<span class="sourceLineNo">197</span>    public RegionInfo getRegionInfo() {<a name="line.197"></a>
+<span class="sourceLineNo">198</span>      return regionInfo;<a name="line.198"></a>
+<span class="sourceLineNo">199</span>    }<a name="line.199"></a>
+<span class="sourceLineNo">200</span><a name="line.200"></a>
+<span class="sourceLineNo">201</span>    // TODO: We should have ProtobufSerialization in Hadoop, and directly use PB objects instead of<a name="line.201"></a>
+<span class="sourceLineNo">202</span>    // doing this wrapping with Writables.<a name="line.202"></a>
+<span class="sourceLineNo">203</span>    @Override<a name="line.203"></a>
+<span class="sourceLineNo">204</span>    public void write(DataOutput out) throws IOException {<a name="line.204"></a>
+<span class="sourceLineNo">205</span>      TableSnapshotRegionSplit.Builder builder = TableSnapshotRegionSplit.newBuilder()<a name="line.205"></a>
+<span class="sourceLineNo">206</span>          .setTable(ProtobufUtil.toTableSchema(htd))<a name="line.206"></a>
+<span class="sourceLineNo">207</span>          .setRegion(ProtobufUtil.toRegionInfo(regionInfo));<a name="line.207"></a>
+<span class="sourceLineNo">208</span><a name="line.208"></a>
+<span class="sourceLineNo">209</span>      for (String location : locations) {<a name="line.209"></a>
+<span class="sourceLineNo">210</span>        builder.addLocations(location);<a name="line.210"></a>
+<span class="sourceLineNo">211</span>      }<a name="line.211"></a>
 <span class="sourceLineNo">212</span><a name="line.212"></a>
-<span class="sourceLineNo">213</span>      Bytes.writeByteArray(out, Bytes.toBytes(scan));<a name="line.213"></a>
-<span class="sourceLineNo">214</span>      Bytes.writeByteArray(out, Bytes.toBytes(restoreDir));<a name="line.214"></a>
-<span class="sourceLineNo">215</span><a name="line.215"></a>
-<span class="sourceLineNo">216</span>    }<a name="line.216"></a>
-<span class="sourceLineNo">217</span><a name="line.217"></a>
-<span class="sourceLineNo">218</span>    @Override<a name="line.218"></a>
-<span class="sourceLineNo">219</span>    public void readFields(DataInput in) throws IOException {<a name="line.219"></a>
-<span class="sourceLineNo">220</span>      int len = in.readInt();<a name="line.220"></a>
-<span class="sourceLineNo">221</span>      byte[] buf = new byte[len];<a name="line.221"></a>
-<span class="sourceLineNo">222</span>      in.readFully(buf);<a name="line.222"></a>
-<span class="sourceLineNo">223</span>      TableSnapshotRegionSplit split = TableSnapshotRegionSplit.parser().parseFrom(buf);<a name="line.223"></a>
-<span class="sourceLineNo">224</span>      this.htd = ProtobufUtil.toTableDescriptor(split.getTable());<a name="line.224"></a>
-<span class="sourceLineNo">225</span>      this.regionInfo = ProtobufUtil.toRegionInfo(split.getRegion());<a name="line.225"></a>
-<span class="sourceLineNo">226</span>      List&lt;String&gt; locationsList = split.getLocationsList();<a name="line.226"></a>
-<span class="sourceLineNo">227</span>      this.locations = locationsList.toArray(new String[locationsList.size()]);<a name="line.227"></a>
-<span class="sourceLineNo">228</span><a name="line.228"></a>
-<span class="sourceLineNo">229</span>      this.scan = Bytes.toString(Bytes.readByteArray(in));<a name="line.229"></a>
-<span class="sourceLineNo">230</span>      this.restoreDir = Bytes.toString(Bytes.readByteArray(in));<a name="line.230"></a>
-<span class="sourceLineNo">231</span>    }<a name="line.231"></a>
-<span class="sourceLineNo">232</span>  }<a name="line.232"></a>
-<span class="sourceLineNo">233</span><a name="line.233"></a>
-<span class="sourceLineNo">234</span>  /**<a name="line.234"></a>
-<span class="sourceLineNo">235</span>   * Implementation class for RecordReader logic common between mapred and mapreduce.<a name="line.235"></a>
-<span class="sourceLineNo">236</span>   */<a name="line.236"></a>
-<span class="sourceLineNo">237</span>  public static class RecordReader {<a name="line.237"></a>
-<span class="sourceLineNo">238</span>    private InputSplit split;<a name="line.238"></a>
-<span class="sourceLineNo">239</span>    private Scan scan;<a name="line.239"></a>
-<span class="sourceLineNo">240</span>    private Result result = null;<a name="line.240"></a>
-<span class="sourceLineNo">241</span>    private ImmutableBytesWritable row = null;<a name="line.241"></a>
-<span class="sourceLineNo">242</span>    private ClientSideRegionScanner scanner;<a name="line.242"></a>
-<span class="sourceLineNo">243</span>    private int numOfCompleteRows = 0;<a name="line.243"></a>
-<span class="sourceLineNo">244</span>    private int rowLimitPerSplit;<a name="line.244"></a>
-<span class="sourceLineNo">245</span><a name="line.245"></a>
-<span class="sourceLineNo">246</span>    public ClientSideRegionScanner getScanner() {<a name="line.246"></a>
-<span class="sourceLineNo">247</span>      return scanner;<a name="line.247"></a>
-<span class="sourceLineNo">248</span>    }<a name="line.248"></a>
-<span class="sourceLineNo">249</span><a name="line.249"></a>
-<span class="sourceLineNo">250</span>    public void initialize(InputSplit split, Configuration conf) throws IOException {<a name="line.250"></a>
-<span class="sourceLineNo">251</span>      this.scan = TableMapReduceUtil.convertStringToScan(split.getScan());<a name="line.251"></a>
-<span class="sourceLineNo">252</span>      this.split = split;<a name="line.252"></a>
-<span class="sourceLineNo">253</span>      this.rowLimitPerSplit = conf.getInt(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT, 0);<a name="line.253"></a>
-<span class="sourceLineNo">254</span>      TableDescriptor htd = split.htd;<a name="line.254"></a>
-<span class="sourceLineNo">255</span>      RegionInfo hri = this.split.getRegionInfo();<a name="line.255"></a>
-<span class="sourceLineNo">256</span>      FileSystem fs = CommonFSUtils.getCurrentFileSystem(conf);<a name="line.256"></a>
-<span class="sourceLineNo">257</span><a name="line.257"></a>
+<span class="sourceLineNo">213</span>      TableSnapshotRegionSplit split = builder.build();<a name="line.213"></a>
+<span class="sourceLineNo">214</span><a name="line.214"></a>
+<span class="sourceLineNo">215</span>      ByteArrayOutputStream baos = new ByteArrayOutputStream();<a name="line.215"></a>
+<span class="sourceLineNo">216</span>      split.writeTo(baos);<a name="line.216"></a>
+<span class="sourceLineNo">217</span>      baos.close();<a name="line.217"></a>
+<span class="sourceLineNo">218</span>      byte[] buf = baos.toByteArray();<a name="line.218"></a>
+<span class="sourceLineNo">219</span>      out.writeInt(buf.length);<a name="line.219"></a>
+<span class="sourceLineNo">220</span>      out.write(buf);<a name="line.220"></a>
+<span class="sourceLineNo">221</span><a name="line.221"></a>
+<span class="sourceLineNo">222</span>      Bytes.writeByteArray(out, Bytes.toBytes(scan));<a name="line.222"></a>
+<span class="sourceLineNo">223</span>      Bytes.writeByteArray(out, Bytes.toBytes(restoreDir));<a name="line.223"></a>
+<span class="sourceLineNo">224</span><a name="line.224"></a>
+<span class="sourceLineNo">225</span>    }<a name="line.225"></a>
+<span class="sourceLineNo">226</span><a name="line.226"></a>
+<span class="sourceLineNo">227</span>    @Override<a name="line.227"></a>
+<span class="sourceLineNo">228</span>    public void readFields(DataInput in) throws IOException {<a name="line.228"></a>
+<span class="sourceLineNo">229</span>      int len = in.readInt();<a name="line.229"></a>
+<span class="sourceLineNo">230</span>      byte[] buf = new byte[len];<a name="line.230"></a>
+<span class="sourceLineNo">231</span>      in.readFully(buf);<a name="line.231"></a>
+<span class="sourceLineNo">232</span>      TableSnapshotRegionSplit split = TableSnapshotRegionSplit.parser().parseFrom(buf);<a name="line.232"></a>
+<span class="sourceLineNo">233</span>      this.htd = ProtobufUtil.toTableDescriptor(split.getTable());<a name="line.233"></a>
+<span class="sourceLineNo">234</span>      this.regionInfo = ProtobufUtil.toRegionInfo(split.getRegion());<a name="line.234"></a>
+<span class="sourceLineNo">235</span>      List&lt;String&gt; locationsList = split.getLocationsList();<a name="line.235"></a>
+<span class="sourceLineNo">236</span>      this.locations = locationsList.toArray(new String[locationsList.size()]);<a name="line.236"></a>
+<span class="sourceLineNo">237</span><a name="line.237"></a>
+<span class="sourceLineNo">238</span>      this.scan = Bytes.toString(Bytes.readByteArray(in));<a name="line.238"></a>
+<span class="sourceLineNo">239</span>      this.restoreDir = Bytes.toString(Bytes.readByteArray(in));<a name="line.239"></a>
+<span class="sourceLineNo">240</span>    }<a name="line.240"></a>
+<span class="sourceLineNo">241</span>  }<a name="line.241"></a>
+<span class="sourceLineNo">242</span><a name="line.242"></a>
+<span class="sourceLineNo">243</span>  /**<a name="line.243"></a>
+<span class="sourceLineNo">244</span>   * Implementation class for RecordReader logic common between mapred and mapreduce.<a name="line.244"></a>
+<span class="sourceLineNo">245</span>   */<a name="line.245"></a>
+<span class="sourceLineNo">246</span>  public static class RecordReader {<a name="line.246"></a>
+<span class="sourceLineNo">247</span>    private InputSplit split;<a name="line.247"></a>
+<span class="sourceLineNo">248</span>    private Scan scan;<a name="line.248"></a>
+<span class="sourceLineNo">249</span>    private Result result = null;<a name="line.249"></a>
+<span class="sourceLineNo">250</span>    private ImmutableBytesWritable row = null;<a name="line.250"></a>
+<span class="sourceLineNo">251</span>    private ClientSideRegionScanner scanner;<a name="line.251"></a>
+<span class="sourceLineNo">252</span>    private int numOfCompleteRows = 0;<a name="line.252"></a>
+<span class="sourceLineNo">253</span>    private int rowLimitPerSplit;<a name="line.253"></a>
+<span class="sourceLineNo">254</span><a name="line.254"></a>
+<span class="sourceLineNo">255</span>    public ClientSideRegionScanner getScanner() {<a name="line.255"></a>
+<span class="sourceLineNo">256</span>      return scanner;<a name="line.256"></a>
+<span class="sourceLineNo">257</span>    }<a name="line.257"></a>
 <span class="sourceLineNo">258</span><a name="line.258"></a>
-<span class="sourceLineNo">259</span>      // region is immutable, this should be fine,<a name="line.259"></a>
-<span class="sourceLineNo">260</span>      // otherwise we have to set the thread read point<a name="line.260"></a>
-<span class="sourceLineNo">261</span>      scan.setIsolationLevel(IsolationLevel.READ_UNCOMMITTED);<a name="line.261"></a>
-<span class="sourceLineNo">262</span>      // disable caching of data blocks<a name="line.262"></a>
-<span class="sourceLineNo">263</span>      scan.setCacheBlocks(false);<a name="line.263"></a>
-<span class="sourceLineNo">264</span><a name="line.264"></a>
-<span class="sourceLineNo">265</span>      scanner =<a name="line.265"></a>
-<span class="sourceLineNo">266</span>          new ClientSideRegionScanner(conf, fs, new Path(split.restoreDir), htd, hri, scan, null);<a name="line.266"></a>
-<span class="sourceLineNo">267</span>    }<a name="line.267"></a>
-<span class="sourceLineNo">268</span><a name="line.268"></a>
-<span class="sourceLineNo">269</span>    public boolean nextKeyValue() throws IOException {<a name="line.269"></a>
-<span class="sourceLineNo">270</span>      result = scanner.next();<a name="line.270"></a>
-<span class="sourceLineNo">271</span>      if (result == null) {<a name="line.271"></a>
-<span class="sourceLineNo">272</span>        //we are done<a name="line.272"></a>
-<span class="sourceLineNo">273</span>        return false;<a name="line.273"></a>
-<span class="sourceLineNo">274</span>      }<a name="line.274"></a>
-<span class="sourceLineNo">275</span><a name="line.275"></a>
-<span class="sourceLineNo">276</span>      if (rowLimitPerSplit &gt; 0 &amp;&amp; ++this.numOfCompleteRows &gt; rowLimitPerSplit) {<a name="line.276"></a>
-<span class="sourceLineNo">277</span>        return false;<a name="line.277"></a>
-<span class="sourceLineNo">278</span>      }<a name="line.278"></a>
-<span class="sourceLineNo">279</span>      if (this.row == null) {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>        this.row = new ImmutableBytesWritable();<a name="line.280"></a>
-<span class="sourceLineNo">281</span>      }<a name="line.281"></a>
-<span class="sourceLineNo">282</span>      this.row.set(result.getRow());<a name="line.282"></a>
-<span class="sourceLineNo">283</span>      return true;<a name="line.283"></a>
-<span class="sourceLineNo">284</span>    }<a name="line.284"></a>
-<span class="sourceLineNo">285</span><a name="line.285"></a>
-<span class="sourceLineNo">286</span>    public ImmutableBytesWritable getCurrentKey() {<a name="line.286"></a>
-<span class="sourceLineNo">287</span>      return row;<a name="line.287"></a>
-<span class="sourceLineNo">288</span>    }<a name="line.288"></a>
-<span class="sourceLineNo">289</span><a name="line.289"></a>
-<span class="sourceLineNo">290</span>    public Result getCurrentValue() {<a name="line.290"></a>
-<span class="sourceLineNo">291</span>      return result;<a name="line.291"></a>
-<span class="sourceLineNo">292</span>    }<a name="line.292"></a>
-<span class="sourceLineNo">293</span><a name="line.293"></a>
-<span class="sourceLineNo">294</span>    public long getPos() {<a name="line.294"></a>
-<span class="sourceLineNo">295</span>      return 0;<a name="line.295"></a>
-<span class="sourceLineNo">296</span>    }<a name="line.296"></a>
-<span class="sourceLineNo">297</span><a name="line.297"></a>
-<span class="sourceLineNo">298</span>    public float getProgress() {<a name="line.298"></a>
-<span class="sourceLineNo">299</span>      return 0; // TODO: use total bytes to estimate<a name="line.299"></a>
-<span class="sourceLineNo">300</span>    }<a name="line.300"></a>
-<span class="sourceLineNo">301</span><a name="line.301"></a>
-<span class="sourceLineNo">302</span>    public void close() {<a name="line.302"></a>
-<span class="sourceLineNo">303</span>      if (this.scanner != null) {<a name="line.303"></a>
-<span class="sourceLineNo">304</span>        this.scanner.close();<a name="line.304"></a>
-<span class="sourceLineNo">305</span>      }<a name="line.305"></a>
-<span class="sourceLineNo">306</span>    }<a name="line.306"></a>
-<span class="sourceLineNo">307</span>  }<a name="line.307"></a>
-<span class="sourceLineNo">308</span><a name="line.308"></a>
-<span class="sourceLineNo">309</span>  public static List&lt;InputSplit&gt; getSplits(Configuration conf) throws IOException {<a name="line.309"></a>
-<span class="sourceLineNo">310</span>    String snapshotName = getSnapshotName(conf);<a name="line.310"></a>
-<span class="sourceLineNo">311</span><a name="line.311"></a>
-<span class="sourceLineNo">312</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.312"></a>
-<span class="sourceLineNo">313</span>    FileSystem fs = rootDir.getFileSystem(conf);<a name="line.313"></a>
-<span class="sourceLineNo">314</span><a name="line.314"></a>
-<span class="sourceLineNo">315</span>    SnapshotManifest manifest = getSnapshotManifest(conf, snapshotName, rootDir, fs);<a name="line.315"></a>
-<span class="sourceLineNo">316</span><a name="line.316"></a>
-<span class="sourceLineNo">317</span>    List&lt;RegionInfo&gt; regionInfos = getRegionInfosFromManifest(manifest);<a name="line.317"></a>
-<span class="sourceLineNo">318</span><a name="line.318"></a>
-<span class="sourceLineNo">319</span>    // TODO: mapred does not support scan as input API. Work around for now.<a name="line.319"></a>
-<span class="sourceLineNo">320</span>    Scan scan = extractScanFromConf(conf);<a name="line.320"></a>
-<span class="sourceLineNo">321</span>    // the temp dir where the snapshot is restored<a name="line.321"></a>
-<span class="sourceLineNo">322</span>    Path restoreDir = new Path(conf.get(RESTORE_DIR_KEY));<a name="line.322"></a>
+<span class="sourceLineNo">259</span>    public void initialize(InputSplit split, Configuration conf) throws IOException {<a name="line.259"></a>
+<span class="sourceLineNo">260</span>      this.scan = TableMapReduceUtil.convertStringToScan(split.getScan());<a name="line.260"></a>
+<span class="sourceLineNo">261</span>      this.split = split;<a name="line.261"></a>
+<span class="sourceLineNo">262</span>      this.rowLimitPerSplit = conf.getInt(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT, 0);<a name="line.262"></a>
+<span class="sourceLineNo">263</span>      TableDescriptor htd = split.htd;<a name="line.263"></a>
+<span class="sourceLineNo">264</span>      RegionInfo hri = this.split.getRegionInfo();<a name="line.264"></a>
+<span class="sourceLineNo">265</span>      FileSystem fs = CommonFSUtils.getCurrentFileSystem(conf);<a name="line.265"></a>
+<span class="sourceLineNo">266</span><a name="line.266"></a>
+<span class="sourceLineNo">267</span><a name="line.267"></a>
+<span class="sourceLineNo">268</span>      // region is immutable, this should be fine,<a name="line.268"></a>
+<span class="sourceLineNo">269</span>      // otherwise we have to set the thread read point<a name="line.269"></a>
+<span class="sourceLineNo">270</span>      scan.setIsolationLevel(IsolationLevel.READ_UNCOMMITTED);<a name="line.270"></a>
+<span class="sourceLineNo">271</span>      // disable caching of data blocks<a name="line.271"></a>
+<span class="sourceLineNo">272</span>      scan.setCacheBlocks(false);<a name="line.272"></a>
+<span class="sourceLineNo">273</span><a name="line.273"></a>
+<span class="sourceLineNo">274</span>      scanner =<a name="line.274"></a>
+<span class="sourceLineNo">275</span>          new ClientSideRegionScanner(conf, fs, new Path(split.restoreDir), htd, hri, scan, null);<a name="line.275"></a>
+<span class="sourceLineNo">276</span>    }<a name="line.276"></a>
+<span class="sourceLineNo">277</span><a name="line.277"></a>
+<span class="sourceLineNo">278</span>    public boolean nextKeyValue() throws IOException {<a name="line.278"></a>
+<span class="sourceLineNo">279</span>      result = scanner.next();<a name="line.279"></a>
+<span class="sourceLineNo">280</span>      if (result == null) {<a name="line.280"></a>
+<span class="sourceLineNo">281</span>        //we are done<a name="line.281"></a>
+<span class="sourceLineNo">282</span>        return false;<a name="line.282"></a>
+<span class="sourceLineNo">283</span>      }<a name="line.283"></a>
+<span class="sourceLineNo">284</span><a name="line.284"></a>
+<span class="sourceLineNo">285</span>      if (rowLimitPerSplit &gt; 0 &amp;&amp; ++this.numOfCompleteRows &gt; rowLimitPerSplit) {<a name="line.285"></a>
+<span class="sourceLineNo">286</span>        return false;<a name="line.286"></a>
+<span class="sourceLineNo">287</span>      }<a name="line.287"></a>
+<span class="sourceLineNo">288</span>      if (this.row == null) {<a name="line.288"></a>
+<span class="sourceLineNo">289</span>        this.row = new ImmutableBytesWritable();<a name="line.289"></a>
+<span class="sourceLineNo">290</span>      }<a name="line.290"></a>
+<span class="sourceLineNo">291</span>      this.row.set(result.getRow());<a name="line.291"></a>
+<span class="sourceLineNo">292</span>      return true;<a name="line.292"></a>
+<span class="sourceLineNo">293</span>    }<a name="line.293"></a>
+<span class="sourceLineNo">294</span><a name="line.294"></a>
+<span class="sourceLineNo">295</span>    public ImmutableBytesWritable getCurrentKey() {<a name="line.295"></a>
+<span class="sourceLineNo">296</span>      return row;<a name="line.296"></a>
+<span class="sourceLineNo">297</span>    }<a name="line.297"></a>
+<span class="sourceLineNo">298</span><a name="line.298"></a>
+<span class="sourceLineNo">299</span>    public Result getCurrentValue() {<a name="line.299"></a>
+<span class="sourceLineNo">300</span>      return result;<a name="line.300"></a>
+<span class="sourceLineNo">301</span>    }<a name="line.301"></a>
+<span class="sourceLineNo">302</span><a name="line.302"></a>
+<span class="sourceLineNo">303</span>    public long getPos() {<a name="line.303"></a>
+<span class="sourceLineNo">304</span>      return 0;<a name="line.304"></a>
+<span class="sourceLineNo">305</span>    }<a name="line.305"></a>
+<span class="sourceLineNo">306</span><a name="line.306"></a>
+<span class="sourceLineNo">307</span>    public float getProgress() {<a name="line.307"></a>
+<span class="sourceLineNo">308</span>      return 0; // TODO: use total bytes to estimate<a name="line.308"></a>
+<span class="sourceLineNo">309</span>    }<a name="line.309"></a>
+<span class="sourceLineNo">310</span><a name="line.310"></a>
+<span class="sourceLineNo">311</span>    public void close() {<a name="line.311"></a>
+<span class="sourceLineNo">312</span>      if (this.scanner != null) {<a name="line.312"></a>
+<span class="sourceLineNo">313</span>        this.scanner.close();<a name="line.313"></a>
+<span class="sourceLineNo">314</span>      }<a name="line.314"></a>
+<span class="sourceLineNo">315</span>    }<a name="line.315"></a>
+<span class="sourceLineNo">316</span>  }<a name="line.316"></a>
+<span class="sourceLineNo">317</span><a name="line.317"></a>
+<span class="sourceLineNo">318</span>  public static List&lt;InputSplit&gt; getSplits(Configuration conf) throws IOException {<a name="line.318"></a>
+<span class="sourceLineNo">319</span>    String snapshotName = getSnapshotName(conf);<a name="line.319"></a>
+<span class="sourceLineNo">320</span><a name="line.320"></a>
+<span class="sourceLineNo">321</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.321"></a>
+<span class="sourceLineNo">322</span>    FileSystem fs = rootDir.getFileSystem(conf);<a name="line.322"></a>
 <span class="sourceLineNo">323</span><a name="line.323"></a>
-<span class="sourceLineNo">324</span>    RegionSplitter.SplitAlgorithm splitAlgo = getSplitAlgo(conf);<a name="line.324"></a>
+<span class="sourceLineNo">324</span>    SnapshotManifest manifest = getSnapshotManifest(conf, snapshotName, rootDir, fs);<a name="line.324"></a>
 <span class="sourceLineNo">325</span><a name="line.325"></a>
-<span class="sourceLineNo">326</span>    int numSplits = conf.getInt(NUM_SPLITS_PER_REGION, 1);<a name="line.326"></a>
+<span class="sourceLineNo">326</span>    List&lt;RegionInfo&gt; regionInfos = getRegionInfosFromManifest(manifest);<a name="line.326"></a>
 <span class="sourceLineNo">327</span><a name="line.327"></a>
-<span class="sourceLineNo">328</span>    return getSplits(scan, manifest, regionInfos, restoreDir, conf, splitAlgo, numSplits);<a name="line.328"></a>
-<span class="sourceLineNo">329</span>  }<a name="line.329"></a>
-<span class="sourceLineNo">330</span><a name="line.330"></a>
-<span class="sourceLineNo">331</span>  public static RegionSplitter.SplitAlgorithm getSplitAlgo(Configuration conf) throws IOException {<a name="line.331"></a>
-<span class="sourceLineNo">332</span>    String splitAlgoClassName = conf.get(SPLIT_ALGO);<a name="line.332"></a>
-<span class="sourceLineNo">333</span>    if (splitAlgoClassName == null) {<a name="line.333"></a>
-<span class="sourceLineNo">334</span>      return null;<a name="line.334"></a>
-<span class="sourceLineNo">335</span>    }<a name="line.335"></a>
-<span class="sourceLineNo">336</span>    try {<a name="line.336"></a>
-<span class="sourceLineNo">337</span>      return Class.forName(splitAlgoClassName).asSubclass(RegionSplitter.SplitAlgorithm.class)<a name="line.337"></a>
-<span class="sourceLineNo">338</span>          .getDeclaredConstructor().newInstance();<a name="line.338"></a>
-<span class="sourceLineNo">339</span>    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException |<a name="line.339"></a>
-<span class="sourceLineNo">340</span>        NoSuchMethodException | InvocationTargetException e) {<a name="line.340"></a>
-<span class="sourceLineNo">341</span>      throw new IOException("SplitAlgo class " + splitAlgoClassName + " is not found", e);<a name="line.341"></a>
-<span class="sourceLineNo">342</span>    }<a name="line.342"></a>
-<span class="sourceLineNo">343</span>  }<a name="line.343"></a>
-<span class="sourceLineNo">344</span><a name="line.344"></a>
-<span class="sourceLineNo">345</span><a name="line.345"></a>
-<span class="sourceLineNo">346</span>  public static List&lt;RegionInfo&gt; getRegionInfosFromManifest(SnapshotManifest manifest) {<a name="line.346"></a>
-<span class="sourceLineNo">347</span>    List&lt;SnapshotRegionManifest&gt; regionManifests = manifest.getRegionManifests();<a name="line.347"></a>
-<span class="sourceLineNo">348</span>    if (regionManifests == null) {<a name="line.348"></a>
-<span class="sourceLineNo">349</span>      throw new IllegalArgumentException("Snapshot seems empty");<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    }<a name="line.350"></a>
-<span class="sourceLineNo">351</span><a name="line.351"></a>
-<span class="sourceLineNo">352</span>    List&lt;RegionInfo&gt; regionInfos = Lists.newArrayListWithCapacity(regionManifests.size());<a name="line.352"></a>
+<span class="sourceLineNo">328</span>    // TODO: mapred does not support scan as input API. Work around for now.<a name="line.328"></a>
+<span class="sourceLineNo">329</span>    Scan scan = extractScanFromConf(conf);<a name="line.329"></a>
+<span class="sourceLineNo">330</span>    // the temp dir where the snapshot is restored<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    Path restoreDir = new Path(conf.get(RESTORE_DIR_KEY));<a name="line.331"></a>
+<span class="sourceLineNo">332</span><a name="line.332"></a>
+<span class="sourceLineNo">333</span>    RegionSplitter.SplitAlgorithm splitAlgo = getSplitAlgo(conf);<a name="line.333"></a>
+<span class="sourceLineNo">334</span><a name="line.334"></a>
+<span class="sourceLineNo">335</span>    int numSplits = conf.getInt(NUM_SPLITS_PER_REGION, 1);<a name="line.335"></a>
+<span class="sourceLineNo">336</span><a name="line.336"></a>
+<span class="sourceLineNo">337</span>    return getSplits(scan, manifest, regionInfos, restoreDir, conf, splitAlgo, numSplits);<a name="line.337"></a>
+<span class="sourceLineNo">338</span>  }<a name="line.338"></a>
+<span class="sourceLineNo">339</span><a name="line.339"></a>
+<span class="sourceLineNo">340</span>  public static RegionSplitter.SplitAlgorithm getSplitAlgo(Configuration conf) throws IOException {<a name="line.340"></a>
+<span class="sourceLineNo">341</span>    String splitAlgoClassName = conf.get(SPLIT_ALGO);<a name="line.341"></a>
+<span class="sourceLineNo">342</span>    if (splitAlgoClassName == null) {<a name="line.342"></a>
+<span class="sourceLineNo">343</span>      return null;<a name="line.343"></a>
+<span class="sourceLineNo">344</span>    }<a name="line.344"></a>
+<span class="sourceLineNo">345</span>    try {<a name="line.345"></a>
+<span class="sourceLineNo">346</span>      return Class.forName(splitAlgoClassName).asSubclass(RegionSplitter.SplitAlgorithm.class)<a name="line.346"></a>
+<span class="sourceLineNo">347</span>          .getDeclaredConstructor().newInstance();<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException |<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        NoSuchMethodException | InvocationTargetException e) {<a name="line.349"></a>
+<span class="sourceLineNo">350</span>      throw new IOException("SplitAlgo class " + splitAlgoClassName + " is not found", e);<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    }<a name="line.351"></a>
+<span class="sourceLineNo">352</span>  }<a name="line.352"></a>
 <span class="sourceLineNo">353</span><a name="line.353"></a>
-<span class="sourceLineNo">354</span>    for (SnapshotRegionManifest regionManifest : regionManifests) {<a name="line.354"></a>
-<span class="sourceLineNo">355</span>      RegionInfo hri = ProtobufUtil.toRegionInfo(regionManifest.getRegionInfo());<a name="line.355"></a>
-<span class="sourceLineNo">356</span>      if (hri.isOffline() &amp;&amp; (hri.isSplit() || hri.isSplitParent())) {<a name="line.356"></a>
-<span class="sourceLineNo">357</span>        continue;<a name="line.357"></a>
-<span class="sourceLineNo">358</span>      }<a name="line.358"></a>
-<span class="sourceLineNo">359</span>      regionInfos.add(hri);<a name="line.359"></a>
-<span class="sourceLineNo">360</span>    }<a name="line.360"></a>
-<span class="sourceLineNo">361</span>    return regionInfos;<a name="line.361"></a>
-<span class="sourceLineNo">362</span>  }<a name="line.362"></a>
-<span class="sourceLineNo">363</span><a name="line.363"></a>
-<span class="sourceLineNo">364</span>  public static SnapshotManifest getSnapshotManifest(Configuration conf, String snapshotName,<a name="line.364"></a>
-<span class="sourceLineNo">365</span>      Path rootDir, FileSystem fs) throws IOException {<a name="line.365"></a>
-<span class="sourceLineNo">366</span>    Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>    SnapshotDescription snapshotDesc = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    return SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);<a name="line.368"></a>
-<span class="sourceLineNo">369</span>  }<a name="line.369"></a>
-<span class="sourceLineNo">370</span><a name="line.370"></a>
-<span class="sourceLineNo">371</span>  public static Scan extractScanFromConf(Configuration conf) throws IOException {<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    Scan scan = null;<a name="line.372"></a>
-<span class="sourceLineNo">373</span>    if (conf.get(TableInputFormat.SCAN) != null) {<a name="line.373"></a>
-<span class="sourceLineNo">374</span>      scan = TableMapReduceUtil.convertStringToScan(conf.get(TableInputFormat.SCAN));<a name="line.374"></a>
-<span class="sourceLineNo">375</span>    } else if (conf.get(org.apache.hadoop.hbase.mapred.TableInputFormat.COLUMN_LIST) != null) {<a name="line.375"></a>
-<span class="sourceLineNo">376</span>      String[] columns =<a name="line.376"></a>
-<span class="sourceLineNo">377</span>        conf.get(org.apache.hadoop.hbase.mapred.TableInputFormat.COLUMN_LIST).split(" ");<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      scan = new Scan();<a name="line.378"></a>
-<span class="sourceLineNo">379</span>      for (String col : columns) {<a name="line.379"></a>
-<span class="sourceLineNo">380</span>        scan.addFamily(Bytes.toBytes(col));<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      }<a name="line.381"></a>
-<span class="sourceLineNo">382</span>    } else {<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      throw new IllegalArgumentException("Unable to create scan");<a name="line.383"></a>
-<span class="sourceLineNo">384</span>    }<a name="line.384"></a>
-<span class="sourceLineNo">385</span>    return scan;<a name="line.385"></a>
-<span class="sourceLineNo">386</span>  }<a name="line.386"></a>
-<span class="sourceLineNo">387</span><a name="line.387"></a>
-<span class="sourceLineNo">388</span>  public static List&lt;InputSplit&gt; getSplits(Scan scan, SnapshotManifest manifest,<a name="line.388"></a>
-<span class="sourceLineNo">389</span>      List&lt;RegionInfo&gt; regionManifests, Path restoreDir, Configuration conf) throws IOException {<a name="line.389"></a>
-<span class="sourceLineNo">390</span>    return getSplits(scan, manifest, regionManifests, restoreDir, conf, null, 1);<a name="line.390"></a>
-<span class="sourceLineNo">391</span>  }<a name="line.391"></a>
-<span class="sourceLineNo">392</span><a name="line.392"></a>
-<span class="sourceLineNo">393</span>  public static List&lt;InputSplit&gt; getSplits(Scan scan, SnapshotManifest manifest,<a name="line.393"></a>
-<span class="sourceLineNo">394</span>      List&lt;RegionInfo&gt; regionManifests, Path restoreDir,<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      Configuration conf, RegionSplitter.SplitAlgorithm sa, int numSplits) throws IOException {<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    // load table descriptor<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    TableDescriptor htd = manifest.getTableDescriptor();<a name="line.397"></a>
-<span class="sourceLineNo">398</span><a name="line.398"></a>
-<span class="sourceLineNo">399</span>    Path tableDir = CommonFSUtils.getTableDir(restoreDir, htd.getTableName());<a name="line.399"></a>
-<span class="sourceLineNo">400</span><a name="line.400"></a>
-<span class="sourceLineNo">401</span>    boolean localityEnabled = conf.getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY,<a name="line.401"></a>
-<span class="sourceLineNo">402</span>                                              SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT);<a name="line.402"></a>
-<span class="sourceLineNo">403</span><a name="line.403"></a>
-<span class="sourceLineNo">404</span>    boolean scanMetricsEnabled = conf.getBoolean(SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED,<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT);<a name="line.405"></a>
-<span class="sourceLineNo">406</span>    scan.setScanMetricsEnabled(scanMetricsEnabled);<a name="line.406"></a>
-<span class="sourceLineNo">407</span><a name="line.407"></a>
-<span class="sourceLineNo">408</span>    boolean useRegionLoc = conf.getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.408"></a>
-<span class="sourceLineNo">409</span>      SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.409"></a>
+<span class="sourceLineNo">354</span><a name="line.354"></a>
+<span class="sourceLineNo">355</span>  public static List&lt;RegionInfo&gt; getRegionInfosFromManifest(SnapshotManifest manifest) {<a name="line.355"></a>
+<span class="sourceLineNo">356</span>    List&lt;SnapshotRegionManifest&gt; regionManifests = manifest.getRegionManifests();<a name="line.356"></a>
+<span class="sourceLineNo">357</span>    if (regionManifests == null) {<a name="line.357"></a>
+<span class="sourceLineNo">358</span>      throw new IllegalArgumentException("Snapshot seems empty");<a name="line.358"></a>
+<span class="sourceLineNo">359</span>    }<a name="line.359"></a>
+<span class="sourceLineNo">360</span><a name="line.360"></a>
+<span class="sourceLineNo">361</span>    List&lt;RegionInfo&gt; regionInfos = Lists.newArrayListWithCapacity(regionManifests.size());<a name="line.361"></a>
+<span class="sourceLineNo">362</span><a name="line.362"></a>
+<span class="sourceLineNo">363</span>    for (SnapshotRegionManifest regionManifest : regionManifests) {<a name="line.363"></a>
+<span class="sourceLineNo">364</span>      RegionInfo hri = ProtobufUtil.toRegionInfo(regionManifest.getRegionInfo());<a name="line.364"></a>
+<span class="sourceLineNo">365</span>      if (hri.isOffline() &amp;&amp; (hri.isSplit() || hri.isSplitParent())) {<a name="line.365"></a>
+<span class="sourceLineNo">366</span>        continue;<a name="line.366"></a>
+<span class="sourceLineNo">367</span>      }<a name="line.367"></a>
+<span class="sourceLineNo">368</span>      regionInfos.add(hri);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>    }<a name="line.369"></a>
+<span class="sourceLineNo">370</span>    return regionInfos;<a name="line.370"></a>
+<span class="sourceLineNo">371</span>  }<a name="line.371"></a>
+<span class="sourceLineNo">372</span><a name="line.372"></a>
+<span class="sourceLineNo">373</span>  public static SnapshotManifest getSnapshotManifest(Configuration conf, String snapshotName,<a name="line.373"></a>
+<span class="sourceLineNo">374</span>      Path rootDir, FileSystem fs) throws IOException {<a name="line.374"></a>
+<span class="sourceLineNo">375</span>    Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);<a name="line.375"></a>
+<span class="sourceLineNo">376</span>    SnapshotDescription snapshotDesc = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    return SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);<a name="line.377"></a>
+<span class="sourceLineNo">378</span>  }<a name="line.378"></a>
+<span class="sourceLineNo">379</span><a name="line.379"></a>
+<span class="sourceLineNo">380</span>  public static Scan extractScanFromConf(Configuration conf) throws IOException {<a name="line.380"></a>
+<span class="sourceLineNo">381</span>    Scan scan = null;<a name="line.381"></a>
+<span class="sourceLineNo">382</span>    if (conf.get(TableInputFormat.SCAN) != null) {<a name="line.382"></a>
+<span class="sourceLineNo">383</span>      scan = TableMapReduceUtil.convertStringToScan(conf.get(TableInputFormat.SCAN));<a name="line.383"></a>
+<span class="sourceLineNo">384</span>    } else if (conf.get(org.apache.hadoop.hbase.mapred.TableInputFormat.COLUMN_LIST) != null) {<a name="line.384"></a>
+<span class="sourceLineNo">385</span>      String[] columns =<a name="line.385"></a>
+<span class="sourceLineNo">386</span>        conf.get(org.apache.hadoop.hbase.mapred.TableInputFormat.COLUMN_LIST).split(" ");<a name="line.386"></a>
+<span class="sourceLineNo">387</span>      scan = new Scan();<a name="line.387"></a>
+<span class="sourceLineNo">388</span>      for (String col : columns) {<a name="line.388"></a>
+<span class="sourceLineNo">389</span>        scan.addFamily(Bytes.toBytes(col));<a name="line.389"></a>
+<span class="sourceLineNo">390</span>      }<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    } else {<a name="line.391"></a>
+<span class="sourceLineNo">392</span>      throw new IllegalArgumentException("Unable to create scan");<a name="line.392"></a>
+<span class="sourceLineNo">393</span>    }<a name="line.393"></a>
+<span class="sourceLineNo">394</span><a name="line.394"></a>
+<span class="sourceLineNo">395</span>    if (scan.getReadType() == ReadType.DEFAULT) {<a name="line.395"></a>
+<span class="sourceLineNo">396</span>      LOG.info("Provided Scan has DEFAULT ReadType,"<a name="line.396"></a>
+<span class="sourceLineNo">397</span>          + " updating STREAM for Snapshot-based InputFormat");<a name="line.397"></a>
+<span class="sourceLineNo">398</span>      // Update the "DEFAULT" ReadType to be "STREAM" to try to improve the default case.<a name="line.398"></a>
+<span class="sourceLineNo">399</span>      scan.setReadType(conf.getEnum(SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE,<a name="line.399"></a>
+<span class="sourceLineNo">400</span>          SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE_DEFAULT));<a name="line.400"></a>
+<span class="sourceLineNo">401</span>    }<a name="line.401"></a>
+<span class="sourceLineNo">402</span><a name="line.402"></a>
+<span class="sourceLineNo">403</span>    return scan;<a name="line.403"></a>
+<span class="sourceLineNo">404</span>  }<a name="line.404"></a>
+<span class="sourceLineNo">405</span><a name="line.405"></a>
+<span class="sourceLineNo">406</span>  public static List&lt;InputSplit&gt; getSplits(Scan scan, SnapshotManifest manifest,<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      List&lt;RegionInfo&gt; regionManifests, Path restoreDir, Configuration conf) throws IOException {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    return getSplits(scan, manifest, regionManifests, restoreDir, conf, null, 1);<a name="line.408"></a>
+<span class="sourceLineNo">409</span>  }<a name="line.409"></a>
 <span class="sourceLineNo">410</span><a name="line.410"></a>
-<span class="sourceLineNo">411</span>    Connection connection = null;<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    RegionLocator regionLocator = null;<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    if (localityEnabled &amp;&amp; useRegionLoc) {<a name="line.413"></a>
-<span class="sourceLineNo">414</span>      Configuration newConf = new Configuration(conf);<a name="line.414"></a>
-<span class="sourceLineNo">415</span>      newConf.setInt("hbase.hconnection.threads.max", 1);<a name="line.415"></a>
-<span class="sourceLineNo">416</span>      try {<a name="line.416"></a>
-<span class="sourceLineNo">417</span>        connection = ConnectionFactory.createConnection(newConf);<a name="line.417"></a>
-<span class="sourceLineNo">418</span>        regionLocator = connection.getRegionLocator(htd.getTableName());<a name="line.418"></a>
-<span class="sourceLineNo">419</span><a name="line.419"></a>
-<span class="sourceLineNo">420</span>        /* Get all locations for the table and cache it */<a name="line.420"></a>
-<span class="sourceLineNo">421</span>        regionLocator.getAllRegionLocations();<a name="line.421"></a>
-<span class="sourceLineNo">422</span>      } finally {<a name="line.422"></a>
-<span class="sourceLineNo">423</span>        if (connection != null) {<a name="line.423"></a>
-<span class="sourceLineNo">424</span>          connection.close();<a name="line.424"></a>
-<span class="sourceLineNo">425</span>        }<a name="line.425"></a>
-<span class="sourceLineNo">426</span>      }<a name="line.426"></a>
-<span class="sourceLineNo">427</span>    }<a name="line.427"></a>
+<span class="sourceLineNo">411</span>  public static List&lt;InputSplit&gt; getSplits(Scan scan, SnapshotManifest manifest,<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      List&lt;RegionInfo&gt; regionManifests, Path restoreDir,<a name="line.412"></a>
+<span class="sourceLineNo">413</span>      Configuration conf, RegionSplitter.SplitAlgorithm sa, int numSplits) throws IOException {<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    // load table descriptor<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    TableDescriptor htd = manifest.getTableDescriptor();<a name="line.415"></a>
+<span class="sourceLineNo">416</span><a name="line.416"></a>
+<span class="sourceLineNo">417</span>    Path tableDir = CommonFSUtils.getTableDir(restoreDir, htd.getTableName());<a name="line.417"></a>
+<span class="sourceLineNo">418</span><a name="line.418"></a>
+<span class="sourceLineNo">419</span>    boolean localityEnabled = conf.getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY,<a name="line.419"></a>
+<span class="sourceLineNo">420</span>                                              SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT);<a name="line.420"></a>
+<span class="sourceLineNo">421</span><a name="line.421"></a>
+<span class="sourceLineNo">422</span>    boolean scanMetricsEnabled = conf.getBoolean(SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED,<a name="line.422"></a>
+<span class="sourceLineNo">423</span>      SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT);<a name="line.423"></a>
+<span class="sourceLineNo">424</span>    scan.setScanMetricsEnabled(scanMetricsEnabled);<a name="line.424"></a>
+<span class="sourceLineNo">425</span><a name="line.425"></a>
+<span class="sourceLineNo">426</span>    boolean useRegionLoc = conf.getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.426"></a>
+<span class="sourceLineNo">427</span>      SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.427"></a>
 <span class="sourceLineNo">428</span><a name="line.428"></a>
-<span class="sourceLineNo">429</span>    List&lt;InputSplit&gt; splits = new ArrayList&lt;&gt;();<a name="line.429"></a>
-<span class="sourceLineNo">430</span>    for (RegionInfo hri : regionManifests) {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      // load region descriptor<a name="line.431"></a>
-<span class="sourceLineNo">432</span>      List&lt;String&gt; hosts = null;<a name="line.432"></a>
-<span class="sourceLineNo">433</span>      if (localityEnabled) {<a name="line.433"></a>
-<span class="sourceLineNo">434</span>        if (regionLocator != null) {<a name="line.434"></a>
-<span class="sourceLineNo">435</span>          /* Get Location from the local cache */<a name="line.435"></a>
-<span class="sourceLineNo">436</span>          HRegionLocation<a name="line.436"></a>
-<span class="sourceLineNo">437</span>            location = regionLocator.getRegionLocation(hri.getStartKey(), false);<a name="line.437"></a>
-<span class="sourceLineNo">438</span><a name="line.438"></a>
-<span class="sourceLineNo">439</span>          hosts = new ArrayList&lt;&gt;(1);<a name="line.439"></a>
-<span class="sourceLineNo">440</span>          hosts.add(location.getHostname());<a name="line.440"></a>
-<span class="sourceLineNo">441</span>        } else {<a name="line.441"></a>
-<span class="sourceLineNo">442</span>          hosts = calculateLocationsForInputSplit(conf, htd, hri, tableDir);<a name="line.442"></a>
+<span class="sourceLineNo">429</span>    Connection connection = null;<a name="line.429"></a>
+<span class="sourceLineNo">430</span>    RegionLocator regionLocator = null;<a name="line.430"></a>
+<span class="sourceLineNo">431</span>    if (localityEnabled &amp;&amp; useRegionLoc) {<a name="line.431"></a>
+<span class="sourceLineNo">432</span>      Configuration newConf = new Configuration(conf);<a name="line.432"></a>
+<span class="sourceLineNo">433</span>      newConf.setInt("hbase.hconnection.threads.max", 1);<a name="line.433"></a>
+<span class="sourceLineNo">434</span>      try {<a name="line.434"></a>
+<span class="sourceLineNo">435</span>        connection = ConnectionFactory.createConnection(newConf);<a name="line.435"></a>
+<span class="sourceLineNo">436</span>        regionLocator = connection.getRegionLocator(htd.getTableName());<a name="line.436"></a>
+<span class="sourceLineNo">437</span><a name="line.437"></a>
+<span class="sourceLineNo">438</span>        /* Get all locations for the table and cache it */<a name="line.438"></a>
+<span class="sourceLineNo">439</span>        regionLocator.getAllRegionLocations();<a name="line.439"></a>
+<span class="sourceLineNo">440</span>      } finally {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>        if (connection != null) {<a name="line.441"></a>
+<span class="sourceLineNo">442</span>          connection.close();<a name="line.442"></a>
 <span class="sourceLineNo">443</span>        }<a name="line.443"></a>
 <span class="sourceLineNo">444</span>      }<a name="line.444"></a>
-<span class="sourceLineNo">445</span><a name="line.445"></a>
-<span class="sourceLineNo">446</span>      if (numSplits &gt; 1) {<a name="line.446"></a>
-<span class="sourceLineNo">447</span>        byte[][] sp = sa.split(hri.getStartKey(), hri.getEndKey(), numSplits, true);<a name="line.447"></a>
-<span class="sourceLineNo">448</span>        for (int i = 0; i &lt; sp.length - 1; i++) {<a name="line.448"></a>
-<span class="sourceLineNo">449</span>          if (PrivateCellUtil.overlappingKeys(scan.getStartRow(), scan.getStopRow(), sp[i],<a name="line.449"></a>
-<span class="sourceLineNo">450</span>                  sp[i + 1])) {<a name="line.450"></a>
-<span class="sourceLineNo">451</span><a name="line.451"></a>
-<span class="sourceLineNo">452</span>            Scan boundedScan = new Scan(scan);<a name="line.452"></a>
-<span class="sourceLineNo">453</span>            if (scan.getStartRow().length == 0) {<a name="line.453"></a>
-<span class="sourceLineNo">454</span>              boundedScan.withStartRow(sp[i]);<a name="line.454"></a>
-<span class="sourceLineNo">455</span>            } else {<a name="line.455"></a>
-<span class="sourceLineNo">456</span>              boundedScan.withStartRow(<a name="line.456"></a>
-<span class="sourceLineNo">457</span>                Bytes.compareTo(scan.getStartRow(), sp[i]) &gt; 0 ? scan.getStartRow() : sp[i]);<a name="line.457"></a>
-<span class="sourceLineNo">458</span>            }<a name="line.458"></a>
-<span class="sourceLineNo">459</span><a name="line.459"></a>
-<span class="sourceLineNo">460</span>            if (scan.getStopRow().length == 0) {<a name="line.460"></a>
-<span class="sourceLineNo">461</span>              boundedScan.withStopRow(sp[i + 1]);<a name="line.461"></a>
-<span class="sourceLineNo">462</span>            } else {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>              boundedScan.withStopRow(<a name="line.463"></a>
-<span class="sourceLineNo">464</span>                Bytes.compareTo(scan.getStopRow(), sp[i + 1]) &lt; 0 ? scan.getStopRow() : sp[i + 1]);<a name="line.464"></a>
-<span class="sourceLineNo">465</span>            }<a name="line.465"></a>
-<span class="sourceLineNo">466</span><a name="line.466"></a>
-<span class="sourceLineNo">467</span>            splits.add(new InputSplit(htd, hri, hosts, boundedScan, restoreDir));<a name="line.467"></a>
-<span class="sourceLineNo">468</span>          }<a name="line.468"></a>
-<span class="sourceLineNo">469</span>        }<a name="line.469"></a>
-<span class="sourceLineNo">470</span>      } else {<a name="line.470"></a>
-<span class="sourceLineNo">471</span>        if (PrivateCellUtil.overlappingKeys(scan.getStartRow(), scan.getStopRow(),<a name="line.471"></a>
-<span class="sourceLineNo">472</span>            hri.getStartKey(), hri.getEndKey())) {<a name="line.472"></a>
-<span class="sourceLineNo">473</span><a name="line.473"></a>
-<span class="sourceLineNo">474</span>          splits.add(new InputSplit(htd, hri, hosts, scan, restoreDir));<a name="line.474"></a>
-<span class="sourceLineNo">475</span>        }<a name="line.475"></a>
-<span class="sourceLineNo">476</span>      }<a name="line.476"></a>
-<span class="sourceLineNo">477</span>    }<a name="line.477"></a>
-<span class="sourceLineNo">478</span><a name="line.478"></a>
-<span class="sourceLineNo">479</span>    return splits;<a name="line.479"></a>
-<span class="sourceLineNo">480</span>  }<a name="line.480"></a>
-<span class="sourceLineNo">481</span><a name="line.481"></a>
-<span class="sourceLineNo">482</span>  /**<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * Compute block locations for snapshot files (which will get the locations for referred hfiles)<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   * only when localityEnabled is true.<a name="line.484"></a>
-<span class="sourceLineNo">485</span>   */<a name="line.485"></a>
-<span class="sourceLineNo">486</span>  private static List&lt;String&gt; calculateLocationsForInputSplit(Configuration conf,<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      TableDescriptor htd, RegionInfo hri, Path tableDir)<a name="line.487"></a>
-<span class="sourceLineNo">488</span>      throws IOException {<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    return getBestLocations(conf, HRegion.computeHDFSBlocksDistribution(conf, htd, hri, tableDir));<a name="line.489"></a>
-<span class="sourceLineNo">490</span>  }<a name="line.490"></a>
+<span class="sourceLineNo">445</span>    }<a name="line.445"></a>
+<span class="sourceLineNo">446</span><a name="line.446"></a>
+<span class="sourceLineNo">447</span>    List&lt;InputSplit&gt; splits = new ArrayList&lt;&gt;();<a name="line.447"></a>
+<span class="sourceLineNo">448</span>    for (RegionInfo hri : regionManifests) {<a name="line.448"></a>
+<span class="sourceLineNo">449</span>      // load region descriptor<a name="line.449"></a>
+<span class="sourceLineNo">450</span>      List&lt;String&gt; hosts = null;<a name="line.450"></a>
+<span class="sourceLineNo">451</span>      if (localityEnabled) {<a name="line.451"></a>
+<span class="sourceLineNo">452</span>        if (regionLocator != null) {<a name="line.452"></a>
+<span class="sourceLineNo">453</span>          /* Get Location from the local cache */<a name="line.453"></a>
+<span class="sourceLineNo">454</span>          HRegionLocation<a name="line.454"></a>
+<span class="sourceLineNo">455</span>            location = regionLocator.getRegionLocation(hri.getStartKey(), false);<a name="line.455"></a>
+<span class="sourceLineNo">456</span><a name="line.456"></a>
+<span class="sourceLineNo">457</span>          hosts = new ArrayList&lt;&gt;(1);<a name="line.457"></a>
+<span class="sourceLineNo">458</span>          hosts.add(location.getHostname());<a name="line.458"></a>
+<span class="sourceLineNo">459</span>        } else {<a name="line.459"></a>
+<span class="sourceLineNo">460</span>          hosts = calculateLocationsForInputSplit(conf, htd, hri, tableDir);<a name="line.460"></a>
+<span class="sourceLineNo">461</span>        }<a name="line.461"></a>
+<span class="sourceLineNo">462</span>      }<a name="line.462"></a>
+<span class="sourceLineNo">463</span><a name="line.463"></a>
+<span class="sourceLineNo">464</span>      if (numSplits &gt; 1) {<a name="line.464"></a>
+<span class="sourceLineNo">465</span>        byte[][] sp = sa.split(hri.getStartKey(), hri.getEndKey(), numSplits, true);<a name="line.465"></a>
+<span class="sourceLineNo">466</span>        for (int i = 0; i &lt; sp.length - 1; i++) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>          if (PrivateCellUtil.overlappingKeys(scan.getStartRow(), scan.getStopRow(), sp[i],<a name="line.467"></a>
+<span class="sourceLineNo">468</span>                  sp[i + 1])) {<a name="line.468"></a>
+<span class="sourceLineNo">469</span><a name="line.469"></a>
+<span class="sourceLineNo">470</span>            Scan boundedScan = new Scan(scan);<a name="line.470"></a>
+<span class="sourceLineNo">471</span>            if (scan.getStartRow().length == 0) {<a name="line.471"></a>
+<span class="sourceLineNo">472</span>              boundedScan.withStartRow(sp[i]);<a name="line.472"></a>
+<span class="sourceLineNo">473</span>            } else {<a name="line.473"></a>
+<span class="sourceLineNo">474</span>              boundedScan.withStartRow(<a name="line.474"></a>
+<span class="sourceLineNo">475</span>                Bytes.compareTo(scan.getStartRow(), sp[i]) &gt; 0 ? scan.getStartRow() : sp[i]);<a name="line.475"></a>
+<span class="sourceLineNo">476</span>            }<a name="line.476"></a>
+<span class="sourceLineNo">477</span><a name="line.477"></a>
+<span class="sourceLineNo">478</span>            if (scan.getStopRow().length == 0) {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>              boundedScan.withStopRow(sp[i + 1]);<a name="line.479"></a>
+<span class="sourceLineNo">480</span>            } else {<a name="line.480"></a>
+<span class="sourceLineNo">481</span>              boundedScan.withStopRow(<a name="line.481"></a>
+<span class="sourceLineNo">482</span>                Bytes.compareTo(scan.getStopRow(), sp[i + 1]) &lt; 0 ? scan.getStopRow() : sp[i + 1]);<a name="line.482"></a>
+<span class="sourceLineNo">483</span>            }<a name="line.483"></a>
+<span class="sourceLineNo">484</span><a name="line.484"></a>
+<span class="sourceLineNo">485</span>            splits.add(new InputSplit(htd, hri, hosts, boundedScan, restoreDir));<a name="line.485"></a>
+<span class="sourceLineNo">486</span>          }<a name="line.486"></a>
+<span class="sourceLineNo">487</span>        }<a name="line.487"></a>
+<span class="sourceLineNo">488</span>      } else {<a name="line.488"></a>
+<span class="sourceLineNo">489</span>        if (PrivateCellUtil.overlappingKeys(scan.getStartRow(), scan.getStopRow(),<a name="line.489"></a>
+<span class="sourceLineNo">490</span>            hri.getStartKey(), hri.getEndKey())) {<a name="line.490"></a>
 <span class="sourceLineNo">491</span><a name="line.491"></a>
-<span class="sourceLineNo">492</span>  /**<a name="line.492"></a>
-<span class="sourceLineNo">493</span>   * This computes the locations to be passed from the InputSplit. MR/Yarn schedulers does not take<a name="line.493"></a>
-<span class="sourceLineNo">494</span>   * weights into account, thus will treat every location passed from the input split as equal. We<a name="line.494"></a>
-<span class="sourceLineNo">495</span>   * do not want to blindly pass all the locations, since we are creating one split per region, and<a name="line.495"></a>
-<span class="sourceLineNo">496</span>   * the region's blocks are all distributed throughout the cluster unless favorite node assignment<a name="line.496"></a>
-<span class="sourceLineNo">497</span>   * is used. On the expected stable case, only one location will contain most of the blocks as<a name="line.497"></a>
-<span class="sourceLineNo">498</span>   * local.<a name="line.498"></a>
-<span class="sourceLineNo">499</span>   * On the other hand, in favored node assignment, 3 nodes will contain highly local blocks. Here<a name="line.499"></a>
-<span class="sourceLineNo">500</span>   * we are doing a simple heuristic, where we will pass all hosts which have at least 80%<a name="line.500"></a>
-<span class="sourceLineNo">501</span>   * (hbase.tablesnapshotinputformat.locality.cutoff.multiplier) as much block locality as the top<a name="line.501"></a>
-<span class="sourceLineNo">502</span>   * host with the best locality.<a name="line.502"></a>
-<span class="sourceLineNo">503</span>   * Return at most numTopsAtMost locations if there are more than that.<a name="line.503"></a>
-<span class="sourceLineNo">504</span>   */<a name="line.504"></a>
-<span class="sourceLineNo">505</span>  private static List&lt;String&gt; getBestLocations(Configuration conf,<a name="line.505"></a>
-<span class="sourceLineNo">506</span>      HDFSBlocksDistribution blockDistribution, int numTopsAtMost) {<a name="line.506"></a>
-<span class="sourceLineNo">507</span>    HostAndWeight[] hostAndWeights = blockDistribution.getTopHostsWithWeights();<a name="line.507"></a>
-<span class="sourceLineNo">508</span><a name="line.508"></a>
-<span class="sourceLineNo">509</span>    if (hostAndWeights.length == 0) { // no matter what numTopsAtMost is<a name="line.509"></a>
-<span class="sourceLineNo">510</span>      return null;<a name="line.510"></a>
-<span class="sourceLineNo">511</span>    }<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span>    if (numTopsAtMost &lt; 1) { // invalid if numTopsAtMost &lt; 1, correct it to be 1<a name="line.513"></a>
-<span class="sourceLineNo">514</span>      numTopsAtMost = 1;<a name="line.514"></a>
-<span class="sourceLineNo">515</span>    }<a name="line.515"></a>
-<span class="sourceLineNo">516</span>    int top = Math.min(numTopsAtMost, hostAndWeights.length);<a name="line.516"></a>
-<span class="sourceLineNo">517</span>    List&lt;String&gt; locations = new ArrayList&lt;&gt;(top);<a name="line.517"></a>
-<span class="sourceLineNo">518</span>    HostAndWeight topHost = hostAndWeights[0];<a name="line.518"></a>
-<span class="sourceLineNo">519</span>    locations.add(topHost.getHost());<a name="line.519"></a>
-<span class="sourceLineNo">520</span><a name="line.520"></a>
-<span class="sourceLineNo">521</span>    if (top == 1) { // only care about the top host<a name="line.521"></a>
-<span class="sourceLineNo">522</span>      return locations;<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    }<a name="line.523"></a>
-<span class="sourceLineNo">524</span><a name="line.524"></a>
-<span class="sourceLineNo">525</span>    // When top &gt;= 2,<a name="line.525"></a>
-<span class="sourceLineNo">526</span>    // do the heuristic: filter all hosts which have at least cutoffMultiplier % of block locality<a name="line.526"></a>
-<span class="sourceLineNo">527</span>    double cutoffMultiplier<a name="line.527"></a>
-<span class="sourceLineNo">528</span>            = conf.getFloat(LOCALITY_CUTOFF_MULTIPLIER, DEFAULT_LOCALITY_CUTOFF_MULTIPLIER);<a name="line.528"></a>
-<span class="sourceLineNo">529</span><a name="line.529"></a>
-<span class="sourceLineNo">530</span>    double filterWeight = topHost.getWeight() * cutoffMultiplier;<a name="line.530"></a>
-<span class="sourceLineNo">531</span><a name="line.531"></a>
-<span class="sourceLineNo">532</span>    for (int i = 1; i &lt;= top - 1; i++) {<a name="line.532"></a>
-<span class="sourceLineNo">533</span>      if (hostAndWeights[i].getWeight() &gt;= filterWeight) {<a name="line.533"></a>
-<span class="sourceLineNo">534</span>        locations.add(hostAndWeights[i].getHost());<a name="line.534"></a>
-<span class="sourceLineNo">535</span>      } else {<a name="line.535"></a>
-<span class="sourceLineNo">536</span>        // As hostAndWeights is in descending order,<a name="line.536"></a>
-<span class="sourceLineNo">537</span>        // we could break the loop as long as we meet a weight which is less than filterWeight.<a name="line.537"></a>
-<span class="sourceLineNo">538</span>        break;<a name="line.538"></a>
-<span class="sourceLineNo">539</span>      }<a name="line.539"></a>
-<span class="sourceLineNo">540</span>    }<a name="line.540"></a>
-<span class="sourceLineNo">541</span><a name="line.541"></a>
-<span class="sourceLineNo">542</span>    return locations;<a name="line.542"></a>
-<span class="sourceLineNo">543</span>  }<a name="line.543"></a>
-<span class="sourceLineNo">544</span><a name="line.544"></a>
-<span class="sourceLineNo">545</span>  public static List&lt;String&gt; getBestLocations(Configuration conf,<a name="line.545"></a>
-<span class="sourceLineNo">546</span>      HDFSBlocksDistribution blockDistribution) {<a name="line.546"></a>
-<span class="sourceLineNo">547</span>    // 3 nodes will contain highly local blocks. So default to 3.<a name="line.547"></a>
-<span class="sourceLineNo">548</span>    return getBestLocations(conf, blockDistribution, 3);<a name="line.548"></a>
-<span class="sourceLineNo">549</span>  }<a name="line.549"></a>
-<span class="sourceLineNo">550</span><a name="line.550"></a>
-<span class="sourceLineNo">551</span>  private static String getSnapshotName(Configuration conf) {<a name="line.551"></a>
-<span class="sourceLineNo">552</span>    String snapshotName = conf.get(SNAPSHOT_NAME_KEY);<a name="line.552"></a>
-<span class="sourceLineNo">553</span>    if (snapshotName == null) {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>      throw new IllegalArgumentException("Snapshot name must be provided");<a name="line.554"></a>
-<span class="sourceLineNo">555</span>    }<a name="line.555"></a>
-<span class="sourceLineNo">556</span>    return snapshotName;<a name="line.556"></a>
-<span class="sourceLineNo">557</span>  }<a name="line.557"></a>
-<span class="sourceLineNo">558</span><a name="line.558"></a>
-<span class="sourceLineNo">559</span>  /**<a name="line.559"></a>
-<span class="sourceLineNo">560</span>   * Configures the job to use TableSnapshotInputFormat to read from a snapshot.<a name="line.560"></a>
-<span class="sourceLineNo">561</span>   * @param conf the job to configuration<a name="line.561"></a>
-<span class="sourceLineNo">562</span>   * @param snapshotName the name of the snapshot to read from<a name="line.562"></a>
-<span class="sourceLineNo">563</span>   * @param restoreDir a temporary directory to restore the snapshot into. Current user should have<a name="line.563"></a>
-<span class="sourceLineNo">564</span>   *          write permissions to this directory, and this should not be a subdirectory of rootdir.<a name="line.564"></a>
-<span class="sourceLineNo">565</span>   *          After the job is finished, restoreDir can be deleted.<a name="line.565"></a>
-<span class="sourceLineNo">566</span>   * @throws IOException if an error occurs<a name="line.566"></a>
-<span class="sourceLineNo">567</span>   */<a name="line.567"></a>
-<span class="sourceLineNo">568</span>  public static void setInput(Configuration conf, String snapshotName, Path restoreDir)<a name="line.568"></a>
-<span class="sourceLineNo">569</span>      throws IOException {<a name="line.569"></a>
-<span class="sourceLineNo">570</span>    setInput(conf, snapshotName, restoreDir, null, 1);<a name="line.570"></a>
-<span class="sourceLineNo">571</span>  }<a name="line.571"></a>
-<span class="sourceLineNo">572</span><a name="line.572"></a>
-<span class="sourceLineNo">573</span>  /**<a name="line.573"></a>
-<span class="sourceLineNo">574</span>   * Configures the job to use TableSnapshotInputFormat to read from a snapshot.<a name="line.574"></a>
-<span class="sourceLineNo">575</span>   * @param conf the job to configure<a name="line.575"></a>
-<span class="sourceLineNo">576</span>   * @param snapshotName the name of the snapshot to read from<a name="line.576"></a>
-<span class="sourceLineNo">577</span>   * @param restoreDir a temporary directory to restore the snapshot into. Current user should have<a name="line.577"></a>
-<span class="sourceLineNo">578</span>   *          write permissions to this directory, and this should not be a subdirectory of rootdir.<a name="line.578"></a>
-<span class="sourceLineNo">579</span>   *          After the job is finished, restoreDir can be deleted.<a name="line.579"></a>
-<span class="sourceLineNo">580</span>   * @param numSplitsPerRegion how many input splits to generate per one region<a name="line.580"></a>
-<span class="sourceLineNo">581</span>   * @param splitAlgo SplitAlgorithm to be used when generating InputSplits<a name="line.581"></a>
-<span class="sourceLineNo">582</span>   * @throws IOException if an error occurs<a name="line.582"></a>
-<span class="sourceLineNo">583</span>   */<a name="line.583"></a>
-<span class="sourceLineNo">584</span>  public static void setInput(Configuration conf, String snapshotName, Path restoreDir,<a name="line.584"></a>
-<span class="sourceLineNo">585</span>                              RegionSplitter.SplitAlgorithm splitAlgo, int numSplitsPerRegion)<a name="line.585"></a>
-<span class="sourceLineNo">586</span>          throws IOException {<a name="line.586"></a>
-<span class="sourceLineNo">587</span>    conf.set(SNAPSHOT_NAME_KEY, snapshotName);<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    if (numSplitsPerRegion &lt; 1) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span>      throw new IllegalArgumentException("numSplits must be &gt;= 1, " +<a name="line.589"></a>
-<span class="sourceLineNo">590</span>              "illegal numSplits : " + numSplitsPerRegion);<a name="line.590"></a>
-<span class="sourceLineNo">591</span>    }<a name="line.591"></a>
-<span class="sourceLineNo">592</span>    if (splitAlgo == null &amp;&amp; numSplitsPerRegion &gt; 1) {<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      throw new IllegalArgumentException("Split algo can't be null when numSplits &gt; 1");<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    }<a name="line.594"></a>
-<span class="sourceLineNo">595</span>    if (splitAlgo != null) {<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      conf.set(SPLIT_ALGO, splitAlgo.getClass().getName());<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    }<a name="line.597"></a>
-<span class="sourceLineNo">598</span>    conf.setInt(NUM_SPLITS_PER_REGION, numSplitsPerRegion);<a name="line.598"></a>
-<span class="sourceLineNo">599</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.599"></a>
-<span class="sourceLineNo">600</span>    FileSystem fs = rootDir.getFileSystem(conf);<a name="line.600"></a>
-<span class="sourceLineNo">601</span><a name="line.601"></a>
-<span class="sourceLineNo">602</span>    restoreDir = new Path(restoreDir, UUID.randomUUID().toString());<a name="line.602"></a>
-<span class="sourceLineNo">603</span><a name="line.603"></a>
-<span class="sourceLineNo">604</span>    RestoreSnapshotHelper.copySnapshotForScanner(conf, fs, rootDir, restoreDir, snapshotName);<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    conf.set(RESTORE_DIR_KEY, restoreDir.toString());<a name="line.605"></a>
-<span class="sourceLineNo">606</span>  }<a name="line.606"></a>
-<span class="sourceLineNo">607</span>}<a name="line.607"></a>
+<span class="sourceLineNo">492</span>          splits.add(new InputSplit(htd, hri, hosts, scan, restoreDir));<a name="line.492"></a>
+<span class="sourceLineNo">493</span>        }<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      }<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    }<a name="line.495"></a>
+<span class="sourceLineNo">496</span><a name="line.496"></a>
+<span class="sourceLineNo">497</span>    return splits;<a name="line.497"></a>
+<span class="sourceLineNo">498</span>  }<a name="line.498"></a>
+<span class="sourceLineNo">499</span><a name="line.499"></a>
+<span class="sourceLineNo">500</span>  /**<a name="line.500"></a>
+<span class="sourceLineNo">501</span>   * Compute block locations for snapshot files (which will get the locations for referred hfiles)<a name="line.501"></a>
+<span class="sourceLineNo">502</span>   * only when localityEnabled is true.<a name="line.502"></a>
+<span class="sourceLineNo">503</span>   */<a name="line.503"></a>
+<span class="sourceLineNo">504</span>  private static List&lt;String&gt; calculateLocationsForInputSplit(Configuration conf,<a name="line.504"></a>
+<span class="sourceLineNo">505</span>      TableDescriptor htd, RegionInfo hri, Path tableDir)<a name="line.505"></a>
+<span class="sourceLineNo">506</span>      throws IOException {<a name="line.506"></a>
+<span class="sourceLineNo">507</span>    return getBestLocations(conf, HRegion.computeHDFSBlocksDistribution(conf, htd, hri, tableDir));<a name="line.507"></a>
+<span class="sourceLineNo">508</span>  }<a name="line.508"></a>
+<span class="sourceLineNo">509</span><a name="line.509"></a>
+<span class="sourceLineNo">510</span>  /**<a name="line.510"></a>
+<span class="sourceLineNo">511</span>   * This computes the locations to be passed from the InputSplit. MR/Yarn schedulers does not take<a name="line.511"></a>
+<span class="sourceLineNo">512</span>   * weights into account, thus will treat every location passed from the input split as equal. We<a name="line.512"></a>
+<span class="sourceLineNo">513</span>   * do not want to blindly pass all the locations, since we are creating one split per region, and<a name="line.513"></a>
+<span class="sourceLineNo">514</span>   * the region's blocks are all distributed throughout the cluster unless favorite node assignment<a name="line.514"></a>
+<span class="sourceLineNo">515</span>   * is used. On the expected stable case, only one location will contain most of the blocks as<a name="line.515"></a>
+<span class="sourceLineNo">516</span>   * local.<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   * On the other hand, in favored node assignment, 3 nodes will contain highly local blocks. Here<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * we are doing a simple heuristic, where we will pass all hosts which have at least 80%<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   * (hbase.tablesnapshotinputformat.locality.cutoff.multiplier) as much block locality as the top<a name="line.519"></a>
+<span class="sourceLineNo">520</span>   * host with the best locality.<a name="line.520"></a>
+<span class="sourceLineNo">521</span>   * Return at most numTopsAtMost locations if there are more than that.<a name="line.521"></a>
+<span class="sourceLineNo">522</span>   */<a name="line.522"></a>
+<span class="sourceLineNo">523</span>  private static List&lt;String&gt; getBestLocations(Configuration conf,<a name="line.523"></a>
+<span class="sourceLineNo">524</span>      HDFSBlocksDistribution blockDistribution, int numTopsAtMost) {<a name="line.524"></a>
+<span class="sourceLineNo">525</span>    HostAndWeight[] hostAndWeights = blockDistribution.getTopHostsWithWeights();<a name="line.525"></a>
+<span class="sourceLineNo">526</span><a name="line.526"></a>
+<span class="sourceLineNo">527</span>    if (hostAndWeights.length == 0) { // no matter what numTopsAtMost is<a name="line.527"></a>
+<span class="sourceLineNo">528</span>      return null;<a name="line.528"></a>
+<span class="sourceLineNo">529</span>    }<a name="line.529"></a>
+<span class="sourceLineNo">530</span><a name="line.530"></a>
+<span class="sourceLineNo">531</span>    if (numTopsAtMost &lt; 1) { // invalid if numTopsAtMost &lt; 1, correct it to be 1<a name="line.531"></a>
+<span class="sourceLineNo">532</span>      numTopsAtMost = 1;<a name="line.532"></a>
+<span class="sourceLineNo">533</span>    }<a name="line.533"></a>
+<span class="sourceLineNo">534</span>    int top = Math.min(numTopsAtMost, hostAndWeights.length);<a name="line.534"></a>
+<span class="sourceLineNo">535</span>    List&lt;String&gt; locations = new ArrayList&lt;&gt;(top);<a name="line.535"></a>
+<span class="sourceLineNo">536</span>    HostAndWeight topHost = hostAndWeights[0];<a name="line.536"></a>
+<span class="sourceLineNo">537</span>    locations.add(topHost.getHost());<a name="line.537"></a>
+<span class="sourceLineNo">538</span><a name="line.538"></a>
+<span class="sourceLineNo">539</span>    if (top == 1) { // only care about the top host<a name="line.539"></a>
+<span class="sourceLineNo">540</span>      return locations;<a name="line.540"></a>
+<span class="sourceLineNo">541</span>    }<a name="line.541"></a>
+<span class="sourceLineNo">542</span><a name="line.542"></a>
+<span class="sourceLineNo">543</span>    // When top &gt;= 2,<a name="line.543"></a>
+<span class="sourceLineNo">544</span>    // do the heuristic: filter all hosts which have at least cutoffMultiplier % of block locality<a name="line.544"></a>
+<span class="sourceLineNo">545</span>    double cutoffMultiplier<a name="line.545"></a>
+<span class="sourceLineNo">546</span>            = conf.getFloat(LOCALITY_CUTOFF_MULTIPLIER, DEFAULT_LOCALITY_CUTOFF_MULTIPLIER);<a name="line.546"></a>
+<span class="sourceLineNo">547</span><a name="line.547"></a>
+<span class="sourceLineNo">548</span>    double filterWeight = topHost.getWeight() * cutoffMultiplier;<a name="line.548"></a>
+<span class="sourceLineNo">549</span><a name="line.549"></a>
+<span class="sourceLineNo">550</span>    for (int i = 1; i &lt;= top - 1; i++) {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>      if (hostAndWeights[i].getWeight() &gt;= filterWeight) {<a name="line.551"></a>
+<span class="sourceLineNo">552</span>        locations.add(hostAndWeights[i].getHost());<a name="line.552"></a>
+<span class="sourceLineNo">553</span>      } else {<a name="line.553"></a>
+<span class="sourceLineNo">554</span>        // As hostAndWeights is in descending order,<a name="line.554"></a>
+<span class="sourceLineNo">555</span>        // we could break the loop as long as we meet a weight which is less than filterWeight.<a name="line.555"></a>
+<span class="sourceLineNo">556</span>        break;<a name="line.556"></a>
+<span class="sourceLineNo">557</span>      }<a name="line.557"></a>
+<span class="sourceLineNo">558</span>    }<a name="line.558"></a>
+<span class="sourceLineNo">559</span><a name="line.559"></a>
+<span class="sourceLineNo">560</span>    return locations;<a name="line.560"></a>
+<span class="sourceLineNo">561</span>  }<a name="line.561"></a>
+<span class="sourceLineNo">562</span><a name="line.562"></a>
+<span class="sourceLineNo">563</span>  public static List&lt;String&gt; getBestLocations(Configuration conf,<a name="line.563"></a>
+<span class="sourceLineNo">564</span>      HDFSBlocksDistribution blockDistribution) {<a name="line.564"></a>
+<span class="sourceLineNo">565</span>    // 3 nodes will contain highly local blocks. So default to 3.<a name="line.565"></a>
+<span class="sourceLineNo">566</span>    return getBestLocations(conf, blockDistribution, 3);<a name="line.566"></a>
+<span class="sourceLineNo">567</span>  }<a name="line.567"></a>
+<span class="sourceLineNo">568</span><a name="line.568"></a>
+<span class="sourceLineNo">569</span>  private static String getSnapshotName(Configuration conf) {<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    String snapshotName = conf.get(SNAPSHOT_NAME_KEY);<a name="line.570"></a>
+<span class="sourceLineNo">571</span>    if (snapshotName == null) {<a name="line.571"></a>
+<span class="sourceLineNo">572</span>      throw new IllegalArgumentException("Snapshot name must be provided");<a name="line.572"></a>
+<span class="sourceLineNo">573</span>    }<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    return snapshotName;<a name="line.574"></a>
+<span class="sourceLineNo">575</span>  }<a name="line.575"></a>
+<span class="sourceLineNo">576</span><a name="line.576"></a>
+<span class="sourceLineNo">577</span>  /**<a name="line.577"></a>
+<span class="sourceLineNo">578</span>   * Configures the job to use TableSnapshotInputFormat to read from a snapshot.<a name="line.578"></a>
+<span class="sourceLineNo">579</span>   * @param conf the job to configuration<a name="line.579"></a>
+<span class="sourceLineNo">580</span>   * @param snapshotName the name of the snapshot to read from<a name="line.580"></a>
+<span class="sourceLineNo">581</span>   * @param restoreDir a temporary directory to restore the snapshot into. Current user should have<a name="line.581"></a>
+<span class="sourceLineNo">582</span>   *          write permissions to this directory, and this should not be a subdirectory of rootdir.<a name="line.582"></a>
+<span class="sourceLineNo">583</span>   *          After the job is finished, restoreDir can be deleted.<a name="line.583"></a>
+<span class="sourceLineNo">584</span>   * @throws IOException if an error occurs<a name="line.584"></a>
+<span class="sourceLineNo">585</span>   */<a name="line.585"></a>
+<span class="sourceLineNo">586</span>  public static void setInput(Configuration conf, String snapshotName, Path restoreDir)<a name="line.586"></a>
+<span class="sourceLineNo">587</span>      throws IOException {<a name="line.587"></a>
+<span class="sourceLineNo">588</span>    setInput(conf, snapshotName, restoreDir, null, 1);<a name="line.588"></a>
+<span class="sourceLineNo">589</span>  }<a name="line.589"></a>
+<span class="sourceLineNo">590</span><a name="line.590"></a>
+<span class="sourceLineNo">591</span>  /**<a name="line.591"></a>
+<span class="sourceLineNo">592</span>   * Configures the job to use TableSnapshotInputFormat to read from a snapshot.<a name="line.592"></a>
+<span class="sourceLineNo">593</span>   * @param conf the job to configure<a name="line.593"></a>
+<span class="sourceLineNo">594</span>   * @param snapshotName the name of the snapshot to read from<a name="line.594"></a>
+<span class="sourceLineNo">595</span>   * @param restoreDir a temporary directory to restore the snapshot into. Current user should have<a name="line.595"></a>
+<span class="sourceLineNo">596</span>   *          write permissions to this directory, and this should not be a subdirectory of rootdir.<a name="line.596"></a>
+<span class="sourceLineNo">597</span>   *          After the job is finished, restoreDir can be deleted.<a name="line.597"></a>
+<span class="sourceLineNo">598</span>   * @param numSplitsPerRegion how many input splits to generate per one region<a name="line.598"></a>
+<span class="sourceLineNo">599</span>   * @param splitAlgo SplitAlgorithm to be used when generating InputSplits<a name="line.599"></a>
+<span class="sourceLineNo">600</span>   * @throws IOException if an error occurs<a name="line.600"></a>
+<span class="sourceLineNo">601</span>   */<a name="line.601"></a>
+<span class="sourceLineNo">602</span>  public static void setInput(Configuration conf, String snapshotName, Path restoreDir,<a name="line.602"></a>
+<span class="sourceLineNo">603</span>                              RegionSplitter.SplitAlgorithm splitAlgo, int numSplitsPerRegion)<a name="line.603"></a>
+<span class="sourceLineNo">604</span>          throws IOException {<a name="line.604"></a>
+<span class="sourceLineNo">605</span>    conf.set(SNAPSHOT_NAME_KEY, snapshotName);<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    if (numSplitsPerRegion &lt; 1) {<a name="line.606"></a>
+<span class="sourceLineNo">607</span>      throw new IllegalArgumentException("numSplits must be &gt;= 1, " +<a name="line.607"></a>
+<span class="sourceLineNo">608</span>              "illegal numSplits : " + numSplitsPerRegion);<a name="line.608"></a>
+<span class="sourceLineNo">609</span>    }<a name="line.609"></a>
+<span class="sourceLineNo">610</span>    if (splitAlgo == null &amp;&amp; numSplitsPerRegion &gt; 1) {<a name="line.610"></a>
+<span class="sourceLineNo">611</span>      throw new IllegalArgumentException("Split algo can't be null when numSplits &gt; 1");<a name="line.611"></a>
+<span class="sourceLineNo">612</span>    }<a name="line.612"></a>
+<span class="sourceLineNo">613</span>    if (splitAlgo != null) {<a name="line.613"></a>
+<span class="sourceLineNo">614</span>      conf.set(SPLIT_ALGO, splitAlgo.getClass().getName());<a name="line.614"></a>
+<span class="sourceLineNo">615</span>    }<a name="line.615"></a>
+<span class="sourceLineNo">616</span>    conf.setInt(NUM_SPLITS_PER_REGION, numSplitsPerRegion);<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.617"></a>
+<span class="sourceLineNo">618</span>    FileSystem fs = rootDir.getFileSystem(conf);<a name="line.618"></a>
+<span class="sourceLineNo">619</span><a name="line.619"></a>
+<span class="sourceLineNo">620</span>    restoreDir = new Path(restoreDir, UUID.randomUUID().toString());<a name="line.620"></a>
+<span class="sourceLineNo">621</span><a name="line.621"></a>
+<span class="sourceLineNo">622</span>    RestoreSnapshotHelper.copySnapshotForScanner(conf, fs, rootDir, restoreDir, snapshotName);<a name="line.622"></a>
+<span class="sourceLineNo">623</span>    conf.set(RESTORE_DIR_KEY, restoreDir.toString());<a name="line.623"></a>
+<span class="sourceLineNo">624</span>  }<a name="line.624"></a>
+<span class="sourceLineNo">625</span>}<a name="line.625"></a>
 
 
 
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html b/devapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html
index b614563..2f3d5ca 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.RecordReader.html
@@ -49,570 +49,588 @@
 <span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.client.RegionLocator;<a name="line.41"></a>
 <span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.client.Result;<a name="line.42"></a>
 <span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.client.Scan;<a name="line.43"></a>
-<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.client.TableDescriptor;<a name="line.44"></a>
-<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<a name="line.45"></a>
-<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.regionserver.HRegion;<a name="line.46"></a>
-<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.snapshot.RestoreSnapshotHelper;<a name="line.47"></a>
-<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;<a name="line.48"></a>
-<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.snapshot.SnapshotManifest;<a name="line.49"></a>
-<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.50"></a>
-<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.51"></a>
-<span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.util.RegionSplitter;<a name="line.52"></a>
-<span class="sourceLineNo">053</span>import org.apache.hadoop.io.Writable;<a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.54"></a>
-<span class="sourceLineNo">055</span>import org.slf4j.Logger;<a name="line.55"></a>
-<span class="sourceLineNo">056</span>import org.slf4j.LoggerFactory;<a name="line.56"></a>
-<span class="sourceLineNo">057</span><a name="line.57"></a>
-<span class="sourceLineNo">058</span>import org.apache.hbase.thirdparty.com.google.common.collect.Lists;<a name="line.58"></a>
-<span class="sourceLineNo">059</span><a name="line.59"></a>
-<span class="sourceLineNo">060</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.60"></a>
-<span class="sourceLineNo">061</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MapReduceProtos.TableSnapshotRegionSplit;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription;<a name="line.62"></a>
-<span class="sourceLineNo">063</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;<a name="line.63"></a>
-<span class="sourceLineNo">064</span><a name="line.64"></a>
-<span class="sourceLineNo">065</span>/**<a name="line.65"></a>
-<span class="sourceLineNo">066</span> * Hadoop MR API-agnostic implementation for mapreduce over table snapshots.<a name="line.66"></a>
-<span class="sourceLineNo">067</span> */<a name="line.67"></a>
-<span class="sourceLineNo">068</span>@InterfaceAudience.Private<a name="line.68"></a>
-<span class="sourceLineNo">069</span>public class TableSnapshotInputFormatImpl {<a name="line.69"></a>
-<span class="sourceLineNo">070</span>  // TODO: Snapshots files are owned in fs by the hbase user. There is no<a name="line.70"></a>
-<span class="sourceLineNo">071</span>  // easy way to delegate access.<a name="line.71"></a>
-<span class="sourceLineNo">072</span><a name="line.72"></a>
-<span class="sourceLineNo">073</span>  public static final Logger LOG = LoggerFactory.getLogger(TableSnapshotInputFormatImpl.class);<a name="line.73"></a>
-<span class="sourceLineNo">074</span><a name="line.74"></a>
-<span class="sourceLineNo">075</span>  private static final String SNAPSHOT_NAME_KEY = "hbase.TableSnapshotInputFormat.snapshot.name";<a name="line.75"></a>
-<span class="sourceLineNo">076</span>  // key for specifying the root dir of the restored snapshot<a name="line.76"></a>
-<span class="sourceLineNo">077</span>  protected static final String RESTORE_DIR_KEY = "hbase.TableSnapshotInputFormat.restore.dir";<a name="line.77"></a>
-<span class="sourceLineNo">078</span><a name="line.78"></a>
-<span class="sourceLineNo">079</span>  /** See {@link #getBestLocations(Configuration, HDFSBlocksDistribution, int)} */<a name="line.79"></a>
-<span class="sourceLineNo">080</span>  private static final String LOCALITY_CUTOFF_MULTIPLIER =<a name="line.80"></a>
-<span class="sourceLineNo">081</span>    "hbase.tablesnapshotinputformat.locality.cutoff.multiplier";<a name="line.81"></a>
-<span class="sourceLineNo">082</span>  private static final float DEFAULT_LOCALITY_CUTOFF_MULTIPLIER = 0.8f;<a name="line.82"></a>
-<span class="sourceLineNo">083</span><a name="line.83"></a>
-<span class="sourceLineNo">084</span>  /**<a name="line.84"></a>
-<span class="sourceLineNo">085</span>   * For MapReduce jobs running multiple mappers per region, determines<a name="line.85"></a>
-<span class="sourceLineNo">086</span>   * what split algorithm we should be using to find split points for scanners.<a name="line.86"></a>
-<span class="sourceLineNo">087</span>   */<a name="line.87"></a>
-<span class="sourceLineNo">088</span>  public static final String SPLIT_ALGO = "hbase.mapreduce.split.algorithm";<a name="line.88"></a>
-<span class="sourceLineNo">089</span>  /**<a name="line.89"></a>
-<span class="sourceLineNo">090</span>   * For MapReduce jobs running multiple mappers per region, determines<a name="line.90"></a>
-<span class="sourceLineNo">091</span>   * number of splits to generate per region.<a name="line.91"></a>
-<span class="sourceLineNo">092</span>   */<a name="line.92"></a>
-<span class="sourceLineNo">093</span>  public static final String NUM_SPLITS_PER_REGION = "hbase.mapreduce.splits.per.region";<a name="line.93"></a>
-<span class="sourceLineNo">094</span><a name="line.94"></a>
-<span class="sourceLineNo">095</span>  /**<a name="line.95"></a>
-<span class="sourceLineNo">096</span>   * Whether to calculate the block location for splits. Default to true.<a name="line.96"></a>
-<span class="sourceLineNo">097</span>   * If the computing layer runs outside of HBase cluster, the block locality does not master.<a name="line.97"></a>
-<span class="sourceLineNo">098</span>   * Setting this value to false could skip the calculation and save some time.<a name="line.98"></a>
-<span class="sourceLineNo">099</span>   *<a name="line.99"></a>
-<span class="sourceLineNo">100</span>   * Set access modifier to "public" so that these could be accessed by test classes of<a name="line.100"></a>
-<span class="sourceLineNo">101</span>   * both org.apache.hadoop.hbase.mapred<a name="line.101"></a>
-<span class="sourceLineNo">102</span>   * and  org.apache.hadoop.hbase.mapreduce.<a name="line.102"></a>
-<span class="sourceLineNo">103</span>   */<a name="line.103"></a>
-<span class="sourceLineNo">104</span>  public static final String  SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY =<a name="line.104"></a>
-<span class="sourceLineNo">105</span>      "hbase.TableSnapshotInputFormat.locality.enabled";<a name="line.105"></a>
-<span class="sourceLineNo">106</span>  public static final boolean SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT = true;<a name="line.106"></a>
-<span class="sourceLineNo">107</span><a name="line.107"></a>
-<span class="sourceLineNo">108</span>  /**<a name="line.108"></a>
-<span class="sourceLineNo">109</span>   * Whether to calculate the Snapshot region location by region location from meta.<a name="line.109"></a>
-<span class="sourceLineNo">110</span>   * It is much faster than computing block locations for splits.<a name="line.110"></a>
-<span class="sourceLineNo">111</span>   */<a name="line.111"></a>
-<span class="sourceLineNo">112</span>  public static final String  SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION =<a name="line.112"></a>
-<span class="sourceLineNo">113</span>    "hbase.TableSnapshotInputFormat.locality.by.region.location";<a name="line.113"></a>
-<span class="sourceLineNo">114</span><a name="line.114"></a>
-<span class="sourceLineNo">115</span>  public static final boolean SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT = false;<a name="line.115"></a>
-<span class="sourceLineNo">116</span><a name="line.116"></a>
-<span class="sourceLineNo">117</span>  /**<a name="line.117"></a>
-<span class="sourceLineNo">118</span>   * In some scenario, scan limited rows on each InputSplit for sampling data extraction<a name="line.118"></a>
-<span class="sourceLineNo">119</span>   */<a name="line.119"></a>
-<span class="sourceLineNo">120</span>  public static final String SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT =<a name="line.120"></a>
-<span class="sourceLineNo">121</span>      "hbase.TableSnapshotInputFormat.row.limit.per.inputsplit";<a name="line.121"></a>
-<span class="sourceLineNo">122</span><a name="line.122"></a>
-<span class="sourceLineNo">123</span>  /**<a name="line.123"></a>
-<span class="sourceLineNo">124</span>   * Whether to enable scan metrics on Scan, default to true<a name="line.124"></a>
-<span class="sourceLineNo">125</span>   */<a name="line.125"></a>
-<span class="sourceLineNo">126</span>  public static final String  SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED =<a name="line.126"></a>
-<span class="sourceLineNo">127</span>    "hbase.TableSnapshotInputFormat.scan_metrics.enabled";<a name="line.127"></a>
-<span class="sourceLineNo">128</span><a name="line.128"></a>
-<span class="sourceLineNo">129</span>  public static final boolean SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT = true;<a name="line.129"></a>
-<span class="sourceLineNo">130</span><a name="line.130"></a>
-<span class="sourceLineNo">131</span>  /**<a name="line.131"></a>
-<span class="sourceLineNo">132</span>   * Implementation class for InputSplit logic common between mapred and mapreduce.<a name="line.132"></a>
-<span class="sourceLineNo">133</span>   */<a name="line.133"></a>
-<span class="sourceLineNo">134</span>  public static class InputSplit implements Writable {<a name="line.134"></a>
-<span class="sourceLineNo">135</span><a name="line.135"></a>
-<span class="sourceLineNo">136</span>    private TableDescriptor htd;<a name="line.136"></a>
-<span class="sourceLineNo">137</span>    private RegionInfo regionInfo;<a name="line.137"></a>
-<span class="sourceLineNo">138</span>    private String[] locations;<a name="line.138"></a>
-<span class="sourceLineNo">139</span>    private String scan;<a name="line.139"></a>
-<span class="sourceLineNo">140</span>    private String restoreDir;<a name="line.140"></a>
-<span class="sourceLineNo">141</span><a name="line.141"></a>
-<span class="sourceLineNo">142</span>    // constructor for mapreduce framework / Writable<a name="line.142"></a>
-<span class="sourceLineNo">143</span>    public InputSplit() {}<a name="line.143"></a>
+<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.client.Scan.ReadType;<a name="line.44"></a>
+<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.client.TableDescriptor;<a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.regionserver.HRegion;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.snapshot.RestoreSnapshotHelper;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;<a name="line.49"></a>
+<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.snapshot.SnapshotManifest;<a name="line.50"></a>
+<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.51"></a>
+<span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.52"></a>
+<span class="sourceLineNo">053</span>import org.apache.hadoop.hbase.util.RegionSplitter;<a name="line.53"></a>
+<span class="sourceLineNo">054</span>import org.apache.hadoop.io.Writable;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>import org.slf4j.Logger;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>import org.slf4j.LoggerFactory;<a name="line.57"></a>
+<span class="sourceLineNo">058</span><a name="line.58"></a>
+<span class="sourceLineNo">059</span>import org.apache.hbase.thirdparty.com.google.common.collect.Lists;<a name="line.59"></a>
+<span class="sourceLineNo">060</span><a name="line.60"></a>
+<span class="sourceLineNo">061</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.61"></a>
+<span class="sourceLineNo">062</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MapReduceProtos.TableSnapshotRegionSplit;<a name="line.62"></a>
+<span class="sourceLineNo">063</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription;<a name="line.63"></a>
+<span class="sourceLineNo">064</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;<a name="line.64"></a>
+<span class="sourceLineNo">065</span><a name="line.65"></a>
+<span class="sourceLineNo">066</span>/**<a name="line.66"></a>
+<span class="sourceLineNo">067</span> * Hadoop MR API-agnostic implementation for mapreduce over table snapshots.<a name="line.67"></a>
+<span class="sourceLineNo">068</span> */<a name="line.68"></a>
+<span class="sourceLineNo">069</span>@InterfaceAudience.Private<a name="line.69"></a>
+<span class="sourceLineNo">070</span>public class TableSnapshotInputFormatImpl {<a name="line.70"></a>
+<span class="sourceLineNo">071</span>  // TODO: Snapshots files are owned in fs by the hbase user. There is no<a name="line.71"></a>
+<span class="sourceLineNo">072</span>  // easy way to delegate access.<a name="line.72"></a>
+<span class="sourceLineNo">073</span><a name="line.73"></a>
+<span class="sourceLineNo">074</span>  public static final Logger LOG = LoggerFactory.getLogger(TableSnapshotInputFormatImpl.class);<a name="line.74"></a>
+<span class="sourceLineNo">075</span><a name="line.75"></a>
+<span class="sourceLineNo">076</span>  private static final String SNAPSHOT_NAME_KEY = "hbase.TableSnapshotInputFormat.snapshot.name";<a name="line.76"></a>
+<span class="sourceLineNo">077</span>  // key for specifying the root dir of the restored snapshot<a name="line.77"></a>
+<span class="sourceLineNo">078</span>  protected static final String RESTORE_DIR_KEY = "hbase.TableSnapshotInputFormat.restore.dir";<a name="line.78"></a>
+<span class="sourceLineNo">079</span><a name="line.79"></a>
+<span class="sourceLineNo">080</span>  /** See {@link #getBestLocations(Configuration, HDFSBlocksDistribution, int)} */<a name="line.80"></a>
+<span class="sourceLineNo">081</span>  private static final String LOCALITY_CUTOFF_MULTIPLIER =<a name="line.81"></a>
+<span class="sourceLineNo">082</span>    "hbase.tablesnapshotinputformat.locality.cutoff.multiplier";<a name="line.82"></a>
+<span class="sourceLineNo">083</span>  private static final float DEFAULT_LOCALITY_CUTOFF_MULTIPLIER = 0.8f;<a name="line.83"></a>
+<span class="sourceLineNo">084</span><a name="line.84"></a>
+<span class="sourceLineNo">085</span>  /**<a name="line.85"></a>
+<span class="sourceLineNo">086</span>   * For MapReduce jobs running multiple mappers per region, determines<a name="line.86"></a>
+<span class="sourceLineNo">087</span>   * what split algorithm we should be using to find split points for scanners.<a name="line.87"></a>
+<span class="sourceLineNo">088</span>   */<a name="line.88"></a>
+<span class="sourceLineNo">089</span>  public static final String SPLIT_ALGO = "hbase.mapreduce.split.algorithm";<a name="line.89"></a>
+<span class="sourceLineNo">090</span>  /**<a name="line.90"></a>
+<span class="sourceLineNo">091</span>   * For MapReduce jobs running multiple mappers per region, determines<a name="line.91"></a>
+<span class="sourceLineNo">092</span>   * number of splits to generate per region.<a name="line.92"></a>
+<span class="sourceLineNo">093</span>   */<a name="line.93"></a>
+<span class="sourceLineNo">094</span>  public static final String NUM_SPLITS_PER_REGION = "hbase.mapreduce.splits.per.region";<a name="line.94"></a>
+<span class="sourceLineNo">095</span><a name="line.95"></a>
+<span class="sourceLineNo">096</span>  /**<a name="line.96"></a>
+<span class="sourceLineNo">097</span>   * Whether to calculate the block location for splits. Default to true.<a name="line.97"></a>
+<span class="sourceLineNo">098</span>   * If the computing layer runs outside of HBase cluster, the block locality does not master.<a name="line.98"></a>
+<span class="sourceLineNo">099</span>   * Setting this value to false could skip the calculation and save some time.<a name="line.99"></a>
+<span class="sourceLineNo">100</span>   *<a name="line.100"></a>
+<span class="sourceLineNo">101</span>   * Set access modifier to "public" so that these could be accessed by test classes of<a name="line.101"></a>
+<span class="sourceLineNo">102</span>   * both org.apache.hadoop.hbase.mapred<a name="line.102"></a>
+<span class="sourceLineNo">103</span>   * and  org.apache.hadoop.hbase.mapreduce.<a name="line.103"></a>
+<span class="sourceLineNo">104</span>   */<a name="line.104"></a>
+<span class="sourceLineNo">105</span>  public static final String  SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY =<a name="line.105"></a>
+<span class="sourceLineNo">106</span>      "hbase.TableSnapshotInputFormat.locality.enabled";<a name="line.106"></a>
+<span class="sourceLineNo">107</span>  public static final boolean SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT = true;<a name="line.107"></a>
+<span class="sourceLineNo">108</span><a name="line.108"></a>
+<span class="sourceLineNo">109</span>  /**<a name="line.109"></a>
+<span class="sourceLineNo">110</span>   * Whether to calculate the Snapshot region location by region location from meta.<a name="line.110"></a>
+<span class="sourceLineNo">111</span>   * It is much faster than computing block locations for splits.<a name="line.111"></a>
+<span class="sourceLineNo">112</span>   */<a name="line.112"></a>
+<span class="sourceLineNo">113</span>  public static final String  SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION =<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    "hbase.TableSnapshotInputFormat.locality.by.region.location";<a name="line.114"></a>
+<span class="sourceLineNo">115</span><a name="line.115"></a>
+<span class="sourceLineNo">116</span>  public static final boolean SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT = false;<a name="line.116"></a>
+<span class="sourceLineNo">117</span><a name="line.117"></a>
+<span class="sourceLineNo">118</span>  /**<a name="line.118"></a>
+<span class="sourceLineNo">119</span>   * In some scenario, scan limited rows on each InputSplit for sampling data extraction<a name="line.119"></a>
+<span class="sourceLineNo">120</span>   */<a name="line.120"></a>
+<span class="sourceLineNo">121</span>  public static final String SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT =<a name="line.121"></a>
+<span class="sourceLineNo">122</span>      "hbase.TableSnapshotInputFormat.row.limit.per.inputsplit";<a name="line.122"></a>
+<span class="sourceLineNo">123</span><a name="line.123"></a>
+<span class="sourceLineNo">124</span>  /**<a name="line.124"></a>
+<span class="sourceLineNo">125</span>   * Whether to enable scan metrics on Scan, default to true<a name="line.125"></a>
+<span class="sourceLineNo">126</span>   */<a name="line.126"></a>
+<span class="sourceLineNo">127</span>  public static final String  SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED =<a name="line.127"></a>
+<span class="sourceLineNo">128</span>    "hbase.TableSnapshotInputFormat.scan_metrics.enabled";<a name="line.128"></a>
+<span class="sourceLineNo">129</span><a name="line.129"></a>
+<span class="sourceLineNo">130</span>  public static final boolean SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT = true;<a name="line.130"></a>
+<span class="sourceLineNo">131</span><a name="line.131"></a>
+<span class="sourceLineNo">132</span>  /**<a name="line.132"></a>
+<span class="sourceLineNo">133</span>   * The {@link ReadType} which should be set on the {@link Scan} to read the HBase Snapshot,<a name="line.133"></a>
+<span class="sourceLineNo">134</span>   * default STREAM.<a name="line.134"></a>
+<span class="sourceLineNo">135</span>   */<a name="line.135"></a>
+<span class="sourceLineNo">136</span>  public static final String SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE =<a name="line.136"></a>
+<span class="sourceLineNo">137</span>      "hbase.TableSnapshotInputFormat.scanner.readtype";<a name="line.137"></a>
+<span class="sourceLineNo">138</span>  public static final ReadType SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE_DEFAULT = ReadType.STREAM;<a name="line.138"></a>
+<span class="sourceLineNo">139</span><a name="line.139"></a>
+<span class="sourceLineNo">140</span>  /**<a name="line.140"></a>
+<span class="sourceLineNo">141</span>   * Implementation class for InputSplit logic common between mapred and mapreduce.<a name="line.141"></a>
+<span class="sourceLineNo">142</span>   */<a name="line.142"></a>
+<span class="sourceLineNo">143</span>  public static class InputSplit implements Writable {<a name="line.143"></a>
 <span class="sourceLineNo">144</span><a name="line.144"></a>
-<span class="sourceLineNo">145</span>    public InputSplit(TableDescriptor htd, RegionInfo regionInfo, List&lt;String&gt; locations,<a name="line.145"></a>
-<span class="sourceLineNo">146</span>        Scan scan, Path restoreDir) {<a name="line.146"></a>
-<span class="sourceLineNo">147</span>      this.htd = htd;<a name="line.147"></a>
-<span class="sourceLineNo">148</span>      this.regionInfo = regionInfo;<a name="line.148"></a>
-<span class="sourceLineNo">149</span>      if (locations == null || locations.isEmpty()) {<a name="line.149"></a>
-<span class="sourceLineNo">150</span>        this.locations = new String[0];<a name="line.150"></a>
-<span class="sourceLineNo">151</span>      } else {<a name="line.151"></a>
-<span class="sourceLineNo">152</span>        this.locations = locations.toArray(new String[locations.size()]);<a name="line.152"></a>
-<span class="sourceLineNo">153</span>      }<a name="line.153"></a>
-<span class="sourceLineNo">154</span>      try {<a name="line.154"></a>
-<span class="sourceLineNo">155</span>        this.scan = scan != null ? TableMapReduceUtil.convertScanToString(scan) : "";<a name="line.155"></a>
-<span class="sourceLineNo">156</span>      } catch (IOException e) {<a name="line.156"></a>
-<span class="sourceLineNo">157</span>        LOG.warn("Failed to convert Scan to String", e);<a name="line.157"></a>
-<span class="sourceLineNo">158</span>      }<a name="line.158"></a>
-<span class="sourceLineNo">159</span><a name="line.159"></a>
-<span class="sourceLineNo">160</span>      this.restoreDir = restoreDir.toString();<a name="line.160"></a>
-<span class="sourceLineNo">161</span>    }<a name="line.161"></a>
-<span class="sourceLineNo">162</span><a name="line.162"></a>
-<span class="sourceLineNo">163</span>    public TableDescriptor getHtd() {<a name="line.163"></a>
-<span class="sourceLineNo">164</span>      return htd;<a name="line.164"></a>
-<span class="sourceLineNo">165</span>    }<a name="line.165"></a>
-<span class="sourceLineNo">166</span><a name="line.166"></a>
-<span class="sourceLineNo">167</span>    public String getScan() {<a name="line.167"></a>
-<span class="sourceLineNo">168</span>      return scan;<a name="line.168"></a>
-<span class="sourceLineNo">169</span>    }<a name="line.169"></a>
-<span class="sourceLineNo">170</span><a name="line.170"></a>
-<span class="sourceLineNo">171</span>    public String getRestoreDir() {<a name="line.171"></a>
-<span class="sourceLineNo">172</span>      return restoreDir;<a name="line.172"></a>
-<span class="sourceLineNo">173</span>    }<a name="line.173"></a>
-<span class="sourceLineNo">174</span><a name="line.174"></a>
-<span class="sourceLineNo">175</span>    public long getLength() {<a name="line.175"></a>
-<span class="sourceLineNo">176</span>      //TODO: We can obtain the file sizes of the snapshot here.<a name="line.176"></a>
-<span class="sourceLineNo">177</span>      return 0;<a name="line.177"></a>
+<span class="sourceLineNo">145</span>    private TableDescriptor htd;<a name="line.145"></a>
+<span class="sourceLineNo">146</span>    private RegionInfo regionInfo;<a name="line.146"></a>
+<span class="sourceLineNo">147</span>    private String[] locations;<a name="line.147"></a>
+<span class="sourceLineNo">148</span>    private String scan;<a name="line.148"></a>
+<span class="sourceLineNo">149</span>    private String restoreDir;<a name="line.149"></a>
+<span class="sourceLineNo">150</span><a name="line.150"></a>
+<span class="sourceLineNo">151</span>    // constructor for mapreduce framework / Writable<a name="line.151"></a>
+<span class="sourceLineNo">152</span>    public InputSplit() {}<a name="line.152"></a>
+<span class="sourceLineNo">153</span><a name="line.153"></a>
+<span class="sourceLineNo">154</span>    public InputSplit(TableDescriptor htd, RegionInfo regionInfo, List&lt;String&gt; locations,<a name="line.154"></a>
+<span class="sourceLineNo">155</span>        Scan scan, Path restoreDir) {<a name="line.155"></a>
+<span class="sourceLineNo">156</span>      this.htd = htd;<a name="line.156"></a>
+<span class="sourceLineNo">157</span>      this.regionInfo = regionInfo;<a name="line.157"></a>
+<span class="sourceLineNo">158</span>      if (locations == null || locations.isEmpty()) {<a name="line.158"></a>
+<span class="sourceLineNo">159</span>        this.locations = new String[0];<a name="line.159"></a>
+<span class="sourceLineNo">160</span>      } else {<a name="line.160"></a>
+<span class="sourceLineNo">161</span>        this.locations = locations.toArray(new String[locations.size()]);<a name="line.161"></a>
+<span class="sourceLineNo">162</span>      }<a name="line.162"></a>
+<span class="sourceLineNo">163</span>      try {<a name="line.163"></a>
+<span class="sourceLineNo">164</span>        this.scan = scan != null ? TableMapReduceUtil.convertScanToString(scan) : "";<a name="line.164"></a>
+<span class="sourceLineNo">165</span>      } catch (IOException e) {<a name="line.165"></a>
+<span class="sourceLineNo">166</span>        LOG.warn("Failed to convert Scan to String", e);<a name="line.166"></a>
+<span class="sourceLineNo">167</span>      }<a name="line.167"></a>
+<span class="sourceLineNo">168</span><a name="line.168"></a>
+<span class="sourceLineNo">169</span>      this.restoreDir = restoreDir.toString();<a name="line.169"></a>
+<span class="sourceLineNo">170</span>    }<a name="line.170"></a>
+<span class="sourceLineNo">171</span><a name="line.171"></a>
+<span class="sourceLineNo">172</span>    public TableDescriptor getHtd() {<a name="line.172"></a>
+<span class="sourceLineNo">173</span>      return htd;<a name="line.173"></a>
+<span class="sourceLineNo">174</span>    }<a name="line.174"></a>
+<span class="sourceLineNo">175</span><a name="line.175"></a>
+<span class="sourceLineNo">176</span>    public String getScan() {<a name="line.176"></a>
+<span class="sourceLineNo">177</span>      return scan;<a name="line.177"></a>
 <span class="sourceLineNo">178</span>    }<a name="line.178"></a>
 <span class="sourceLineNo">179</span><a name="line.179"></a>
-<span class="sourceLineNo">180</span>    public String[] getLocations() {<a name="line.180"></a>
-<span class="sourceLineNo">181</span>      return locations;<a name="line.181"></a>
+<span class="sourceLineNo">180</span>    public String getRestoreDir() {<a name="line.180"></a>
+<span class="sourceLineNo">181</span>      return restoreDir;<a name="line.181"></a>
 <span class="sourceLineNo">182</span>    }<a name="line.182"></a>
 <span class="sourceLineNo">183</span><a name="line.183"></a>
-<span class="sourceLineNo">184</span>    public TableDescriptor getTableDescriptor() {<a name="line.184"></a>
-<span class="sourceLineNo">185</span>      return htd;<a name="line.185"></a>
-<span class="sourceLineNo">186</span>    }<a name="line.186"></a>
-<span class="sourceLineNo">187</span><a name="line.187"></a>
-<span class="sourceLineNo">188</span>    public RegionInfo getRegionInfo() {<a name="line.188"></a>
-<span class="sourceLineNo">189</span>      return regionInfo;<a name="line.189"></a>
-<span class="sourceLineNo">190</span>    }<a name="line.190"></a>
-<span class="sourceLineNo">191</span><a name="line.191"></a>
-<span class="sourceLineNo">192</span>    // TODO: We should have ProtobufSerialization in Hadoop, and directly use PB objects instead of<a name="line.192"></a>
-<span class="sourceLineNo">193</span>    // doing this wrapping with Writables.<a name="line.193"></a>
-<span class="sourceLineNo">194</span>    @Override<a name="line.194"></a>
-<span class="sourceLineNo">195</span>    public void write(DataOutput out) throws IOException {<a name="line.195"></a>
-<span class="sourceLineNo">196</span>      TableSnapshotRegionSplit.Builder builder = TableSnapshotRegionSplit.newBuilder()<a name="line.196"></a>
-<span class="sourceLineNo">197</span>          .setTable(ProtobufUtil.toTableSchema(htd))<a name="line.197"></a>
-<span class="sourceLineNo">198</span>          .setRegion(ProtobufUtil.toRegionInfo(regionInfo));<a name="line.198"></a>
-<span class="sourceLineNo">199</span><a name="line.199"></a>
-<span class="sourceLineNo">200</span>      for (String location : locations) {<a name="line.200"></a>
-<span class="sourceLineNo">201</span>        builder.addLocations(location);<a name="line.201"></a>
-<span class="sourceLineNo">202</span>      }<a name="line.202"></a>
-<span class="sourceLineNo">203</span><a name="line.203"></a>
-<span class="sourceLineNo">204</span>      TableSnapshotRegionSplit split = builder.build();<a name="line.204"></a>
-<span class="sourceLineNo">205</span><a name="line.205"></a>
-<span class="sourceLineNo">206</span>      ByteArrayOutputStream baos = new ByteArrayOutputStream();<a name="line.206"></a>
-<span class="sourceLineNo">207</span>      split.writeTo(baos);<a name="line.207"></a>
-<span class="sourceLineNo">208</span>      baos.close();<a name="line.208"></a>
-<span class="sourceLineNo">209</span>      byte[] buf = baos.toByteArray();<a name="line.209"></a>
-<span class="sourceLineNo">210</span>      out.writeInt(buf.length);<a name="line.210"></a>
-<span class="sourceLineNo">211</span>      out.write(buf);<a name="line.211"></a>
+<span class="sourceLineNo">184</span>    public long getLength() {<a name="line.184"></a>
+<span class="sourceLineNo">185</span>      //TODO: We can obtain the file sizes of the snapshot here.<a name="line.185"></a>
+<span class="sourceLineNo">186</span>      return 0;<a name="line.186"></a>
+<span class="sourceLineNo">187</span>    }<a name="line.187"></a>
+<span class="sourceLineNo">188</span><a name="line.188"></a>
+<span class="sourceLineNo">189</span>    public String[] getLocations() {<a name="line.189"></a>
+<span class="sourceLineNo">190</span>      return locations;<a name="line.190"></a>
+<span class="sourceLineNo">191</span>    }<a name="line.191"></a>
+<span class="sourceLineNo">192</span><a name="line.192"></a>
+<span class="sourceLineNo">193</span>    public TableDescriptor getTableDescriptor() {<a name="line.193"></a>
+<span class="sourceLineNo">194</span>      return htd;<a name="line.194"></a>
+<span class="sourceLineNo">195</span>    }<a name="line.195"></a>
+<span class="sourceLineNo">196</span><a name="line.196"></a>
+<span class="sourceLineNo">197</span>    public RegionInfo getRegionInfo() {<a name="line.197"></a>
+<span class="sourceLineNo">198</span>      return regionInfo;<a name="line.198"></a>
+<span class="sourceLineNo">199</span>    }<a name="line.199"></a>
+<span class="sourceLineNo">200</span><a name="line.200"></a>
+<span class="sourceLineNo">201</span>    // TODO: We should have ProtobufSerialization in Hadoop, and directly use PB objects instead of<a name="line.201"></a>
+<span class="sourceLineNo">202</span>    // doing this wrapping with Writables.<a name="line.202"></a>
+<span class="sourceLineNo">203</span>    @Override<a name="line.203"></a>
+<span class="sourceLineNo">204</span>    public void write(DataOutput out) throws IOException {<a name="line.204"></a>
+<span class="sourceLineNo">205</span>      TableSnapshotRegionSplit.Builder builder = TableSnapshotRegionSplit.newBuilder()<a name="line.205"></a>
+<span class="sourceLineNo">206</span>          .setTable(ProtobufUtil.toTableSchema(htd))<a name="line.206"></a>
+<span class="sourceLineNo">207</span>          .setRegion(ProtobufUtil.toRegionInfo(regionInfo));<a name="line.207"></a>
+<span class="sourceLineNo">208</span><a name="line.208"></a>
+<span class="sourceLineNo">209</span>      for (String location : locations) {<a name="line.209"></a>
+<span class="sourceLineNo">210</span>        builder.addLocations(location);<a name="line.210"></a>
+<span class="sourceLineNo">211</span>      }<a name="line.211"></a>
 <span class="sourceLineNo">212</span><a name="line.212"></a>
-<span class="sourceLineNo">213</span>      Bytes.writeByteArray(out, Bytes.toBytes(scan));<a name="line.213"></a>
-<span class="sourceLineNo">214</span>      Bytes.writeByteArray(out, Bytes.toBytes(restoreDir));<a name="line.214"></a>
-<span class="sourceLineNo">215</span><a name="line.215"></a>
-<span class="sourceLineNo">216</span>    }<a name="line.216"></a>
-<span class="sourceLineNo">217</span><a name="line.217"></a>
-<span class="sourceLineNo">218</span>    @Override<a name="line.218"></a>
-<span class="sourceLineNo">219</span>    public void readFields(DataInput in) throws IOException {<a name="line.219"></a>
-<span class="sourceLineNo">220</span>      int len = in.readInt();<a name="line.220"></a>
-<span class="sourceLineNo">221</span>      byte[] buf = new byte[len];<a name="line.221"></a>
-<span class="sourceLineNo">222</span>      in.readFully(buf);<a name="line.222"></a>
-<span class="sourceLineNo">223</span>      TableSnapshotRegionSplit split = TableSnapshotRegionSplit.parser().parseFrom(buf);<a name="line.223"></a>
-<span class="sourceLineNo">224</span>      this.htd = ProtobufUtil.toTableDescriptor(split.getTable());<a name="line.224"></a>
-<span class="sourceLineNo">225</span>      this.regionInfo = ProtobufUtil.toRegionInfo(split.getRegion());<a name="line.225"></a>
-<span class="sourceLineNo">226</span>      List&lt;String&gt; locationsList = split.getLocationsList();<a name="line.226"></a>
-<span class="sourceLineNo">227</span>      this.locations = locationsList.toArray(new String[locationsList.size()]);<a name="line.227"></a>
-<span class="sourceLineNo">228</span><a name="line.228"></a>
-<span class="sourceLineNo">229</span>      this.scan = Bytes.toString(Bytes.readByteArray(in));<a name="line.229"></a>
-<span class="sourceLineNo">230</span>      this.restoreDir = Bytes.toString(Bytes.readByteArray(in));<a name="line.230"></a>
-<span class="sourceLineNo">231</span>    }<a name="line.231"></a>
-<span class="sourceLineNo">232</span>  }<a name="line.232"></a>
-<span class="sourceLineNo">233</span><a name="line.233"></a>
-<span class="sourceLineNo">234</span>  /**<a name="line.234"></a>
-<span class="sourceLineNo">235</span>   * Implementation class for RecordReader logic common between mapred and mapreduce.<a name="line.235"></a>
-<span class="sourceLineNo">236</span>   */<a name="line.236"></a>
-<span class="sourceLineNo">237</span>  public static class RecordReader {<a name="line.237"></a>
-<span class="sourceLineNo">238</span>    private InputSplit split;<a name="line.238"></a>
-<span class="sourceLineNo">239</span>    private Scan scan;<a name="line.239"></a>
-<span class="sourceLineNo">240</span>    private Result result = null;<a name="line.240"></a>
-<span class="sourceLineNo">241</span>    private ImmutableBytesWritable row = null;<a name="line.241"></a>
-<span class="sourceLineNo">242</span>    private ClientSideRegionScanner scanner;<a name="line.242"></a>
-<span class="sourceLineNo">243</span>    private int numOfCompleteRows = 0;<a name="line.243"></a>
-<span class="sourceLineNo">244</span>    private int rowLimitPerSplit;<a name="line.244"></a>
-<span class="sourceLineNo">245</span><a name="line.245"></a>
-<span class="sourceLineNo">246</span>    public ClientSideRegionScanner getScanner() {<a name="line.246"></a>
-<span class="sourceLineNo">247</span>      return scanner;<a name="line.247"></a>
-<span class="sourceLineNo">248</span>    }<a name="line.248"></a>
-<span class="sourceLineNo">249</span><a name="line.249"></a>
-<span class="sourceLineNo">250</span>    public void initialize(InputSplit split, Configuration conf) throws IOException {<a name="line.250"></a>
-<span class="sourceLineNo">251</span>      this.scan = TableMapReduceUtil.convertStringToScan(split.getScan());<a name="line.251"></a>
-<span class="sourceLineNo">252</span>      this.split = split;<a name="line.252"></a>
-<span class="sourceLineNo">253</span>      this.rowLimitPerSplit = conf.getInt(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT, 0);<a name="line.253"></a>
-<span class="sourceLineNo">254</span>      TableDescriptor htd = split.htd;<a name="line.254"></a>
-<span class="sourceLineNo">255</span>      RegionInfo hri = this.split.getRegionInfo();<a name="line.255"></a>
-<span class="sourceLineNo">256</span>      FileSystem fs = CommonFSUtils.getCurrentFileSystem(conf);<a name="line.256"></a>
-<span class="sourceLineNo">257</span><a name="line.257"></a>
+<span class="sourceLineNo">213</span>      TableSnapshotRegionSplit split = builder.build();<a name="line.213"></a>
+<span class="sourceLineNo">214</span><a name="line.214"></a>
+<span class="sourceLineNo">215</span>      ByteArrayOutputStream baos = new ByteArrayOutputStream();<a name="line.215"></a>
+<span class="sourceLineNo">216</span>      split.writeTo(baos);<a name="line.216"></a>
+<span class="sourceLineNo">217</span>      baos.close();<a name="line.217"></a>
+<span class="sourceLineNo">218</span>      byte[] buf = baos.toByteArray();<a name="line.218"></a>
+<span class="sourceLineNo">219</span>      out.writeInt(buf.length);<a name="line.219"></a>
+<span class="sourceLineNo">220</span>      out.write(buf);<a name="line.220"></a>
+<span class="sourceLineNo">221</span><a name="line.221"></a>
+<span class="sourceLineNo">222</span>      Bytes.writeByteArray(out, Bytes.toBytes(scan));<a name="line.222"></a>
+<span class="sourceLineNo">223</span>      Bytes.writeByteArray(out, Bytes.toBytes(restoreDir));<a name="line.223"></a>
+<span class="sourceLineNo">224</span><a name="line.224"></a>
+<span class="sourceLineNo">225</span>    }<a name="line.225"></a>
+<span class="sourceLineNo">226</span><a name="line.226"></a>
+<span class="sourceLineNo">227</span>    @Override<a name="line.227"></a>
+<span class="sourceLineNo">228</span>    public void readFields(DataInput in) throws IOException {<a name="line.228"></a>
+<span class="sourceLineNo">229</span>      int len = in.readInt();<a name="line.229"></a>
+<span class="sourceLineNo">230</span>      byte[] buf = new byte[len];<a name="line.230"></a>
+<span class="sourceLineNo">231</span>      in.readFully(buf);<a name="line.231"></a>
+<span class="sourceLineNo">232</span>      TableSnapshotRegionSplit split = TableSnapshotRegionSplit.parser().parseFrom(buf);<a name="line.232"></a>
+<span class="sourceLineNo">233</span>      this.htd = ProtobufUtil.toTableDescriptor(split.getTable());<a name="line.233"></a>
+<span class="sourceLineNo">234</span>      this.regionInfo = ProtobufUtil.toRegionInfo(split.getRegion());<a name="line.234"></a>
+<span class="sourceLineNo">235</span>      List&lt;String&gt; locationsList = split.getLocationsList();<a name="line.235"></a>
+<span class="sourceLineNo">236</span>      this.locations = locationsList.toArray(new String[locationsList.size()]);<a name="line.236"></a>
+<span class="sourceLineNo">237</span><a name="line.237"></a>
+<span class="sourceLineNo">238</span>      this.scan = Bytes.toString(Bytes.readByteArray(in));<a name="line.238"></a>
+<span class="sourceLineNo">239</span>      this.restoreDir = Bytes.toString(Bytes.readByteArray(in));<a name="line.239"></a>
+<span class="sourceLineNo">240</span>    }<a name="line.240"></a>
+<span class="sourceLineNo">241</span>  }<a name="line.241"></a>
+<span class="sourceLineNo">242</span><a name="line.242"></a>
+<span class="sourceLineNo">243</span>  /**<a name="line.243"></a>
+<span class="sourceLineNo">244</span>   * Implementation class for RecordReader logic common between mapred and mapreduce.<a name="line.244"></a>
+<span class="sourceLineNo">245</span>   */<a name="line.245"></a>
+<span class="sourceLineNo">246</span>  public static class RecordReader {<a name="line.246"></a>
+<span class="sourceLineNo">247</span>    private InputSplit split;<a name="line.247"></a>
+<span class="sourceLineNo">248</span>    private Scan scan;<a name="line.248"></a>
+<span class="sourceLineNo">249</span>    private Result result = null;<a name="line.249"></a>
+<span class="sourceLineNo">250</span>    private ImmutableBytesWritable row = null;<a name="line.250"></a>
+<span class="sourceLineNo">251</span>    private ClientSideRegionScanner scanner;<a name="line.251"></a>
+<span class="sourceLineNo">252</span>    private int numOfCompleteRows = 0;<a name="line.252"></a>
+<span class="sourceLineNo">253</span>    private int rowLimitPerSplit;<a name="line.253"></a>
+<span class="sourceLineNo">254</span><a name="line.254"></a>
+<span class="sourceLineNo">255</span>    public ClientSideRegionScanner getScanner() {<a name="line.255"></a>
+<span class="sourceLineNo">256</span>      return scanner;<a name="line.256"></a>
+<span class="sourceLineNo">257</span>    }<a name="line.257"></a>
 <span class="sourceLineNo">258</span><a name="line.258"></a>
-<span class="sourceLineNo">259</span>      // region is immutable, this should be fine,<a name="line.259"></a>
-<span class="sourceLineNo">260</span>      // otherwise we have to set the thread read point<a name="line.260"></a>
-<span class="sourceLineNo">261</span>      scan.setIsolationLevel(IsolationLevel.READ_UNCOMMITTED);<a name="line.261"></a>
-<span class="sourceLineNo">262</span>      // disable caching of data blocks<a name="line.262"></a>
-<span class="sourceLineNo">263</span>      scan.setCacheBlocks(false);<a name="line.263"></a>
-<span class="sourceLineNo">264</span><a name="line.264"></a>
-<span class="sourceLineNo">265</span>      scanner =<a name="line.265"></a>
-<span class="sourceLineNo">266</span>          new ClientSideRegionScanner(conf, fs, new Path(split.restoreDir), htd, hri, scan, null);<a name="line.266"></a>
-<span class="sourceLineNo">267</span>    }<a name="line.267"></a>
-<span class="sourceLineNo">268</span><a name="line.268"></a>
-<span class="sourceLineNo">269</span>    public boolean nextKeyValue() throws IOException {<a name="line.269"></a>
-<span class="sourceLineNo">270</span>      result = scanner.next();<a name="line.270"></a>
-<span class="sourceLineNo">271</span>      if (result == null) {<a name="line.271"></a>
-<span class="sourceLineNo">272</span>        //we are done<a name="line.272"></a>
-<span class="sourceLineNo">273</span>        return false;<a name="line.273"></a>
-<span class="sourceLineNo">274</span>      }<a name="line.274"></a>
-<span class="sourceLineNo">275</span><a name="line.275"></a>
-<span class="sourceLineNo">276</span>      if (rowLimitPerSplit &gt; 0 &amp;&amp; ++this.numOfCompleteRows &gt; rowLimitPerSplit) {<a name="line.276"></a>
-<span class="sourceLineNo">277</span>        return false;<a name="line.277"></a>
-<span class="sourceLineNo">278</span>      }<a name="line.278"></a>
-<span class="sourceLineNo">279</span>      if (this.row == null) {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>        this.row = new ImmutableBytesWritable();<a name="line.280"></a>
-<span class="sourceLineNo">281</span>      }<a name="line.281"></a>
-<span class="sourceLineNo">282</span>      this.row.set(result.getRow());<a name="line.282"></a>
-<span class="sourceLineNo">283</span>      return true;<a name="line.283"></a>
-<span class="sourceLineNo">284</span>    }<a name="line.284"></a>
-<span class="sourceLineNo">285</span><a name="line.285"></a>
-<span class="sourceLineNo">286</span>    public ImmutableBytesWritable getCurrentKey() {<a name="line.286"></a>
-<span class="sourceLineNo">287</span>      return row;<a name="line.287"></a>
-<span class="sourceLineNo">288</span>    }<a name="line.288"></a>
-<span class="sourceLineNo">289</span><a name="line.289"></a>
-<span class="sourceLineNo">290</span>    public Result getCurrentValue() {<a name="line.290"></a>
-<span class="sourceLineNo">291</span>      return result;<a name="line.291"></a>
-<span class="sourceLineNo">292</span>    }<a name="line.292"></a>
-<span class="sourceLineNo">293</span><a name="line.293"></a>
-<span class="sourceLineNo">294</span>    public long getPos() {<a name="line.294"></a>
-<span class="sourceLineNo">295</span>      return 0;<a name="line.295"></a>
-<span class="sourceLineNo">296</span>    }<a name="line.296"></a>
-<span class="sourceLineNo">297</span><a name="line.297"></a>
-<span class="sourceLineNo">298</span>    public float getProgress() {<a name="line.298"></a>
-<span class="sourceLineNo">299</span>      return 0; // TODO: use total bytes to estimate<a name="line.299"></a>
-<span class="sourceLineNo">300</span>    }<a name="line.300"></a>
-<span class="sourceLineNo">301</span><a name="line.301"></a>
-<span class="sourceLineNo">302</span>    public void close() {<a name="line.302"></a>
-<span class="sourceLineNo">303</span>      if (this.scanner != null) {<a name="line.303"></a>
-<span class="sourceLineNo">304</span>        this.scanner.close();<a name="line.304"></a>
-<span class="sourceLineNo">305</span>      }<a name="line.305"></a>
-<span class="sourceLineNo">306</span>    }<a name="line.306"></a>
-<span class="sourceLineNo">307</span>  }<a name="line.307"></a>
-<span class="sourceLineNo">308</span><a name="line.308"></a>
-<span class="sourceLineNo">309</span>  public static List&lt;InputSplit&gt; getSplits(Configuration conf) throws IOException {<a name="line.309"></a>
-<span class="sourceLineNo">310</span>    String snapshotName = getSnapshotName(conf);<a name="line.310"></a>
-<span class="sourceLineNo">311</span><a name="line.311"></a>
-<span class="sourceLineNo">312</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.312"></a>
-<span class="sourceLineNo">313</span>    FileSystem fs = rootDir.getFileSystem(conf);<a name="line.313"></a>
-<span class="sourceLineNo">314</span><a name="line.314"></a>
-<span class="sourceLineNo">315</span>    SnapshotManifest manifest = getSnapshotManifest(conf, snapshotName, rootDir, fs);<a name="line.315"></a>
-<span class="sourceLineNo">316</span><a name="line.316"></a>
-<span class="sourceLineNo">317</span>    List&lt;RegionInfo&gt; regionInfos = getRegionInfosFromManifest(manifest);<a name="line.317"></a>
-<span class="sourceLineNo">318</span><a name="line.318"></a>
-<span class="sourceLineNo">319</span>    // TODO: mapred does not support scan as input API. Work around for now.<a name="line.319"></a>
-<span class="sourceLineNo">320</span>    Scan scan = extractScanFromConf(conf);<a name="line.320"></a>
-<span class="sourceLineNo">321</span>    // the temp dir where the snapshot is restored<a name="line.321"></a>
-<span class="sourceLineNo">322</span>    Path restoreDir = new Path(conf.get(RESTORE_DIR_KEY));<a name="line.322"></a>
+<span class="sourceLineNo">259</span>    public void initialize(InputSplit split, Configuration conf) throws IOException {<a name="line.259"></a>
+<span class="sourceLineNo">260</span>      this.scan = TableMapReduceUtil.convertStringToScan(split.getScan());<a name="line.260"></a>
+<span class="sourceLineNo">261</span>      this.split = split;<a name="line.261"></a>
+<span class="sourceLineNo">262</span>      this.rowLimitPerSplit = conf.getInt(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT, 0);<a name="line.262"></a>
+<span class="sourceLineNo">263</span>      TableDescriptor htd = split.htd;<a name="line.263"></a>
+<span class="sourceLineNo">264</span>      RegionInfo hri = this.split.getRegionInfo();<a name="line.264"></a>
+<span class="sourceLineNo">265</span>      FileSystem fs = CommonFSUtils.getCurrentFileSystem(conf);<a name="line.265"></a>
+<span class="sourceLineNo">266</span><a name="line.266"></a>
+<span class="sourceLineNo">267</span><a name="line.267"></a>
+<span class="sourceLineNo">268</span>      // region is immutable, this should be fine,<a name="line.268"></a>
+<span class="sourceLineNo">269</span>      // otherwise we have to set the thread read point<a name="line.269"></a>
+<span class="sourceLineNo">270</span>      scan.setIsolationLevel(IsolationLevel.READ_UNCOMMITTED);<a name="line.270"></a>
+<span class="sourceLineNo">271</span>      // disable caching of data blocks<a name="line.271"></a>
+<span class="sourceLineNo">272</span>      scan.setCacheBlocks(false);<a name="line.272"></a>
+<span class="sourceLineNo">273</span><a name="line.273"></a>
+<span class="sourceLineNo">274</span>      scanner =<a name="line.274"></a>
+<span class="sourceLineNo">275</span>          new ClientSideRegionScanner(conf, fs, new Path(split.restoreDir), htd, hri, scan, null);<a name="line.275"></a>
+<span class="sourceLineNo">276</span>    }<a name="line.276"></a>
+<span class="sourceLineNo">277</span><a name="line.277"></a>
+<span class="sourceLineNo">278</span>    public boolean nextKeyValue() throws IOException {<a name="line.278"></a>
+<span class="sourceLineNo">279</span>      result = scanner.next();<a name="line.279"></a>
+<span class="sourceLineNo">280</span>      if (result == null) {<a name="line.280"></a>
+<span class="sourceLineNo">281</span>        //we are done<a name="line.281"></a>
+<span class="sourceLineNo">282</span>        return false;<a name="line.282"></a>
+<span class="sourceLineNo">283</span>      }<a name="line.283"></a>
+<span class="sourceLineNo">284</span><a name="line.284"></a>
+<span class="sourceLineNo">285</span>      if (rowLimitPerSplit &gt; 0 &amp;&amp; ++this.numOfCompleteRows &gt; rowLimitPerSplit) {<a name="line.285"></a>
+<span class="sourceLineNo">286</span>        return false;<a name="line.286"></a>
+<span class="sourceLineNo">287</span>      }<a name="line.287"></a>
+<span class="sourceLineNo">288</span>      if (this.row == null) {<a name="line.288"></a>
+<span class="sourceLineNo">289</span>        this.row = new ImmutableBytesWritable();<a name="line.289"></a>
+<span class="sourceLineNo">290</span>      }<a name="line.290"></a>
+<span class="sourceLineNo">291</span>      this.row.set(result.getRow());<a name="line.291"></a>
+<span class="sourceLineNo">292</span>      return true;<a name="line.292"></a>
+<span class="sourceLineNo">293</span>    }<a name="line.293"></a>
+<span class="sourceLineNo">294</span><a name="line.294"></a>
+<span class="sourceLineNo">295</span>    public ImmutableBytesWritable getCurrentKey() {<a name="line.295"></a>
+<span class="sourceLineNo">296</span>      return row;<a name="line.296"></a>
+<span class="sourceLineNo">297</span>    }<a name="line.297"></a>
+<span class="sourceLineNo">298</span><a name="line.298"></a>
+<span class="sourceLineNo">299</span>    public Result getCurrentValue() {<a name="line.299"></a>
+<span class="sourceLineNo">300</span>      return result;<a name="line.300"></a>
+<span class="sourceLineNo">301</span>    }<a name="line.301"></a>
+<span class="sourceLineNo">302</span><a name="line.302"></a>
+<span class="sourceLineNo">303</span>    public long getPos() {<a name="line.303"></a>
+<span class="sourceLineNo">304</span>      return 0;<a name="line.304"></a>
+<span class="sourceLineNo">305</span>    }<a name="line.305"></a>
+<span class="sourceLineNo">306</span><a name="line.306"></a>
+<span class="sourceLineNo">307</span>    public float getProgress() {<a name="line.307"></a>
+<span class="sourceLineNo">308</span>      return 0; // TODO: use total bytes to estimate<a name="line.308"></a>
+<span class="sourceLineNo">309</span>    }<a name="line.309"></a>
+<span class="sourceLineNo">310</span><a name="line.310"></a>
+<span class="sourceLineNo">311</span>    public void close() {<a name="line.311"></a>
+<span class="sourceLineNo">312</span>      if (this.scanner != null) {<a name="line.312"></a>
+<span class="sourceLineNo">313</span>        this.scanner.close();<a name="line.313"></a>
+<span class="sourceLineNo">314</span>      }<a name="line.314"></a>
+<span class="sourceLineNo">315</span>    }<a name="line.315"></a>
+<span class="sourceLineNo">316</span>  }<a name="line.316"></a>
+<span class="sourceLineNo">317</span><a name="line.317"></a>
+<span class="sourceLineNo">318</span>  public static List&lt;InputSplit&gt; getSplits(Configuration conf) throws IOException {<a name="line.318"></a>
+<span class="sourceLineNo">319</span>    String snapshotName = getSnapshotName(conf);<a name="line.319"></a>
+<span class="sourceLineNo">320</span><a name="line.320"></a>
+<span class="sourceLineNo">321</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.321"></a>
+<span class="sourceLineNo">322</span>    FileSystem fs = rootDir.getFileSystem(conf);<a name="line.322"></a>
 <span class="sourceLineNo">323</span><a name="line.323"></a>
-<span class="sourceLineNo">324</span>    RegionSplitter.SplitAlgorithm splitAlgo = getSplitAlgo(conf);<a name="line.324"></a>
+<span class="sourceLineNo">324</span>    SnapshotManifest manifest = getSnapshotManifest(conf, snapshotName, rootDir, fs);<a name="line.324"></a>
 <span class="sourceLineNo">325</span><a name="line.325"></a>
-<span class="sourceLineNo">326</span>    int numSplits = conf.getInt(NUM_SPLITS_PER_REGION, 1);<a name="line.326"></a>
+<span class="sourceLineNo">326</span>    List&lt;RegionInfo&gt; regionInfos = getRegionInfosFromManifest(manifest);<a name="line.326"></a>
 <span class="sourceLineNo">327</span><a name="line.327"></a>
-<span class="sourceLineNo">328</span>    return getSplits(scan, manifest, regionInfos, restoreDir, conf, splitAlgo, numSplits);<a name="line.328"></a>
-<span class="sourceLineNo">329</span>  }<a name="line.329"></a>
-<span class="sourceLineNo">330</span><a name="line.330"></a>
-<span class="sourceLineNo">331</span>  public static RegionSplitter.SplitAlgorithm getSplitAlgo(Configuration conf) throws IOException {<a name="line.331"></a>
-<span class="sourceLineNo">332</span>    String splitAlgoClassName = conf.get(SPLIT_ALGO);<a name="line.332"></a>
-<span class="sourceLineNo">333</span>    if (splitAlgoClassName == null) {<a name="line.333"></a>
-<span class="sourceLineNo">334</span>      return null;<a name="line.334"></a>
-<span class="sourceLineNo">335</span>    }<a name="line.335"></a>
-<span class="sourceLineNo">336</span>    try {<a name="line.336"></a>
-<span class="sourceLineNo">337</span>      return Class.forName(splitAlgoClassName).asSubclass(RegionSplitter.SplitAlgorithm.class)<a name="line.337"></a>
-<span class="sourceLineNo">338</span>          .getDeclaredConstructor().newInstance();<a name="line.338"></a>
-<span class="sourceLineNo">339</span>    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException |<a name="line.339"></a>
-<span class="sourceLineNo">340</span>        NoSuchMethodException | InvocationTargetException e) {<a name="line.340"></a>
-<span class="sourceLineNo">341</span>      throw new IOException("SplitAlgo class " + splitAlgoClassName + " is not found", e);<a name="line.341"></a>
-<span class="sourceLineNo">342</span>    }<a name="line.342"></a>
-<span class="sourceLineNo">343</span>  }<a name="line.343"></a>
-<span class="sourceLineNo">344</span><a name="line.344"></a>
-<span class="sourceLineNo">345</span><a name="line.345"></a>
-<span class="sourceLineNo">346</span>  public static List&lt;RegionInfo&gt; getRegionInfosFromManifest(SnapshotManifest manifest) {<a name="line.346"></a>
-<span class="sourceLineNo">347</span>    List&lt;SnapshotRegionManifest&gt; regionManifests = manifest.getRegionManifests();<a name="line.347"></a>
-<span class="sourceLineNo">348</span>    if (regionManifests == null) {<a name="line.348"></a>
-<span class="sourceLineNo">349</span>      throw new IllegalArgumentException("Snapshot seems empty");<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    }<a name="line.350"></a>
-<span class="sourceLineNo">351</span><a name="line.351"></a>
-<span class="sourceLineNo">352</span>    List&lt;RegionInfo&gt; regionInfos = Lists.newArrayListWithCapacity(regionManifests.size());<a name="line.352"></a>
+<span class="sourceLineNo">328</span>    // TODO: mapred does not support scan as input API. Work around for now.<a name="line.328"></a>
+<span class="sourceLineNo">329</span>    Scan scan = extractScanFromConf(conf);<a name="line.329"></a>
+<span class="sourceLineNo">330</span>    // the temp dir where the snapshot is restored<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    Path restoreDir = new Path(conf.get(RESTORE_DIR_KEY));<a name="line.331"></a>
+<span class="sourceLineNo">332</span><a name="line.332"></a>
+<span class="sourceLineNo">333</span>    RegionSplitter.SplitAlgorithm splitAlgo = getSplitAlgo(conf);<a name="line.333"></a>
+<span class="sourceLineNo">334</span><a name="line.334"></a>
+<span class="sourceLineNo">335</span>    int numSplits = conf.getInt(NUM_SPLITS_PER_REGION, 1);<a name="line.335"></a>
+<span class="sourceLineNo">336</span><a name="line.336"></a>
+<span class="sourceLineNo">337</span>    return getSplits(scan, manifest, regionInfos, restoreDir, conf, splitAlgo, numSplits);<a name="line.337"></a>
+<span class="sourceLineNo">338</span>  }<a name="line.338"></a>
+<span class="sourceLineNo">339</span><a name="line.339"></a>
+<span class="sourceLineNo">340</span>  public static RegionSplitter.SplitAlgorithm getSplitAlgo(Configuration conf) throws IOException {<a name="line.340"></a>
+<span class="sourceLineNo">341</span>    String splitAlgoClassName = conf.get(SPLIT_ALGO);<a name="line.341"></a>
+<span class="sourceLineNo">342</span>    if (splitAlgoClassName == null) {<a name="line.342"></a>
+<span class="sourceLineNo">343</span>      return null;<a name="line.343"></a>
+<span class="sourceLineNo">344</span>    }<a name="line.344"></a>
+<span class="sourceLineNo">345</span>    try {<a name="line.345"></a>
+<span class="sourceLineNo">346</span>      return Class.forName(splitAlgoClassName).asSubclass(RegionSplitter.SplitAlgorithm.class)<a name="line.346"></a>
+<span class="sourceLineNo">347</span>          .getDeclaredConstructor().newInstance();<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException |<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        NoSuchMethodException | InvocationTargetException e) {<a name="line.349"></a>
+<span class="sourceLineNo">350</span>      throw new IOException("SplitAlgo class " + splitAlgoClassName + " is not found", e);<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    }<a name="line.351"></a>
+<span class="sourceLineNo">352</span>  }<a name="line.352"></a>
 <span class="sourceLineNo">353</span><a name="line.353"></a>
-<span class="sourceLineNo">354</span>    for (SnapshotRegionManifest regionManifest : regionManifests) {<a name="line.354"></a>
-<span class="sourceLineNo">355</span>      RegionInfo hri = ProtobufUtil.toRegionInfo(regionManifest.getRegionInfo());<a name="line.355"></a>
-<span class="sourceLineNo">356</span>      if (hri.isOffline() &amp;&amp; (hri.isSplit() || hri.isSplitParent())) {<a name="line.356"></a>
-<span class="sourceLineNo">357</span>        continue;<a name="line.357"></a>
-<span class="sourceLineNo">358</span>      }<a name="line.358"></a>
-<span class="sourceLineNo">359</span>      regionInfos.add(hri);<a name="line.359"></a>
-<span class="sourceLineNo">360</span>    }<a name="line.360"></a>
-<span class="sourceLineNo">361</span>    return regionInfos;<a name="line.361"></a>
-<span class="sourceLineNo">362</span>  }<a name="line.362"></a>
-<span class="sourceLineNo">363</span><a name="line.363"></a>
-<span class="sourceLineNo">364</span>  public static SnapshotManifest getSnapshotManifest(Configuration conf, String snapshotName,<a name="line.364"></a>
-<span class="sourceLineNo">365</span>      Path rootDir, FileSystem fs) throws IOException {<a name="line.365"></a>
-<span class="sourceLineNo">366</span>    Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>    SnapshotDescription snapshotDesc = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    return SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);<a name="line.368"></a>
-<span class="sourceLineNo">369</span>  }<a name="line.369"></a>
-<span class="sourceLineNo">370</span><a name="line.370"></a>
-<span class="sourceLineNo">371</span>  public static Scan extractScanFromConf(Configuration conf) throws IOException {<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    Scan scan = null;<a name="line.372"></a>
-<span class="sourceLineNo">373</span>    if (conf.get(TableInputFormat.SCAN) != null) {<a name="line.373"></a>
-<span class="sourceLineNo">374</span>      scan = TableMapReduceUtil.convertStringToScan(conf.get(TableInputFormat.SCAN));<a name="line.374"></a>
-<span class="sourceLineNo">375</span>    } else if (conf.get(org.apache.hadoop.hbase.mapred.TableInputFormat.COLUMN_LIST) != null) {<a name="line.375"></a>
-<span class="sourceLineNo">376</span>      String[] columns =<a name="line.376"></a>
-<span class="sourceLineNo">377</span>        conf.get(org.apache.hadoop.hbase.mapred.TableInputFormat.COLUMN_LIST).split(" ");<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      scan = new Scan();<a name="line.378"></a>
-<span class="sourceLineNo">379</span>      for (String col : columns) {<a name="line.379"></a>
-<span class="sourceLineNo">380</span>        scan.addFamily(Bytes.toBytes(col));<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      }<a name="line.381"></a>
-<span class="sourceLineNo">382</span>    } else {<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      throw new IllegalArgumentException("Unable to create scan");<a name="line.383"></a>
-<span class="sourceLineNo">384</span>    }<a name="line.384"></a>
-<span class="sourceLineNo">385</span>    return scan;<a name="line.385"></a>
-<span class="sourceLineNo">386</span>  }<a name="line.386"></a>
-<span class="sourceLineNo">387</span><a name="line.387"></a>
-<span class="sourceLineNo">388</span>  public static List&lt;InputSplit&gt; getSplits(Scan scan, SnapshotManifest manifest,<a name="line.388"></a>
-<span class="sourceLineNo">389</span>      List&lt;RegionInfo&gt; regionManifests, Path restoreDir, Configuration conf) throws IOException {<a name="line.389"></a>
-<span class="sourceLineNo">390</span>    return getSplits(scan, manifest, regionManifests, restoreDir, conf, null, 1);<a name="line.390"></a>
-<span class="sourceLineNo">391</span>  }<a name="line.391"></a>
-<span class="sourceLineNo">392</span><a name="line.392"></a>
-<span class="sourceLineNo">393</span>  public static List&lt;InputSplit&gt; getSplits(Scan scan, SnapshotManifest manifest,<a name="line.393"></a>
-<span class="sourceLineNo">394</span>      List&lt;RegionInfo&gt; regionManifests, Path restoreDir,<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      Configuration conf, RegionSplitter.SplitAlgorithm sa, int numSplits) throws IOException {<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    // load table descriptor<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    TableDescriptor htd = manifest.getTableDescriptor();<a name="line.397"></a>
-<span class="sourceLineNo">398</span><a name="line.398"></a>
-<span class="sourceLineNo">399</span>    Path tableDir = CommonFSUtils.getTableDir(restoreDir, htd.getTableName());<a name="line.399"></a>
-<span class="sourceLineNo">400</span><a name="line.400"></a>
-<span class="sourceLineNo">401</span>    boolean localityEnabled = conf.getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY,<a name="line.401"></a>
-<span class="sourceLineNo">402</span>                                              SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT);<a name="line.402"></a>
-<span class="sourceLineNo">403</span><a name="line.403"></a>
-<span class="sourceLineNo">404</span>    boolean scanMetricsEnabled = conf.getBoolean(SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED,<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT);<a name="line.405"></a>
-<span class="sourceLineNo">406</span>    scan.setScanMetricsEnabled(scanMetricsEnabled);<a name="line.406"></a>
-<span class="sourceLineNo">407</span><a name="line.407"></a>
-<span class="sourceLineNo">408</span>    boolean useRegionLoc = conf.getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.408"></a>
-<span class="sourceLineNo">409</span>      SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.409"></a>
+<span class="sourceLineNo">354</span><a name="line.354"></a>
+<span class="sourceLineNo">355</span>  public static List&lt;RegionInfo&gt; getRegionInfosFromManifest(SnapshotManifest manifest) {<a name="line.355"></a>
+<span class="sourceLineNo">356</span>    List&lt;SnapshotRegionManifest&gt; regionManifests = manifest.getRegionManifests();<a name="line.356"></a>
+<span class="sourceLineNo">357</span>    if (regionManifests == null) {<a name="line.357"></a>
+<span class="sourceLineNo">358</span>      throw new IllegalArgumentException("Snapshot seems empty");<a name="line.358"></a>
+<span class="sourceLineNo">359</span>    }<a name="line.359"></a>
+<span class="sourceLineNo">360</span><a name="line.360"></a>
+<span class="sourceLineNo">361</span>    List&lt;RegionInfo&gt; regionInfos = Lists.newArrayListWithCapacity(regionManifests.size());<a name="line.361"></a>
+<span class="sourceLineNo">362</span><a name="line.362"></a>
+<span class="sourceLineNo">363</span>    for (SnapshotRegionManifest regionManifest : regionManifests) {<a name="line.363"></a>
+<span class="sourceLineNo">364</span>      RegionInfo hri = ProtobufUtil.toRegionInfo(regionManifest.getRegionInfo());<a name="line.364"></a>
+<span class="sourceLineNo">365</span>      if (hri.isOffline() &amp;&amp; (hri.isSplit() || hri.isSplitParent())) {<a name="line.365"></a>
+<span class="sourceLineNo">366</span>        continue;<a name="line.366"></a>
+<span class="sourceLineNo">367</span>      }<a name="line.367"></a>
+<span class="sourceLineNo">368</span>      regionInfos.add(hri);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>    }<a name="line.369"></a>
+<span class="sourceLineNo">370</span>    return regionInfos;<a name="line.370"></a>
+<span class="sourceLineNo">371</span>  }<a name="line.371"></a>
+<span class="sourceLineNo">372</span><a name="line.372"></a>
+<span class="sourceLineNo">373</span>  public static SnapshotManifest getSnapshotManifest(Configuration conf, String snapshotName,<a name="line.373"></a>
+<span class="sourceLineNo">374</span>      Path rootDir, FileSystem fs) throws IOException {<a name="line.374"></a>
+<span class="sourceLineNo">375</span>    Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);<a name="line.375"></a>
+<span class="sourceLineNo">376</span>    SnapshotDescription snapshotDesc = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    return SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);<a name="line.377"></a>
+<span class="sourceLineNo">378</span>  }<a name="line.378"></a>
+<span class="sourceLineNo">379</span><a name="line.379"></a>
+<span class="sourceLineNo">380</span>  public static Scan extractScanFromConf(Configuration conf) throws IOException {<a name="line.380"></a>
+<span class="sourceLineNo">381</span>    Scan scan = null;<a name="line.381"></a>
+<span class="sourceLineNo">382</span>    if (conf.get(TableInputFormat.SCAN) != null) {<a name="line.382"></a>
+<span class="sourceLineNo">383</span>      scan = TableMapReduceUtil.convertStringToScan(conf.get(TableInputFormat.SCAN));<a name="line.383"></a>
+<span class="sourceLineNo">384</span>    } else if (conf.get(org.apache.hadoop.hbase.mapred.TableInputFormat.COLUMN_LIST) != null) {<a name="line.384"></a>
+<span class="sourceLineNo">385</span>      String[] columns =<a name="line.385"></a>
+<span class="sourceLineNo">386</span>        conf.get(org.apache.hadoop.hbase.mapred.TableInputFormat.COLUMN_LIST).split(" ");<a name="line.386"></a>
+<span class="sourceLineNo">387</span>      scan = new Scan();<a name="line.387"></a>
+<span class="sourceLineNo">388</span>      for (String col : columns) {<a name="line.388"></a>
+<span class="sourceLineNo">389</span>        scan.addFamily(Bytes.toBytes(col));<a name="line.389"></a>
+<span class="sourceLineNo">390</span>      }<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    } else {<a name="line.391"></a>
+<span class="sourceLineNo">392</span>      throw new IllegalArgumentException("Unable to create scan");<a name="line.392"></a>
+<span class="sourceLineNo">393</span>    }<a name="line.393"></a>
+<span class="sourceLineNo">394</span><a name="line.394"></a>
+<span class="sourceLineNo">395</span>    if (scan.getReadType() == ReadType.DEFAULT) {<a name="line.395"></a>
+<span class="sourceLineNo">396</span>      LOG.info("Provided Scan has DEFAULT ReadType,"<a name="line.396"></a>
+<span class="sourceLineNo">397</span>          + " updating STREAM for Snapshot-based InputFormat");<a name="line.397"></a>
+<span class="sourceLineNo">398</span>      // Update the "DEFAULT" ReadType to be "STREAM" to try to improve the default case.<a name="line.398"></a>
+<span class="sourceLineNo">399</span>      scan.setReadType(conf.getEnum(SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE,<a name="line.399"></a>
+<span class="sourceLineNo">400</span>          SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE_DEFAULT));<a name="line.400"></a>
+<span class="sourceLineNo">401</span>    }<a name="line.401"></a>
+<span class="sourceLineNo">402</span><a name="line.402"></a>
+<span class="sourceLineNo">403</span>    return scan;<a name="line.403"></a>
+<span class="sourceLineNo">404</span>  }<a name="line.404"></a>
+<span class="sourceLineNo">405</span><a name="line.405"></a>
+<span class="sourceLineNo">406</span>  public static List&lt;InputSplit&gt; getSplits(Scan scan, SnapshotManifest manifest,<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      List&lt;RegionInfo&gt; regionManifests, Path restoreDir, Configuration conf) throws IOException {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    return getSplits(scan, manifest, regionManifests, restoreDir, conf, null, 1);<a name="line.408"></a>
+<span class="sourceLineNo">409</span>  }<a name="line.409"></a>
 <span class="sourceLineNo">410</span><a name="line.410"></a>
-<span class="sourceLineNo">411</span>    Connection connection = null;<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    RegionLocator regionLocator = null;<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    if (localityEnabled &amp;&amp; useRegionLoc) {<a name="line.413"></a>
-<span class="sourceLineNo">414</span>      Configuration newConf = new Configuration(conf);<a name="line.414"></a>
-<span class="sourceLineNo">415</span>      newConf.setInt("hbase.hconnection.threads.max", 1);<a name="line.415"></a>
-<span class="sourceLineNo">416</span>      try {<a name="line.416"></a>
-<span class="sourceLineNo">417</span>        connection = ConnectionFactory.createConnection(newConf);<a name="line.417"></a>
-<span class="sourceLineNo">418</span>        regionLocator = connection.getRegionLocator(htd.getTableName());<a name="line.418"></a>
-<span class="sourceLineNo">419</span><a name="line.419"></a>
-<span class="sourceLineNo">420</span>        /* Get all locations for the table and cache it */<a name="line.420"></a>
-<span class="sourceLineNo">421</span>        regionLocator.getAllRegionLocations();<a name="line.421"></a>
-<span class="sourceLineNo">422</span>      } finally {<a name="line.422"></a>
-<span class="sourceLineNo">423</span>        if (connection != null) {<a name="line.423"></a>
-<span class="sourceLineNo">424</span>          connection.close();<a name="line.424"></a>
-<span class="sourceLineNo">425</span>        }<a name="line.425"></a>
-<span class="sourceLineNo">426</span>      }<a name="line.426"></a>
-<span class="sourceLineNo">427</span>    }<a name="line.427"></a>
+<span class="sourceLineNo">411</span>  public static List&lt;InputSplit&gt; getSplits(Scan scan, SnapshotManifest manifest,<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      List&lt;RegionInfo&gt; regionManifests, Path restoreDir,<a name="line.412"></a>
+<span class="sourceLineNo">413</span>      Configuration conf, RegionSplitter.SplitAlgorithm sa, int numSplits) throws IOException {<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    // load table descriptor<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    TableDescriptor htd = manifest.getTableDescriptor();<a name="line.415"></a>
+<span class="sourceLineNo">416</span><a name="line.416"></a>
+<span class="sourceLineNo">417</span>    Path tableDir = CommonFSUtils.getTableDir(restoreDir, htd.getTableName());<a name="line.417"></a>
+<span class="sourceLineNo">418</span><a name="line.418"></a>
+<span class="sourceLineNo">419</span>    boolean localityEnabled = conf.getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY,<a name="line.419"></a>
+<span class="sourceLineNo">420</span>                                              SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT);<a name="line.420"></a>
+<span class="sourceLineNo">421</span><a name="line.421"></a>
+<span class="sourceLineNo">422</span>    boolean scanMetricsEnabled = conf.getBoolean(SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED,<a name="line.422"></a>
+<span class="sourceLineNo">423</span>      SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT);<a name="line.423"></a>
+<span class="sourceLineNo">424</span>    scan.setScanMetricsEnabled(scanMetricsEnabled);<a name="line.424"></a>
+<span class="sourceLineNo">425</span><a name="line.425"></a>
+<span class="sourceLineNo">426</span>    boolean useRegionLoc = conf.getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.426"></a>
+<span class="sourceLineNo">427</span>      SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.427"></a>
 <span class="sourceLineNo">428</span><a name="line.428"></a>
-<span class="sourceLineNo">429</span>    List&lt;InputSplit&gt; splits = new ArrayList&lt;&gt;();<a name="line.429"></a>
-<span class="sourceLineNo">430</span>    for (RegionInfo hri : regionManifests) {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      // load region descriptor<a name="line.431"></a>
-<span class="sourceLineNo">432</span>      List&lt;String&gt; hosts = null;<a name="line.432"></a>
-<span class="sourceLineNo">433</span>      if (localityEnabled) {<a name="line.433"></a>
-<span class="sourceLineNo">434</span>        if (regionLocator != null) {<a name="line.434"></a>
-<span class="sourceLineNo">435</span>          /* Get Location from the local cache */<a name="line.435"></a>
-<span class="sourceLineNo">436</span>          HRegionLocation<a name="line.436"></a>
-<span class="sourceLineNo">437</span>            location = regionLocator.getRegionLocation(hri.getStartKey(), false);<a name="line.437"></a>
-<span class="sourceLineNo">438</span><a name="line.438"></a>
-<span class="sourceLineNo">439</span>          hosts = new ArrayList&lt;&gt;(1);<a name="line.439"></a>
-<span class="sourceLineNo">440</span>          hosts.add(location.getHostname());<a name="line.440"></a>
-<span class="sourceLineNo">441</span>        } else {<a name="line.441"></a>
-<span class="sourceLineNo">442</span>          hosts = calculateLocationsForInputSplit(conf, htd, hri, tableDir);<a name="line.442"></a>
+<span class="sourceLineNo">429</span>    Connection connection = null;<a name="line.429"></a>
+<span class="sourceLineNo">430</span>    RegionLocator regionLocator = null;<a name="line.430"></a>
+<span class="sourceLineNo">431</span>    if (localityEnabled &amp;&amp; useRegionLoc) {<a name="line.431"></a>
+<span class="sourceLineNo">432</span>      Configuration newConf = new Configuration(conf);<a name="line.432"></a>
+<span class="sourceLineNo">433</span>      newConf.setInt("hbase.hconnection.threads.max", 1);<a name="line.433"></a>
+<span class="sourceLineNo">434</span>      try {<a name="line.434"></a>
+<span class="sourceLineNo">435</span>        connection = ConnectionFactory.createConnection(newConf);<a name="line.435"></a>
+<span class="sourceLineNo">436</span>        regionLocator = connection.getRegionLocator(htd.getTableName());<a name="line.436"></a>
+<span class="sourceLineNo">437</span><a name="line.437"></a>
+<span class="sourceLineNo">438</span>        /* Get all locations for the table and cache it */<a name="line.438"></a>
+<span class="sourceLineNo">439</span>        regionLocator.getAllRegionLocations();<a name="line.439"></a>
+<span class="sourceLineNo">440</span>      } finally {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>        if (connection != null) {<a name="line.441"></a>
+<span class="sourceLineNo">442</span>          connection.close();<a name="line.442"></a>
 <span class="sourceLineNo">443</span>        }<a name="line.443"></a>
 <span class="sourceLineNo">444</span>      }<a name="line.444"></a>
-<span class="sourceLineNo">445</span><a name="line.445"></a>
-<span class="sourceLineNo">446</span>      if (numSplits &gt; 1) {<a name="line.446"></a>
-<span class="sourceLineNo">447</span>        byte[][] sp = sa.split(hri.getStartKey(), hri.getEndKey(), numSplits, true);<a name="line.447"></a>
-<span class="sourceLineNo">448</span>        for (int i = 0; i &lt; sp.length - 1; i++) {<a name="line.448"></a>
-<span class="sourceLineNo">449</span>          if (PrivateCellUtil.overlappingKeys(scan.getStartRow(), scan.getStopRow(), sp[i],<a name="line.449"></a>
-<span class="sourceLineNo">450</span>                  sp[i + 1])) {<a name="line.450"></a>
-<span class="sourceLineNo">451</span><a name="line.451"></a>
-<span class="sourceLineNo">452</span>            Scan boundedScan = new Scan(scan);<a name="line.452"></a>
-<span class="sourceLineNo">453</span>            if (scan.getStartRow().length == 0) {<a name="line.453"></a>
-<span class="sourceLineNo">454</span>              boundedScan.withStartRow(sp[i]);<a name="line.454"></a>
-<span class="sourceLineNo">455</span>            } else {<a name="line.455"></a>
-<span class="sourceLineNo">456</span>              boundedScan.withStartRow(<a name="line.456"></a>
-<span class="sourceLineNo">457</span>                Bytes.compareTo(scan.getStartRow(), sp[i]) &gt; 0 ? scan.getStartRow() : sp[i]);<a name="line.457"></a>
-<span class="sourceLineNo">458</span>            }<a name="line.458"></a>
-<span class="sourceLineNo">459</span><a name="line.459"></a>
-<span class="sourceLineNo">460</span>            if (scan.getStopRow().length == 0) {<a name="line.460"></a>
-<span class="sourceLineNo">461</span>              boundedScan.withStopRow(sp[i + 1]);<a name="line.461"></a>
-<span class="sourceLineNo">462</span>            } else {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>              boundedScan.withStopRow(<a name="line.463"></a>
-<span class="sourceLineNo">464</span>                Bytes.compareTo(scan.getStopRow(), sp[i + 1]) &lt; 0 ? scan.getStopRow() : sp[i + 1]);<a name="line.464"></a>
-<span class="sourceLineNo">465</span>            }<a name="line.465"></a>
-<span class="sourceLineNo">466</span><a name="line.466"></a>
-<span class="sourceLineNo">467</span>            splits.add(new InputSplit(htd, hri, hosts, boundedScan, restoreDir));<a name="line.467"></a>
-<span class="sourceLineNo">468</span>          }<a name="line.468"></a>
-<span class="sourceLineNo">469</span>        }<a name="line.469"></a>
-<span class="sourceLineNo">470</span>      } else {<a name="line.470"></a>
-<span class="sourceLineNo">471</span>        if (PrivateCellUtil.overlappingKeys(scan.getStartRow(), scan.getStopRow(),<a name="line.471"></a>
-<span class="sourceLineNo">472</span>            hri.getStartKey(), hri.getEndKey())) {<a name="line.472"></a>
-<span class="sourceLineNo">473</span><a name="line.473"></a>
-<span class="sourceLineNo">474</span>          splits.add(new InputSplit(htd, hri, hosts, scan, restoreDir));<a name="line.474"></a>
-<span class="sourceLineNo">475</span>        }<a name="line.475"></a>
-<span class="sourceLineNo">476</span>      }<a name="line.476"></a>
-<span class="sourceLineNo">477</span>    }<a name="line.477"></a>
-<span class="sourceLineNo">478</span><a name="line.478"></a>
-<span class="sourceLineNo">479</span>    return splits;<a name="line.479"></a>
-<span class="sourceLineNo">480</span>  }<a name="line.480"></a>
-<span class="sourceLineNo">481</span><a name="line.481"></a>
-<span class="sourceLineNo">482</span>  /**<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * Compute block locations for snapshot files (which will get the locations for referred hfiles)<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   * only when localityEnabled is true.<a name="line.484"></a>
-<span class="sourceLineNo">485</span>   */<a name="line.485"></a>
-<span class="sourceLineNo">486</span>  private static List&lt;String&gt; calculateLocationsForInputSplit(Configuration conf,<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      TableDescriptor htd, RegionInfo hri, Path tableDir)<a name="line.487"></a>
-<span class="sourceLineNo">488</span>      throws IOException {<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    return getBestLocations(conf, HRegion.computeHDFSBlocksDistribution(conf, htd, hri, tableDir));<a name="line.489"></a>
-<span class="sourceLineNo">490</span>  }<a name="line.490"></a>
+<span class="sourceLineNo">445</span>    }<a name="line.445"></a>
+<span class="sourceLineNo">446</span><a name="line.446"></a>
+<span class="sourceLineNo">447</span>    List&lt;InputSplit&gt; splits = new ArrayList&lt;&gt;();<a name="line.447"></a>
+<span class="sourceLineNo">448</span>    for (RegionInfo hri : regionManifests) {<a name="line.448"></a>
+<span class="sourceLineNo">449</span>      // load region descriptor<a name="line.449"></a>
+<span class="sourceLineNo">450</span>      List&lt;String&gt; hosts = null;<a name="line.450"></a>
+<span class="sourceLineNo">451</span>      if (localityEnabled) {<a name="line.451"></a>
+<span class="sourceLineNo">452</span>        if (regionLocator != null) {<a name="line.452"></a>
+<span class="sourceLineNo">453</span>          /* Get Location from the local cache */<a name="line.453"></a>
+<span class="sourceLineNo">454</span>          HRegionLocation<a name="line.454"></a>
+<span class="sourceLineNo">455</span>            location = regionLocator.getRegionLocation(hri.getStartKey(), false);<a name="line.455"></a>
+<span class="sourceLineNo">456</span><a name="line.456"></a>
+<span class="sourceLineNo">457</span>          hosts = new ArrayList&lt;&gt;(1);<a name="line.457"></a>
+<span class="sourceLineNo">458</span>          hosts.add(location.getHostname());<a name="line.458"></a>
+<span class="sourceLineNo">459</span>        } else {<a name="line.459"></a>
+<span class="sourceLineNo">460</span>          hosts = calculateLocationsForInputSplit(conf, htd, hri, tableDir);<a name="line.460"></a>
+<span class="sourceLineNo">461</span>        }<a name="line.461"></a>
+<span class="sourceLineNo">462</span>      }<a name="line.462"></a>
+<span class="sourceLineNo">463</span><a name="line.463"></a>
+<span class="sourceLineNo">464</span>      if (numSplits &gt; 1) {<a name="line.464"></a>
+<span class="sourceLineNo">465</span>        byte[][] sp = sa.split(hri.getStartKey(), hri.getEndKey(), numSplits, true);<a name="line.465"></a>
+<span class="sourceLineNo">466</span>        for (int i = 0; i &lt; sp.length - 1; i++) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>          if (PrivateCellUtil.overlappingKeys(scan.getStartRow(), scan.getStopRow(), sp[i],<a name="line.467"></a>
+<span class="sourceLineNo">468</span>                  sp[i + 1])) {<a name="line.468"></a>
+<span class="sourceLineNo">469</span><a name="line.469"></a>
+<span class="sourceLineNo">470</span>            Scan boundedScan = new Scan(scan);<a name="line.470"></a>
+<span class="sourceLineNo">471</span>            if (scan.getStartRow().length == 0) {<a name="line.471"></a>
+<span class="sourceLineNo">472</span>              boundedScan.withStartRow(sp[i]);<a name="line.472"></a>
+<span class="sourceLineNo">473</span>            } else {<a name="line.473"></a>
+<span class="sourceLineNo">474</span>              boundedScan.withStartRow(<a name="line.474"></a>
+<span class="sourceLineNo">475</span>                Bytes.compareTo(scan.getStartRow(), sp[i]) &gt; 0 ? scan.getStartRow() : sp[i]);<a name="line.475"></a>
+<span class="sourceLineNo">476</span>            }<a name="line.476"></a>
+<span class="sourceLineNo">477</span><a name="line.477"></a>
+<span class="sourceLineNo">478</span>            if (scan.getStopRow().length == 0) {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>              boundedScan.withStopRow(sp[i + 1]);<a name="line.479"></a>
+<span class="sourceLineNo">480</span>            } else {<a name="line.480"></a>
+<span class="sourceLineNo">481</span>              boundedScan.withStopRow(<a name="line.481"></a>
+<span class="sourceLineNo">482</span>                Bytes.compareTo(scan.getStopRow(), sp[i + 1]) &lt; 0 ? scan.getStopRow() : sp[i + 1]);<a name="line.482"></a>
+<span class="sourceLineNo">483</span>            }<a name="line.483"></a>
+<span class="sourceLineNo">484</span><a name="line.484"></a>
+<span class="sourceLineNo">485</span>            splits.add(new InputSplit(htd, hri, hosts, boundedScan, restoreDir));<a name="line.485"></a>
+<span class="sourceLineNo">486</span>          }<a name="line.486"></a>
+<span class="sourceLineNo">487</span>        }<a name="line.487"></a>
+<span class="sourceLineNo">488</span>      } else {<a name="line.488"></a>
+<span class="sourceLineNo">489</span>        if (PrivateCellUtil.overlappingKeys(scan.getStartRow(), scan.getStopRow(),<a name="line.489"></a>
+<span class="sourceLineNo">490</span>            hri.getStartKey(), hri.getEndKey())) {<a name="line.490"></a>
 <span class="sourceLineNo">491</span><a name="line.491"></a>
-<span class="sourceLineNo">492</span>  /**<a name="line.492"></a>
-<span class="sourceLineNo">493</span>   * This computes the locations to be passed from the InputSplit. MR/Yarn schedulers does not take<a name="line.493"></a>
-<span class="sourceLineNo">494</span>   * weights into account, thus will treat every location passed from the input split as equal. We<a name="line.494"></a>
-<span class="sourceLineNo">495</span>   * do not want to blindly pass all the locations, since we are creating one split per region, and<a name="line.495"></a>
-<span class="sourceLineNo">496</span>   * the region's blocks are all distributed throughout the cluster unless favorite node assignment<a name="line.496"></a>
-<span class="sourceLineNo">497</span>   * is used. On the expected stable case, only one location will contain most of the blocks as<a name="line.497"></a>
-<span class="sourceLineNo">498</span>   * local.<a name="line.498"></a>
-<span class="sourceLineNo">499</span>   * On the other hand, in favored node assignment, 3 nodes will contain highly local blocks. Here<a name="line.499"></a>
-<span class="sourceLineNo">500</span>   * we are doing a simple heuristic, where we will pass all hosts which have at least 80%<a name="line.500"></a>
-<span class="sourceLineNo">501</span>   * (hbase.tablesnapshotinputformat.locality.cutoff.multiplier) as much block locality as the top<a name="line.501"></a>
-<span class="sourceLineNo">502</span>   * host with the best locality.<a name="line.502"></a>
-<span class="sourceLineNo">503</span>   * Return at most numTopsAtMost locations if there are more than that.<a name="line.503"></a>
-<span class="sourceLineNo">504</span>   */<a name="line.504"></a>
-<span class="sourceLineNo">505</span>  private static List&lt;String&gt; getBestLocations(Configuration conf,<a name="line.505"></a>
-<span class="sourceLineNo">506</span>      HDFSBlocksDistribution blockDistribution, int numTopsAtMost) {<a name="line.506"></a>
-<span class="sourceLineNo">507</span>    HostAndWeight[] hostAndWeights = blockDistribution.getTopHostsWithWeights();<a name="line.507"></a>
-<span class="sourceLineNo">508</span><a name="line.508"></a>
-<span class="sourceLineNo">509</span>    if (hostAndWeights.length == 0) { // no matter what numTopsAtMost is<a name="line.509"></a>
-<span class="sourceLineNo">510</span>      return null;<a name="line.510"></a>
-<span class="sourceLineNo">511</span>    }<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span>    if (numTopsAtMost &lt; 1) { // invalid if numTopsAtMost &lt; 1, correct it to be 1<a name="line.513"></a>
-<span class="sourceLineNo">514</span>      numTopsAtMost = 1;<a name="line.514"></a>
-<span class="sourceLineNo">515</span>    }<a name="line.515"></a>
-<span class="sourceLineNo">516</span>    int top = Math.min(numTopsAtMost, hostAndWeights.length);<a name="line.516"></a>
-<span class="sourceLineNo">517</span>    List&lt;String&gt; locations = new ArrayList&lt;&gt;(top);<a name="line.517"></a>
-<span class="sourceLineNo">518</span>    HostAndWeight topHost = hostAndWeights[0];<a name="line.518"></a>
-<span class="sourceLineNo">519</span>    locations.add(topHost.getHost());<a name="line.519"></a>
-<span class="sourceLineNo">520</span><a name="line.520"></a>
-<span class="sourceLineNo">521</span>    if (top == 1) { // only care about the top host<a name="line.521"></a>
-<span class="sourceLineNo">522</span>      return locations;<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    }<a name="line.523"></a>
-<span class="sourceLineNo">524</span><a name="line.524"></a>
-<span class="sourceLineNo">525</span>    // When top &gt;= 2,<a name="line.525"></a>
-<span class="sourceLineNo">526</span>    // do the heuristic: filter all hosts which have at least cutoffMultiplier % of block locality<a name="line.526"></a>
-<span class="sourceLineNo">527</span>    double cutoffMultiplier<a name="line.527"></a>
-<span class="sourceLineNo">528</span>            = conf.getFloat(LOCALITY_CUTOFF_MULTIPLIER, DEFAULT_LOCALITY_CUTOFF_MULTIPLIER);<a name="line.528"></a>
-<span class="sourceLineNo">529</span><a name="line.529"></a>
-<span class="sourceLineNo">530</span>    double filterWeight = topHost.getWeight() * cutoffMultiplier;<a name="line.530"></a>
-<span class="sourceLineNo">531</span><a name="line.531"></a>
-<span class="sourceLineNo">532</span>    for (int i = 1; i &lt;= top - 1; i++) {<a name="line.532"></a>
-<span class="sourceLineNo">533</span>      if (hostAndWeights[i].getWeight() &gt;= filterWeight) {<a name="line.533"></a>
-<span class="sourceLineNo">534</span>        locations.add(hostAndWeights[i].getHost());<a name="line.534"></a>
-<span class="sourceLineNo">535</span>      } else {<a name="line.535"></a>
-<span class="sourceLineNo">536</span>        // As hostAndWeights is in descending order,<a name="line.536"></a>
-<span class="sourceLineNo">537</span>        // we could break the loop as long as we meet a weight which is less than filterWeight.<a name="line.537"></a>
-<span class="sourceLineNo">538</span>        break;<a name="line.538"></a>
-<span class="sourceLineNo">539</span>      }<a name="line.539"></a>
-<span class="sourceLineNo">540</span>    }<a name="line.540"></a>
-<span class="sourceLineNo">541</span><a name="line.541"></a>
-<span class="sourceLineNo">542</span>    return locations;<a name="line.542"></a>
-<span class="sourceLineNo">543</span>  }<a name="line.543"></a>
-<span class="sourceLineNo">544</span><a name="line.544"></a>
-<span class="sourceLineNo">545</span>  public static List&lt;String&gt; getBestLocations(Configuration conf,<a name="line.545"></a>
-<span class="sourceLineNo">546</span>      HDFSBlocksDistribution blockDistribution) {<a name="line.546"></a>
-<span class="sourceLineNo">547</span>    // 3 nodes will contain highly local blocks. So default to 3.<a name="line.547"></a>
-<span class="sourceLineNo">548</span>    return getBestLocations(conf, blockDistribution, 3);<a name="line.548"></a>
-<span class="sourceLineNo">549</span>  }<a name="line.549"></a>
-<span class="sourceLineNo">550</span><a name="line.550"></a>
-<span class="sourceLineNo">551</span>  private static String getSnapshotName(Configuration conf) {<a name="line.551"></a>
-<span class="sourceLineNo">552</span>    String snapshotName = conf.get(SNAPSHOT_NAME_KEY);<a name="line.552"></a>
-<span class="sourceLineNo">553</span>    if (snapshotName == null) {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>      throw new IllegalArgumentException("Snapshot name must be provided");<a name="line.554"></a>
-<span class="sourceLineNo">555</span>    }<a name="line.555"></a>
-<span class="sourceLineNo">556</span>    return snapshotName;<a name="line.556"></a>
-<span class="sourceLineNo">557</span>  }<a name="line.557"></a>
-<span class="sourceLineNo">558</span><a name="line.558"></a>
-<span class="sourceLineNo">559</span>  /**<a name="line.559"></a>
-<span class="sourceLineNo">560</span>   * Configures the job to use TableSnapshotInputFormat to read from a snapshot.<a name="line.560"></a>
-<span class="sourceLineNo">561</span>   * @param conf the job to configuration<a name="line.561"></a>
-<span class="sourceLineNo">562</span>   * @param snapshotName the name of the snapshot to read from<a name="line.562"></a>
-<span class="sourceLineNo">563</span>   * @param restoreDir a temporary directory to restore the snapshot into. Current user should have<a name="line.563"></a>
-<span class="sourceLineNo">564</span>   *          write permissions to this directory, and this should not be a subdirectory of rootdir.<a name="line.564"></a>
-<span class="sourceLineNo">565</span>   *          After the job is finished, restoreDir can be deleted.<a name="line.565"></a>
-<span class="sourceLineNo">566</span>   * @throws IOException if an error occurs<a name="line.566"></a>
-<span class="sourceLineNo">567</span>   */<a name="line.567"></a>
-<span class="sourceLineNo">568</span>  public static void setInput(Configuration conf, String snapshotName, Path restoreDir)<a name="line.568"></a>
-<span class="sourceLineNo">569</span>      throws IOException {<a name="line.569"></a>
-<span class="sourceLineNo">570</span>    setInput(conf, snapshotName, restoreDir, null, 1);<a name="line.570"></a>
-<span class="sourceLineNo">571</span>  }<a name="line.571"></a>
-<span class="sourceLineNo">572</span><a name="line.572"></a>
-<span class="sourceLineNo">573</span>  /**<a name="line.573"></a>
-<span class="sourceLineNo">574</span>   * Configures the job to use TableSnapshotInputFormat to read from a snapshot.<a name="line.574"></a>
-<span class="sourceLineNo">575</span>   * @param conf the job to configure<a name="line.575"></a>
-<span class="sourceLineNo">576</span>   * @param snapshotName the name of the snapshot to read from<a name="line.576"></a>
-<span class="sourceLineNo">577</span>   * @param restoreDir a temporary directory to restore the snapshot into. Current user should have<a name="line.577"></a>
-<span class="sourceLineNo">578</span>   *          write permissions to this directory, and this should not be a subdirectory of rootdir.<a name="line.578"></a>
-<span class="sourceLineNo">579</span>   *          After the job is finished, restoreDir can be deleted.<a name="line.579"></a>
-<span class="sourceLineNo">580</span>   * @param numSplitsPerRegion how many input splits to generate per one region<a name="line.580"></a>
-<span class="sourceLineNo">581</span>   * @param splitAlgo SplitAlgorithm to be used when generating InputSplits<a name="line.581"></a>
-<span class="sourceLineNo">582</span>   * @throws IOException if an error occurs<a name="line.582"></a>
-<span class="sourceLineNo">583</span>   */<a name="line.583"></a>
-<span class="sourceLineNo">584</span>  public static void setInput(Configuration conf, String snapshotName, Path restoreDir,<a name="line.584"></a>
-<span class="sourceLineNo">585</span>                              RegionSplitter.SplitAlgorithm splitAlgo, int numSplitsPerRegion)<a name="line.585"></a>
-<span class="sourceLineNo">586</span>          throws IOException {<a name="line.586"></a>
-<span class="sourceLineNo">587</span>    conf.set(SNAPSHOT_NAME_KEY, snapshotName);<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    if (numSplitsPerRegion &lt; 1) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span>      throw new IllegalArgumentException("numSplits must be &gt;= 1, " +<a name="line.589"></a>
-<span class="sourceLineNo">590</span>              "illegal numSplits : " + numSplitsPerRegion);<a name="line.590"></a>
-<span class="sourceLineNo">591</span>    }<a name="line.591"></a>
-<span class="sourceLineNo">592</span>    if (splitAlgo == null &amp;&amp; numSplitsPerRegion &gt; 1) {<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      throw new IllegalArgumentException("Split algo can't be null when numSplits &gt; 1");<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    }<a name="line.594"></a>
-<span class="sourceLineNo">595</span>    if (splitAlgo != null) {<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      conf.set(SPLIT_ALGO, splitAlgo.getClass().getName());<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    }<a name="line.597"></a>
-<span class="sourceLineNo">598</span>    conf.setInt(NUM_SPLITS_PER_REGION, numSplitsPerRegion);<a name="line.598"></a>
-<span class="sourceLineNo">599</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.599"></a>
-<span class="sourceLineNo">600</span>    FileSystem fs = rootDir.getFileSystem(conf);<a name="line.600"></a>
-<span class="sourceLineNo">601</span><a name="line.601"></a>
-<span class="sourceLineNo">602</span>    restoreDir = new Path(restoreDir, UUID.randomUUID().toString());<a name="line.602"></a>
-<span class="sourceLineNo">603</span><a name="line.603"></a>
-<span class="sourceLineNo">604</span>    RestoreSnapshotHelper.copySnapshotForScanner(conf, fs, rootDir, restoreDir, snapshotName);<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    conf.set(RESTORE_DIR_KEY, restoreDir.toString());<a name="line.605"></a>
-<span class="sourceLineNo">606</span>  }<a name="line.606"></a>
-<span class="sourceLineNo">607</span>}<a name="line.607"></a>
+<span class="sourceLineNo">492</span>          splits.add(new InputSplit(htd, hri, hosts, scan, restoreDir));<a name="line.492"></a>
+<span class="sourceLineNo">493</span>        }<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      }<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    }<a name="line.495"></a>
+<span class="sourceLineNo">496</span><a name="line.496"></a>
+<span class="sourceLineNo">497</span>    return splits;<a name="line.497"></a>
+<span class="sourceLineNo">498</span>  }<a name="line.498"></a>
+<span class="sourceLineNo">499</span><a name="line.499"></a>
+<span class="sourceLineNo">500</span>  /**<a name="line.500"></a>
+<span class="sourceLineNo">501</span>   * Compute block locations for snapshot files (which will get the locations for referred hfiles)<a name="line.501"></a>
+<span class="sourceLineNo">502</span>   * only when localityEnabled is true.<a name="line.502"></a>
+<span class="sourceLineNo">503</span>   */<a name="line.503"></a>
+<span class="sourceLineNo">504</span>  private static List&lt;String&gt; calculateLocationsForInputSplit(Configuration conf,<a name="line.504"></a>
+<span class="sourceLineNo">505</span>      TableDescriptor htd, RegionInfo hri, Path tableDir)<a name="line.505"></a>
+<span class="sourceLineNo">506</span>      throws IOException {<a name="line.506"></a>
+<span class="sourceLineNo">507</span>    return getBestLocations(conf, HRegion.computeHDFSBlocksDistribution(conf, htd, hri, tableDir));<a name="line.507"></a>
+<span class="sourceLineNo">508</span>  }<a name="line.508"></a>
+<span class="sourceLineNo">509</span><a name="line.509"></a>
+<span class="sourceLineNo">510</span>  /**<a name="line.510"></a>
+<span class="sourceLineNo">511</span>   * This computes the locations to be passed from the InputSplit. MR/Yarn schedulers does not take<a name="line.511"></a>
+<span class="sourceLineNo">512</span>   * weights into account, thus will treat every location passed from the input split as equal. We<a name="line.512"></a>
+<span class="sourceLineNo">513</span>   * do not want to blindly pass all the locations, since we are creating one split per region, and<a name="line.513"></a>
+<span class="sourceLineNo">514</span>   * the region's blocks are all distributed throughout the cluster unless favorite node assignment<a name="line.514"></a>
+<span class="sourceLineNo">515</span>   * is used. On the expected stable case, only one location will contain most of the blocks as<a name="line.515"></a>
+<span class="sourceLineNo">516</span>   * local.<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   * On the other hand, in favored node assignment, 3 nodes will contain highly local blocks. Here<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * we are doing a simple heuristic, where we will pass all hosts which have at least 80%<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   * (hbase.tablesnapshotinputformat.locality.cutoff.multiplier) as much block locality as the top<a name="line.519"></a>
+<span class="sourceLineNo">520</span>   * host with the best locality.<a name="line.520"></a>
+<span class="sourceLineNo">521</span>   * Return at most numTopsAtMost locations if there are more than that.<a name="line.521"></a>
+<span class="sourceLineNo">522</span>   */<a name="line.522"></a>
+<span class="sourceLineNo">523</span>  private static List&lt;String&gt; getBestLocations(Configuration conf,<a name="line.523"></a>
+<span class="sourceLineNo">524</span>      HDFSBlocksDistribution blockDistribution, int numTopsAtMost) {<a name="line.524"></a>
+<span class="sourceLineNo">525</span>    HostAndWeight[] hostAndWeights = blockDistribution.getTopHostsWithWeights();<a name="line.525"></a>
+<span class="sourceLineNo">526</span><a name="line.526"></a>
+<span class="sourceLineNo">527</span>    if (hostAndWeights.length == 0) { // no matter what numTopsAtMost is<a name="line.527"></a>
+<span class="sourceLineNo">528</span>      return null;<a name="line.528"></a>
+<span class="sourceLineNo">529</span>    }<a name="line.529"></a>
+<span class="sourceLineNo">530</span><a name="line.530"></a>
+<span class="sourceLineNo">531</span>    if (numTopsAtMost &lt; 1) { // invalid if numTopsAtMost &lt; 1, correct it to be 1<a name="line.531"></a>
+<span class="sourceLineNo">532</span>      numTopsAtMost = 1;<a name="line.532"></a>
+<span class="sourceLineNo">533</span>    }<a name="line.533"></a>
+<span class="sourceLineNo">534</span>    int top = Math.min(numTopsAtMost, hostAndWeights.length);<a name="line.534"></a>
+<span class="sourceLineNo">535</span>    List&lt;String&gt; locations = new ArrayList&lt;&gt;(top);<a name="line.535"></a>
+<span class="sourceLineNo">536</span>    HostAndWeight topHost = hostAndWeights[0];<a name="line.536"></a>
+<span class="sourceLineNo">537</span>    locations.add(topHost.getHost());<a name="line.537"></a>
+<span class="sourceLineNo">538</span><a name="line.538"></a>
+<span class="sourceLineNo">539</span>    if (top == 1) { // only care about the top host<a name="line.539"></a>
+<span class="sourceLineNo">540</span>      return locations;<a name="line.540"></a>
+<span class="sourceLineNo">541</span>    }<a name="line.541"></a>
+<span class="sourceLineNo">542</span><a name="line.542"></a>
+<span class="sourceLineNo">543</span>    // When top &gt;= 2,<a name="line.543"></a>
+<span class="sourceLineNo">544</span>    // do the heuristic: filter all hosts which have at least cutoffMultiplier % of block locality<a name="line.544"></a>
+<span class="sourceLineNo">545</span>    double cutoffMultiplier<a name="line.545"></a>
+<span class="sourceLineNo">546</span>            = conf.getFloat(LOCALITY_CUTOFF_MULTIPLIER, DEFAULT_LOCALITY_CUTOFF_MULTIPLIER);<a name="line.546"></a>
+<span class="sourceLineNo">547</span><a name="line.547"></a>
+<span class="sourceLineNo">548</span>    double filterWeight = topHost.getWeight() * cutoffMultiplier;<a name="line.548"></a>
+<span class="sourceLineNo">549</span><a name="line.549"></a>
+<span class="sourceLineNo">550</span>    for (int i = 1; i &lt;= top - 1; i++) {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>      if (hostAndWeights[i].getWeight() &gt;= filterWeight) {<a name="line.551"></a>
+<span class="sourceLineNo">552</span>        locations.add(hostAndWeights[i].getHost());<a name="line.552"></a>
+<span class="sourceLineNo">553</span>      } else {<a name="line.553"></a>
+<span class="sourceLineNo">554</span>        // As hostAndWeights is in descending order,<a name="line.554"></a>
+<span class="sourceLineNo">555</span>        // we could break the loop as long as we meet a weight which is less than filterWeight.<a name="line.555"></a>
+<span class="sourceLineNo">556</span>        break;<a name="line.556"></a>
+<span class="sourceLineNo">557</span>      }<a name="line.557"></a>
+<span class="sourceLineNo">558</span>    }<a name="line.558"></a>
+<span class="sourceLineNo">559</span><a name="line.559"></a>
+<span class="sourceLineNo">560</span>    return locations;<a name="line.560"></a>
+<span class="sourceLineNo">561</span>  }<a name="line.561"></a>
+<span class="sourceLineNo">562</span><a name="line.562"></a>
+<span class="sourceLineNo">563</span>  public static List&lt;String&gt; getBestLocations(Configuration conf,<a name="line.563"></a>
+<span class="sourceLineNo">564</span>      HDFSBlocksDistribution blockDistribution) {<a name="line.564"></a>
+<span class="sourceLineNo">565</span>    // 3 nodes will contain highly local blocks. So default to 3.<a name="line.565"></a>
+<span class="sourceLineNo">566</span>    return getBestLocations(conf, blockDistribution, 3);<a name="line.566"></a>
+<span class="sourceLineNo">567</span>  }<a name="line.567"></a>
+<span class="sourceLineNo">568</span><a name="line.568"></a>
+<span class="sourceLineNo">569</span>  private static String getSnapshotName(Configuration conf) {<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    String snapshotName = conf.get(SNAPSHOT_NAME_KEY);<a name="line.570"></a>
+<span class="sourceLineNo">571</span>    if (snapshotName == null) {<a name="line.571"></a>
+<span class="sourceLineNo">572</span>      throw new IllegalArgumentException("Snapshot name must be provided");<a name="line.572"></a>
+<span class="sourceLineNo">573</span>    }<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    return snapshotName;<a name="line.574"></a>
+<span class="sourceLineNo">575</span>  }<a name="line.575"></a>
+<span class="sourceLineNo">576</span><a name="line.576"></a>
+<span class="sourceLineNo">577</span>  /**<a name="line.577"></a>
+<span class="sourceLineNo">578</span>   * Configures the job to use TableSnapshotInputFormat to read from a snapshot.<a name="line.578"></a>
+<span class="sourceLineNo">579</span>   * @param conf the job to configuration<a name="line.579"></a>
+<span class="sourceLineNo">580</span>   * @param snapshotName the name of the snapshot to read from<a name="line.580"></a>
+<span class="sourceLineNo">581</span>   * @param restoreDir a temporary directory to restore the snapshot into. Current user should have<a name="line.581"></a>
+<span class="sourceLineNo">582</span>   *          write permissions to this directory, and this should not be a subdirectory of rootdir.<a name="line.582"></a>
+<span class="sourceLineNo">583</span>   *          After the job is finished, restoreDir can be deleted.<a name="line.583"></a>
+<span class="sourceLineNo">584</span>   * @throws IOException if an error occurs<a name="line.584"></a>
+<span class="sourceLineNo">585</span>   */<a name="line.585"></a>
+<span class="sourceLineNo">586</span>  public static void setInput(Configuration conf, String snapshotName, Path restoreDir)<a name="line.586"></a>
+<span class="sourceLineNo">587</span>      throws IOException {<a name="line.587"></a>
+<span class="sourceLineNo">588</span>    setInput(conf, snapshotName, restoreDir, null, 1);<a name="line.588"></a>
+<span class="sourceLineNo">589</span>  }<a name="line.589"></a>
+<span class="sourceLineNo">590</span><a name="line.590"></a>
+<span class="sourceLineNo">591</span>  /**<a name="line.591"></a>
+<span class="sourceLineNo">592</span>   * Configures the job to use TableSnapshotInputFormat to read from a snapshot.<a name="line.592"></a>
+<span class="sourceLineNo">593</span>   * @param conf the job to configure<a name="line.593"></a>
+<span class="sourceLineNo">594</span>   * @param snapshotName the name of the snapshot to read from<a name="line.594"></a>
+<span class="sourceLineNo">595</span>   * @param restoreDir a temporary directory to restore the snapshot into. Current user should have<a name="line.595"></a>
+<span class="sourceLineNo">596</span>   *          write permissions to this directory, and this should not be a subdirectory of rootdir.<a name="line.596"></a>
+<span class="sourceLineNo">597</span>   *          After the job is finished, restoreDir can be deleted.<a name="line.597"></a>
+<span class="sourceLineNo">598</span>   * @param numSplitsPerRegion how many input splits to generate per one region<a name="line.598"></a>
+<span class="sourceLineNo">599</span>   * @param splitAlgo SplitAlgorithm to be used when generating InputSplits<a name="line.599"></a>
+<span class="sourceLineNo">600</span>   * @throws IOException if an error occurs<a name="line.600"></a>
+<span class="sourceLineNo">601</span>   */<a name="line.601"></a>
+<span class="sourceLineNo">602</span>  public static void setInput(Configuration conf, String snapshotName, Path restoreDir,<a name="line.602"></a>
+<span class="sourceLineNo">603</span>                              RegionSplitter.SplitAlgorithm splitAlgo, int numSplitsPerRegion)<a name="line.603"></a>
+<span class="sourceLineNo">604</span>          throws IOException {<a name="line.604"></a>
+<span class="sourceLineNo">605</span>    conf.set(SNAPSHOT_NAME_KEY, snapshotName);<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    if (numSplitsPerRegion &lt; 1) {<a name="line.606"></a>
+<span class="sourceLineNo">607</span>      throw new IllegalArgumentException("numSplits must be &gt;= 1, " +<a name="line.607"></a>
+<span class="sourceLineNo">608</span>              "illegal numSplits : " + numSplitsPerRegion);<a name="line.608"></a>
+<span class="sourceLineNo">609</span>    }<a name="line.609"></a>
+<span class="sourceLineNo">610</span>    if (splitAlgo == null &amp;&amp; numSplitsPerRegion &gt; 1) {<a name="line.610"></a>
+<span class="sourceLineNo">611</span>      throw new IllegalArgumentException("Split algo can't be null when numSplits &gt; 1");<a name="line.611"></a>
+<span class="sourceLineNo">612</span>    }<a name="line.612"></a>
+<span class="sourceLineNo">613</span>    if (splitAlgo != null) {<a name="line.613"></a>
+<span class="sourceLineNo">614</span>      conf.set(SPLIT_ALGO, splitAlgo.getClass().getName());<a name="line.614"></a>
+<span class="sourceLineNo">615</span>    }<a name="line.615"></a>
+<span class="sourceLineNo">616</span>    conf.setInt(NUM_SPLITS_PER_REGION, numSplitsPerRegion);<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.617"></a>
+<span class="sourceLineNo">618</span>    FileSystem fs = rootDir.getFileSystem(conf);<a name="line.618"></a>
+<span class="sourceLineNo">619</span><a name="line.619"></a>
+<span class="sourceLineNo">620</span>    restoreDir = new Path(restoreDir, UUID.randomUUID().toString());<a name="line.620"></a>
+<span class="sourceLineNo">621</span><a name="line.621"></a>
+<span class="sourceLineNo">622</span>    RestoreSnapshotHelper.copySnapshotForScanner(conf, fs, rootDir, restoreDir, snapshotName);<a name="line.622"></a>
+<span class="sourceLineNo">623</span>    conf.set(RESTORE_DIR_KEY, restoreDir.toString());<a name="line.623"></a>
+<span class="sourceLineNo">624</span>  }<a name="line.624"></a>
+<span class="sourceLineNo">625</span>}<a name="line.625"></a>
 
 
 
diff --git a/devapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html b/devapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html
index b614563..2f3d5ca 100644
--- a/devapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html
+++ b/devapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatImpl.html
@@ -49,570 +49,588 @@
 <span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.client.RegionLocator;<a name="line.41"></a>
 <span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.client.Result;<a name="line.42"></a>
 <span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.client.Scan;<a name="line.43"></a>
-<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.client.TableDescriptor;<a name="line.44"></a>
-<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<a name="line.45"></a>
-<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.regionserver.HRegion;<a name="line.46"></a>
-<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.snapshot.RestoreSnapshotHelper;<a name="line.47"></a>
-<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;<a name="line.48"></a>
-<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.snapshot.SnapshotManifest;<a name="line.49"></a>
-<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.50"></a>
-<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.51"></a>
-<span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.util.RegionSplitter;<a name="line.52"></a>
-<span class="sourceLineNo">053</span>import org.apache.hadoop.io.Writable;<a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.54"></a>
-<span class="sourceLineNo">055</span>import org.slf4j.Logger;<a name="line.55"></a>
-<span class="sourceLineNo">056</span>import org.slf4j.LoggerFactory;<a name="line.56"></a>
-<span class="sourceLineNo">057</span><a name="line.57"></a>
-<span class="sourceLineNo">058</span>import org.apache.hbase.thirdparty.com.google.common.collect.Lists;<a name="line.58"></a>
-<span class="sourceLineNo">059</span><a name="line.59"></a>
-<span class="sourceLineNo">060</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.60"></a>
-<span class="sourceLineNo">061</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MapReduceProtos.TableSnapshotRegionSplit;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription;<a name="line.62"></a>
-<span class="sourceLineNo">063</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;<a name="line.63"></a>
-<span class="sourceLineNo">064</span><a name="line.64"></a>
-<span class="sourceLineNo">065</span>/**<a name="line.65"></a>
-<span class="sourceLineNo">066</span> * Hadoop MR API-agnostic implementation for mapreduce over table snapshots.<a name="line.66"></a>
-<span class="sourceLineNo">067</span> */<a name="line.67"></a>
-<span class="sourceLineNo">068</span>@InterfaceAudience.Private<a name="line.68"></a>
-<span class="sourceLineNo">069</span>public class TableSnapshotInputFormatImpl {<a name="line.69"></a>
-<span class="sourceLineNo">070</span>  // TODO: Snapshots files are owned in fs by the hbase user. There is no<a name="line.70"></a>
-<span class="sourceLineNo">071</span>  // easy way to delegate access.<a name="line.71"></a>
-<span class="sourceLineNo">072</span><a name="line.72"></a>
-<span class="sourceLineNo">073</span>  public static final Logger LOG = LoggerFactory.getLogger(TableSnapshotInputFormatImpl.class);<a name="line.73"></a>
-<span class="sourceLineNo">074</span><a name="line.74"></a>
-<span class="sourceLineNo">075</span>  private static final String SNAPSHOT_NAME_KEY = "hbase.TableSnapshotInputFormat.snapshot.name";<a name="line.75"></a>
-<span class="sourceLineNo">076</span>  // key for specifying the root dir of the restored snapshot<a name="line.76"></a>
-<span class="sourceLineNo">077</span>  protected static final String RESTORE_DIR_KEY = "hbase.TableSnapshotInputFormat.restore.dir";<a name="line.77"></a>
-<span class="sourceLineNo">078</span><a name="line.78"></a>
-<span class="sourceLineNo">079</span>  /** See {@link #getBestLocations(Configuration, HDFSBlocksDistribution, int)} */<a name="line.79"></a>
-<span class="sourceLineNo">080</span>  private static final String LOCALITY_CUTOFF_MULTIPLIER =<a name="line.80"></a>
-<span class="sourceLineNo">081</span>    "hbase.tablesnapshotinputformat.locality.cutoff.multiplier";<a name="line.81"></a>
-<span class="sourceLineNo">082</span>  private static final float DEFAULT_LOCALITY_CUTOFF_MULTIPLIER = 0.8f;<a name="line.82"></a>
-<span class="sourceLineNo">083</span><a name="line.83"></a>
-<span class="sourceLineNo">084</span>  /**<a name="line.84"></a>
-<span class="sourceLineNo">085</span>   * For MapReduce jobs running multiple mappers per region, determines<a name="line.85"></a>
-<span class="sourceLineNo">086</span>   * what split algorithm we should be using to find split points for scanners.<a name="line.86"></a>
-<span class="sourceLineNo">087</span>   */<a name="line.87"></a>
-<span class="sourceLineNo">088</span>  public static final String SPLIT_ALGO = "hbase.mapreduce.split.algorithm";<a name="line.88"></a>
-<span class="sourceLineNo">089</span>  /**<a name="line.89"></a>
-<span class="sourceLineNo">090</span>   * For MapReduce jobs running multiple mappers per region, determines<a name="line.90"></a>
-<span class="sourceLineNo">091</span>   * number of splits to generate per region.<a name="line.91"></a>
-<span class="sourceLineNo">092</span>   */<a name="line.92"></a>
-<span class="sourceLineNo">093</span>  public static final String NUM_SPLITS_PER_REGION = "hbase.mapreduce.splits.per.region";<a name="line.93"></a>
-<span class="sourceLineNo">094</span><a name="line.94"></a>
-<span class="sourceLineNo">095</span>  /**<a name="line.95"></a>
-<span class="sourceLineNo">096</span>   * Whether to calculate the block location for splits. Default to true.<a name="line.96"></a>
-<span class="sourceLineNo">097</span>   * If the computing layer runs outside of HBase cluster, the block locality does not master.<a name="line.97"></a>
-<span class="sourceLineNo">098</span>   * Setting this value to false could skip the calculation and save some time.<a name="line.98"></a>
-<span class="sourceLineNo">099</span>   *<a name="line.99"></a>
-<span class="sourceLineNo">100</span>   * Set access modifier to "public" so that these could be accessed by test classes of<a name="line.100"></a>
-<span class="sourceLineNo">101</span>   * both org.apache.hadoop.hbase.mapred<a name="line.101"></a>
-<span class="sourceLineNo">102</span>   * and  org.apache.hadoop.hbase.mapreduce.<a name="line.102"></a>
-<span class="sourceLineNo">103</span>   */<a name="line.103"></a>
-<span class="sourceLineNo">104</span>  public static final String  SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY =<a name="line.104"></a>
-<span class="sourceLineNo">105</span>      "hbase.TableSnapshotInputFormat.locality.enabled";<a name="line.105"></a>
-<span class="sourceLineNo">106</span>  public static final boolean SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT = true;<a name="line.106"></a>
-<span class="sourceLineNo">107</span><a name="line.107"></a>
-<span class="sourceLineNo">108</span>  /**<a name="line.108"></a>
-<span class="sourceLineNo">109</span>   * Whether to calculate the Snapshot region location by region location from meta.<a name="line.109"></a>
-<span class="sourceLineNo">110</span>   * It is much faster than computing block locations for splits.<a name="line.110"></a>
-<span class="sourceLineNo">111</span>   */<a name="line.111"></a>
-<span class="sourceLineNo">112</span>  public static final String  SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION =<a name="line.112"></a>
-<span class="sourceLineNo">113</span>    "hbase.TableSnapshotInputFormat.locality.by.region.location";<a name="line.113"></a>
-<span class="sourceLineNo">114</span><a name="line.114"></a>
-<span class="sourceLineNo">115</span>  public static final boolean SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT = false;<a name="line.115"></a>
-<span class="sourceLineNo">116</span><a name="line.116"></a>
-<span class="sourceLineNo">117</span>  /**<a name="line.117"></a>
-<span class="sourceLineNo">118</span>   * In some scenario, scan limited rows on each InputSplit for sampling data extraction<a name="line.118"></a>
-<span class="sourceLineNo">119</span>   */<a name="line.119"></a>
-<span class="sourceLineNo">120</span>  public static final String SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT =<a name="line.120"></a>
-<span class="sourceLineNo">121</span>      "hbase.TableSnapshotInputFormat.row.limit.per.inputsplit";<a name="line.121"></a>
-<span class="sourceLineNo">122</span><a name="line.122"></a>
-<span class="sourceLineNo">123</span>  /**<a name="line.123"></a>
-<span class="sourceLineNo">124</span>   * Whether to enable scan metrics on Scan, default to true<a name="line.124"></a>
-<span class="sourceLineNo">125</span>   */<a name="line.125"></a>
-<span class="sourceLineNo">126</span>  public static final String  SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED =<a name="line.126"></a>
-<span class="sourceLineNo">127</span>    "hbase.TableSnapshotInputFormat.scan_metrics.enabled";<a name="line.127"></a>
-<span class="sourceLineNo">128</span><a name="line.128"></a>
-<span class="sourceLineNo">129</span>  public static final boolean SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT = true;<a name="line.129"></a>
-<span class="sourceLineNo">130</span><a name="line.130"></a>
-<span class="sourceLineNo">131</span>  /**<a name="line.131"></a>
-<span class="sourceLineNo">132</span>   * Implementation class for InputSplit logic common between mapred and mapreduce.<a name="line.132"></a>
-<span class="sourceLineNo">133</span>   */<a name="line.133"></a>
-<span class="sourceLineNo">134</span>  public static class InputSplit implements Writable {<a name="line.134"></a>
-<span class="sourceLineNo">135</span><a name="line.135"></a>
-<span class="sourceLineNo">136</span>    private TableDescriptor htd;<a name="line.136"></a>
-<span class="sourceLineNo">137</span>    private RegionInfo regionInfo;<a name="line.137"></a>
-<span class="sourceLineNo">138</span>    private String[] locations;<a name="line.138"></a>
-<span class="sourceLineNo">139</span>    private String scan;<a name="line.139"></a>
-<span class="sourceLineNo">140</span>    private String restoreDir;<a name="line.140"></a>
-<span class="sourceLineNo">141</span><a name="line.141"></a>
-<span class="sourceLineNo">142</span>    // constructor for mapreduce framework / Writable<a name="line.142"></a>
-<span class="sourceLineNo">143</span>    public InputSplit() {}<a name="line.143"></a>
+<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.client.Scan.ReadType;<a name="line.44"></a>
+<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.client.TableDescriptor;<a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.regionserver.HRegion;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.snapshot.RestoreSnapshotHelper;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.snapshot.SnapshotDescriptionUtils;<a name="line.49"></a>
+<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.snapshot.SnapshotManifest;<a name="line.50"></a>
+<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.51"></a>
+<span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.52"></a>
+<span class="sourceLineNo">053</span>import org.apache.hadoop.hbase.util.RegionSplitter;<a name="line.53"></a>
+<span class="sourceLineNo">054</span>import org.apache.hadoop.io.Writable;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>import org.slf4j.Logger;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>import org.slf4j.LoggerFactory;<a name="line.57"></a>
+<span class="sourceLineNo">058</span><a name="line.58"></a>
+<span class="sourceLineNo">059</span>import org.apache.hbase.thirdparty.com.google.common.collect.Lists;<a name="line.59"></a>
+<span class="sourceLineNo">060</span><a name="line.60"></a>
+<span class="sourceLineNo">061</span>import org.apache.hadoop.hbase.shaded.protobuf.ProtobufUtil;<a name="line.61"></a>
+<span class="sourceLineNo">062</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.MapReduceProtos.TableSnapshotRegionSplit;<a name="line.62"></a>
+<span class="sourceLineNo">063</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotDescription;<a name="line.63"></a>
+<span class="sourceLineNo">064</span>import org.apache.hadoop.hbase.shaded.protobuf.generated.SnapshotProtos.SnapshotRegionManifest;<a name="line.64"></a>
+<span class="sourceLineNo">065</span><a name="line.65"></a>
+<span class="sourceLineNo">066</span>/**<a name="line.66"></a>
+<span class="sourceLineNo">067</span> * Hadoop MR API-agnostic implementation for mapreduce over table snapshots.<a name="line.67"></a>
+<span class="sourceLineNo">068</span> */<a name="line.68"></a>
+<span class="sourceLineNo">069</span>@InterfaceAudience.Private<a name="line.69"></a>
+<span class="sourceLineNo">070</span>public class TableSnapshotInputFormatImpl {<a name="line.70"></a>
+<span class="sourceLineNo">071</span>  // TODO: Snapshots files are owned in fs by the hbase user. There is no<a name="line.71"></a>
+<span class="sourceLineNo">072</span>  // easy way to delegate access.<a name="line.72"></a>
+<span class="sourceLineNo">073</span><a name="line.73"></a>
+<span class="sourceLineNo">074</span>  public static final Logger LOG = LoggerFactory.getLogger(TableSnapshotInputFormatImpl.class);<a name="line.74"></a>
+<span class="sourceLineNo">075</span><a name="line.75"></a>
+<span class="sourceLineNo">076</span>  private static final String SNAPSHOT_NAME_KEY = "hbase.TableSnapshotInputFormat.snapshot.name";<a name="line.76"></a>
+<span class="sourceLineNo">077</span>  // key for specifying the root dir of the restored snapshot<a name="line.77"></a>
+<span class="sourceLineNo">078</span>  protected static final String RESTORE_DIR_KEY = "hbase.TableSnapshotInputFormat.restore.dir";<a name="line.78"></a>
+<span class="sourceLineNo">079</span><a name="line.79"></a>
+<span class="sourceLineNo">080</span>  /** See {@link #getBestLocations(Configuration, HDFSBlocksDistribution, int)} */<a name="line.80"></a>
+<span class="sourceLineNo">081</span>  private static final String LOCALITY_CUTOFF_MULTIPLIER =<a name="line.81"></a>
+<span class="sourceLineNo">082</span>    "hbase.tablesnapshotinputformat.locality.cutoff.multiplier";<a name="line.82"></a>
+<span class="sourceLineNo">083</span>  private static final float DEFAULT_LOCALITY_CUTOFF_MULTIPLIER = 0.8f;<a name="line.83"></a>
+<span class="sourceLineNo">084</span><a name="line.84"></a>
+<span class="sourceLineNo">085</span>  /**<a name="line.85"></a>
+<span class="sourceLineNo">086</span>   * For MapReduce jobs running multiple mappers per region, determines<a name="line.86"></a>
+<span class="sourceLineNo">087</span>   * what split algorithm we should be using to find split points for scanners.<a name="line.87"></a>
+<span class="sourceLineNo">088</span>   */<a name="line.88"></a>
+<span class="sourceLineNo">089</span>  public static final String SPLIT_ALGO = "hbase.mapreduce.split.algorithm";<a name="line.89"></a>
+<span class="sourceLineNo">090</span>  /**<a name="line.90"></a>
+<span class="sourceLineNo">091</span>   * For MapReduce jobs running multiple mappers per region, determines<a name="line.91"></a>
+<span class="sourceLineNo">092</span>   * number of splits to generate per region.<a name="line.92"></a>
+<span class="sourceLineNo">093</span>   */<a name="line.93"></a>
+<span class="sourceLineNo">094</span>  public static final String NUM_SPLITS_PER_REGION = "hbase.mapreduce.splits.per.region";<a name="line.94"></a>
+<span class="sourceLineNo">095</span><a name="line.95"></a>
+<span class="sourceLineNo">096</span>  /**<a name="line.96"></a>
+<span class="sourceLineNo">097</span>   * Whether to calculate the block location for splits. Default to true.<a name="line.97"></a>
+<span class="sourceLineNo">098</span>   * If the computing layer runs outside of HBase cluster, the block locality does not master.<a name="line.98"></a>
+<span class="sourceLineNo">099</span>   * Setting this value to false could skip the calculation and save some time.<a name="line.99"></a>
+<span class="sourceLineNo">100</span>   *<a name="line.100"></a>
+<span class="sourceLineNo">101</span>   * Set access modifier to "public" so that these could be accessed by test classes of<a name="line.101"></a>
+<span class="sourceLineNo">102</span>   * both org.apache.hadoop.hbase.mapred<a name="line.102"></a>
+<span class="sourceLineNo">103</span>   * and  org.apache.hadoop.hbase.mapreduce.<a name="line.103"></a>
+<span class="sourceLineNo">104</span>   */<a name="line.104"></a>
+<span class="sourceLineNo">105</span>  public static final String  SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY =<a name="line.105"></a>
+<span class="sourceLineNo">106</span>      "hbase.TableSnapshotInputFormat.locality.enabled";<a name="line.106"></a>
+<span class="sourceLineNo">107</span>  public static final boolean SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT = true;<a name="line.107"></a>
+<span class="sourceLineNo">108</span><a name="line.108"></a>
+<span class="sourceLineNo">109</span>  /**<a name="line.109"></a>
+<span class="sourceLineNo">110</span>   * Whether to calculate the Snapshot region location by region location from meta.<a name="line.110"></a>
+<span class="sourceLineNo">111</span>   * It is much faster than computing block locations for splits.<a name="line.111"></a>
+<span class="sourceLineNo">112</span>   */<a name="line.112"></a>
+<span class="sourceLineNo">113</span>  public static final String  SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION =<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    "hbase.TableSnapshotInputFormat.locality.by.region.location";<a name="line.114"></a>
+<span class="sourceLineNo">115</span><a name="line.115"></a>
+<span class="sourceLineNo">116</span>  public static final boolean SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT = false;<a name="line.116"></a>
+<span class="sourceLineNo">117</span><a name="line.117"></a>
+<span class="sourceLineNo">118</span>  /**<a name="line.118"></a>
+<span class="sourceLineNo">119</span>   * In some scenario, scan limited rows on each InputSplit for sampling data extraction<a name="line.119"></a>
+<span class="sourceLineNo">120</span>   */<a name="line.120"></a>
+<span class="sourceLineNo">121</span>  public static final String SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT =<a name="line.121"></a>
+<span class="sourceLineNo">122</span>      "hbase.TableSnapshotInputFormat.row.limit.per.inputsplit";<a name="line.122"></a>
+<span class="sourceLineNo">123</span><a name="line.123"></a>
+<span class="sourceLineNo">124</span>  /**<a name="line.124"></a>
+<span class="sourceLineNo">125</span>   * Whether to enable scan metrics on Scan, default to true<a name="line.125"></a>
+<span class="sourceLineNo">126</span>   */<a name="line.126"></a>
+<span class="sourceLineNo">127</span>  public static final String  SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED =<a name="line.127"></a>
+<span class="sourceLineNo">128</span>    "hbase.TableSnapshotInputFormat.scan_metrics.enabled";<a name="line.128"></a>
+<span class="sourceLineNo">129</span><a name="line.129"></a>
+<span class="sourceLineNo">130</span>  public static final boolean SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT = true;<a name="line.130"></a>
+<span class="sourceLineNo">131</span><a name="line.131"></a>
+<span class="sourceLineNo">132</span>  /**<a name="line.132"></a>
+<span class="sourceLineNo">133</span>   * The {@link ReadType} which should be set on the {@link Scan} to read the HBase Snapshot,<a name="line.133"></a>
+<span class="sourceLineNo">134</span>   * default STREAM.<a name="line.134"></a>
+<span class="sourceLineNo">135</span>   */<a name="line.135"></a>
+<span class="sourceLineNo">136</span>  public static final String SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE =<a name="line.136"></a>
+<span class="sourceLineNo">137</span>      "hbase.TableSnapshotInputFormat.scanner.readtype";<a name="line.137"></a>
+<span class="sourceLineNo">138</span>  public static final ReadType SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE_DEFAULT = ReadType.STREAM;<a name="line.138"></a>
+<span class="sourceLineNo">139</span><a name="line.139"></a>
+<span class="sourceLineNo">140</span>  /**<a name="line.140"></a>
+<span class="sourceLineNo">141</span>   * Implementation class for InputSplit logic common between mapred and mapreduce.<a name="line.141"></a>
+<span class="sourceLineNo">142</span>   */<a name="line.142"></a>
+<span class="sourceLineNo">143</span>  public static class InputSplit implements Writable {<a name="line.143"></a>
 <span class="sourceLineNo">144</span><a name="line.144"></a>
-<span class="sourceLineNo">145</span>    public InputSplit(TableDescriptor htd, RegionInfo regionInfo, List&lt;String&gt; locations,<a name="line.145"></a>
-<span class="sourceLineNo">146</span>        Scan scan, Path restoreDir) {<a name="line.146"></a>
-<span class="sourceLineNo">147</span>      this.htd = htd;<a name="line.147"></a>
-<span class="sourceLineNo">148</span>      this.regionInfo = regionInfo;<a name="line.148"></a>
-<span class="sourceLineNo">149</span>      if (locations == null || locations.isEmpty()) {<a name="line.149"></a>
-<span class="sourceLineNo">150</span>        this.locations = new String[0];<a name="line.150"></a>
-<span class="sourceLineNo">151</span>      } else {<a name="line.151"></a>
-<span class="sourceLineNo">152</span>        this.locations = locations.toArray(new String[locations.size()]);<a name="line.152"></a>
-<span class="sourceLineNo">153</span>      }<a name="line.153"></a>
-<span class="sourceLineNo">154</span>      try {<a name="line.154"></a>
-<span class="sourceLineNo">155</span>        this.scan = scan != null ? TableMapReduceUtil.convertScanToString(scan) : "";<a name="line.155"></a>
-<span class="sourceLineNo">156</span>      } catch (IOException e) {<a name="line.156"></a>
-<span class="sourceLineNo">157</span>        LOG.warn("Failed to convert Scan to String", e);<a name="line.157"></a>
-<span class="sourceLineNo">158</span>      }<a name="line.158"></a>
-<span class="sourceLineNo">159</span><a name="line.159"></a>
-<span class="sourceLineNo">160</span>      this.restoreDir = restoreDir.toString();<a name="line.160"></a>
-<span class="sourceLineNo">161</span>    }<a name="line.161"></a>
-<span class="sourceLineNo">162</span><a name="line.162"></a>
-<span class="sourceLineNo">163</span>    public TableDescriptor getHtd() {<a name="line.163"></a>
-<span class="sourceLineNo">164</span>      return htd;<a name="line.164"></a>
-<span class="sourceLineNo">165</span>    }<a name="line.165"></a>
-<span class="sourceLineNo">166</span><a name="line.166"></a>
-<span class="sourceLineNo">167</span>    public String getScan() {<a name="line.167"></a>
-<span class="sourceLineNo">168</span>      return scan;<a name="line.168"></a>
-<span class="sourceLineNo">169</span>    }<a name="line.169"></a>
-<span class="sourceLineNo">170</span><a name="line.170"></a>
-<span class="sourceLineNo">171</span>    public String getRestoreDir() {<a name="line.171"></a>
-<span class="sourceLineNo">172</span>      return restoreDir;<a name="line.172"></a>
-<span class="sourceLineNo">173</span>    }<a name="line.173"></a>
-<span class="sourceLineNo">174</span><a name="line.174"></a>
-<span class="sourceLineNo">175</span>    public long getLength() {<a name="line.175"></a>
-<span class="sourceLineNo">176</span>      //TODO: We can obtain the file sizes of the snapshot here.<a name="line.176"></a>
-<span class="sourceLineNo">177</span>      return 0;<a name="line.177"></a>
+<span class="sourceLineNo">145</span>    private TableDescriptor htd;<a name="line.145"></a>
+<span class="sourceLineNo">146</span>    private RegionInfo regionInfo;<a name="line.146"></a>
+<span class="sourceLineNo">147</span>    private String[] locations;<a name="line.147"></a>
+<span class="sourceLineNo">148</span>    private String scan;<a name="line.148"></a>
+<span class="sourceLineNo">149</span>    private String restoreDir;<a name="line.149"></a>
+<span class="sourceLineNo">150</span><a name="line.150"></a>
+<span class="sourceLineNo">151</span>    // constructor for mapreduce framework / Writable<a name="line.151"></a>
+<span class="sourceLineNo">152</span>    public InputSplit() {}<a name="line.152"></a>
+<span class="sourceLineNo">153</span><a name="line.153"></a>
+<span class="sourceLineNo">154</span>    public InputSplit(TableDescriptor htd, RegionInfo regionInfo, List&lt;String&gt; locations,<a name="line.154"></a>
+<span class="sourceLineNo">155</span>        Scan scan, Path restoreDir) {<a name="line.155"></a>
+<span class="sourceLineNo">156</span>      this.htd = htd;<a name="line.156"></a>
+<span class="sourceLineNo">157</span>      this.regionInfo = regionInfo;<a name="line.157"></a>
+<span class="sourceLineNo">158</span>      if (locations == null || locations.isEmpty()) {<a name="line.158"></a>
+<span class="sourceLineNo">159</span>        this.locations = new String[0];<a name="line.159"></a>
+<span class="sourceLineNo">160</span>      } else {<a name="line.160"></a>
+<span class="sourceLineNo">161</span>        this.locations = locations.toArray(new String[locations.size()]);<a name="line.161"></a>
+<span class="sourceLineNo">162</span>      }<a name="line.162"></a>
+<span class="sourceLineNo">163</span>      try {<a name="line.163"></a>
+<span class="sourceLineNo">164</span>        this.scan = scan != null ? TableMapReduceUtil.convertScanToString(scan) : "";<a name="line.164"></a>
+<span class="sourceLineNo">165</span>      } catch (IOException e) {<a name="line.165"></a>
+<span class="sourceLineNo">166</span>        LOG.warn("Failed to convert Scan to String", e);<a name="line.166"></a>
+<span class="sourceLineNo">167</span>      }<a name="line.167"></a>
+<span class="sourceLineNo">168</span><a name="line.168"></a>
+<span class="sourceLineNo">169</span>      this.restoreDir = restoreDir.toString();<a name="line.169"></a>
+<span class="sourceLineNo">170</span>    }<a name="line.170"></a>
+<span class="sourceLineNo">171</span><a name="line.171"></a>
+<span class="sourceLineNo">172</span>    public TableDescriptor getHtd() {<a name="line.172"></a>
+<span class="sourceLineNo">173</span>      return htd;<a name="line.173"></a>
+<span class="sourceLineNo">174</span>    }<a name="line.174"></a>
+<span class="sourceLineNo">175</span><a name="line.175"></a>
+<span class="sourceLineNo">176</span>    public String getScan() {<a name="line.176"></a>
+<span class="sourceLineNo">177</span>      return scan;<a name="line.177"></a>
 <span class="sourceLineNo">178</span>    }<a name="line.178"></a>
 <span class="sourceLineNo">179</span><a name="line.179"></a>
-<span class="sourceLineNo">180</span>    public String[] getLocations() {<a name="line.180"></a>
-<span class="sourceLineNo">181</span>      return locations;<a name="line.181"></a>
+<span class="sourceLineNo">180</span>    public String getRestoreDir() {<a name="line.180"></a>
+<span class="sourceLineNo">181</span>      return restoreDir;<a name="line.181"></a>
 <span class="sourceLineNo">182</span>    }<a name="line.182"></a>
 <span class="sourceLineNo">183</span><a name="line.183"></a>
-<span class="sourceLineNo">184</span>    public TableDescriptor getTableDescriptor() {<a name="line.184"></a>
-<span class="sourceLineNo">185</span>      return htd;<a name="line.185"></a>
-<span class="sourceLineNo">186</span>    }<a name="line.186"></a>
-<span class="sourceLineNo">187</span><a name="line.187"></a>
-<span class="sourceLineNo">188</span>    public RegionInfo getRegionInfo() {<a name="line.188"></a>
-<span class="sourceLineNo">189</span>      return regionInfo;<a name="line.189"></a>
-<span class="sourceLineNo">190</span>    }<a name="line.190"></a>
-<span class="sourceLineNo">191</span><a name="line.191"></a>
-<span class="sourceLineNo">192</span>    // TODO: We should have ProtobufSerialization in Hadoop, and directly use PB objects instead of<a name="line.192"></a>
-<span class="sourceLineNo">193</span>    // doing this wrapping with Writables.<a name="line.193"></a>
-<span class="sourceLineNo">194</span>    @Override<a name="line.194"></a>
-<span class="sourceLineNo">195</span>    public void write(DataOutput out) throws IOException {<a name="line.195"></a>
-<span class="sourceLineNo">196</span>      TableSnapshotRegionSplit.Builder builder = TableSnapshotRegionSplit.newBuilder()<a name="line.196"></a>
-<span class="sourceLineNo">197</span>          .setTable(ProtobufUtil.toTableSchema(htd))<a name="line.197"></a>
-<span class="sourceLineNo">198</span>          .setRegion(ProtobufUtil.toRegionInfo(regionInfo));<a name="line.198"></a>
-<span class="sourceLineNo">199</span><a name="line.199"></a>
-<span class="sourceLineNo">200</span>      for (String location : locations) {<a name="line.200"></a>
-<span class="sourceLineNo">201</span>        builder.addLocations(location);<a name="line.201"></a>
-<span class="sourceLineNo">202</span>      }<a name="line.202"></a>
-<span class="sourceLineNo">203</span><a name="line.203"></a>
-<span class="sourceLineNo">204</span>      TableSnapshotRegionSplit split = builder.build();<a name="line.204"></a>
-<span class="sourceLineNo">205</span><a name="line.205"></a>
-<span class="sourceLineNo">206</span>      ByteArrayOutputStream baos = new ByteArrayOutputStream();<a name="line.206"></a>
-<span class="sourceLineNo">207</span>      split.writeTo(baos);<a name="line.207"></a>
-<span class="sourceLineNo">208</span>      baos.close();<a name="line.208"></a>
-<span class="sourceLineNo">209</span>      byte[] buf = baos.toByteArray();<a name="line.209"></a>
-<span class="sourceLineNo">210</span>      out.writeInt(buf.length);<a name="line.210"></a>
-<span class="sourceLineNo">211</span>      out.write(buf);<a name="line.211"></a>
+<span class="sourceLineNo">184</span>    public long getLength() {<a name="line.184"></a>
+<span class="sourceLineNo">185</span>      //TODO: We can obtain the file sizes of the snapshot here.<a name="line.185"></a>
+<span class="sourceLineNo">186</span>      return 0;<a name="line.186"></a>
+<span class="sourceLineNo">187</span>    }<a name="line.187"></a>
+<span class="sourceLineNo">188</span><a name="line.188"></a>
+<span class="sourceLineNo">189</span>    public String[] getLocations() {<a name="line.189"></a>
+<span class="sourceLineNo">190</span>      return locations;<a name="line.190"></a>
+<span class="sourceLineNo">191</span>    }<a name="line.191"></a>
+<span class="sourceLineNo">192</span><a name="line.192"></a>
+<span class="sourceLineNo">193</span>    public TableDescriptor getTableDescriptor() {<a name="line.193"></a>
+<span class="sourceLineNo">194</span>      return htd;<a name="line.194"></a>
+<span class="sourceLineNo">195</span>    }<a name="line.195"></a>
+<span class="sourceLineNo">196</span><a name="line.196"></a>
+<span class="sourceLineNo">197</span>    public RegionInfo getRegionInfo() {<a name="line.197"></a>
+<span class="sourceLineNo">198</span>      return regionInfo;<a name="line.198"></a>
+<span class="sourceLineNo">199</span>    }<a name="line.199"></a>
+<span class="sourceLineNo">200</span><a name="line.200"></a>
+<span class="sourceLineNo">201</span>    // TODO: We should have ProtobufSerialization in Hadoop, and directly use PB objects instead of<a name="line.201"></a>
+<span class="sourceLineNo">202</span>    // doing this wrapping with Writables.<a name="line.202"></a>
+<span class="sourceLineNo">203</span>    @Override<a name="line.203"></a>
+<span class="sourceLineNo">204</span>    public void write(DataOutput out) throws IOException {<a name="line.204"></a>
+<span class="sourceLineNo">205</span>      TableSnapshotRegionSplit.Builder builder = TableSnapshotRegionSplit.newBuilder()<a name="line.205"></a>
+<span class="sourceLineNo">206</span>          .setTable(ProtobufUtil.toTableSchema(htd))<a name="line.206"></a>
+<span class="sourceLineNo">207</span>          .setRegion(ProtobufUtil.toRegionInfo(regionInfo));<a name="line.207"></a>
+<span class="sourceLineNo">208</span><a name="line.208"></a>
+<span class="sourceLineNo">209</span>      for (String location : locations) {<a name="line.209"></a>
+<span class="sourceLineNo">210</span>        builder.addLocations(location);<a name="line.210"></a>
+<span class="sourceLineNo">211</span>      }<a name="line.211"></a>
 <span class="sourceLineNo">212</span><a name="line.212"></a>
-<span class="sourceLineNo">213</span>      Bytes.writeByteArray(out, Bytes.toBytes(scan));<a name="line.213"></a>
-<span class="sourceLineNo">214</span>      Bytes.writeByteArray(out, Bytes.toBytes(restoreDir));<a name="line.214"></a>
-<span class="sourceLineNo">215</span><a name="line.215"></a>
-<span class="sourceLineNo">216</span>    }<a name="line.216"></a>
-<span class="sourceLineNo">217</span><a name="line.217"></a>
-<span class="sourceLineNo">218</span>    @Override<a name="line.218"></a>
-<span class="sourceLineNo">219</span>    public void readFields(DataInput in) throws IOException {<a name="line.219"></a>
-<span class="sourceLineNo">220</span>      int len = in.readInt();<a name="line.220"></a>
-<span class="sourceLineNo">221</span>      byte[] buf = new byte[len];<a name="line.221"></a>
-<span class="sourceLineNo">222</span>      in.readFully(buf);<a name="line.222"></a>
-<span class="sourceLineNo">223</span>      TableSnapshotRegionSplit split = TableSnapshotRegionSplit.parser().parseFrom(buf);<a name="line.223"></a>
-<span class="sourceLineNo">224</span>      this.htd = ProtobufUtil.toTableDescriptor(split.getTable());<a name="line.224"></a>
-<span class="sourceLineNo">225</span>      this.regionInfo = ProtobufUtil.toRegionInfo(split.getRegion());<a name="line.225"></a>
-<span class="sourceLineNo">226</span>      List&lt;String&gt; locationsList = split.getLocationsList();<a name="line.226"></a>
-<span class="sourceLineNo">227</span>      this.locations = locationsList.toArray(new String[locationsList.size()]);<a name="line.227"></a>
-<span class="sourceLineNo">228</span><a name="line.228"></a>
-<span class="sourceLineNo">229</span>      this.scan = Bytes.toString(Bytes.readByteArray(in));<a name="line.229"></a>
-<span class="sourceLineNo">230</span>      this.restoreDir = Bytes.toString(Bytes.readByteArray(in));<a name="line.230"></a>
-<span class="sourceLineNo">231</span>    }<a name="line.231"></a>
-<span class="sourceLineNo">232</span>  }<a name="line.232"></a>
-<span class="sourceLineNo">233</span><a name="line.233"></a>
-<span class="sourceLineNo">234</span>  /**<a name="line.234"></a>
-<span class="sourceLineNo">235</span>   * Implementation class for RecordReader logic common between mapred and mapreduce.<a name="line.235"></a>
-<span class="sourceLineNo">236</span>   */<a name="line.236"></a>
-<span class="sourceLineNo">237</span>  public static class RecordReader {<a name="line.237"></a>
-<span class="sourceLineNo">238</span>    private InputSplit split;<a name="line.238"></a>
-<span class="sourceLineNo">239</span>    private Scan scan;<a name="line.239"></a>
-<span class="sourceLineNo">240</span>    private Result result = null;<a name="line.240"></a>
-<span class="sourceLineNo">241</span>    private ImmutableBytesWritable row = null;<a name="line.241"></a>
-<span class="sourceLineNo">242</span>    private ClientSideRegionScanner scanner;<a name="line.242"></a>
-<span class="sourceLineNo">243</span>    private int numOfCompleteRows = 0;<a name="line.243"></a>
-<span class="sourceLineNo">244</span>    private int rowLimitPerSplit;<a name="line.244"></a>
-<span class="sourceLineNo">245</span><a name="line.245"></a>
-<span class="sourceLineNo">246</span>    public ClientSideRegionScanner getScanner() {<a name="line.246"></a>
-<span class="sourceLineNo">247</span>      return scanner;<a name="line.247"></a>
-<span class="sourceLineNo">248</span>    }<a name="line.248"></a>
-<span class="sourceLineNo">249</span><a name="line.249"></a>
-<span class="sourceLineNo">250</span>    public void initialize(InputSplit split, Configuration conf) throws IOException {<a name="line.250"></a>
-<span class="sourceLineNo">251</span>      this.scan = TableMapReduceUtil.convertStringToScan(split.getScan());<a name="line.251"></a>
-<span class="sourceLineNo">252</span>      this.split = split;<a name="line.252"></a>
-<span class="sourceLineNo">253</span>      this.rowLimitPerSplit = conf.getInt(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT, 0);<a name="line.253"></a>
-<span class="sourceLineNo">254</span>      TableDescriptor htd = split.htd;<a name="line.254"></a>
-<span class="sourceLineNo">255</span>      RegionInfo hri = this.split.getRegionInfo();<a name="line.255"></a>
-<span class="sourceLineNo">256</span>      FileSystem fs = CommonFSUtils.getCurrentFileSystem(conf);<a name="line.256"></a>
-<span class="sourceLineNo">257</span><a name="line.257"></a>
+<span class="sourceLineNo">213</span>      TableSnapshotRegionSplit split = builder.build();<a name="line.213"></a>
+<span class="sourceLineNo">214</span><a name="line.214"></a>
+<span class="sourceLineNo">215</span>      ByteArrayOutputStream baos = new ByteArrayOutputStream();<a name="line.215"></a>
+<span class="sourceLineNo">216</span>      split.writeTo(baos);<a name="line.216"></a>
+<span class="sourceLineNo">217</span>      baos.close();<a name="line.217"></a>
+<span class="sourceLineNo">218</span>      byte[] buf = baos.toByteArray();<a name="line.218"></a>
+<span class="sourceLineNo">219</span>      out.writeInt(buf.length);<a name="line.219"></a>
+<span class="sourceLineNo">220</span>      out.write(buf);<a name="line.220"></a>
+<span class="sourceLineNo">221</span><a name="line.221"></a>
+<span class="sourceLineNo">222</span>      Bytes.writeByteArray(out, Bytes.toBytes(scan));<a name="line.222"></a>
+<span class="sourceLineNo">223</span>      Bytes.writeByteArray(out, Bytes.toBytes(restoreDir));<a name="line.223"></a>
+<span class="sourceLineNo">224</span><a name="line.224"></a>
+<span class="sourceLineNo">225</span>    }<a name="line.225"></a>
+<span class="sourceLineNo">226</span><a name="line.226"></a>
+<span class="sourceLineNo">227</span>    @Override<a name="line.227"></a>
+<span class="sourceLineNo">228</span>    public void readFields(DataInput in) throws IOException {<a name="line.228"></a>
+<span class="sourceLineNo">229</span>      int len = in.readInt();<a name="line.229"></a>
+<span class="sourceLineNo">230</span>      byte[] buf = new byte[len];<a name="line.230"></a>
+<span class="sourceLineNo">231</span>      in.readFully(buf);<a name="line.231"></a>
+<span class="sourceLineNo">232</span>      TableSnapshotRegionSplit split = TableSnapshotRegionSplit.parser().parseFrom(buf);<a name="line.232"></a>
+<span class="sourceLineNo">233</span>      this.htd = ProtobufUtil.toTableDescriptor(split.getTable());<a name="line.233"></a>
+<span class="sourceLineNo">234</span>      this.regionInfo = ProtobufUtil.toRegionInfo(split.getRegion());<a name="line.234"></a>
+<span class="sourceLineNo">235</span>      List&lt;String&gt; locationsList = split.getLocationsList();<a name="line.235"></a>
+<span class="sourceLineNo">236</span>      this.locations = locationsList.toArray(new String[locationsList.size()]);<a name="line.236"></a>
+<span class="sourceLineNo">237</span><a name="line.237"></a>
+<span class="sourceLineNo">238</span>      this.scan = Bytes.toString(Bytes.readByteArray(in));<a name="line.238"></a>
+<span class="sourceLineNo">239</span>      this.restoreDir = Bytes.toString(Bytes.readByteArray(in));<a name="line.239"></a>
+<span class="sourceLineNo">240</span>    }<a name="line.240"></a>
+<span class="sourceLineNo">241</span>  }<a name="line.241"></a>
+<span class="sourceLineNo">242</span><a name="line.242"></a>
+<span class="sourceLineNo">243</span>  /**<a name="line.243"></a>
+<span class="sourceLineNo">244</span>   * Implementation class for RecordReader logic common between mapred and mapreduce.<a name="line.244"></a>
+<span class="sourceLineNo">245</span>   */<a name="line.245"></a>
+<span class="sourceLineNo">246</span>  public static class RecordReader {<a name="line.246"></a>
+<span class="sourceLineNo">247</span>    private InputSplit split;<a name="line.247"></a>
+<span class="sourceLineNo">248</span>    private Scan scan;<a name="line.248"></a>
+<span class="sourceLineNo">249</span>    private Result result = null;<a name="line.249"></a>
+<span class="sourceLineNo">250</span>    private ImmutableBytesWritable row = null;<a name="line.250"></a>
+<span class="sourceLineNo">251</span>    private ClientSideRegionScanner scanner;<a name="line.251"></a>
+<span class="sourceLineNo">252</span>    private int numOfCompleteRows = 0;<a name="line.252"></a>
+<span class="sourceLineNo">253</span>    private int rowLimitPerSplit;<a name="line.253"></a>
+<span class="sourceLineNo">254</span><a name="line.254"></a>
+<span class="sourceLineNo">255</span>    public ClientSideRegionScanner getScanner() {<a name="line.255"></a>
+<span class="sourceLineNo">256</span>      return scanner;<a name="line.256"></a>
+<span class="sourceLineNo">257</span>    }<a name="line.257"></a>
 <span class="sourceLineNo">258</span><a name="line.258"></a>
-<span class="sourceLineNo">259</span>      // region is immutable, this should be fine,<a name="line.259"></a>
-<span class="sourceLineNo">260</span>      // otherwise we have to set the thread read point<a name="line.260"></a>
-<span class="sourceLineNo">261</span>      scan.setIsolationLevel(IsolationLevel.READ_UNCOMMITTED);<a name="line.261"></a>
-<span class="sourceLineNo">262</span>      // disable caching of data blocks<a name="line.262"></a>
-<span class="sourceLineNo">263</span>      scan.setCacheBlocks(false);<a name="line.263"></a>
-<span class="sourceLineNo">264</span><a name="line.264"></a>
-<span class="sourceLineNo">265</span>      scanner =<a name="line.265"></a>
-<span class="sourceLineNo">266</span>          new ClientSideRegionScanner(conf, fs, new Path(split.restoreDir), htd, hri, scan, null);<a name="line.266"></a>
-<span class="sourceLineNo">267</span>    }<a name="line.267"></a>
-<span class="sourceLineNo">268</span><a name="line.268"></a>
-<span class="sourceLineNo">269</span>    public boolean nextKeyValue() throws IOException {<a name="line.269"></a>
-<span class="sourceLineNo">270</span>      result = scanner.next();<a name="line.270"></a>
-<span class="sourceLineNo">271</span>      if (result == null) {<a name="line.271"></a>
-<span class="sourceLineNo">272</span>        //we are done<a name="line.272"></a>
-<span class="sourceLineNo">273</span>        return false;<a name="line.273"></a>
-<span class="sourceLineNo">274</span>      }<a name="line.274"></a>
-<span class="sourceLineNo">275</span><a name="line.275"></a>
-<span class="sourceLineNo">276</span>      if (rowLimitPerSplit &gt; 0 &amp;&amp; ++this.numOfCompleteRows &gt; rowLimitPerSplit) {<a name="line.276"></a>
-<span class="sourceLineNo">277</span>        return false;<a name="line.277"></a>
-<span class="sourceLineNo">278</span>      }<a name="line.278"></a>
-<span class="sourceLineNo">279</span>      if (this.row == null) {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>        this.row = new ImmutableBytesWritable();<a name="line.280"></a>
-<span class="sourceLineNo">281</span>      }<a name="line.281"></a>
-<span class="sourceLineNo">282</span>      this.row.set(result.getRow());<a name="line.282"></a>
-<span class="sourceLineNo">283</span>      return true;<a name="line.283"></a>
-<span class="sourceLineNo">284</span>    }<a name="line.284"></a>
-<span class="sourceLineNo">285</span><a name="line.285"></a>
-<span class="sourceLineNo">286</span>    public ImmutableBytesWritable getCurrentKey() {<a name="line.286"></a>
-<span class="sourceLineNo">287</span>      return row;<a name="line.287"></a>
-<span class="sourceLineNo">288</span>    }<a name="line.288"></a>
-<span class="sourceLineNo">289</span><a name="line.289"></a>
-<span class="sourceLineNo">290</span>    public Result getCurrentValue() {<a name="line.290"></a>
-<span class="sourceLineNo">291</span>      return result;<a name="line.291"></a>
-<span class="sourceLineNo">292</span>    }<a name="line.292"></a>
-<span class="sourceLineNo">293</span><a name="line.293"></a>
-<span class="sourceLineNo">294</span>    public long getPos() {<a name="line.294"></a>
-<span class="sourceLineNo">295</span>      return 0;<a name="line.295"></a>
-<span class="sourceLineNo">296</span>    }<a name="line.296"></a>
-<span class="sourceLineNo">297</span><a name="line.297"></a>
-<span class="sourceLineNo">298</span>    public float getProgress() {<a name="line.298"></a>
-<span class="sourceLineNo">299</span>      return 0; // TODO: use total bytes to estimate<a name="line.299"></a>
-<span class="sourceLineNo">300</span>    }<a name="line.300"></a>
-<span class="sourceLineNo">301</span><a name="line.301"></a>
-<span class="sourceLineNo">302</span>    public void close() {<a name="line.302"></a>
-<span class="sourceLineNo">303</span>      if (this.scanner != null) {<a name="line.303"></a>
-<span class="sourceLineNo">304</span>        this.scanner.close();<a name="line.304"></a>
-<span class="sourceLineNo">305</span>      }<a name="line.305"></a>
-<span class="sourceLineNo">306</span>    }<a name="line.306"></a>
-<span class="sourceLineNo">307</span>  }<a name="line.307"></a>
-<span class="sourceLineNo">308</span><a name="line.308"></a>
-<span class="sourceLineNo">309</span>  public static List&lt;InputSplit&gt; getSplits(Configuration conf) throws IOException {<a name="line.309"></a>
-<span class="sourceLineNo">310</span>    String snapshotName = getSnapshotName(conf);<a name="line.310"></a>
-<span class="sourceLineNo">311</span><a name="line.311"></a>
-<span class="sourceLineNo">312</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.312"></a>
-<span class="sourceLineNo">313</span>    FileSystem fs = rootDir.getFileSystem(conf);<a name="line.313"></a>
-<span class="sourceLineNo">314</span><a name="line.314"></a>
-<span class="sourceLineNo">315</span>    SnapshotManifest manifest = getSnapshotManifest(conf, snapshotName, rootDir, fs);<a name="line.315"></a>
-<span class="sourceLineNo">316</span><a name="line.316"></a>
-<span class="sourceLineNo">317</span>    List&lt;RegionInfo&gt; regionInfos = getRegionInfosFromManifest(manifest);<a name="line.317"></a>
-<span class="sourceLineNo">318</span><a name="line.318"></a>
-<span class="sourceLineNo">319</span>    // TODO: mapred does not support scan as input API. Work around for now.<a name="line.319"></a>
-<span class="sourceLineNo">320</span>    Scan scan = extractScanFromConf(conf);<a name="line.320"></a>
-<span class="sourceLineNo">321</span>    // the temp dir where the snapshot is restored<a name="line.321"></a>
-<span class="sourceLineNo">322</span>    Path restoreDir = new Path(conf.get(RESTORE_DIR_KEY));<a name="line.322"></a>
+<span class="sourceLineNo">259</span>    public void initialize(InputSplit split, Configuration conf) throws IOException {<a name="line.259"></a>
+<span class="sourceLineNo">260</span>      this.scan = TableMapReduceUtil.convertStringToScan(split.getScan());<a name="line.260"></a>
+<span class="sourceLineNo">261</span>      this.split = split;<a name="line.261"></a>
+<span class="sourceLineNo">262</span>      this.rowLimitPerSplit = conf.getInt(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT, 0);<a name="line.262"></a>
+<span class="sourceLineNo">263</span>      TableDescriptor htd = split.htd;<a name="line.263"></a>
+<span class="sourceLineNo">264</span>      RegionInfo hri = this.split.getRegionInfo();<a name="line.264"></a>
+<span class="sourceLineNo">265</span>      FileSystem fs = CommonFSUtils.getCurrentFileSystem(conf);<a name="line.265"></a>
+<span class="sourceLineNo">266</span><a name="line.266"></a>
+<span class="sourceLineNo">267</span><a name="line.267"></a>
+<span class="sourceLineNo">268</span>      // region is immutable, this should be fine,<a name="line.268"></a>
+<span class="sourceLineNo">269</span>      // otherwise we have to set the thread read point<a name="line.269"></a>
+<span class="sourceLineNo">270</span>      scan.setIsolationLevel(IsolationLevel.READ_UNCOMMITTED);<a name="line.270"></a>
+<span class="sourceLineNo">271</span>      // disable caching of data blocks<a name="line.271"></a>
+<span class="sourceLineNo">272</span>      scan.setCacheBlocks(false);<a name="line.272"></a>
+<span class="sourceLineNo">273</span><a name="line.273"></a>
+<span class="sourceLineNo">274</span>      scanner =<a name="line.274"></a>
+<span class="sourceLineNo">275</span>          new ClientSideRegionScanner(conf, fs, new Path(split.restoreDir), htd, hri, scan, null);<a name="line.275"></a>
+<span class="sourceLineNo">276</span>    }<a name="line.276"></a>
+<span class="sourceLineNo">277</span><a name="line.277"></a>
+<span class="sourceLineNo">278</span>    public boolean nextKeyValue() throws IOException {<a name="line.278"></a>
+<span class="sourceLineNo">279</span>      result = scanner.next();<a name="line.279"></a>
+<span class="sourceLineNo">280</span>      if (result == null) {<a name="line.280"></a>
+<span class="sourceLineNo">281</span>        //we are done<a name="line.281"></a>
+<span class="sourceLineNo">282</span>        return false;<a name="line.282"></a>
+<span class="sourceLineNo">283</span>      }<a name="line.283"></a>
+<span class="sourceLineNo">284</span><a name="line.284"></a>
+<span class="sourceLineNo">285</span>      if (rowLimitPerSplit &gt; 0 &amp;&amp; ++this.numOfCompleteRows &gt; rowLimitPerSplit) {<a name="line.285"></a>
+<span class="sourceLineNo">286</span>        return false;<a name="line.286"></a>
+<span class="sourceLineNo">287</span>      }<a name="line.287"></a>
+<span class="sourceLineNo">288</span>      if (this.row == null) {<a name="line.288"></a>
+<span class="sourceLineNo">289</span>        this.row = new ImmutableBytesWritable();<a name="line.289"></a>
+<span class="sourceLineNo">290</span>      }<a name="line.290"></a>
+<span class="sourceLineNo">291</span>      this.row.set(result.getRow());<a name="line.291"></a>
+<span class="sourceLineNo">292</span>      return true;<a name="line.292"></a>
+<span class="sourceLineNo">293</span>    }<a name="line.293"></a>
+<span class="sourceLineNo">294</span><a name="line.294"></a>
+<span class="sourceLineNo">295</span>    public ImmutableBytesWritable getCurrentKey() {<a name="line.295"></a>
+<span class="sourceLineNo">296</span>      return row;<a name="line.296"></a>
+<span class="sourceLineNo">297</span>    }<a name="line.297"></a>
+<span class="sourceLineNo">298</span><a name="line.298"></a>
+<span class="sourceLineNo">299</span>    public Result getCurrentValue() {<a name="line.299"></a>
+<span class="sourceLineNo">300</span>      return result;<a name="line.300"></a>
+<span class="sourceLineNo">301</span>    }<a name="line.301"></a>
+<span class="sourceLineNo">302</span><a name="line.302"></a>
+<span class="sourceLineNo">303</span>    public long getPos() {<a name="line.303"></a>
+<span class="sourceLineNo">304</span>      return 0;<a name="line.304"></a>
+<span class="sourceLineNo">305</span>    }<a name="line.305"></a>
+<span class="sourceLineNo">306</span><a name="line.306"></a>
+<span class="sourceLineNo">307</span>    public float getProgress() {<a name="line.307"></a>
+<span class="sourceLineNo">308</span>      return 0; // TODO: use total bytes to estimate<a name="line.308"></a>
+<span class="sourceLineNo">309</span>    }<a name="line.309"></a>
+<span class="sourceLineNo">310</span><a name="line.310"></a>
+<span class="sourceLineNo">311</span>    public void close() {<a name="line.311"></a>
+<span class="sourceLineNo">312</span>      if (this.scanner != null) {<a name="line.312"></a>
+<span class="sourceLineNo">313</span>        this.scanner.close();<a name="line.313"></a>
+<span class="sourceLineNo">314</span>      }<a name="line.314"></a>
+<span class="sourceLineNo">315</span>    }<a name="line.315"></a>
+<span class="sourceLineNo">316</span>  }<a name="line.316"></a>
+<span class="sourceLineNo">317</span><a name="line.317"></a>
+<span class="sourceLineNo">318</span>  public static List&lt;InputSplit&gt; getSplits(Configuration conf) throws IOException {<a name="line.318"></a>
+<span class="sourceLineNo">319</span>    String snapshotName = getSnapshotName(conf);<a name="line.319"></a>
+<span class="sourceLineNo">320</span><a name="line.320"></a>
+<span class="sourceLineNo">321</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.321"></a>
+<span class="sourceLineNo">322</span>    FileSystem fs = rootDir.getFileSystem(conf);<a name="line.322"></a>
 <span class="sourceLineNo">323</span><a name="line.323"></a>
-<span class="sourceLineNo">324</span>    RegionSplitter.SplitAlgorithm splitAlgo = getSplitAlgo(conf);<a name="line.324"></a>
+<span class="sourceLineNo">324</span>    SnapshotManifest manifest = getSnapshotManifest(conf, snapshotName, rootDir, fs);<a name="line.324"></a>
 <span class="sourceLineNo">325</span><a name="line.325"></a>
-<span class="sourceLineNo">326</span>    int numSplits = conf.getInt(NUM_SPLITS_PER_REGION, 1);<a name="line.326"></a>
+<span class="sourceLineNo">326</span>    List&lt;RegionInfo&gt; regionInfos = getRegionInfosFromManifest(manifest);<a name="line.326"></a>
 <span class="sourceLineNo">327</span><a name="line.327"></a>
-<span class="sourceLineNo">328</span>    return getSplits(scan, manifest, regionInfos, restoreDir, conf, splitAlgo, numSplits);<a name="line.328"></a>
-<span class="sourceLineNo">329</span>  }<a name="line.329"></a>
-<span class="sourceLineNo">330</span><a name="line.330"></a>
-<span class="sourceLineNo">331</span>  public static RegionSplitter.SplitAlgorithm getSplitAlgo(Configuration conf) throws IOException {<a name="line.331"></a>
-<span class="sourceLineNo">332</span>    String splitAlgoClassName = conf.get(SPLIT_ALGO);<a name="line.332"></a>
-<span class="sourceLineNo">333</span>    if (splitAlgoClassName == null) {<a name="line.333"></a>
-<span class="sourceLineNo">334</span>      return null;<a name="line.334"></a>
-<span class="sourceLineNo">335</span>    }<a name="line.335"></a>
-<span class="sourceLineNo">336</span>    try {<a name="line.336"></a>
-<span class="sourceLineNo">337</span>      return Class.forName(splitAlgoClassName).asSubclass(RegionSplitter.SplitAlgorithm.class)<a name="line.337"></a>
-<span class="sourceLineNo">338</span>          .getDeclaredConstructor().newInstance();<a name="line.338"></a>
-<span class="sourceLineNo">339</span>    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException |<a name="line.339"></a>
-<span class="sourceLineNo">340</span>        NoSuchMethodException | InvocationTargetException e) {<a name="line.340"></a>
-<span class="sourceLineNo">341</span>      throw new IOException("SplitAlgo class " + splitAlgoClassName + " is not found", e);<a name="line.341"></a>
-<span class="sourceLineNo">342</span>    }<a name="line.342"></a>
-<span class="sourceLineNo">343</span>  }<a name="line.343"></a>
-<span class="sourceLineNo">344</span><a name="line.344"></a>
-<span class="sourceLineNo">345</span><a name="line.345"></a>
-<span class="sourceLineNo">346</span>  public static List&lt;RegionInfo&gt; getRegionInfosFromManifest(SnapshotManifest manifest) {<a name="line.346"></a>
-<span class="sourceLineNo">347</span>    List&lt;SnapshotRegionManifest&gt; regionManifests = manifest.getRegionManifests();<a name="line.347"></a>
-<span class="sourceLineNo">348</span>    if (regionManifests == null) {<a name="line.348"></a>
-<span class="sourceLineNo">349</span>      throw new IllegalArgumentException("Snapshot seems empty");<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    }<a name="line.350"></a>
-<span class="sourceLineNo">351</span><a name="line.351"></a>
-<span class="sourceLineNo">352</span>    List&lt;RegionInfo&gt; regionInfos = Lists.newArrayListWithCapacity(regionManifests.size());<a name="line.352"></a>
+<span class="sourceLineNo">328</span>    // TODO: mapred does not support scan as input API. Work around for now.<a name="line.328"></a>
+<span class="sourceLineNo">329</span>    Scan scan = extractScanFromConf(conf);<a name="line.329"></a>
+<span class="sourceLineNo">330</span>    // the temp dir where the snapshot is restored<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    Path restoreDir = new Path(conf.get(RESTORE_DIR_KEY));<a name="line.331"></a>
+<span class="sourceLineNo">332</span><a name="line.332"></a>
+<span class="sourceLineNo">333</span>    RegionSplitter.SplitAlgorithm splitAlgo = getSplitAlgo(conf);<a name="line.333"></a>
+<span class="sourceLineNo">334</span><a name="line.334"></a>
+<span class="sourceLineNo">335</span>    int numSplits = conf.getInt(NUM_SPLITS_PER_REGION, 1);<a name="line.335"></a>
+<span class="sourceLineNo">336</span><a name="line.336"></a>
+<span class="sourceLineNo">337</span>    return getSplits(scan, manifest, regionInfos, restoreDir, conf, splitAlgo, numSplits);<a name="line.337"></a>
+<span class="sourceLineNo">338</span>  }<a name="line.338"></a>
+<span class="sourceLineNo">339</span><a name="line.339"></a>
+<span class="sourceLineNo">340</span>  public static RegionSplitter.SplitAlgorithm getSplitAlgo(Configuration conf) throws IOException {<a name="line.340"></a>
+<span class="sourceLineNo">341</span>    String splitAlgoClassName = conf.get(SPLIT_ALGO);<a name="line.341"></a>
+<span class="sourceLineNo">342</span>    if (splitAlgoClassName == null) {<a name="line.342"></a>
+<span class="sourceLineNo">343</span>      return null;<a name="line.343"></a>
+<span class="sourceLineNo">344</span>    }<a name="line.344"></a>
+<span class="sourceLineNo">345</span>    try {<a name="line.345"></a>
+<span class="sourceLineNo">346</span>      return Class.forName(splitAlgoClassName).asSubclass(RegionSplitter.SplitAlgorithm.class)<a name="line.346"></a>
+<span class="sourceLineNo">347</span>          .getDeclaredConstructor().newInstance();<a name="line.347"></a>
+<span class="sourceLineNo">348</span>    } catch (ClassNotFoundException | InstantiationException | IllegalAccessException |<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        NoSuchMethodException | InvocationTargetException e) {<a name="line.349"></a>
+<span class="sourceLineNo">350</span>      throw new IOException("SplitAlgo class " + splitAlgoClassName + " is not found", e);<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    }<a name="line.351"></a>
+<span class="sourceLineNo">352</span>  }<a name="line.352"></a>
 <span class="sourceLineNo">353</span><a name="line.353"></a>
-<span class="sourceLineNo">354</span>    for (SnapshotRegionManifest regionManifest : regionManifests) {<a name="line.354"></a>
-<span class="sourceLineNo">355</span>      RegionInfo hri = ProtobufUtil.toRegionInfo(regionManifest.getRegionInfo());<a name="line.355"></a>
-<span class="sourceLineNo">356</span>      if (hri.isOffline() &amp;&amp; (hri.isSplit() || hri.isSplitParent())) {<a name="line.356"></a>
-<span class="sourceLineNo">357</span>        continue;<a name="line.357"></a>
-<span class="sourceLineNo">358</span>      }<a name="line.358"></a>
-<span class="sourceLineNo">359</span>      regionInfos.add(hri);<a name="line.359"></a>
-<span class="sourceLineNo">360</span>    }<a name="line.360"></a>
-<span class="sourceLineNo">361</span>    return regionInfos;<a name="line.361"></a>
-<span class="sourceLineNo">362</span>  }<a name="line.362"></a>
-<span class="sourceLineNo">363</span><a name="line.363"></a>
-<span class="sourceLineNo">364</span>  public static SnapshotManifest getSnapshotManifest(Configuration conf, String snapshotName,<a name="line.364"></a>
-<span class="sourceLineNo">365</span>      Path rootDir, FileSystem fs) throws IOException {<a name="line.365"></a>
-<span class="sourceLineNo">366</span>    Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>    SnapshotDescription snapshotDesc = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    return SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);<a name="line.368"></a>
-<span class="sourceLineNo">369</span>  }<a name="line.369"></a>
-<span class="sourceLineNo">370</span><a name="line.370"></a>
-<span class="sourceLineNo">371</span>  public static Scan extractScanFromConf(Configuration conf) throws IOException {<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    Scan scan = null;<a name="line.372"></a>
-<span class="sourceLineNo">373</span>    if (conf.get(TableInputFormat.SCAN) != null) {<a name="line.373"></a>
-<span class="sourceLineNo">374</span>      scan = TableMapReduceUtil.convertStringToScan(conf.get(TableInputFormat.SCAN));<a name="line.374"></a>
-<span class="sourceLineNo">375</span>    } else if (conf.get(org.apache.hadoop.hbase.mapred.TableInputFormat.COLUMN_LIST) != null) {<a name="line.375"></a>
-<span class="sourceLineNo">376</span>      String[] columns =<a name="line.376"></a>
-<span class="sourceLineNo">377</span>        conf.get(org.apache.hadoop.hbase.mapred.TableInputFormat.COLUMN_LIST).split(" ");<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      scan = new Scan();<a name="line.378"></a>
-<span class="sourceLineNo">379</span>      for (String col : columns) {<a name="line.379"></a>
-<span class="sourceLineNo">380</span>        scan.addFamily(Bytes.toBytes(col));<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      }<a name="line.381"></a>
-<span class="sourceLineNo">382</span>    } else {<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      throw new IllegalArgumentException("Unable to create scan");<a name="line.383"></a>
-<span class="sourceLineNo">384</span>    }<a name="line.384"></a>
-<span class="sourceLineNo">385</span>    return scan;<a name="line.385"></a>
-<span class="sourceLineNo">386</span>  }<a name="line.386"></a>
-<span class="sourceLineNo">387</span><a name="line.387"></a>
-<span class="sourceLineNo">388</span>  public static List&lt;InputSplit&gt; getSplits(Scan scan, SnapshotManifest manifest,<a name="line.388"></a>
-<span class="sourceLineNo">389</span>      List&lt;RegionInfo&gt; regionManifests, Path restoreDir, Configuration conf) throws IOException {<a name="line.389"></a>
-<span class="sourceLineNo">390</span>    return getSplits(scan, manifest, regionManifests, restoreDir, conf, null, 1);<a name="line.390"></a>
-<span class="sourceLineNo">391</span>  }<a name="line.391"></a>
-<span class="sourceLineNo">392</span><a name="line.392"></a>
-<span class="sourceLineNo">393</span>  public static List&lt;InputSplit&gt; getSplits(Scan scan, SnapshotManifest manifest,<a name="line.393"></a>
-<span class="sourceLineNo">394</span>      List&lt;RegionInfo&gt; regionManifests, Path restoreDir,<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      Configuration conf, RegionSplitter.SplitAlgorithm sa, int numSplits) throws IOException {<a name="line.395"></a>
-<span class="sourceLineNo">396</span>    // load table descriptor<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    TableDescriptor htd = manifest.getTableDescriptor();<a name="line.397"></a>
-<span class="sourceLineNo">398</span><a name="line.398"></a>
-<span class="sourceLineNo">399</span>    Path tableDir = CommonFSUtils.getTableDir(restoreDir, htd.getTableName());<a name="line.399"></a>
-<span class="sourceLineNo">400</span><a name="line.400"></a>
-<span class="sourceLineNo">401</span>    boolean localityEnabled = conf.getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY,<a name="line.401"></a>
-<span class="sourceLineNo">402</span>                                              SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT);<a name="line.402"></a>
-<span class="sourceLineNo">403</span><a name="line.403"></a>
-<span class="sourceLineNo">404</span>    boolean scanMetricsEnabled = conf.getBoolean(SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED,<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT);<a name="line.405"></a>
-<span class="sourceLineNo">406</span>    scan.setScanMetricsEnabled(scanMetricsEnabled);<a name="line.406"></a>
-<span class="sourceLineNo">407</span><a name="line.407"></a>
-<span class="sourceLineNo">408</span>    boolean useRegionLoc = conf.getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.408"></a>
-<span class="sourceLineNo">409</span>      SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.409"></a>
+<span class="sourceLineNo">354</span><a name="line.354"></a>
+<span class="sourceLineNo">355</span>  public static List&lt;RegionInfo&gt; getRegionInfosFromManifest(SnapshotManifest manifest) {<a name="line.355"></a>
+<span class="sourceLineNo">356</span>    List&lt;SnapshotRegionManifest&gt; regionManifests = manifest.getRegionManifests();<a name="line.356"></a>
+<span class="sourceLineNo">357</span>    if (regionManifests == null) {<a name="line.357"></a>
+<span class="sourceLineNo">358</span>      throw new IllegalArgumentException("Snapshot seems empty");<a name="line.358"></a>
+<span class="sourceLineNo">359</span>    }<a name="line.359"></a>
+<span class="sourceLineNo">360</span><a name="line.360"></a>
+<span class="sourceLineNo">361</span>    List&lt;RegionInfo&gt; regionInfos = Lists.newArrayListWithCapacity(regionManifests.size());<a name="line.361"></a>
+<span class="sourceLineNo">362</span><a name="line.362"></a>
+<span class="sourceLineNo">363</span>    for (SnapshotRegionManifest regionManifest : regionManifests) {<a name="line.363"></a>
+<span class="sourceLineNo">364</span>      RegionInfo hri = ProtobufUtil.toRegionInfo(regionManifest.getRegionInfo());<a name="line.364"></a>
+<span class="sourceLineNo">365</span>      if (hri.isOffline() &amp;&amp; (hri.isSplit() || hri.isSplitParent())) {<a name="line.365"></a>
+<span class="sourceLineNo">366</span>        continue;<a name="line.366"></a>
+<span class="sourceLineNo">367</span>      }<a name="line.367"></a>
+<span class="sourceLineNo">368</span>      regionInfos.add(hri);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>    }<a name="line.369"></a>
+<span class="sourceLineNo">370</span>    return regionInfos;<a name="line.370"></a>
+<span class="sourceLineNo">371</span>  }<a name="line.371"></a>
+<span class="sourceLineNo">372</span><a name="line.372"></a>
+<span class="sourceLineNo">373</span>  public static SnapshotManifest getSnapshotManifest(Configuration conf, String snapshotName,<a name="line.373"></a>
+<span class="sourceLineNo">374</span>      Path rootDir, FileSystem fs) throws IOException {<a name="line.374"></a>
+<span class="sourceLineNo">375</span>    Path snapshotDir = SnapshotDescriptionUtils.getCompletedSnapshotDir(snapshotName, rootDir);<a name="line.375"></a>
+<span class="sourceLineNo">376</span>    SnapshotDescription snapshotDesc = SnapshotDescriptionUtils.readSnapshotInfo(fs, snapshotDir);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    return SnapshotManifest.open(conf, fs, snapshotDir, snapshotDesc);<a name="line.377"></a>
+<span class="sourceLineNo">378</span>  }<a name="line.378"></a>
+<span class="sourceLineNo">379</span><a name="line.379"></a>
+<span class="sourceLineNo">380</span>  public static Scan extractScanFromConf(Configuration conf) throws IOException {<a name="line.380"></a>
+<span class="sourceLineNo">381</span>    Scan scan = null;<a name="line.381"></a>
+<span class="sourceLineNo">382</span>    if (conf.get(TableInputFormat.SCAN) != null) {<a name="line.382"></a>
+<span class="sourceLineNo">383</span>      scan = TableMapReduceUtil.convertStringToScan(conf.get(TableInputFormat.SCAN));<a name="line.383"></a>
+<span class="sourceLineNo">384</span>    } else if (conf.get(org.apache.hadoop.hbase.mapred.TableInputFormat.COLUMN_LIST) != null) {<a name="line.384"></a>
+<span class="sourceLineNo">385</span>      String[] columns =<a name="line.385"></a>
+<span class="sourceLineNo">386</span>        conf.get(org.apache.hadoop.hbase.mapred.TableInputFormat.COLUMN_LIST).split(" ");<a name="line.386"></a>
+<span class="sourceLineNo">387</span>      scan = new Scan();<a name="line.387"></a>
+<span class="sourceLineNo">388</span>      for (String col : columns) {<a name="line.388"></a>
+<span class="sourceLineNo">389</span>        scan.addFamily(Bytes.toBytes(col));<a name="line.389"></a>
+<span class="sourceLineNo">390</span>      }<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    } else {<a name="line.391"></a>
+<span class="sourceLineNo">392</span>      throw new IllegalArgumentException("Unable to create scan");<a name="line.392"></a>
+<span class="sourceLineNo">393</span>    }<a name="line.393"></a>
+<span class="sourceLineNo">394</span><a name="line.394"></a>
+<span class="sourceLineNo">395</span>    if (scan.getReadType() == ReadType.DEFAULT) {<a name="line.395"></a>
+<span class="sourceLineNo">396</span>      LOG.info("Provided Scan has DEFAULT ReadType,"<a name="line.396"></a>
+<span class="sourceLineNo">397</span>          + " updating STREAM for Snapshot-based InputFormat");<a name="line.397"></a>
+<span class="sourceLineNo">398</span>      // Update the "DEFAULT" ReadType to be "STREAM" to try to improve the default case.<a name="line.398"></a>
+<span class="sourceLineNo">399</span>      scan.setReadType(conf.getEnum(SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE,<a name="line.399"></a>
+<span class="sourceLineNo">400</span>          SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE_DEFAULT));<a name="line.400"></a>
+<span class="sourceLineNo">401</span>    }<a name="line.401"></a>
+<span class="sourceLineNo">402</span><a name="line.402"></a>
+<span class="sourceLineNo">403</span>    return scan;<a name="line.403"></a>
+<span class="sourceLineNo">404</span>  }<a name="line.404"></a>
+<span class="sourceLineNo">405</span><a name="line.405"></a>
+<span class="sourceLineNo">406</span>  public static List&lt;InputSplit&gt; getSplits(Scan scan, SnapshotManifest manifest,<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      List&lt;RegionInfo&gt; regionManifests, Path restoreDir, Configuration conf) throws IOException {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>    return getSplits(scan, manifest, regionManifests, restoreDir, conf, null, 1);<a name="line.408"></a>
+<span class="sourceLineNo">409</span>  }<a name="line.409"></a>
 <span class="sourceLineNo">410</span><a name="line.410"></a>
-<span class="sourceLineNo">411</span>    Connection connection = null;<a name="line.411"></a>
-<span class="sourceLineNo">412</span>    RegionLocator regionLocator = null;<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    if (localityEnabled &amp;&amp; useRegionLoc) {<a name="line.413"></a>
-<span class="sourceLineNo">414</span>      Configuration newConf = new Configuration(conf);<a name="line.414"></a>
-<span class="sourceLineNo">415</span>      newConf.setInt("hbase.hconnection.threads.max", 1);<a name="line.415"></a>
-<span class="sourceLineNo">416</span>      try {<a name="line.416"></a>
-<span class="sourceLineNo">417</span>        connection = ConnectionFactory.createConnection(newConf);<a name="line.417"></a>
-<span class="sourceLineNo">418</span>        regionLocator = connection.getRegionLocator(htd.getTableName());<a name="line.418"></a>
-<span class="sourceLineNo">419</span><a name="line.419"></a>
-<span class="sourceLineNo">420</span>        /* Get all locations for the table and cache it */<a name="line.420"></a>
-<span class="sourceLineNo">421</span>        regionLocator.getAllRegionLocations();<a name="line.421"></a>
-<span class="sourceLineNo">422</span>      } finally {<a name="line.422"></a>
-<span class="sourceLineNo">423</span>        if (connection != null) {<a name="line.423"></a>
-<span class="sourceLineNo">424</span>          connection.close();<a name="line.424"></a>
-<span class="sourceLineNo">425</span>        }<a name="line.425"></a>
-<span class="sourceLineNo">426</span>      }<a name="line.426"></a>
-<span class="sourceLineNo">427</span>    }<a name="line.427"></a>
+<span class="sourceLineNo">411</span>  public static List&lt;InputSplit&gt; getSplits(Scan scan, SnapshotManifest manifest,<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      List&lt;RegionInfo&gt; regionManifests, Path restoreDir,<a name="line.412"></a>
+<span class="sourceLineNo">413</span>      Configuration conf, RegionSplitter.SplitAlgorithm sa, int numSplits) throws IOException {<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    // load table descriptor<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    TableDescriptor htd = manifest.getTableDescriptor();<a name="line.415"></a>
+<span class="sourceLineNo">416</span><a name="line.416"></a>
+<span class="sourceLineNo">417</span>    Path tableDir = CommonFSUtils.getTableDir(restoreDir, htd.getTableName());<a name="line.417"></a>
+<span class="sourceLineNo">418</span><a name="line.418"></a>
+<span class="sourceLineNo">419</span>    boolean localityEnabled = conf.getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY,<a name="line.419"></a>
+<span class="sourceLineNo">420</span>                                              SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT);<a name="line.420"></a>
+<span class="sourceLineNo">421</span><a name="line.421"></a>
+<span class="sourceLineNo">422</span>    boolean scanMetricsEnabled = conf.getBoolean(SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED,<a name="line.422"></a>
+<span class="sourceLineNo">423</span>      SNAPSHOT_INPUTFORMAT_SCAN_METRICS_ENABLED_DEFAULT);<a name="line.423"></a>
+<span class="sourceLineNo">424</span>    scan.setScanMetricsEnabled(scanMetricsEnabled);<a name="line.424"></a>
+<span class="sourceLineNo">425</span><a name="line.425"></a>
+<span class="sourceLineNo">426</span>    boolean useRegionLoc = conf.getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.426"></a>
+<span class="sourceLineNo">427</span>      SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.427"></a>
 <span class="sourceLineNo">428</span><a name="line.428"></a>
-<span class="sourceLineNo">429</span>    List&lt;InputSplit&gt; splits = new ArrayList&lt;&gt;();<a name="line.429"></a>
-<span class="sourceLineNo">430</span>    for (RegionInfo hri : regionManifests) {<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      // load region descriptor<a name="line.431"></a>
-<span class="sourceLineNo">432</span>      List&lt;String&gt; hosts = null;<a name="line.432"></a>
-<span class="sourceLineNo">433</span>      if (localityEnabled) {<a name="line.433"></a>
-<span class="sourceLineNo">434</span>        if (regionLocator != null) {<a name="line.434"></a>
-<span class="sourceLineNo">435</span>          /* Get Location from the local cache */<a name="line.435"></a>
-<span class="sourceLineNo">436</span>          HRegionLocation<a name="line.436"></a>
-<span class="sourceLineNo">437</span>            location = regionLocator.getRegionLocation(hri.getStartKey(), false);<a name="line.437"></a>
-<span class="sourceLineNo">438</span><a name="line.438"></a>
-<span class="sourceLineNo">439</span>          hosts = new ArrayList&lt;&gt;(1);<a name="line.439"></a>
-<span class="sourceLineNo">440</span>          hosts.add(location.getHostname());<a name="line.440"></a>
-<span class="sourceLineNo">441</span>        } else {<a name="line.441"></a>
-<span class="sourceLineNo">442</span>          hosts = calculateLocationsForInputSplit(conf, htd, hri, tableDir);<a name="line.442"></a>
+<span class="sourceLineNo">429</span>    Connection connection = null;<a name="line.429"></a>
+<span class="sourceLineNo">430</span>    RegionLocator regionLocator = null;<a name="line.430"></a>
+<span class="sourceLineNo">431</span>    if (localityEnabled &amp;&amp; useRegionLoc) {<a name="line.431"></a>
+<span class="sourceLineNo">432</span>      Configuration newConf = new Configuration(conf);<a name="line.432"></a>
+<span class="sourceLineNo">433</span>      newConf.setInt("hbase.hconnection.threads.max", 1);<a name="line.433"></a>
+<span class="sourceLineNo">434</span>      try {<a name="line.434"></a>
+<span class="sourceLineNo">435</span>        connection = ConnectionFactory.createConnection(newConf);<a name="line.435"></a>
+<span class="sourceLineNo">436</span>        regionLocator = connection.getRegionLocator(htd.getTableName());<a name="line.436"></a>
+<span class="sourceLineNo">437</span><a name="line.437"></a>
+<span class="sourceLineNo">438</span>        /* Get all locations for the table and cache it */<a name="line.438"></a>
+<span class="sourceLineNo">439</span>        regionLocator.getAllRegionLocations();<a name="line.439"></a>
+<span class="sourceLineNo">440</span>      } finally {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>        if (connection != null) {<a name="line.441"></a>
+<span class="sourceLineNo">442</span>          connection.close();<a name="line.442"></a>
 <span class="sourceLineNo">443</span>        }<a name="line.443"></a>
 <span class="sourceLineNo">444</span>      }<a name="line.444"></a>
-<span class="sourceLineNo">445</span><a name="line.445"></a>
-<span class="sourceLineNo">446</span>      if (numSplits &gt; 1) {<a name="line.446"></a>
-<span class="sourceLineNo">447</span>        byte[][] sp = sa.split(hri.getStartKey(), hri.getEndKey(), numSplits, true);<a name="line.447"></a>
-<span class="sourceLineNo">448</span>        for (int i = 0; i &lt; sp.length - 1; i++) {<a name="line.448"></a>
-<span class="sourceLineNo">449</span>          if (PrivateCellUtil.overlappingKeys(scan.getStartRow(), scan.getStopRow(), sp[i],<a name="line.449"></a>
-<span class="sourceLineNo">450</span>                  sp[i + 1])) {<a name="line.450"></a>
-<span class="sourceLineNo">451</span><a name="line.451"></a>
-<span class="sourceLineNo">452</span>            Scan boundedScan = new Scan(scan);<a name="line.452"></a>
-<span class="sourceLineNo">453</span>            if (scan.getStartRow().length == 0) {<a name="line.453"></a>
-<span class="sourceLineNo">454</span>              boundedScan.withStartRow(sp[i]);<a name="line.454"></a>
-<span class="sourceLineNo">455</span>            } else {<a name="line.455"></a>
-<span class="sourceLineNo">456</span>              boundedScan.withStartRow(<a name="line.456"></a>
-<span class="sourceLineNo">457</span>                Bytes.compareTo(scan.getStartRow(), sp[i]) &gt; 0 ? scan.getStartRow() : sp[i]);<a name="line.457"></a>
-<span class="sourceLineNo">458</span>            }<a name="line.458"></a>
-<span class="sourceLineNo">459</span><a name="line.459"></a>
-<span class="sourceLineNo">460</span>            if (scan.getStopRow().length == 0) {<a name="line.460"></a>
-<span class="sourceLineNo">461</span>              boundedScan.withStopRow(sp[i + 1]);<a name="line.461"></a>
-<span class="sourceLineNo">462</span>            } else {<a name="line.462"></a>
-<span class="sourceLineNo">463</span>              boundedScan.withStopRow(<a name="line.463"></a>
-<span class="sourceLineNo">464</span>                Bytes.compareTo(scan.getStopRow(), sp[i + 1]) &lt; 0 ? scan.getStopRow() : sp[i + 1]);<a name="line.464"></a>
-<span class="sourceLineNo">465</span>            }<a name="line.465"></a>
-<span class="sourceLineNo">466</span><a name="line.466"></a>
-<span class="sourceLineNo">467</span>            splits.add(new InputSplit(htd, hri, hosts, boundedScan, restoreDir));<a name="line.467"></a>
-<span class="sourceLineNo">468</span>          }<a name="line.468"></a>
-<span class="sourceLineNo">469</span>        }<a name="line.469"></a>
-<span class="sourceLineNo">470</span>      } else {<a name="line.470"></a>
-<span class="sourceLineNo">471</span>        if (PrivateCellUtil.overlappingKeys(scan.getStartRow(), scan.getStopRow(),<a name="line.471"></a>
-<span class="sourceLineNo">472</span>            hri.getStartKey(), hri.getEndKey())) {<a name="line.472"></a>
-<span class="sourceLineNo">473</span><a name="line.473"></a>
-<span class="sourceLineNo">474</span>          splits.add(new InputSplit(htd, hri, hosts, scan, restoreDir));<a name="line.474"></a>
-<span class="sourceLineNo">475</span>        }<a name="line.475"></a>
-<span class="sourceLineNo">476</span>      }<a name="line.476"></a>
-<span class="sourceLineNo">477</span>    }<a name="line.477"></a>
-<span class="sourceLineNo">478</span><a name="line.478"></a>
-<span class="sourceLineNo">479</span>    return splits;<a name="line.479"></a>
-<span class="sourceLineNo">480</span>  }<a name="line.480"></a>
-<span class="sourceLineNo">481</span><a name="line.481"></a>
-<span class="sourceLineNo">482</span>  /**<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * Compute block locations for snapshot files (which will get the locations for referred hfiles)<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   * only when localityEnabled is true.<a name="line.484"></a>
-<span class="sourceLineNo">485</span>   */<a name="line.485"></a>
-<span class="sourceLineNo">486</span>  private static List&lt;String&gt; calculateLocationsForInputSplit(Configuration conf,<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      TableDescriptor htd, RegionInfo hri, Path tableDir)<a name="line.487"></a>
-<span class="sourceLineNo">488</span>      throws IOException {<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    return getBestLocations(conf, HRegion.computeHDFSBlocksDistribution(conf, htd, hri, tableDir));<a name="line.489"></a>
-<span class="sourceLineNo">490</span>  }<a name="line.490"></a>
+<span class="sourceLineNo">445</span>    }<a name="line.445"></a>
+<span class="sourceLineNo">446</span><a name="line.446"></a>
+<span class="sourceLineNo">447</span>    List&lt;InputSplit&gt; splits = new ArrayList&lt;&gt;();<a name="line.447"></a>
+<span class="sourceLineNo">448</span>    for (RegionInfo hri : regionManifests) {<a name="line.448"></a>
+<span class="sourceLineNo">449</span>      // load region descriptor<a name="line.449"></a>
+<span class="sourceLineNo">450</span>      List&lt;String&gt; hosts = null;<a name="line.450"></a>
+<span class="sourceLineNo">451</span>      if (localityEnabled) {<a name="line.451"></a>
+<span class="sourceLineNo">452</span>        if (regionLocator != null) {<a name="line.452"></a>
+<span class="sourceLineNo">453</span>          /* Get Location from the local cache */<a name="line.453"></a>
+<span class="sourceLineNo">454</span>          HRegionLocation<a name="line.454"></a>
+<span class="sourceLineNo">455</span>            location = regionLocator.getRegionLocation(hri.getStartKey(), false);<a name="line.455"></a>
+<span class="sourceLineNo">456</span><a name="line.456"></a>
+<span class="sourceLineNo">457</span>          hosts = new ArrayList&lt;&gt;(1);<a name="line.457"></a>
+<span class="sourceLineNo">458</span>          hosts.add(location.getHostname());<a name="line.458"></a>
+<span class="sourceLineNo">459</span>        } else {<a name="line.459"></a>
+<span class="sourceLineNo">460</span>          hosts = calculateLocationsForInputSplit(conf, htd, hri, tableDir);<a name="line.460"></a>
+<span class="sourceLineNo">461</span>        }<a name="line.461"></a>
+<span class="sourceLineNo">462</span>      }<a name="line.462"></a>
+<span class="sourceLineNo">463</span><a name="line.463"></a>
+<span class="sourceLineNo">464</span>      if (numSplits &gt; 1) {<a name="line.464"></a>
+<span class="sourceLineNo">465</span>        byte[][] sp = sa.split(hri.getStartKey(), hri.getEndKey(), numSplits, true);<a name="line.465"></a>
+<span class="sourceLineNo">466</span>        for (int i = 0; i &lt; sp.length - 1; i++) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>          if (PrivateCellUtil.overlappingKeys(scan.getStartRow(), scan.getStopRow(), sp[i],<a name="line.467"></a>
+<span class="sourceLineNo">468</span>                  sp[i + 1])) {<a name="line.468"></a>
+<span class="sourceLineNo">469</span><a name="line.469"></a>
+<span class="sourceLineNo">470</span>            Scan boundedScan = new Scan(scan);<a name="line.470"></a>
+<span class="sourceLineNo">471</span>            if (scan.getStartRow().length == 0) {<a name="line.471"></a>
+<span class="sourceLineNo">472</span>              boundedScan.withStartRow(sp[i]);<a name="line.472"></a>
+<span class="sourceLineNo">473</span>            } else {<a name="line.473"></a>
+<span class="sourceLineNo">474</span>              boundedScan.withStartRow(<a name="line.474"></a>
+<span class="sourceLineNo">475</span>                Bytes.compareTo(scan.getStartRow(), sp[i]) &gt; 0 ? scan.getStartRow() : sp[i]);<a name="line.475"></a>
+<span class="sourceLineNo">476</span>            }<a name="line.476"></a>
+<span class="sourceLineNo">477</span><a name="line.477"></a>
+<span class="sourceLineNo">478</span>            if (scan.getStopRow().length == 0) {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>              boundedScan.withStopRow(sp[i + 1]);<a name="line.479"></a>
+<span class="sourceLineNo">480</span>            } else {<a name="line.480"></a>
+<span class="sourceLineNo">481</span>              boundedScan.withStopRow(<a name="line.481"></a>
+<span class="sourceLineNo">482</span>                Bytes.compareTo(scan.getStopRow(), sp[i + 1]) &lt; 0 ? scan.getStopRow() : sp[i + 1]);<a name="line.482"></a>
+<span class="sourceLineNo">483</span>            }<a name="line.483"></a>
+<span class="sourceLineNo">484</span><a name="line.484"></a>
+<span class="sourceLineNo">485</span>            splits.add(new InputSplit(htd, hri, hosts, boundedScan, restoreDir));<a name="line.485"></a>
+<span class="sourceLineNo">486</span>          }<a name="line.486"></a>
+<span class="sourceLineNo">487</span>        }<a name="line.487"></a>
+<span class="sourceLineNo">488</span>      } else {<a name="line.488"></a>
+<span class="sourceLineNo">489</span>        if (PrivateCellUtil.overlappingKeys(scan.getStartRow(), scan.getStopRow(),<a name="line.489"></a>
+<span class="sourceLineNo">490</span>            hri.getStartKey(), hri.getEndKey())) {<a name="line.490"></a>
 <span class="sourceLineNo">491</span><a name="line.491"></a>
-<span class="sourceLineNo">492</span>  /**<a name="line.492"></a>
-<span class="sourceLineNo">493</span>   * This computes the locations to be passed from the InputSplit. MR/Yarn schedulers does not take<a name="line.493"></a>
-<span class="sourceLineNo">494</span>   * weights into account, thus will treat every location passed from the input split as equal. We<a name="line.494"></a>
-<span class="sourceLineNo">495</span>   * do not want to blindly pass all the locations, since we are creating one split per region, and<a name="line.495"></a>
-<span class="sourceLineNo">496</span>   * the region's blocks are all distributed throughout the cluster unless favorite node assignment<a name="line.496"></a>
-<span class="sourceLineNo">497</span>   * is used. On the expected stable case, only one location will contain most of the blocks as<a name="line.497"></a>
-<span class="sourceLineNo">498</span>   * local.<a name="line.498"></a>
-<span class="sourceLineNo">499</span>   * On the other hand, in favored node assignment, 3 nodes will contain highly local blocks. Here<a name="line.499"></a>
-<span class="sourceLineNo">500</span>   * we are doing a simple heuristic, where we will pass all hosts which have at least 80%<a name="line.500"></a>
-<span class="sourceLineNo">501</span>   * (hbase.tablesnapshotinputformat.locality.cutoff.multiplier) as much block locality as the top<a name="line.501"></a>
-<span class="sourceLineNo">502</span>   * host with the best locality.<a name="line.502"></a>
-<span class="sourceLineNo">503</span>   * Return at most numTopsAtMost locations if there are more than that.<a name="line.503"></a>
-<span class="sourceLineNo">504</span>   */<a name="line.504"></a>
-<span class="sourceLineNo">505</span>  private static List&lt;String&gt; getBestLocations(Configuration conf,<a name="line.505"></a>
-<span class="sourceLineNo">506</span>      HDFSBlocksDistribution blockDistribution, int numTopsAtMost) {<a name="line.506"></a>
-<span class="sourceLineNo">507</span>    HostAndWeight[] hostAndWeights = blockDistribution.getTopHostsWithWeights();<a name="line.507"></a>
-<span class="sourceLineNo">508</span><a name="line.508"></a>
-<span class="sourceLineNo">509</span>    if (hostAndWeights.length == 0) { // no matter what numTopsAtMost is<a name="line.509"></a>
-<span class="sourceLineNo">510</span>      return null;<a name="line.510"></a>
-<span class="sourceLineNo">511</span>    }<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span>    if (numTopsAtMost &lt; 1) { // invalid if numTopsAtMost &lt; 1, correct it to be 1<a name="line.513"></a>
-<span class="sourceLineNo">514</span>      numTopsAtMost = 1;<a name="line.514"></a>
-<span class="sourceLineNo">515</span>    }<a name="line.515"></a>
-<span class="sourceLineNo">516</span>    int top = Math.min(numTopsAtMost, hostAndWeights.length);<a name="line.516"></a>
-<span class="sourceLineNo">517</span>    List&lt;String&gt; locations = new ArrayList&lt;&gt;(top);<a name="line.517"></a>
-<span class="sourceLineNo">518</span>    HostAndWeight topHost = hostAndWeights[0];<a name="line.518"></a>
-<span class="sourceLineNo">519</span>    locations.add(topHost.getHost());<a name="line.519"></a>
-<span class="sourceLineNo">520</span><a name="line.520"></a>
-<span class="sourceLineNo">521</span>    if (top == 1) { // only care about the top host<a name="line.521"></a>
-<span class="sourceLineNo">522</span>      return locations;<a name="line.522"></a>
-<span class="sourceLineNo">523</span>    }<a name="line.523"></a>
-<span class="sourceLineNo">524</span><a name="line.524"></a>
-<span class="sourceLineNo">525</span>    // When top &gt;= 2,<a name="line.525"></a>
-<span class="sourceLineNo">526</span>    // do the heuristic: filter all hosts which have at least cutoffMultiplier % of block locality<a name="line.526"></a>
-<span class="sourceLineNo">527</span>    double cutoffMultiplier<a name="line.527"></a>
-<span class="sourceLineNo">528</span>            = conf.getFloat(LOCALITY_CUTOFF_MULTIPLIER, DEFAULT_LOCALITY_CUTOFF_MULTIPLIER);<a name="line.528"></a>
-<span class="sourceLineNo">529</span><a name="line.529"></a>
-<span class="sourceLineNo">530</span>    double filterWeight = topHost.getWeight() * cutoffMultiplier;<a name="line.530"></a>
-<span class="sourceLineNo">531</span><a name="line.531"></a>
-<span class="sourceLineNo">532</span>    for (int i = 1; i &lt;= top - 1; i++) {<a name="line.532"></a>
-<span class="sourceLineNo">533</span>      if (hostAndWeights[i].getWeight() &gt;= filterWeight) {<a name="line.533"></a>
-<span class="sourceLineNo">534</span>        locations.add(hostAndWeights[i].getHost());<a name="line.534"></a>
-<span class="sourceLineNo">535</span>      } else {<a name="line.535"></a>
-<span class="sourceLineNo">536</span>        // As hostAndWeights is in descending order,<a name="line.536"></a>
-<span class="sourceLineNo">537</span>        // we could break the loop as long as we meet a weight which is less than filterWeight.<a name="line.537"></a>
-<span class="sourceLineNo">538</span>        break;<a name="line.538"></a>
-<span class="sourceLineNo">539</span>      }<a name="line.539"></a>
-<span class="sourceLineNo">540</span>    }<a name="line.540"></a>
-<span class="sourceLineNo">541</span><a name="line.541"></a>
-<span class="sourceLineNo">542</span>    return locations;<a name="line.542"></a>
-<span class="sourceLineNo">543</span>  }<a name="line.543"></a>
-<span class="sourceLineNo">544</span><a name="line.544"></a>
-<span class="sourceLineNo">545</span>  public static List&lt;String&gt; getBestLocations(Configuration conf,<a name="line.545"></a>
-<span class="sourceLineNo">546</span>      HDFSBlocksDistribution blockDistribution) {<a name="line.546"></a>
-<span class="sourceLineNo">547</span>    // 3 nodes will contain highly local blocks. So default to 3.<a name="line.547"></a>
-<span class="sourceLineNo">548</span>    return getBestLocations(conf, blockDistribution, 3);<a name="line.548"></a>
-<span class="sourceLineNo">549</span>  }<a name="line.549"></a>
-<span class="sourceLineNo">550</span><a name="line.550"></a>
-<span class="sourceLineNo">551</span>  private static String getSnapshotName(Configuration conf) {<a name="line.551"></a>
-<span class="sourceLineNo">552</span>    String snapshotName = conf.get(SNAPSHOT_NAME_KEY);<a name="line.552"></a>
-<span class="sourceLineNo">553</span>    if (snapshotName == null) {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>      throw new IllegalArgumentException("Snapshot name must be provided");<a name="line.554"></a>
-<span class="sourceLineNo">555</span>    }<a name="line.555"></a>
-<span class="sourceLineNo">556</span>    return snapshotName;<a name="line.556"></a>
-<span class="sourceLineNo">557</span>  }<a name="line.557"></a>
-<span class="sourceLineNo">558</span><a name="line.558"></a>
-<span class="sourceLineNo">559</span>  /**<a name="line.559"></a>
-<span class="sourceLineNo">560</span>   * Configures the job to use TableSnapshotInputFormat to read from a snapshot.<a name="line.560"></a>
-<span class="sourceLineNo">561</span>   * @param conf the job to configuration<a name="line.561"></a>
-<span class="sourceLineNo">562</span>   * @param snapshotName the name of the snapshot to read from<a name="line.562"></a>
-<span class="sourceLineNo">563</span>   * @param restoreDir a temporary directory to restore the snapshot into. Current user should have<a name="line.563"></a>
-<span class="sourceLineNo">564</span>   *          write permissions to this directory, and this should not be a subdirectory of rootdir.<a name="line.564"></a>
-<span class="sourceLineNo">565</span>   *          After the job is finished, restoreDir can be deleted.<a name="line.565"></a>
-<span class="sourceLineNo">566</span>   * @throws IOException if an error occurs<a name="line.566"></a>
-<span class="sourceLineNo">567</span>   */<a name="line.567"></a>
-<span class="sourceLineNo">568</span>  public static void setInput(Configuration conf, String snapshotName, Path restoreDir)<a name="line.568"></a>
-<span class="sourceLineNo">569</span>      throws IOException {<a name="line.569"></a>
-<span class="sourceLineNo">570</span>    setInput(conf, snapshotName, restoreDir, null, 1);<a name="line.570"></a>
-<span class="sourceLineNo">571</span>  }<a name="line.571"></a>
-<span class="sourceLineNo">572</span><a name="line.572"></a>
-<span class="sourceLineNo">573</span>  /**<a name="line.573"></a>
-<span class="sourceLineNo">574</span>   * Configures the job to use TableSnapshotInputFormat to read from a snapshot.<a name="line.574"></a>
-<span class="sourceLineNo">575</span>   * @param conf the job to configure<a name="line.575"></a>
-<span class="sourceLineNo">576</span>   * @param snapshotName the name of the snapshot to read from<a name="line.576"></a>
-<span class="sourceLineNo">577</span>   * @param restoreDir a temporary directory to restore the snapshot into. Current user should have<a name="line.577"></a>
-<span class="sourceLineNo">578</span>   *          write permissions to this directory, and this should not be a subdirectory of rootdir.<a name="line.578"></a>
-<span class="sourceLineNo">579</span>   *          After the job is finished, restoreDir can be deleted.<a name="line.579"></a>
-<span class="sourceLineNo">580</span>   * @param numSplitsPerRegion how many input splits to generate per one region<a name="line.580"></a>
-<span class="sourceLineNo">581</span>   * @param splitAlgo SplitAlgorithm to be used when generating InputSplits<a name="line.581"></a>
-<span class="sourceLineNo">582</span>   * @throws IOException if an error occurs<a name="line.582"></a>
-<span class="sourceLineNo">583</span>   */<a name="line.583"></a>
-<span class="sourceLineNo">584</span>  public static void setInput(Configuration conf, String snapshotName, Path restoreDir,<a name="line.584"></a>
-<span class="sourceLineNo">585</span>                              RegionSplitter.SplitAlgorithm splitAlgo, int numSplitsPerRegion)<a name="line.585"></a>
-<span class="sourceLineNo">586</span>          throws IOException {<a name="line.586"></a>
-<span class="sourceLineNo">587</span>    conf.set(SNAPSHOT_NAME_KEY, snapshotName);<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    if (numSplitsPerRegion &lt; 1) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span>      throw new IllegalArgumentException("numSplits must be &gt;= 1, " +<a name="line.589"></a>
-<span class="sourceLineNo">590</span>              "illegal numSplits : " + numSplitsPerRegion);<a name="line.590"></a>
-<span class="sourceLineNo">591</span>    }<a name="line.591"></a>
-<span class="sourceLineNo">592</span>    if (splitAlgo == null &amp;&amp; numSplitsPerRegion &gt; 1) {<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      throw new IllegalArgumentException("Split algo can't be null when numSplits &gt; 1");<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    }<a name="line.594"></a>
-<span class="sourceLineNo">595</span>    if (splitAlgo != null) {<a name="line.595"></a>
-<span class="sourceLineNo">596</span>      conf.set(SPLIT_ALGO, splitAlgo.getClass().getName());<a name="line.596"></a>
-<span class="sourceLineNo">597</span>    }<a name="line.597"></a>
-<span class="sourceLineNo">598</span>    conf.setInt(NUM_SPLITS_PER_REGION, numSplitsPerRegion);<a name="line.598"></a>
-<span class="sourceLineNo">599</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.599"></a>
-<span class="sourceLineNo">600</span>    FileSystem fs = rootDir.getFileSystem(conf);<a name="line.600"></a>
-<span class="sourceLineNo">601</span><a name="line.601"></a>
-<span class="sourceLineNo">602</span>    restoreDir = new Path(restoreDir, UUID.randomUUID().toString());<a name="line.602"></a>
-<span class="sourceLineNo">603</span><a name="line.603"></a>
-<span class="sourceLineNo">604</span>    RestoreSnapshotHelper.copySnapshotForScanner(conf, fs, rootDir, restoreDir, snapshotName);<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    conf.set(RESTORE_DIR_KEY, restoreDir.toString());<a name="line.605"></a>
-<span class="sourceLineNo">606</span>  }<a name="line.606"></a>
-<span class="sourceLineNo">607</span>}<a name="line.607"></a>
+<span class="sourceLineNo">492</span>          splits.add(new InputSplit(htd, hri, hosts, scan, restoreDir));<a name="line.492"></a>
+<span class="sourceLineNo">493</span>        }<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      }<a name="line.494"></a>
+<span class="sourceLineNo">495</span>    }<a name="line.495"></a>
+<span class="sourceLineNo">496</span><a name="line.496"></a>
+<span class="sourceLineNo">497</span>    return splits;<a name="line.497"></a>
+<span class="sourceLineNo">498</span>  }<a name="line.498"></a>
+<span class="sourceLineNo">499</span><a name="line.499"></a>
+<span class="sourceLineNo">500</span>  /**<a name="line.500"></a>
+<span class="sourceLineNo">501</span>   * Compute block locations for snapshot files (which will get the locations for referred hfiles)<a name="line.501"></a>
+<span class="sourceLineNo">502</span>   * only when localityEnabled is true.<a name="line.502"></a>
+<span class="sourceLineNo">503</span>   */<a name="line.503"></a>
+<span class="sourceLineNo">504</span>  private static List&lt;String&gt; calculateLocationsForInputSplit(Configuration conf,<a name="line.504"></a>
+<span class="sourceLineNo">505</span>      TableDescriptor htd, RegionInfo hri, Path tableDir)<a name="line.505"></a>
+<span class="sourceLineNo">506</span>      throws IOException {<a name="line.506"></a>
+<span class="sourceLineNo">507</span>    return getBestLocations(conf, HRegion.computeHDFSBlocksDistribution(conf, htd, hri, tableDir));<a name="line.507"></a>
+<span class="sourceLineNo">508</span>  }<a name="line.508"></a>
+<span class="sourceLineNo">509</span><a name="line.509"></a>
+<span class="sourceLineNo">510</span>  /**<a name="line.510"></a>
+<span class="sourceLineNo">511</span>   * This computes the locations to be passed from the InputSplit. MR/Yarn schedulers does not take<a name="line.511"></a>
+<span class="sourceLineNo">512</span>   * weights into account, thus will treat every location passed from the input split as equal. We<a name="line.512"></a>
+<span class="sourceLineNo">513</span>   * do not want to blindly pass all the locations, since we are creating one split per region, and<a name="line.513"></a>
+<span class="sourceLineNo">514</span>   * the region's blocks are all distributed throughout the cluster unless favorite node assignment<a name="line.514"></a>
+<span class="sourceLineNo">515</span>   * is used. On the expected stable case, only one location will contain most of the blocks as<a name="line.515"></a>
+<span class="sourceLineNo">516</span>   * local.<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   * On the other hand, in favored node assignment, 3 nodes will contain highly local blocks. Here<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * we are doing a simple heuristic, where we will pass all hosts which have at least 80%<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   * (hbase.tablesnapshotinputformat.locality.cutoff.multiplier) as much block locality as the top<a name="line.519"></a>
+<span class="sourceLineNo">520</span>   * host with the best locality.<a name="line.520"></a>
+<span class="sourceLineNo">521</span>   * Return at most numTopsAtMost locations if there are more than that.<a name="line.521"></a>
+<span class="sourceLineNo">522</span>   */<a name="line.522"></a>
+<span class="sourceLineNo">523</span>  private static List&lt;String&gt; getBestLocations(Configuration conf,<a name="line.523"></a>
+<span class="sourceLineNo">524</span>      HDFSBlocksDistribution blockDistribution, int numTopsAtMost) {<a name="line.524"></a>
+<span class="sourceLineNo">525</span>    HostAndWeight[] hostAndWeights = blockDistribution.getTopHostsWithWeights();<a name="line.525"></a>
+<span class="sourceLineNo">526</span><a name="line.526"></a>
+<span class="sourceLineNo">527</span>    if (hostAndWeights.length == 0) { // no matter what numTopsAtMost is<a name="line.527"></a>
+<span class="sourceLineNo">528</span>      return null;<a name="line.528"></a>
+<span class="sourceLineNo">529</span>    }<a name="line.529"></a>
+<span class="sourceLineNo">530</span><a name="line.530"></a>
+<span class="sourceLineNo">531</span>    if (numTopsAtMost &lt; 1) { // invalid if numTopsAtMost &lt; 1, correct it to be 1<a name="line.531"></a>
+<span class="sourceLineNo">532</span>      numTopsAtMost = 1;<a name="line.532"></a>
+<span class="sourceLineNo">533</span>    }<a name="line.533"></a>
+<span class="sourceLineNo">534</span>    int top = Math.min(numTopsAtMost, hostAndWeights.length);<a name="line.534"></a>
+<span class="sourceLineNo">535</span>    List&lt;String&gt; locations = new ArrayList&lt;&gt;(top);<a name="line.535"></a>
+<span class="sourceLineNo">536</span>    HostAndWeight topHost = hostAndWeights[0];<a name="line.536"></a>
+<span class="sourceLineNo">537</span>    locations.add(topHost.getHost());<a name="line.537"></a>
+<span class="sourceLineNo">538</span><a name="line.538"></a>
+<span class="sourceLineNo">539</span>    if (top == 1) { // only care about the top host<a name="line.539"></a>
+<span class="sourceLineNo">540</span>      return locations;<a name="line.540"></a>
+<span class="sourceLineNo">541</span>    }<a name="line.541"></a>
+<span class="sourceLineNo">542</span><a name="line.542"></a>
+<span class="sourceLineNo">543</span>    // When top &gt;= 2,<a name="line.543"></a>
+<span class="sourceLineNo">544</span>    // do the heuristic: filter all hosts which have at least cutoffMultiplier % of block locality<a name="line.544"></a>
+<span class="sourceLineNo">545</span>    double cutoffMultiplier<a name="line.545"></a>
+<span class="sourceLineNo">546</span>            = conf.getFloat(LOCALITY_CUTOFF_MULTIPLIER, DEFAULT_LOCALITY_CUTOFF_MULTIPLIER);<a name="line.546"></a>
+<span class="sourceLineNo">547</span><a name="line.547"></a>
+<span class="sourceLineNo">548</span>    double filterWeight = topHost.getWeight() * cutoffMultiplier;<a name="line.548"></a>
+<span class="sourceLineNo">549</span><a name="line.549"></a>
+<span class="sourceLineNo">550</span>    for (int i = 1; i &lt;= top - 1; i++) {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>      if (hostAndWeights[i].getWeight() &gt;= filterWeight) {<a name="line.551"></a>
+<span class="sourceLineNo">552</span>        locations.add(hostAndWeights[i].getHost());<a name="line.552"></a>
+<span class="sourceLineNo">553</span>      } else {<a name="line.553"></a>
+<span class="sourceLineNo">554</span>        // As hostAndWeights is in descending order,<a name="line.554"></a>
+<span class="sourceLineNo">555</span>        // we could break the loop as long as we meet a weight which is less than filterWeight.<a name="line.555"></a>
+<span class="sourceLineNo">556</span>        break;<a name="line.556"></a>
+<span class="sourceLineNo">557</span>      }<a name="line.557"></a>
+<span class="sourceLineNo">558</span>    }<a name="line.558"></a>
+<span class="sourceLineNo">559</span><a name="line.559"></a>
+<span class="sourceLineNo">560</span>    return locations;<a name="line.560"></a>
+<span class="sourceLineNo">561</span>  }<a name="line.561"></a>
+<span class="sourceLineNo">562</span><a name="line.562"></a>
+<span class="sourceLineNo">563</span>  public static List&lt;String&gt; getBestLocations(Configuration conf,<a name="line.563"></a>
+<span class="sourceLineNo">564</span>      HDFSBlocksDistribution blockDistribution) {<a name="line.564"></a>
+<span class="sourceLineNo">565</span>    // 3 nodes will contain highly local blocks. So default to 3.<a name="line.565"></a>
+<span class="sourceLineNo">566</span>    return getBestLocations(conf, blockDistribution, 3);<a name="line.566"></a>
+<span class="sourceLineNo">567</span>  }<a name="line.567"></a>
+<span class="sourceLineNo">568</span><a name="line.568"></a>
+<span class="sourceLineNo">569</span>  private static String getSnapshotName(Configuration conf) {<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    String snapshotName = conf.get(SNAPSHOT_NAME_KEY);<a name="line.570"></a>
+<span class="sourceLineNo">571</span>    if (snapshotName == null) {<a name="line.571"></a>
+<span class="sourceLineNo">572</span>      throw new IllegalArgumentException("Snapshot name must be provided");<a name="line.572"></a>
+<span class="sourceLineNo">573</span>    }<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    return snapshotName;<a name="line.574"></a>
+<span class="sourceLineNo">575</span>  }<a name="line.575"></a>
+<span class="sourceLineNo">576</span><a name="line.576"></a>
+<span class="sourceLineNo">577</span>  /**<a name="line.577"></a>
+<span class="sourceLineNo">578</span>   * Configures the job to use TableSnapshotInputFormat to read from a snapshot.<a name="line.578"></a>
+<span class="sourceLineNo">579</span>   * @param conf the job to configuration<a name="line.579"></a>
+<span class="sourceLineNo">580</span>   * @param snapshotName the name of the snapshot to read from<a name="line.580"></a>
+<span class="sourceLineNo">581</span>   * @param restoreDir a temporary directory to restore the snapshot into. Current user should have<a name="line.581"></a>
+<span class="sourceLineNo">582</span>   *          write permissions to this directory, and this should not be a subdirectory of rootdir.<a name="line.582"></a>
+<span class="sourceLineNo">583</span>   *          After the job is finished, restoreDir can be deleted.<a name="line.583"></a>
+<span class="sourceLineNo">584</span>   * @throws IOException if an error occurs<a name="line.584"></a>
+<span class="sourceLineNo">585</span>   */<a name="line.585"></a>
+<span class="sourceLineNo">586</span>  public static void setInput(Configuration conf, String snapshotName, Path restoreDir)<a name="line.586"></a>
+<span class="sourceLineNo">587</span>      throws IOException {<a name="line.587"></a>
+<span class="sourceLineNo">588</span>    setInput(conf, snapshotName, restoreDir, null, 1);<a name="line.588"></a>
+<span class="sourceLineNo">589</span>  }<a name="line.589"></a>
+<span class="sourceLineNo">590</span><a name="line.590"></a>
+<span class="sourceLineNo">591</span>  /**<a name="line.591"></a>
+<span class="sourceLineNo">592</span>   * Configures the job to use TableSnapshotInputFormat to read from a snapshot.<a name="line.592"></a>
+<span class="sourceLineNo">593</span>   * @param conf the job to configure<a name="line.593"></a>
+<span class="sourceLineNo">594</span>   * @param snapshotName the name of the snapshot to read from<a name="line.594"></a>
+<span class="sourceLineNo">595</span>   * @param restoreDir a temporary directory to restore the snapshot into. Current user should have<a name="line.595"></a>
+<span class="sourceLineNo">596</span>   *          write permissions to this directory, and this should not be a subdirectory of rootdir.<a name="line.596"></a>
+<span class="sourceLineNo">597</span>   *          After the job is finished, restoreDir can be deleted.<a name="line.597"></a>
+<span class="sourceLineNo">598</span>   * @param numSplitsPerRegion how many input splits to generate per one region<a name="line.598"></a>
+<span class="sourceLineNo">599</span>   * @param splitAlgo SplitAlgorithm to be used when generating InputSplits<a name="line.599"></a>
+<span class="sourceLineNo">600</span>   * @throws IOException if an error occurs<a name="line.600"></a>
+<span class="sourceLineNo">601</span>   */<a name="line.601"></a>
+<span class="sourceLineNo">602</span>  public static void setInput(Configuration conf, String snapshotName, Path restoreDir,<a name="line.602"></a>
+<span class="sourceLineNo">603</span>                              RegionSplitter.SplitAlgorithm splitAlgo, int numSplitsPerRegion)<a name="line.603"></a>
+<span class="sourceLineNo">604</span>          throws IOException {<a name="line.604"></a>
+<span class="sourceLineNo">605</span>    conf.set(SNAPSHOT_NAME_KEY, snapshotName);<a name="line.605"></a>
+<span class="sourceLineNo">606</span>    if (numSplitsPerRegion &lt; 1) {<a name="line.606"></a>
+<span class="sourceLineNo">607</span>      throw new IllegalArgumentException("numSplits must be &gt;= 1, " +<a name="line.607"></a>
+<span class="sourceLineNo">608</span>              "illegal numSplits : " + numSplitsPerRegion);<a name="line.608"></a>
+<span class="sourceLineNo">609</span>    }<a name="line.609"></a>
+<span class="sourceLineNo">610</span>    if (splitAlgo == null &amp;&amp; numSplitsPerRegion &gt; 1) {<a name="line.610"></a>
+<span class="sourceLineNo">611</span>      throw new IllegalArgumentException("Split algo can't be null when numSplits &gt; 1");<a name="line.611"></a>
+<span class="sourceLineNo">612</span>    }<a name="line.612"></a>
+<span class="sourceLineNo">613</span>    if (splitAlgo != null) {<a name="line.613"></a>
+<span class="sourceLineNo">614</span>      conf.set(SPLIT_ALGO, splitAlgo.getClass().getName());<a name="line.614"></a>
+<span class="sourceLineNo">615</span>    }<a name="line.615"></a>
+<span class="sourceLineNo">616</span>    conf.setInt(NUM_SPLITS_PER_REGION, numSplitsPerRegion);<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    Path rootDir = CommonFSUtils.getRootDir(conf);<a name="line.617"></a>
+<span class="sourceLineNo">618</span>    FileSystem fs = rootDir.getFileSystem(conf);<a name="line.618"></a>
+<span class="sourceLineNo">619</span><a name="line.619"></a>
+<span class="sourceLineNo">620</span>    restoreDir = new Path(restoreDir, UUID.randomUUID().toString());<a name="line.620"></a>
+<span class="sourceLineNo">621</span><a name="line.621"></a>
+<span class="sourceLineNo">622</span>    RestoreSnapshotHelper.copySnapshotForScanner(conf, fs, rootDir, restoreDir, snapshotName);<a name="line.622"></a>
+<span class="sourceLineNo">623</span>    conf.set(RESTORE_DIR_KEY, restoreDir.toString());<a name="line.623"></a>
+<span class="sourceLineNo">624</span>  }<a name="line.624"></a>
+<span class="sourceLineNo">625</span>}<a name="line.625"></a>
 
 
 
diff --git a/downloads.html b/downloads.html
index c5fcd30..2ffdecd 100644
--- a/downloads.html
+++ b/downloads.html
@@ -213,29 +213,29 @@
 <tr class="a">
       
 <td style="test-align: left">
-        2.4.5
+        2.4.6
       </td>
       
 <td style="test-align: left">
-        2021/07/31
+        2021/09/13
       </td>
       
 <td style="test-align: left">
-        <a class="externalLink" href="https://downloads.apache.org/hbase/2.4.5/api_compare_2.4.4_to_2.4.5RC1.html">2.4.5 vs 2.4.4</a>
+        <a class="externalLink" href="https://downloads.apache.org/hbase/2.4.6/api_compare_2.4.5_to_2.4.6RC0.html">2.4.6 vs 2.4.5</a>
       </td>
       
 <td style="test-align: left">
-        <a class="externalLink" href="https://downloads.apache.org/hbase/2.4.5/CHANGES.md">Changes</a>
+        <a class="externalLink" href="https://downloads.apache.org/hbase/2.4.6/CHANGES.md">Changes</a>
       </td>
       
 <td style="test-align: left">
-        <a class="externalLink" href="https://downloads.apache.org/hbase/2.4.5/RELEASENOTES.md">Release Notes</a>
+        <a class="externalLink" href="https://downloads.apache.org/hbase/2.4.6/RELEASENOTES.md">Release Notes</a>
       </td>
       
 <td style="test-align: left">
-        <a class="externalLink" href="https://www.apache.org/dyn/closer.lua/hbase/2.4.5/hbase-2.4.5-src.tar.gz">src</a> (<a class="externalLink" href="https://downloads.apache.org/hbase/2.4.5/hbase-2.4.5-src.tar.gz.sha512">sha512</a> <a class="externalLink" href="https://downloads.apache.org/hbase/2.4.5/hbase-2.4.5-src.tar.gz.asc">asc</a>) <br />
-        <a class="externalLink" href="https://www.apache.org/dyn/closer.lua/hbase/2.4.5/hbase-2.4.5-bin.tar.gz">bin</a> (<a class="externalLink" href="https://downloads.apache.org/hbase/2.4.5/hbase-2.4.5-bin.tar.gz.sha512">sha512</a> <a class="externalLink" href="https://downloads.apache.org/hbase/2.4.5/hbase-2.4.5-bin.tar.gz.asc">asc</a>) <br />
-        <a class="externalLink" href="https://www.apache.org/dyn/closer.lua/hbase/2.4.5/hbase-2.4.5-client-bin.tar.gz">client-bin</a> (<a class="externalLink" href="https://downloads.apache.org/hbase/2.4.5/hbase-2.4.5-client-bin.tar.gz.sha512">sha512</a> <a class="externalLink" href="https://downloads.apache.org/hbase/2.4.5/hbase-2.4.5-client-bin.tar.gz.asc">asc</a>)
+        <a class="externalLink" href="https://www.apache.org/dyn/closer.lua/hbase/2.4.6/hbase-2.4.6-src.tar.gz">src</a> (<a class="externalLink" href="https://downloads.apache.org/hbase/2.4.6/hbase-2.4.6-src.tar.gz.sha512">sha512</a> <a class="externalLink" href="https://downloads.apache.org/hbase/2.4.6/hbase-2.4.6-src.tar.gz.asc">asc</a>) <br />
+        <a class="externalLink" href="https://www.apache.org/dyn/closer.lua/hbase/2.4.6/hbase-2.4.6-bin.tar.gz">bin</a> (<a class="externalLink" href="https://downloads.apache.org/hbase/2.4.6/hbase-2.4.6-bin.tar.gz.sha512">sha512</a> <a class="externalLink" href="https://downloads.apache.org/hbase/2.4.6/hbase-2.4.6-bin.tar.gz.asc">asc</a>) <br />
+        <a class="externalLink" href="https://www.apache.org/dyn/closer.lua/hbase/2.4.6/hbase-2.4.6-client-bin.tar.gz">client-bin</a> (<a class="externalLink" href="https://downloads.apache.org/hbase/2.4.6/hbase-2.4.6-client-bin.tar.gz.sha512">sha512</a> <a class="externalLink" href="https://downloads.apache.org/hbase/2.4.6/hbase-2.4.6-client-bin.tar.gz.asc">asc</a>)
       </td>
       
 <td></td>
@@ -457,7 +457,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/export_control.html b/export_control.html
index c24b7e4..0f1f7d1 100644
--- a/export_control.html
+++ b/export_control.html
@@ -186,7 +186,7 @@ for more details.</p>
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/index.html b/index.html
index 705e46ea..f2776e9 100644
--- a/index.html
+++ b/index.html
@@ -264,7 +264,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/issue-tracking.html b/issue-tracking.html
index cad8a74..459897b 100644
--- a/issue-tracking.html
+++ b/issue-tracking.html
@@ -158,7 +158,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/mail-lists.html b/mail-lists.html
index 7bf0a3f..3184d55 100644
--- a/mail-lists.html
+++ b/mail-lists.html
@@ -204,7 +204,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/metrics.html b/metrics.html
index e883f19..207406e 100644
--- a/metrics.html
+++ b/metrics.html
@@ -314,7 +314,7 @@ export HBASE_REGIONSERVER_OPTS=&quot;$HBASE_JMX_OPTS -Dcom.sun.management.jmxrem
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/old_news.html b/old_news.html
index 7e1b9f5..8e2209a 100644
--- a/old_news.html
+++ b/old_news.html
@@ -305,7 +305,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/plugin-management.html b/plugin-management.html
index 9698cfd..d7ad5c2 100644
--- a/plugin-management.html
+++ b/plugin-management.html
@@ -310,7 +310,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/plugins.html b/plugins.html
index 56a16c7..64091a4 100644
--- a/plugins.html
+++ b/plugins.html
@@ -237,7 +237,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/poweredbyhbase.html b/poweredbyhbase.html
index 8d66102..125bf6c 100644
--- a/poweredbyhbase.html
+++ b/poweredbyhbase.html
@@ -639,7 +639,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/project-info.html b/project-info.html
index 141a848..ba194bd 100644
--- a/project-info.html
+++ b/project-info.html
@@ -199,7 +199,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/project-reports.html b/project-reports.html
index c8d116b..b98281b 100644
--- a/project-reports.html
+++ b/project-reports.html
@@ -175,7 +175,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/project-summary.html b/project-summary.html
index 1843b7a..adf58d8 100644
--- a/project-summary.html
+++ b/project-summary.html
@@ -201,7 +201,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/pseudo-distributed.html b/pseudo-distributed.html
index 4d2e297..3a4fabc 100644
--- a/pseudo-distributed.html
+++ b/pseudo-distributed.html
@@ -163,7 +163,7 @@ Running Apache HBase (TM) in pseudo-distributed mode
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/replication.html b/replication.html
index 8e54544..e9c64e9 100644
--- a/replication.html
+++ b/replication.html
@@ -158,7 +158,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/resources.html b/resources.html
index 7661f5e..06a38ee 100644
--- a/resources.html
+++ b/resources.html
@@ -186,7 +186,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/source-repository.html b/source-repository.html
index efd1182..da1854d 100644
--- a/source-repository.html
+++ b/source-repository.html
@@ -169,7 +169,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/sponsors.html b/sponsors.html
index 34e2aff..f1d58bd 100644
--- a/sponsors.html
+++ b/sponsors.html
@@ -188,7 +188,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/supportingprojects.html b/supportingprojects.html
index 21f3dfb..578edac 100644
--- a/supportingprojects.html
+++ b/supportingprojects.html
@@ -379,7 +379,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/team-list.html b/team-list.html
index 2cae661..75324d8 100644
--- a/team-list.html
+++ b/team-list.html
@@ -732,7 +732,7 @@
         <div class="row">
             <p>Copyright &copy;2007&#x2013;2021
 <a href="https://www.apache.org/">The Apache Software Foundation</a>.
-All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-13</li>
+All rights reserved.        <li id="publishDate" class="pull-right">Last Published: 2021-09-14</li>
 </p>
         </div>
         <p id="poweredBy" class="pull-right"><a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
diff --git a/testdevapidocs/index-all.html b/testdevapidocs/index-all.html
index 2595d9b..b6ca49e 100644
--- a/testdevapidocs/index-all.html
+++ b/testdevapidocs/index-all.html
@@ -42738,6 +42738,11 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/TestTinyLfuBlockCache.CachedItem.html#serialize-java.nio.ByteBuffer-boolean-">serialize(ByteBuffer, boolean)</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/TestTinyLfuBlockCache.CachedItem.html" title="class in org.apache.hadoop.hbase.io.hfile">TestTinyLfuBlockCache.CachedItem</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#serializeAndReturn-org.apache.hadoop.conf.Configuration-org.apache.hadoop.hbase.client.Scan-">serializeAndReturn(Configuration, Scan)</a></span> - Method in class org.apache.hadoop.hbase.mapreduce.<a href="org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html" title="class in org.apache.hadoop.hbase.mapreduce">TestTableSnapshotInputFormat</a></dt>
+<dd>
+<div class="block">Serializes and deserializes the given scan in the same manner that
+ TableSnapshotInputFormat does.</div>
+</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/io/hfile/TestFixedFileTrailer.html#serializeAsWritable-java.io.DataOutputStream-org.apache.hadoop.hbase.io.hfile.FixedFileTrailer-">serializeAsWritable(DataOutputStream, FixedFileTrailer)</a></span> - Method in class org.apache.hadoop.hbase.io.hfile.<a href="org/apache/hadoop/hbase/io/hfile/TestFixedFileTrailer.html" title="class in org.apache.hadoop.hbase.io.hfile">TestFixedFileTrailer</a></dt>
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/procedure2/store/ProcedureStorePerformanceEvaluation.html#SERIALIZED_STATE">SERIALIZED_STATE</a></span> - Static variable in class org.apache.hadoop.hbase.procedure2.store.<a href="org/apache/hadoop/hbase/procedure2/store/ProcedureStorePerformanceEvaluation.html" title="class in org.apache.hadoop.hbase.procedure2.store">ProcedureStorePerformanceEvaluation</a></dt>
@@ -72789,6 +72794,8 @@
 <dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/client/TestClientScannerRPCTimeout.html#testScannerNextRPCTimesout--">testScannerNextRPCTimesout()</a></span> - Method in class org.apache.hadoop.hbase.client.<a href="org/apache/hadoop/hbase/client/TestClientScannerRPCTimeout.html" title="class in org.apache.hadoop.hbase.client">TestClientScannerRPCTimeout</a></dt>
 <dd>&nbsp;</dd>
+<dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#testScannerReadTypeConfiguration--">testScannerReadTypeConfiguration()</a></span> - Method in class org.apache.hadoop.hbase.mapreduce.<a href="org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html" title="class in org.apache.hadoop.hbase.mapreduce">TestTableSnapshotInputFormat</a></dt>
+<dd>&nbsp;</dd>
 <dt><span class="memberNameLink"><a href="org/apache/hadoop/hbase/regionserver/TestStoreScanner.html#testScannerReseekDoesntNPE--">testScannerReseekDoesntNPE()</a></span> - Method in class org.apache.hadoop.hbase.regionserver.<a href="org/apache/hadoop/hbase/regionserver/TestStoreScanner.html" title="class in org.apache.hadoop.hbase.regionserver">TestStoreScanner</a></dt>
 <dd>&nbsp;</dd>
 <dt><a href="org/apache/hadoop/hbase/rest/TestScannerResource.html" title="class in org.apache.hadoop.hbase.rest"><span class="typeNameLink">TestScannerResource</span></a> - Class in <a href="org/apache/hadoop/hbase/rest/package-summary.html">org.apache.hadoop.hbase.rest</a></dt>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/chaos/actions/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/chaos/actions/package-tree.html
index d7d9b9a..24c8931 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/chaos/actions/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/chaos/actions/package-tree.html
@@ -159,8 +159,8 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.chaos.actions.<a href="../../../../../../org/apache/hadoop/hbase/chaos/actions/RollingBatchRestartRsAction.KillOrStart.html" title="enum in org.apache.hadoop.hbase.chaos.actions"><span class="typeNameLink">RollingBatchRestartRsAction.KillOrStart</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.chaos.actions.<a href="../../../../../../org/apache/hadoop/hbase/chaos/actions/RollingBatchSuspendResumeRsAction.SuspendOrResume.html" title="enum in org.apache.hadoop.hbase.chaos.actions"><span class="typeNameLink">RollingBatchSuspendResumeRsAction.SuspendOrResume</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.chaos.actions.<a href="../../../../../../org/apache/hadoop/hbase/chaos/actions/RollingBatchRestartRsAction.KillOrStart.html" title="enum in org.apache.hadoop.hbase.chaos.actions"><span class="typeNameLink">RollingBatchRestartRsAction.KillOrStart</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html b/testdevapidocs/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html
index 6a1b59c..f483856 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html
@@ -122,7 +122,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>public static enum <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.142">TestTableSnapshotInputFormat.TestTableSnapshotCounters</a>
+<pre>public static enum <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.145">TestTableSnapshotInputFormat.TestTableSnapshotCounters</a>
 extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang">Enum</a>&lt;<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html" title="enum in org.apache.hadoop.hbase.mapreduce">TestTableSnapshotInputFormat.TestTableSnapshotCounters</a>&gt;</pre>
 </li>
 </ul>
@@ -207,7 +207,7 @@ the order they are declared.</div>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>VALIDATION_ERROR</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html" title="enum in org.apache.hadoop.hbase.mapreduce">TestTableSnapshotInputFormat.TestTableSnapshotCounters</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html#line.143">VALIDATION_ERROR</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html" title="enum in org.apache.hadoop.hbase.mapreduce">TestTableSnapshotInputFormat.TestTableSnapshotCounters</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html#line.146">VALIDATION_ERROR</a></pre>
 </li>
 </ul>
 </li>
@@ -224,7 +224,7 @@ the order they are declared.</div>
 <ul class="blockList">
 <li class="blockList">
 <h4>values</h4>
-<pre>public static&nbsp;<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html" title="enum in org.apache.hadoop.hbase.mapreduce">TestTableSnapshotInputFormat.TestTableSnapshotCounters</a>[]&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html#line.142">values</a>()</pre>
+<pre>public static&nbsp;<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html" title="enum in org.apache.hadoop.hbase.mapreduce">TestTableSnapshotInputFormat.TestTableSnapshotCounters</a>[]&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html#line.145">values</a>()</pre>
 <div class="block">Returns an array containing the constants of this enum type, in
 the order they are declared.  This method may be used to iterate
 over the constants as follows:
@@ -244,7 +244,7 @@ for (TestTableSnapshotInputFormat.TestTableSnapshotCounters c : TestTableSnapsho
 <ul class="blockListLast">
 <li class="blockList">
 <h4>valueOf</h4>
-<pre>public static&nbsp;<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html" title="enum in org.apache.hadoop.hbase.mapreduce">TestTableSnapshotInputFormat.TestTableSnapshotCounters</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html#line.142">valueOf</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=t [...]
+<pre>public static&nbsp;<a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html" title="enum in org.apache.hadoop.hbase.mapreduce">TestTableSnapshotInputFormat.TestTableSnapshotCounters</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html#line.145">valueOf</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=t [...]
 <div class="block">Returns the enum constant of this type with the specified name.
 The string must match <i>exactly</i> an identifier used to declare an
 enum constant in this type.  (Extraneous whitespace characters are 
diff --git a/testdevapidocs/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotMapper.html b/testdevapidocs/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotMapper.html
index 155cdb3..f4bc284 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotMapper.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotMapper.html
@@ -123,7 +123,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>public static class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.146">TestTableSnapshotInputFormat.TestTableSnapshotMapper</a>
+<pre>public static class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.149">TestTableSnapshotInputFormat.TestTableSnapshotMapper</a>
 extends org.apache.hadoop.hbase.mapreduce.TableMapper&lt;org.apache.hadoop.hbase.io.ImmutableBytesWritable,org.apache.hadoop.io.NullWritable&gt;</pre>
 </li>
 </ul>
@@ -216,7 +216,7 @@ extends org.apache.hadoop.hbase.mapreduce.TableMapper&lt;org.apache.hadoop.hbase
 <ul class="blockListLast">
 <li class="blockList">
 <h4>TestTableSnapshotMapper</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotMapper.html#line.146">TestTableSnapshotMapper</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotMapper.html#line.149">TestTableSnapshotMapper</a>()</pre>
 </li>
 </ul>
 </li>
@@ -233,7 +233,7 @@ extends org.apache.hadoop.hbase.mapreduce.TableMapper&lt;org.apache.hadoop.hbase
 <ul class="blockListLast">
 <li class="blockList">
 <h4>map</h4>
-<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotMapper.html#line.149">map</a>(org.apache.hadoop.hbase.io.ImmutableBytesWritable&nbsp;key,
+<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotMapper.html#line.152">map</a>(org.apache.hadoop.hbase.io.ImmutableBytesWritable&nbsp;key,
                    org.apache.hadoop.hbase.client.Result&nbsp;value,
                    org.apache.hadoop.mapreduce.Mapper.Context&nbsp;context)
             throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a>,
diff --git a/testdevapidocs/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotReducer.html b/testdevapidocs/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotReducer.html
index 353ad02..3b4e8ca 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotReducer.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotReducer.html
@@ -118,7 +118,7 @@ var activeTableTab = "activeTableTab";
 </dl>
 <hr>
 <br>
-<pre>public static class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.157">TestTableSnapshotInputFormat.TestTableSnapshotReducer</a>
+<pre>public static class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.160">TestTableSnapshotInputFormat.TestTableSnapshotReducer</a>
 extends org.apache.hadoop.mapreduce.Reducer&lt;org.apache.hadoop.hbase.io.ImmutableBytesWritable,org.apache.hadoop.io.NullWritable,org.apache.hadoop.io.NullWritable,org.apache.hadoop.io.NullWritable&gt;</pre>
 </li>
 </ul>
@@ -234,7 +234,7 @@ extends org.apache.hadoop.mapreduce.Reducer&lt;org.apache.hadoop.hbase.io.Immuta
 <ul class="blockListLast">
 <li class="blockList">
 <h4>rowTracker</h4>
-<pre><a href="../../../../../org/apache/hadoop/hbase/HBaseTestingUtil.SeenRowTracker.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtil.SeenRowTracker</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotReducer.html#line.159">rowTracker</a></pre>
+<pre><a href="../../../../../org/apache/hadoop/hbase/HBaseTestingUtil.SeenRowTracker.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtil.SeenRowTracker</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotReducer.html#line.162">rowTracker</a></pre>
 </li>
 </ul>
 </li>
@@ -251,7 +251,7 @@ extends org.apache.hadoop.mapreduce.Reducer&lt;org.apache.hadoop.hbase.io.Immuta
 <ul class="blockListLast">
 <li class="blockList">
 <h4>TestTableSnapshotReducer</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotReducer.html#line.157">TestTableSnapshotReducer</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotReducer.html#line.160">TestTableSnapshotReducer</a>()</pre>
 </li>
 </ul>
 </li>
@@ -268,7 +268,7 @@ extends org.apache.hadoop.mapreduce.Reducer&lt;org.apache.hadoop.hbase.io.Immuta
 <ul class="blockList">
 <li class="blockList">
 <h4>reduce</h4>
-<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotReducer.html#line.162">reduce</a>(org.apache.hadoop.hbase.io.ImmutableBytesWritable&nbsp;key,
+<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotReducer.html#line.165">reduce</a>(org.apache.hadoop.hbase.io.ImmutableBytesWritable&nbsp;key,
                       <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Iterable.html?is-external=true" title="class or interface in java.lang">Iterable</a>&lt;org.apache.hadoop.io.NullWritable&gt;&nbsp;values,
                       org.apache.hadoop.mapreduce.Reducer.Context&nbsp;context)
                throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a>,
@@ -288,7 +288,7 @@ extends org.apache.hadoop.mapreduce.Reducer&lt;org.apache.hadoop.hbase.io.Immuta
 <ul class="blockListLast">
 <li class="blockList">
 <h4>cleanup</h4>
-<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotReducer.html#line.168">cleanup</a>(org.apache.hadoop.mapreduce.Reducer.Context&nbsp;context)
+<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotReducer.html#line.171">cleanup</a>(org.apache.hadoop.mapreduce.Reducer.Context&nbsp;context)
                 throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a>,
                        <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InterruptedException.html?is-external=true" title="class or interface in java.lang">InterruptedException</a></pre>
 <dl>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html b/testdevapidocs/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html
index 98bda3d..0d91132 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html
@@ -18,7 +18,7 @@
     catch(err) {
     }
 //-->
-var methods = {"i0":9,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10};
+var methods = {"i0":9,"i1":10,"i2":10,"i3":10,"i4":10,"i5":10,"i6":10,"i7":10,"i8":10,"i9":10,"i10":10,"i11":10,"i12":10,"i13":10,"i14":10,"i15":10,"i16":10};
 var tabs = {65535:["t0","All Methods"],1:["t1","Static Methods"],2:["t2","Instance Methods"],8:["t4","Concrete Methods"]};
 var altColor = "altColor";
 var rowColor = "rowColor";
@@ -114,7 +114,7 @@ var activeTableTab = "activeTableTab";
 <li class="blockList">
 <hr>
 <br>
-<pre>public class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.71">TestTableSnapshotInputFormat</a>
+<pre>public class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.74">TestTableSnapshotInputFormat</a>
 extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatTestBase.html" title="class in org.apache.hadoop.hbase.mapreduce">TableSnapshotInputFormatTestBase</a></pre>
 </li>
 </ul>
@@ -250,28 +250,40 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#getStartRow--">getStartRow</a></span>()</code>&nbsp;</td>
 </tr>
 <tr id="i3" class="rowColor">
+<td class="colFirst"><code>private org.apache.hadoop.hbase.client.Scan</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#serializeAndReturn-org.apache.hadoop.conf.Configuration-org.apache.hadoop.hbase.client.Scan-">serializeAndReturn</a></span>(org.apache.hadoop.conf.Configuration&nbsp;conf,
+                  org.apache.hadoop.hbase.client.Scan&nbsp;s)</code>
+<div class="block">Serializes and deserializes the given scan in the same manner that
+ TableSnapshotInputFormat does.</div>
+</td>
+</tr>
+<tr id="i4" class="altColor">
 <td class="colFirst"><code>void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#testGetBestLocations--">testGetBestLocations</a></span>()</code>&nbsp;</td>
 </tr>
-<tr id="i4" class="altColor">
+<tr id="i5" class="rowColor">
 <td class="colFirst"><code>void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#testInitTableSnapshotMapperJobConfig--">testInitTableSnapshotMapperJobConfig</a></span>()</code>&nbsp;</td>
 </tr>
-<tr id="i5" class="rowColor">
+<tr id="i6" class="altColor">
 <td class="colFirst"><code>void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#testNoDuplicateResultsWhenSplitting--">testNoDuplicateResultsWhenSplitting</a></span>()</code>&nbsp;</td>
 </tr>
-<tr id="i6" class="altColor">
+<tr id="i7" class="rowColor">
 <td class="colFirst"><code>void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#testRestoreSnapshotDoesNotCreateBackRefLinksInit-org.apache.hadoop.hbase.TableName-java.lang.String-org.apache.hadoop.fs.Path-">testRestoreSnapshotDoesNotCreateBackRefLinksInit</a></span>(org.apache.hadoop.hbase.TableName&nbsp;tableName,
                                                 <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;snapshotName,
                                                 org.apache.hadoop.fs.Path&nbsp;tmpTableDir)</code>&nbsp;</td>
 </tr>
-<tr id="i7" class="rowColor">
+<tr id="i8" class="altColor">
 <td class="colFirst"><code>void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#testScanLimit--">testScanLimit</a></span>()</code>&nbsp;</td>
 </tr>
-<tr id="i8" class="altColor">
+<tr id="i9" class="rowColor">
+<td class="colFirst"><code>void</code></td>
+<td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#testScannerReadTypeConfiguration--">testScannerReadTypeConfiguration</a></span>()</code>&nbsp;</td>
+</tr>
+<tr id="i10" class="altColor">
 <td class="colFirst"><code>protected void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#testWithMapReduceImpl-org.apache.hadoop.hbase.HBaseTestingUtil-org.apache.hadoop.hbase.TableName-java.lang.String-org.apache.hadoop.fs.Path-int-int-int-boolean-">testWithMapReduceImpl</a></span>(<a href="../../../../../org/apache/hadoop/hbase/HBaseTestingUtil.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtil</a>&nbsp;util,
                      org.apache.hadoop.hbase.TableName&nbsp;tableName,
@@ -282,11 +294,11 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
                      int&nbsp;expectedNumSplits,
                      boolean&nbsp;shutdownCluster)</code>&nbsp;</td>
 </tr>
-<tr id="i9" class="rowColor">
+<tr id="i11" class="rowColor">
 <td class="colFirst"><code>void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#testWithMapReduceMultipleMappersPerRegion--">testWithMapReduceMultipleMappersPerRegion</a></span>()</code>&nbsp;</td>
 </tr>
-<tr id="i10" class="altColor">
+<tr id="i12" class="altColor">
 <td class="colFirst"><code>void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#testWithMockedMapReduce-org.apache.hadoop.hbase.HBaseTestingUtil-java.lang.String-int-int-int-boolean-">testWithMockedMapReduce</a></span>(<a href="../../../../../org/apache/hadoop/hbase/HBaseTestingUtil.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtil</a>&nbsp;util,
                        <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;snapshotName,
@@ -295,19 +307,19 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
                        int&nbsp;expectedNumSplits,
                        boolean&nbsp;setLocalityEnabledTo)</code>&nbsp;</td>
 </tr>
-<tr id="i11" class="rowColor">
+<tr id="i13" class="rowColor">
 <td class="colFirst"><code>void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#testWithMockedMapReduceSingleRegionByRegionLocation--">testWithMockedMapReduceSingleRegionByRegionLocation</a></span>()</code>&nbsp;</td>
 </tr>
-<tr id="i12" class="altColor">
+<tr id="i14" class="altColor">
 <td class="colFirst"><code>void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#testWithMockedMapReduceWithNoStartRowStopRow--">testWithMockedMapReduceWithNoStartRowStopRow</a></span>()</code>&nbsp;</td>
 </tr>
-<tr id="i13" class="rowColor">
+<tr id="i15" class="rowColor">
 <td class="colFirst"><code>void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#testWithMockedMapReduceWithSplitsPerRegion--">testWithMockedMapReduceWithSplitsPerRegion</a></span>()</code>&nbsp;</td>
 </tr>
-<tr id="i14" class="altColor">
+<tr id="i16" class="altColor">
 <td class="colFirst"><code>private void</code></td>
 <td class="colLast"><code><span class="memberNameLink"><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#verifyWithMockedMapReduce-org.apache.hadoop.mapreduce.Job-int-int-byte:A-byte:A-">verifyWithMockedMapReduce</a></span>(org.apache.hadoop.mapreduce.Job&nbsp;job,
                          int&nbsp;numRegions,
@@ -350,7 +362,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>CLASS_RULE</h4>
-<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/HBaseClassTestRule.html" title="class in org.apache.hadoop.hbase">HBaseClassTestRule</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.74">CLASS_RULE</a></pre>
+<pre>public static final&nbsp;<a href="../../../../../org/apache/hadoop/hbase/HBaseClassTestRule.html" title="class in org.apache.hadoop.hbase">HBaseClassTestRule</a> <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.77">CLASS_RULE</a></pre>
 </li>
 </ul>
 <a name="LOG">
@@ -359,7 +371,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>LOG</h4>
-<pre>private static final&nbsp;org.slf4j.Logger <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.77">LOG</a></pre>
+<pre>private static final&nbsp;org.slf4j.Logger <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.80">LOG</a></pre>
 </li>
 </ul>
 <a name="bbb">
@@ -368,7 +380,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>bbb</h4>
-<pre>private static final&nbsp;byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.79">bbb</a></pre>
+<pre>private static final&nbsp;byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.82">bbb</a></pre>
 </li>
 </ul>
 <a name="yyy">
@@ -377,7 +389,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>yyy</h4>
-<pre>private static final&nbsp;byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.80">yyy</a></pre>
+<pre>private static final&nbsp;byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.83">yyy</a></pre>
 </li>
 </ul>
 <a name="bbc">
@@ -386,7 +398,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>bbc</h4>
-<pre>private static final&nbsp;byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.81">bbc</a></pre>
+<pre>private static final&nbsp;byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.84">bbc</a></pre>
 </li>
 </ul>
 <a name="yya">
@@ -395,7 +407,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>yya</h4>
-<pre>private static final&nbsp;byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.82">yya</a></pre>
+<pre>private static final&nbsp;byte[] <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.85">yya</a></pre>
 </li>
 </ul>
 <a name="name">
@@ -404,7 +416,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockListLast">
 <li class="blockList">
 <h4>name</h4>
-<pre>public&nbsp;org.junit.rules.TestName <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.85">name</a></pre>
+<pre>public&nbsp;org.junit.rules.TestName <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.88">name</a></pre>
 </li>
 </ul>
 </li>
@@ -421,7 +433,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockListLast">
 <li class="blockList">
 <h4>TestTableSnapshotInputFormat</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.71">TestTableSnapshotInputFormat</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.74">TestTableSnapshotInputFormat</a>()</pre>
 </li>
 </ul>
 </li>
@@ -438,7 +450,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>getStartRow</h4>
-<pre>protected&nbsp;byte[]&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.88">getStartRow</a>()</pre>
+<pre>protected&nbsp;byte[]&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.91">getStartRow</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatTestBase.html#getStartRow--">getStartRow</a></code>&nbsp;in class&nbsp;<code><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatTestBase.html" title="class in org.apache.hadoop.hbase.mapreduce">TableSnapshotInputFormatTestBase</a></code></dd>
@@ -451,7 +463,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>getEndRow</h4>
-<pre>protected&nbsp;byte[]&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.93">getEndRow</a>()</pre>
+<pre>protected&nbsp;byte[]&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.96">getEndRow</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatTestBase.html#getEndRow--">getEndRow</a></code>&nbsp;in class&nbsp;<code><a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotInputFormatTestBase.html" title="class in org.apache.hadoop.hbase.mapreduce">TableSnapshotInputFormatTestBase</a></code></dd>
@@ -464,7 +476,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>testGetBestLocations</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.99">testGetBestLocations</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.102">testGetBestLocations</a>()
                           throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -478,7 +490,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>testInitTableSnapshotMapperJobConfig</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.175">testInitTableSnapshotMapperJobConfig</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.178">testInitTableSnapshotMapperJobConfig</a>()
                                           throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -492,7 +504,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>testWithMockedMapReduceSingleRegionByRegionLocation</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.204">testWithMockedMapReduceSingleRegionByRegionLocation</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.207">testWithMockedMapReduceSingleRegionByRegionLocation</a>()
                                                          throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -506,7 +518,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>testRestoreSnapshotDoesNotCreateBackRefLinksInit</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.216">testRestoreSnapshotDoesNotCreateBackRefLinksInit</a>(org.apache.hadoop.hbase.TableName&nbsp;tableName,
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.219">testRestoreSnapshotDoesNotCreateBackRefLinksInit</a>(org.apache.hadoop.hbase.TableName&nbsp;tableName,
                                                              <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;snapshotName,
                                                              org.apache.hadoop.fs.Path&nbsp;tmpTableDir)
                                                       throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
@@ -524,7 +536,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>testWithMockedMapReduce</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.225">testWithMockedMapReduce</a>(<a href="../../../../../org/apache/hadoop/hbase/HBaseTestingUtil.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtil</a>&nbsp;util,
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.228">testWithMockedMapReduce</a>(<a href="../../../../../org/apache/hadoop/hbase/HBaseTestingUtil.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtil</a>&nbsp;util,
                                     <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;snapshotName,
                                     int&nbsp;numRegions,
                                     int&nbsp;numSplitsPerRegion,
@@ -545,7 +557,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>testWithMockedMapReduceWithSplitsPerRegion</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.261">testWithMockedMapReduceWithSplitsPerRegion</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.264">testWithMockedMapReduceWithSplitsPerRegion</a>()
                                                 throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -559,7 +571,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>testWithMockedMapReduceWithNoStartRowStopRow</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.286">testWithMockedMapReduceWithNoStartRowStopRow</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.289">testWithMockedMapReduceWithNoStartRowStopRow</a>()
                                                   throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -573,7 +585,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>testScanLimit</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.313">testScanLimit</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.316">testScanLimit</a>()
                    throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -587,7 +599,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>testNoDuplicateResultsWhenSplitting</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.361">testNoDuplicateResultsWhenSplitting</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.364">testNoDuplicateResultsWhenSplitting</a>()
                                          throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
@@ -595,13 +607,44 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 </dl>
 </li>
 </ul>
+<a name="testScannerReadTypeConfiguration--">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>testScannerReadTypeConfiguration</h4>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.414">testScannerReadTypeConfiguration</a>()
+                                      throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
+<dl>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></code></dd>
+</dl>
+</li>
+</ul>
+<a name="serializeAndReturn-org.apache.hadoop.conf.Configuration-org.apache.hadoop.hbase.client.Scan-">
+<!--   -->
+</a>
+<ul class="blockList">
+<li class="blockList">
+<h4>serializeAndReturn</h4>
+<pre>private&nbsp;org.apache.hadoop.hbase.client.Scan&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.438">serializeAndReturn</a>(org.apache.hadoop.conf.Configuration&nbsp;conf,
+                                                               org.apache.hadoop.hbase.client.Scan&nbsp;s)
+                                                        throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
+<div class="block">Serializes and deserializes the given scan in the same manner that
+ TableSnapshotInputFormat does.</div>
+<dl>
+<dt><span class="throwsLabel">Throws:</span></dt>
+<dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></code></dd>
+</dl>
+</li>
+</ul>
 <a name="verifyWithMockedMapReduce-org.apache.hadoop.mapreduce.Job-int-int-byte:A-byte:A-">
 <!--   -->
 </a>
 <ul class="blockList">
 <li class="blockList">
 <h4>verifyWithMockedMapReduce</h4>
-<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.410">verifyWithMockedMapReduce</a>(org.apache.hadoop.mapreduce.Job&nbsp;job,
+<pre>private&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.443">verifyWithMockedMapReduce</a>(org.apache.hadoop.mapreduce.Job&nbsp;job,
                                        int&nbsp;numRegions,
                                        int&nbsp;expectedNumSplits,
                                        byte[]&nbsp;startRow,
@@ -621,7 +664,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>testWithMapReduceImpl</h4>
-<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.486">testWithMapReduceImpl</a>(<a href="../../../../../org/apache/hadoop/hbase/HBaseTestingUtil.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtil</a>&nbsp;util,
+<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.519">testWithMapReduceImpl</a>(<a href="../../../../../org/apache/hadoop/hbase/HBaseTestingUtil.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtil</a>&nbsp;util,
                                      org.apache.hadoop.hbase.TableName&nbsp;tableName,
                                      <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;snapshotName,
                                      org.apache.hadoop.fs.Path&nbsp;tableDir,
@@ -644,7 +687,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockList">
 <li class="blockList">
 <h4>doTestWithMapReduce</h4>
-<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.494">doTestWithMapReduce</a>(<a href="../../../../../org/apache/hadoop/hbase/HBaseTestingUtil.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtil</a>&nbsp;util,
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.527">doTestWithMapReduce</a>(<a href="../../../../../org/apache/hadoop/hbase/HBaseTestingUtil.html" title="class in org.apache.hadoop.hbase">HBaseTestingUtil</a>&nbsp;util,
                                        org.apache.hadoop.hbase.TableName&nbsp;tableName,
                                        <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;snapshotName,
                                        byte[]&nbsp;startRow,
@@ -667,7 +710,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/mapreduce/TableSnapshotI
 <ul class="blockListLast">
 <li class="blockList">
 <h4>testWithMapReduceMultipleMappersPerRegion</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.542">testWithMapReduceMultipleMappersPerRegion</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html#line.575">testWithMapReduceMultipleMappersPerRegion</a>()
                                                throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <dl>
 <dt><span class="throwsLabel">Throws:</span></dt>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/package-tree.html
index 64b82e8..233c5a2 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/package-tree.html
@@ -665,19 +665,19 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ScanPerformanceEvaluation.ScanCounter.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ScanPerformanceEvaluation.ScanCounter</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/IntegrationTestDDLMasterFailover.ACTION.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">IntegrationTestDDLMasterFailover.ACTION</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ClusterManager.ServiceType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ClusterManager.ServiceType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.RoleCommand.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.RoleCommand</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ZNodeClusterManager.CmdType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ZNodeClusterManager.CmdType</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ResourceChecker.Phase.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ResourceChecker.Phase</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.RoleState.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.RoleState</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/IntegrationTestDDLMasterFailover.ACTION.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">IntegrationTestDDLMasterFailover.ACTION</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/IntegrationTestRegionReplicaPerf.Stat.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">IntegrationTestRegionReplicaPerf.Stat</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ScanPerformanceEvaluation.ScanCounter.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ScanPerformanceEvaluation.ScanCounter</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HBaseClusterManager.Signal.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HBaseClusterManager.Signal</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ClusterManager.ServiceType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ClusterManager.ServiceType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.HealthSummary.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.HealthSummary</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HBaseClusterManager.CommandProvider.Operation.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HBaseClusterManager.CommandProvider.Operation</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.RoleState.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.RoleState</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/PerformanceEvaluation.Counter.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">PerformanceEvaluation.Counter</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HBaseClusterManager.Signal.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HBaseClusterManager.Signal</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ResourceChecker.Phase.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ResourceChecker.Phase</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/ZNodeClusterManager.CmdType.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">ZNodeClusterManager.CmdType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/RESTApiClusterManager.Service.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">RESTApiClusterManager.Service</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.<a href="../../../../org/apache/hadoop/hbase/HBaseClusterManager.CommandProvider.Operation.html" title="enum in org.apache.hadoop.hbase"><span class="typeNameLink">HBaseClusterManager.CommandProvider.Operation</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/procedure/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/procedure/package-tree.html
index 3ce38a7..4309238 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/procedure/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/procedure/package-tree.html
@@ -81,14 +81,14 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Object</span></a>
 <ul>
-<li type="circle">org.apache.hadoop.hbase.procedure2.Procedure&lt;TEnvironment&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;)
+<li type="circle">org.apache.hadoop.hbase.procedure.Procedure (implements java.util.concurrent.<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Callable.html?is-external=true" title="class or interface in java.util.concurrent">Callable</a>&lt;V&gt;, org.apache.hadoop.hbase.errorhandling.ForeignExceptionListener)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.procedure.<a href="../../../../../org/apache/hadoop/hbase/procedure/TestProcedureDescriber.TestProcedure.html" title="class in org.apache.hadoop.hbase.procedure"><span class="typeNameLink">TestProcedureDescriber.TestProcedure</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure.<a href="../../../../../org/apache/hadoop/hbase/procedure/TestProcedure.LatchedProcedure.html" title="class in org.apache.hadoop.hbase.procedure"><span class="typeNameLink">TestProcedure.LatchedProcedure</span></a></li>
 </ul>
 </li>
-<li type="circle">org.apache.hadoop.hbase.procedure.Procedure (implements java.util.concurrent.<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Callable.html?is-external=true" title="class or interface in java.util.concurrent">Callable</a>&lt;V&gt;, org.apache.hadoop.hbase.errorhandling.ForeignExceptionListener)
+<li type="circle">org.apache.hadoop.hbase.procedure2.Procedure&lt;TEnvironment&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;)
 <ul>
-<li type="circle">org.apache.hadoop.hbase.procedure.<a href="../../../../../org/apache/hadoop/hbase/procedure/TestProcedure.LatchedProcedure.html" title="class in org.apache.hadoop.hbase.procedure"><span class="typeNameLink">TestProcedure.LatchedProcedure</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure.<a href="../../../../../org/apache/hadoop/hbase/procedure/TestProcedureDescriber.TestProcedure.html" title="class in org.apache.hadoop.hbase.procedure"><span class="typeNameLink">TestProcedureDescriber.TestProcedure</span></a></li>
 </ul>
 </li>
 <li type="circle">org.apache.hadoop.hbase.procedure.ProcedureManager
diff --git a/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
index b3d77cd..7066e86 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/procedure2/package-tree.html
@@ -241,10 +241,10 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestStateMachineProcedure.TestSMProcedureState.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestStateMachineProcedure.TestSMProcedureState</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestYieldProcedures.TestStateMachineProcedure.State.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestYieldProcedures.TestStateMachineProcedure.State</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestProcedureRecovery.TestStateMachineProcedure.State.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestProcedureRecovery.TestStateMachineProcedure.State</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestProcedureBypass.StuckStateMachineState.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestProcedureBypass.StuckStateMachineState</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestStateMachineProcedure.TestSMProcedureState.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestStateMachineProcedure.TestSMProcedureState</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.procedure2.<a href="../../../../../org/apache/hadoop/hbase/procedure2/TestProcedureRecovery.TestStateMachineProcedure.State.html" title="enum in org.apache.hadoop.hbase.procedure2"><span class="typeNameLink">TestProcedureRecovery.TestStateMachineProcedure.State</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
index 13ed8be..ae1056d 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/regionserver/package-tree.html
@@ -734,12 +734,12 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestCacheOnWriteInSchema.CacheOnWriteType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestCacheOnWriteInSchema.CacheOnWriteType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestMultiLogThreshold.ActionType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestMultiLogThreshold.ActionType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/DataBlockEncodingTool.Manipulation.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">DataBlockEncodingTool.Manipulation</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestRegionServerReadRequestMetrics.Metric.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestRegionServerReadRequestMetrics.Metric</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestCompactionState.StateSource.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestCompactionState.StateSource</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestCacheOnWriteInSchema.CacheOnWriteType.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestCacheOnWriteInSchema.CacheOnWriteType</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestAtomicOperation.TestStep.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestAtomicOperation.TestStep</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/DataBlockEncodingTool.Manipulation.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">DataBlockEncodingTool.Manipulation</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.regionserver.<a href="../../../../../org/apache/hadoop/hbase/regionserver/TestRegionServerReadRequestMetrics.Metric.html" title="enum in org.apache.hadoop.hbase.regionserver"><span class="typeNameLink">TestRegionServerReadRequestMetrics.Metric</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html
index 8f059aa..507c98c 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/test/package-tree.html
@@ -260,11 +260,11 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestLoadAndVerify.Counters.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestLoadAndVerify.Counters</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.Counters.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestWithCellVisibilityLoadAndVerify.Counters</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestBigLinkedList.Verify.Counts.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestBigLinkedList.Verify.Counts</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestLoadCommonCrawl.Counts.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestLoadCommonCrawl.Counts</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestWithCellVisibilityLoadAndVerify.Counters.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestWithCellVisibilityLoadAndVerify.Counters</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestBigLinkedList.Generator.Counts.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestBigLinkedList.Generator.Counts</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.test.<a href="../../../../../org/apache/hadoop/hbase/test/IntegrationTestLoadAndVerify.Counters.html" title="enum in org.apache.hadoop.hbase.test"><span class="typeNameLink">IntegrationTestLoadAndVerify.Counters</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html b/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html
index 1a776a54..12bf261 100644
--- a/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html
+++ b/testdevapidocs/org/apache/hadoop/hbase/wal/package-tree.html
@@ -201,9 +201,9 @@
 <ul>
 <li type="circle">java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html?is-external=true" title="class or interface in java.lang"><span class="typeNameLink">Enum</span></a>&lt;E&gt; (implements java.lang.<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html?is-external=true" title="class or interface in java.lang">Comparable</a>&lt;T&gt;, java.io.<a href="https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html?is-external=true [...]
 <ul>
-<li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/FaultyFSLog.FailureType.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">FaultyFSLog.FailureType</span></a></li>
-<li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/IOTestProvider.AllowedOperations.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">IOTestProvider.AllowedOperations</span></a></li>
 <li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/TestWALSplit.Corruptions.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">TestWALSplit.Corruptions</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/IOTestProvider.AllowedOperations.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">IOTestProvider.AllowedOperations</span></a></li>
+<li type="circle">org.apache.hadoop.hbase.wal.<a href="../../../../../org/apache/hadoop/hbase/wal/FaultyFSLog.FailureType.html" title="enum in org.apache.hadoop.hbase.wal"><span class="typeNameLink">FaultyFSLog.FailureType</span></a></li>
 </ul>
 </li>
 </ul>
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html
index 8d67eec..82673a9 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotCounters.html
@@ -30,527 +30,560 @@
 <span class="sourceLineNo">022</span>import static org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT;<a name="line.22"></a>
 <span class="sourceLineNo">023</span>import static org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION;<a name="line.23"></a>
 <span class="sourceLineNo">024</span>import static org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT;<a name="line.24"></a>
-<span class="sourceLineNo">025</span>import static org.mockito.Mockito.mock;<a name="line.25"></a>
-<span class="sourceLineNo">026</span>import static org.mockito.Mockito.when;<a name="line.26"></a>
-<span class="sourceLineNo">027</span><a name="line.27"></a>
-<span class="sourceLineNo">028</span>import java.io.IOException;<a name="line.28"></a>
-<span class="sourceLineNo">029</span>import java.util.Arrays;<a name="line.29"></a>
-<span class="sourceLineNo">030</span>import java.util.List;<a name="line.30"></a>
-<span class="sourceLineNo">031</span>import org.apache.hadoop.conf.Configuration;<a name="line.31"></a>
-<span class="sourceLineNo">032</span>import org.apache.hadoop.fs.FileSystem;<a name="line.32"></a>
-<span class="sourceLineNo">033</span>import org.apache.hadoop.fs.Path;<a name="line.33"></a>
-<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.34"></a>
-<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.HBaseTestingUtil;<a name="line.35"></a>
-<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.HConstants;<a name="line.36"></a>
-<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.HDFSBlocksDistribution;<a name="line.37"></a>
-<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.TableName;<a name="line.38"></a>
-<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.client.Admin;<a name="line.39"></a>
-<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.client.Result;<a name="line.40"></a>
-<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.client.Scan;<a name="line.41"></a>
-<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.client.Table;<a name="line.42"></a>
-<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.client.TestTableSnapshotScanner;<a name="line.43"></a>
-<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<a name="line.44"></a>
-<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormat.TableSnapshotRegionSplit;<a name="line.45"></a>
-<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.snapshot.SnapshotTestingUtils;<a name="line.46"></a>
-<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.testclassification.LargeTests;<a name="line.47"></a>
-<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.testclassification.VerySlowMapReduceTests;<a name="line.48"></a>
-<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.49"></a>
-<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.50"></a>
-<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.util.RegionSplitter;<a name="line.51"></a>
-<span class="sourceLineNo">052</span>import org.apache.hadoop.io.NullWritable;<a name="line.52"></a>
-<span class="sourceLineNo">053</span>import org.apache.hadoop.mapreduce.InputSplit;<a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.apache.hadoop.mapreduce.Job;<a name="line.54"></a>
-<span class="sourceLineNo">055</span>import org.apache.hadoop.mapreduce.RecordReader;<a name="line.55"></a>
-<span class="sourceLineNo">056</span>import org.apache.hadoop.mapreduce.Reducer;<a name="line.56"></a>
-<span class="sourceLineNo">057</span>import org.apache.hadoop.mapreduce.TaskAttemptContext;<a name="line.57"></a>
-<span class="sourceLineNo">058</span>import org.apache.hadoop.mapreduce.lib.output.NullOutputFormat;<a name="line.58"></a>
-<span class="sourceLineNo">059</span>import org.junit.Assert;<a name="line.59"></a>
-<span class="sourceLineNo">060</span>import org.junit.ClassRule;<a name="line.60"></a>
-<span class="sourceLineNo">061</span>import org.junit.Rule;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>import org.junit.Test;<a name="line.62"></a>
-<span class="sourceLineNo">063</span>import org.junit.experimental.categories.Category;<a name="line.63"></a>
-<span class="sourceLineNo">064</span>import org.junit.rules.TestName;<a name="line.64"></a>
-<span class="sourceLineNo">065</span>import org.slf4j.Logger;<a name="line.65"></a>
-<span class="sourceLineNo">066</span>import org.slf4j.LoggerFactory;<a name="line.66"></a>
-<span class="sourceLineNo">067</span><a name="line.67"></a>
-<span class="sourceLineNo">068</span>import org.apache.hbase.thirdparty.com.google.common.collect.Lists;<a name="line.68"></a>
-<span class="sourceLineNo">069</span><a name="line.69"></a>
-<span class="sourceLineNo">070</span>@Category({VerySlowMapReduceTests.class, LargeTests.class})<a name="line.70"></a>
-<span class="sourceLineNo">071</span>public class TestTableSnapshotInputFormat extends TableSnapshotInputFormatTestBase {<a name="line.71"></a>
+<span class="sourceLineNo">025</span>import static org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE;<a name="line.25"></a>
+<span class="sourceLineNo">026</span>import static org.junit.Assert.assertEquals;<a name="line.26"></a>
+<span class="sourceLineNo">027</span>import static org.mockito.Mockito.mock;<a name="line.27"></a>
+<span class="sourceLineNo">028</span>import static org.mockito.Mockito.when;<a name="line.28"></a>
+<span class="sourceLineNo">029</span><a name="line.29"></a>
+<span class="sourceLineNo">030</span>import java.io.IOException;<a name="line.30"></a>
+<span class="sourceLineNo">031</span>import java.util.Arrays;<a name="line.31"></a>
+<span class="sourceLineNo">032</span>import java.util.List;<a name="line.32"></a>
+<span class="sourceLineNo">033</span>import org.apache.hadoop.conf.Configuration;<a name="line.33"></a>
+<span class="sourceLineNo">034</span>import org.apache.hadoop.fs.FileSystem;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.fs.Path;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.HBaseTestingUtil;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.HConstants;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.HDFSBlocksDistribution;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.TableName;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.client.Admin;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.client.Result;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.client.Scan;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.client.Scan.ReadType;<a name="line.44"></a>
+<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.client.Table;<a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.client.TestTableSnapshotScanner;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormat.TableSnapshotRegionSplit;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.snapshot.SnapshotTestingUtils;<a name="line.49"></a>
+<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.testclassification.LargeTests;<a name="line.50"></a>
+<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.testclassification.VerySlowMapReduceTests;<a name="line.51"></a>
+<span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.52"></a>
+<span class="sourceLineNo">053</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.53"></a>
+<span class="sourceLineNo">054</span>import org.apache.hadoop.hbase.util.RegionSplitter;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>import org.apache.hadoop.io.NullWritable;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>import org.apache.hadoop.mapreduce.InputSplit;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>import org.apache.hadoop.mapreduce.Job;<a name="line.57"></a>
+<span class="sourceLineNo">058</span>import org.apache.hadoop.mapreduce.RecordReader;<a name="line.58"></a>
+<span class="sourceLineNo">059</span>import org.apache.hadoop.mapreduce.Reducer;<a name="line.59"></a>
+<span class="sourceLineNo">060</span>import org.apache.hadoop.mapreduce.TaskAttemptContext;<a name="line.60"></a>
+<span class="sourceLineNo">061</span>import org.apache.hadoop.mapreduce.lib.output.NullOutputFormat;<a name="line.61"></a>
+<span class="sourceLineNo">062</span>import org.junit.Assert;<a name="line.62"></a>
+<span class="sourceLineNo">063</span>import org.junit.ClassRule;<a name="line.63"></a>
+<span class="sourceLineNo">064</span>import org.junit.Rule;<a name="line.64"></a>
+<span class="sourceLineNo">065</span>import org.junit.Test;<a name="line.65"></a>
+<span class="sourceLineNo">066</span>import org.junit.experimental.categories.Category;<a name="line.66"></a>
+<span class="sourceLineNo">067</span>import org.junit.rules.TestName;<a name="line.67"></a>
+<span class="sourceLineNo">068</span>import org.slf4j.Logger;<a name="line.68"></a>
+<span class="sourceLineNo">069</span>import org.slf4j.LoggerFactory;<a name="line.69"></a>
+<span class="sourceLineNo">070</span><a name="line.70"></a>
+<span class="sourceLineNo">071</span>import org.apache.hbase.thirdparty.com.google.common.collect.Lists;<a name="line.71"></a>
 <span class="sourceLineNo">072</span><a name="line.72"></a>
-<span class="sourceLineNo">073</span>  @ClassRule<a name="line.73"></a>
-<span class="sourceLineNo">074</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.74"></a>
-<span class="sourceLineNo">075</span>      HBaseClassTestRule.forClass(TestTableSnapshotInputFormat.class);<a name="line.75"></a>
-<span class="sourceLineNo">076</span><a name="line.76"></a>
-<span class="sourceLineNo">077</span>  private static final Logger LOG = LoggerFactory.getLogger(TestTableSnapshotInputFormat.class);<a name="line.77"></a>
-<span class="sourceLineNo">078</span><a name="line.78"></a>
-<span class="sourceLineNo">079</span>  private static final byte[] bbb = Bytes.toBytes("bbb");<a name="line.79"></a>
-<span class="sourceLineNo">080</span>  private static final byte[] yyy = Bytes.toBytes("yyy");<a name="line.80"></a>
-<span class="sourceLineNo">081</span>  private static final byte[] bbc = Bytes.toBytes("bbc");<a name="line.81"></a>
-<span class="sourceLineNo">082</span>  private static final byte[] yya = Bytes.toBytes("yya");<a name="line.82"></a>
-<span class="sourceLineNo">083</span><a name="line.83"></a>
-<span class="sourceLineNo">084</span>  @Rule<a name="line.84"></a>
-<span class="sourceLineNo">085</span>  public TestName name = new TestName();<a name="line.85"></a>
+<span class="sourceLineNo">073</span>@Category({VerySlowMapReduceTests.class, LargeTests.class})<a name="line.73"></a>
+<span class="sourceLineNo">074</span>public class TestTableSnapshotInputFormat extends TableSnapshotInputFormatTestBase {<a name="line.74"></a>
+<span class="sourceLineNo">075</span><a name="line.75"></a>
+<span class="sourceLineNo">076</span>  @ClassRule<a name="line.76"></a>
+<span class="sourceLineNo">077</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.77"></a>
+<span class="sourceLineNo">078</span>      HBaseClassTestRule.forClass(TestTableSnapshotInputFormat.class);<a name="line.78"></a>
+<span class="sourceLineNo">079</span><a name="line.79"></a>
+<span class="sourceLineNo">080</span>  private static final Logger LOG = LoggerFactory.getLogger(TestTableSnapshotInputFormat.class);<a name="line.80"></a>
+<span class="sourceLineNo">081</span><a name="line.81"></a>
+<span class="sourceLineNo">082</span>  private static final byte[] bbb = Bytes.toBytes("bbb");<a name="line.82"></a>
+<span class="sourceLineNo">083</span>  private static final byte[] yyy = Bytes.toBytes("yyy");<a name="line.83"></a>
+<span class="sourceLineNo">084</span>  private static final byte[] bbc = Bytes.toBytes("bbc");<a name="line.84"></a>
+<span class="sourceLineNo">085</span>  private static final byte[] yya = Bytes.toBytes("yya");<a name="line.85"></a>
 <span class="sourceLineNo">086</span><a name="line.86"></a>
-<span class="sourceLineNo">087</span>  @Override<a name="line.87"></a>
-<span class="sourceLineNo">088</span>  protected byte[] getStartRow() {<a name="line.88"></a>
-<span class="sourceLineNo">089</span>    return bbb;<a name="line.89"></a>
-<span class="sourceLineNo">090</span>  }<a name="line.90"></a>
-<span class="sourceLineNo">091</span><a name="line.91"></a>
-<span class="sourceLineNo">092</span>  @Override<a name="line.92"></a>
-<span class="sourceLineNo">093</span>  protected byte[] getEndRow() {<a name="line.93"></a>
-<span class="sourceLineNo">094</span>    return yyy;<a name="line.94"></a>
-<span class="sourceLineNo">095</span>  }<a name="line.95"></a>
-<span class="sourceLineNo">096</span><a name="line.96"></a>
-<span class="sourceLineNo">097</span><a name="line.97"></a>
-<span class="sourceLineNo">098</span>  @Test<a name="line.98"></a>
-<span class="sourceLineNo">099</span>  public void testGetBestLocations() throws IOException {<a name="line.99"></a>
-<span class="sourceLineNo">100</span>    TableSnapshotInputFormatImpl tsif = new TableSnapshotInputFormatImpl();<a name="line.100"></a>
-<span class="sourceLineNo">101</span>    Configuration conf = UTIL.getConfiguration();<a name="line.101"></a>
-<span class="sourceLineNo">102</span><a name="line.102"></a>
-<span class="sourceLineNo">103</span>    HDFSBlocksDistribution blockDistribution = new HDFSBlocksDistribution();<a name="line.103"></a>
-<span class="sourceLineNo">104</span>    Assert.assertEquals(null,<a name="line.104"></a>
-<span class="sourceLineNo">105</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.105"></a>
-<span class="sourceLineNo">106</span><a name="line.106"></a>
-<span class="sourceLineNo">107</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 1);<a name="line.107"></a>
-<span class="sourceLineNo">108</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.108"></a>
-<span class="sourceLineNo">109</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.109"></a>
-<span class="sourceLineNo">110</span><a name="line.110"></a>
-<span class="sourceLineNo">111</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 1);<a name="line.111"></a>
-<span class="sourceLineNo">112</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.112"></a>
-<span class="sourceLineNo">113</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.113"></a>
-<span class="sourceLineNo">114</span><a name="line.114"></a>
-<span class="sourceLineNo">115</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 1);<a name="line.115"></a>
-<span class="sourceLineNo">116</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.116"></a>
-<span class="sourceLineNo">117</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.117"></a>
-<span class="sourceLineNo">118</span><a name="line.118"></a>
-<span class="sourceLineNo">119</span>    blockDistribution = new HDFSBlocksDistribution();<a name="line.119"></a>
-<span class="sourceLineNo">120</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 10);<a name="line.120"></a>
-<span class="sourceLineNo">121</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 7);<a name="line.121"></a>
-<span class="sourceLineNo">122</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h3"}, 5);<a name="line.122"></a>
-<span class="sourceLineNo">123</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h4"}, 1);<a name="line.123"></a>
-<span class="sourceLineNo">124</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.124"></a>
-<span class="sourceLineNo">125</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.125"></a>
-<span class="sourceLineNo">126</span><a name="line.126"></a>
-<span class="sourceLineNo">127</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 2);<a name="line.127"></a>
-<span class="sourceLineNo">128</span>    Assert.assertEquals(Lists.newArrayList("h1", "h2"),<a name="line.128"></a>
-<span class="sourceLineNo">129</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.129"></a>
-<span class="sourceLineNo">130</span><a name="line.130"></a>
-<span class="sourceLineNo">131</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 3);<a name="line.131"></a>
-<span class="sourceLineNo">132</span>    Assert.assertEquals(Lists.newArrayList("h2", "h1"),<a name="line.132"></a>
-<span class="sourceLineNo">133</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.133"></a>
-<span class="sourceLineNo">134</span><a name="line.134"></a>
-<span class="sourceLineNo">135</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h3"}, 6);<a name="line.135"></a>
-<span class="sourceLineNo">136</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h4"}, 9);<a name="line.136"></a>
+<span class="sourceLineNo">087</span>  @Rule<a name="line.87"></a>
+<span class="sourceLineNo">088</span>  public TestName name = new TestName();<a name="line.88"></a>
+<span class="sourceLineNo">089</span><a name="line.89"></a>
+<span class="sourceLineNo">090</span>  @Override<a name="line.90"></a>
+<span class="sourceLineNo">091</span>  protected byte[] getStartRow() {<a name="line.91"></a>
+<span class="sourceLineNo">092</span>    return bbb;<a name="line.92"></a>
+<span class="sourceLineNo">093</span>  }<a name="line.93"></a>
+<span class="sourceLineNo">094</span><a name="line.94"></a>
+<span class="sourceLineNo">095</span>  @Override<a name="line.95"></a>
+<span class="sourceLineNo">096</span>  protected byte[] getEndRow() {<a name="line.96"></a>
+<span class="sourceLineNo">097</span>    return yyy;<a name="line.97"></a>
+<span class="sourceLineNo">098</span>  }<a name="line.98"></a>
+<span class="sourceLineNo">099</span><a name="line.99"></a>
+<span class="sourceLineNo">100</span><a name="line.100"></a>
+<span class="sourceLineNo">101</span>  @Test<a name="line.101"></a>
+<span class="sourceLineNo">102</span>  public void testGetBestLocations() throws IOException {<a name="line.102"></a>
+<span class="sourceLineNo">103</span>    TableSnapshotInputFormatImpl tsif = new TableSnapshotInputFormatImpl();<a name="line.103"></a>
+<span class="sourceLineNo">104</span>    Configuration conf = UTIL.getConfiguration();<a name="line.104"></a>
+<span class="sourceLineNo">105</span><a name="line.105"></a>
+<span class="sourceLineNo">106</span>    HDFSBlocksDistribution blockDistribution = new HDFSBlocksDistribution();<a name="line.106"></a>
+<span class="sourceLineNo">107</span>    Assert.assertEquals(null,<a name="line.107"></a>
+<span class="sourceLineNo">108</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.108"></a>
+<span class="sourceLineNo">109</span><a name="line.109"></a>
+<span class="sourceLineNo">110</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 1);<a name="line.110"></a>
+<span class="sourceLineNo">111</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.111"></a>
+<span class="sourceLineNo">112</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.112"></a>
+<span class="sourceLineNo">113</span><a name="line.113"></a>
+<span class="sourceLineNo">114</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 1);<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.115"></a>
+<span class="sourceLineNo">116</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.116"></a>
+<span class="sourceLineNo">117</span><a name="line.117"></a>
+<span class="sourceLineNo">118</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 1);<a name="line.118"></a>
+<span class="sourceLineNo">119</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.119"></a>
+<span class="sourceLineNo">120</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.120"></a>
+<span class="sourceLineNo">121</span><a name="line.121"></a>
+<span class="sourceLineNo">122</span>    blockDistribution = new HDFSBlocksDistribution();<a name="line.122"></a>
+<span class="sourceLineNo">123</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 10);<a name="line.123"></a>
+<span class="sourceLineNo">124</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 7);<a name="line.124"></a>
+<span class="sourceLineNo">125</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h3"}, 5);<a name="line.125"></a>
+<span class="sourceLineNo">126</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h4"}, 1);<a name="line.126"></a>
+<span class="sourceLineNo">127</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.127"></a>
+<span class="sourceLineNo">128</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.128"></a>
+<span class="sourceLineNo">129</span><a name="line.129"></a>
+<span class="sourceLineNo">130</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 2);<a name="line.130"></a>
+<span class="sourceLineNo">131</span>    Assert.assertEquals(Lists.newArrayList("h1", "h2"),<a name="line.131"></a>
+<span class="sourceLineNo">132</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.132"></a>
+<span class="sourceLineNo">133</span><a name="line.133"></a>
+<span class="sourceLineNo">134</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 3);<a name="line.134"></a>
+<span class="sourceLineNo">135</span>    Assert.assertEquals(Lists.newArrayList("h2", "h1"),<a name="line.135"></a>
+<span class="sourceLineNo">136</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.136"></a>
 <span class="sourceLineNo">137</span><a name="line.137"></a>
-<span class="sourceLineNo">138</span>    Assert.assertEquals(Lists.newArrayList("h2", "h3", "h4"),<a name="line.138"></a>
-<span class="sourceLineNo">139</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.139"></a>
-<span class="sourceLineNo">140</span>  }<a name="line.140"></a>
-<span class="sourceLineNo">141</span><a name="line.141"></a>
-<span class="sourceLineNo">142</span>  public static enum TestTableSnapshotCounters {<a name="line.142"></a>
-<span class="sourceLineNo">143</span>    VALIDATION_ERROR<a name="line.143"></a>
-<span class="sourceLineNo">144</span>  }<a name="line.144"></a>
-<span class="sourceLineNo">145</span><a name="line.145"></a>
-<span class="sourceLineNo">146</span>  public static class TestTableSnapshotMapper<a name="line.146"></a>
-<span class="sourceLineNo">147</span>    extends TableMapper&lt;ImmutableBytesWritable, NullWritable&gt; {<a name="line.147"></a>
-<span class="sourceLineNo">148</span>    @Override<a name="line.148"></a>
-<span class="sourceLineNo">149</span>    protected void map(ImmutableBytesWritable key, Result value,<a name="line.149"></a>
-<span class="sourceLineNo">150</span>        Context context) throws IOException, InterruptedException {<a name="line.150"></a>
-<span class="sourceLineNo">151</span>      // Validate a single row coming from the snapshot, and emit the row key<a name="line.151"></a>
-<span class="sourceLineNo">152</span>      verifyRowFromMap(key, value);<a name="line.152"></a>
-<span class="sourceLineNo">153</span>      context.write(key, NullWritable.get());<a name="line.153"></a>
-<span class="sourceLineNo">154</span>    }<a name="line.154"></a>
-<span class="sourceLineNo">155</span>  }<a name="line.155"></a>
-<span class="sourceLineNo">156</span><a name="line.156"></a>
-<span class="sourceLineNo">157</span>  public static class TestTableSnapshotReducer<a name="line.157"></a>
-<span class="sourceLineNo">158</span>    extends Reducer&lt;ImmutableBytesWritable, NullWritable, NullWritable, NullWritable&gt; {<a name="line.158"></a>
-<span class="sourceLineNo">159</span>    HBaseTestingUtil.SeenRowTracker rowTracker =<a name="line.159"></a>
-<span class="sourceLineNo">160</span>        new HBaseTestingUtil.SeenRowTracker(bbb, yyy);<a name="line.160"></a>
-<span class="sourceLineNo">161</span>    @Override<a name="line.161"></a>
-<span class="sourceLineNo">162</span>    protected void reduce(ImmutableBytesWritable key, Iterable&lt;NullWritable&gt; values,<a name="line.162"></a>
-<span class="sourceLineNo">163</span>       Context context) throws IOException, InterruptedException {<a name="line.163"></a>
-<span class="sourceLineNo">164</span>      rowTracker.addRow(key.get());<a name="line.164"></a>
-<span class="sourceLineNo">165</span>    }<a name="line.165"></a>
-<span class="sourceLineNo">166</span><a name="line.166"></a>
-<span class="sourceLineNo">167</span>    @Override<a name="line.167"></a>
-<span class="sourceLineNo">168</span>    protected void cleanup(Context context) throws IOException,<a name="line.168"></a>
-<span class="sourceLineNo">169</span>        InterruptedException {<a name="line.169"></a>
-<span class="sourceLineNo">170</span>      rowTracker.validate();<a name="line.170"></a>
-<span class="sourceLineNo">171</span>    }<a name="line.171"></a>
-<span class="sourceLineNo">172</span>  }<a name="line.172"></a>
-<span class="sourceLineNo">173</span><a name="line.173"></a>
-<span class="sourceLineNo">174</span>  @Test<a name="line.174"></a>
-<span class="sourceLineNo">175</span>  public void testInitTableSnapshotMapperJobConfig() throws Exception {<a name="line.175"></a>
-<span class="sourceLineNo">176</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.176"></a>
-<span class="sourceLineNo">177</span>    String snapshotName = "foo";<a name="line.177"></a>
-<span class="sourceLineNo">178</span><a name="line.178"></a>
-<span class="sourceLineNo">179</span>    try {<a name="line.179"></a>
-<span class="sourceLineNo">180</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 1);<a name="line.180"></a>
-<span class="sourceLineNo">181</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.181"></a>
-<span class="sourceLineNo">182</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.182"></a>
-<span class="sourceLineNo">183</span><a name="line.183"></a>
-<span class="sourceLineNo">184</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.184"></a>
-<span class="sourceLineNo">185</span>        new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.185"></a>
-<span class="sourceLineNo">186</span>        NullWritable.class, job, false, tmpTableDir);<a name="line.186"></a>
-<span class="sourceLineNo">187</span><a name="line.187"></a>
-<span class="sourceLineNo">188</span>      // TODO: would be better to examine directly the cache instance that results from this<a name="line.188"></a>
-<span class="sourceLineNo">189</span>      // config. Currently this is not possible because BlockCache initialization is static.<a name="line.189"></a>
-<span class="sourceLineNo">190</span>      Assert.assertEquals(<a name="line.190"></a>
-<span class="sourceLineNo">191</span>        "Snapshot job should be configured for default LruBlockCache.",<a name="line.191"></a>
-<span class="sourceLineNo">192</span>        HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT,<a name="line.192"></a>
-<span class="sourceLineNo">193</span>        job.getConfiguration().getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, -1), 0.01);<a name="line.193"></a>
-<span class="sourceLineNo">194</span>      Assert.assertEquals(<a name="line.194"></a>
-<span class="sourceLineNo">195</span>        "Snapshot job should not use BucketCache.",<a name="line.195"></a>
-<span class="sourceLineNo">196</span>        0, job.getConfiguration().getFloat("hbase.bucketcache.size", -1), 0.01);<a name="line.196"></a>
-<span class="sourceLineNo">197</span>    } finally {<a name="line.197"></a>
-<span class="sourceLineNo">198</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.198"></a>
-<span class="sourceLineNo">199</span>      UTIL.deleteTable(tableName);<a name="line.199"></a>
-<span class="sourceLineNo">200</span>    }<a name="line.200"></a>
-<span class="sourceLineNo">201</span>  }<a name="line.201"></a>
-<span class="sourceLineNo">202</span><a name="line.202"></a>
-<span class="sourceLineNo">203</span>  @Test<a name="line.203"></a>
-<span class="sourceLineNo">204</span>  public void testWithMockedMapReduceSingleRegionByRegionLocation() throws Exception {<a name="line.204"></a>
-<span class="sourceLineNo">205</span>    Configuration conf = UTIL.getConfiguration();<a name="line.205"></a>
-<span class="sourceLineNo">206</span>    conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION, true);<a name="line.206"></a>
-<span class="sourceLineNo">207</span>    try {<a name="line.207"></a>
-<span class="sourceLineNo">208</span>      testWithMockedMapReduce(UTIL, name.getMethodName() + "Snapshot", 1, 1, 1,<a name="line.208"></a>
-<span class="sourceLineNo">209</span>        true);<a name="line.209"></a>
-<span class="sourceLineNo">210</span>    } finally {<a name="line.210"></a>
-<span class="sourceLineNo">211</span>      conf.unset(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION);<a name="line.211"></a>
-<span class="sourceLineNo">212</span>    }<a name="line.212"></a>
-<span class="sourceLineNo">213</span>  }<a name="line.213"></a>
-<span class="sourceLineNo">214</span><a name="line.214"></a>
-<span class="sourceLineNo">215</span>  @Override<a name="line.215"></a>
-<span class="sourceLineNo">216</span>  public void testRestoreSnapshotDoesNotCreateBackRefLinksInit(TableName tableName,<a name="line.216"></a>
-<span class="sourceLineNo">217</span>      String snapshotName, Path tmpTableDir) throws Exception {<a name="line.217"></a>
-<span class="sourceLineNo">218</span>    Job job = new Job(UTIL.getConfiguration());<a name="line.218"></a>
-<span class="sourceLineNo">219</span>    TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.219"></a>
-<span class="sourceLineNo">220</span>      new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.220"></a>
-<span class="sourceLineNo">221</span>      NullWritable.class, job, false, tmpTableDir);<a name="line.221"></a>
-<span class="sourceLineNo">222</span>  }<a name="line.222"></a>
-<span class="sourceLineNo">223</span><a name="line.223"></a>
-<span class="sourceLineNo">224</span>  @Override<a name="line.224"></a>
-<span class="sourceLineNo">225</span>  public void testWithMockedMapReduce(HBaseTestingUtil util, String snapshotName,<a name="line.225"></a>
-<span class="sourceLineNo">226</span>      int numRegions, int numSplitsPerRegion, int expectedNumSplits, boolean setLocalityEnabledTo)<a name="line.226"></a>
-<span class="sourceLineNo">227</span>      throws Exception {<a name="line.227"></a>
-<span class="sourceLineNo">228</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.228"></a>
-<span class="sourceLineNo">229</span>    try {<a name="line.229"></a>
-<span class="sourceLineNo">230</span>      createTableAndSnapshot(<a name="line.230"></a>
-<span class="sourceLineNo">231</span>        util, tableName, snapshotName, getStartRow(), getEndRow(), numRegions);<a name="line.231"></a>
-<span class="sourceLineNo">232</span><a name="line.232"></a>
-<span class="sourceLineNo">233</span>      Configuration conf = util.getConfiguration();<a name="line.233"></a>
-<span class="sourceLineNo">234</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, setLocalityEnabledTo);<a name="line.234"></a>
-<span class="sourceLineNo">235</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.235"></a>
-<span class="sourceLineNo">236</span>        SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.236"></a>
-<span class="sourceLineNo">237</span>      Job job = new Job(conf);<a name="line.237"></a>
-<span class="sourceLineNo">238</span>      Path tmpTableDir = util.getDataTestDirOnTestFS(snapshotName);<a name="line.238"></a>
-<span class="sourceLineNo">239</span>      Scan scan = new Scan().withStartRow(getStartRow()).withStopRow(getEndRow()); // limit the scan<a name="line.239"></a>
-<span class="sourceLineNo">240</span><a name="line.240"></a>
-<span class="sourceLineNo">241</span>      if (numSplitsPerRegion &gt; 1) {<a name="line.241"></a>
-<span class="sourceLineNo">242</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.242"></a>
-<span class="sourceLineNo">243</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.243"></a>
-<span class="sourceLineNo">244</span>                NullWritable.class, job, false, tmpTableDir, new RegionSplitter.UniformSplit(),<a name="line.244"></a>
-<span class="sourceLineNo">245</span>                numSplitsPerRegion);<a name="line.245"></a>
-<span class="sourceLineNo">246</span>      } else {<a name="line.246"></a>
-<span class="sourceLineNo">247</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.247"></a>
-<span class="sourceLineNo">248</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.248"></a>
-<span class="sourceLineNo">249</span>                NullWritable.class, job, false, tmpTableDir);<a name="line.249"></a>
-<span class="sourceLineNo">250</span>      }<a name="line.250"></a>
-<span class="sourceLineNo">251</span><a name="line.251"></a>
-<span class="sourceLineNo">252</span>      verifyWithMockedMapReduce(job, numRegions, expectedNumSplits, getStartRow(), getEndRow());<a name="line.252"></a>
-<span class="sourceLineNo">253</span><a name="line.253"></a>
-<span class="sourceLineNo">254</span>    } finally {<a name="line.254"></a>
-<span class="sourceLineNo">255</span>      util.getAdmin().deleteSnapshot(snapshotName);<a name="line.255"></a>
-<span class="sourceLineNo">256</span>      util.deleteTable(tableName);<a name="line.256"></a>
-<span class="sourceLineNo">257</span>    }<a name="line.257"></a>
-<span class="sourceLineNo">258</span>  }<a name="line.258"></a>
-<span class="sourceLineNo">259</span><a name="line.259"></a>
-<span class="sourceLineNo">260</span>  @Test<a name="line.260"></a>
-<span class="sourceLineNo">261</span>  public void testWithMockedMapReduceWithSplitsPerRegion() throws Exception {<a name="line.261"></a>
-<span class="sourceLineNo">262</span>    String snapshotName = "testWithMockedMapReduceMultiRegion";<a name="line.262"></a>
-<span class="sourceLineNo">263</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.263"></a>
-<span class="sourceLineNo">264</span>    try {<a name="line.264"></a>
-<span class="sourceLineNo">265</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 10);<a name="line.265"></a>
-<span class="sourceLineNo">266</span><a name="line.266"></a>
-<span class="sourceLineNo">267</span>      Configuration conf = UTIL.getConfiguration();<a name="line.267"></a>
-<span class="sourceLineNo">268</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, false);<a name="line.268"></a>
-<span class="sourceLineNo">269</span>      Job job = new Job(conf);<a name="line.269"></a>
-<span class="sourceLineNo">270</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.270"></a>
-<span class="sourceLineNo">271</span>      // test scan with startRow and stopRow<a name="line.271"></a>
-<span class="sourceLineNo">272</span>      Scan scan = new Scan().withStartRow(bbc).withStopRow(yya);<a name="line.272"></a>
-<span class="sourceLineNo">273</span><a name="line.273"></a>
-<span class="sourceLineNo">274</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.274"></a>
-<span class="sourceLineNo">275</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.275"></a>
-<span class="sourceLineNo">276</span>        tmpTableDir, new RegionSplitter.UniformSplit(), 5);<a name="line.276"></a>
-<span class="sourceLineNo">277</span><a name="line.277"></a>
-<span class="sourceLineNo">278</span>      verifyWithMockedMapReduce(job, 10, 40, bbc, yya);<a name="line.278"></a>
-<span class="sourceLineNo">279</span>    } finally {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.280"></a>
-<span class="sourceLineNo">281</span>      UTIL.deleteTable(tableName);<a name="line.281"></a>
-<span class="sourceLineNo">282</span>    }<a name="line.282"></a>
-<span class="sourceLineNo">283</span>  }<a name="line.283"></a>
-<span class="sourceLineNo">284</span><a name="line.284"></a>
-<span class="sourceLineNo">285</span>  @Test<a name="line.285"></a>
-<span class="sourceLineNo">286</span>  public void testWithMockedMapReduceWithNoStartRowStopRow() throws Exception {<a name="line.286"></a>
-<span class="sourceLineNo">287</span>    String snapshotName = "testWithMockedMapReduceMultiRegion";<a name="line.287"></a>
-<span class="sourceLineNo">288</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.288"></a>
-<span class="sourceLineNo">289</span>    try {<a name="line.289"></a>
-<span class="sourceLineNo">290</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 10);<a name="line.290"></a>
-<span class="sourceLineNo">291</span><a name="line.291"></a>
-<span class="sourceLineNo">292</span>      Configuration conf = UTIL.getConfiguration();<a name="line.292"></a>
-<span class="sourceLineNo">293</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, false);<a name="line.293"></a>
-<span class="sourceLineNo">294</span>      Job job = new Job(conf);<a name="line.294"></a>
-<span class="sourceLineNo">295</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.295"></a>
-<span class="sourceLineNo">296</span>      // test scan without startRow and stopRow<a name="line.296"></a>
-<span class="sourceLineNo">297</span>      Scan scan2 = new Scan();<a name="line.297"></a>
-<span class="sourceLineNo">298</span><a name="line.298"></a>
-<span class="sourceLineNo">299</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan2,<a name="line.299"></a>
-<span class="sourceLineNo">300</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.300"></a>
-<span class="sourceLineNo">301</span>        tmpTableDir, new RegionSplitter.UniformSplit(), 5);<a name="line.301"></a>
-<span class="sourceLineNo">302</span><a name="line.302"></a>
-<span class="sourceLineNo">303</span>      verifyWithMockedMapReduce(job, 10, 50, HConstants.EMPTY_START_ROW,<a name="line.303"></a>
-<span class="sourceLineNo">304</span>        HConstants.EMPTY_START_ROW);<a name="line.304"></a>
+<span class="sourceLineNo">138</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h3"}, 6);<a name="line.138"></a>
+<span class="sourceLineNo">139</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h4"}, 9);<a name="line.139"></a>
+<span class="sourceLineNo">140</span><a name="line.140"></a>
+<span class="sourceLineNo">141</span>    Assert.assertEquals(Lists.newArrayList("h2", "h3", "h4"),<a name="line.141"></a>
+<span class="sourceLineNo">142</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.142"></a>
+<span class="sourceLineNo">143</span>  }<a name="line.143"></a>
+<span class="sourceLineNo">144</span><a name="line.144"></a>
+<span class="sourceLineNo">145</span>  public static enum TestTableSnapshotCounters {<a name="line.145"></a>
+<span class="sourceLineNo">146</span>    VALIDATION_ERROR<a name="line.146"></a>
+<span class="sourceLineNo">147</span>  }<a name="line.147"></a>
+<span class="sourceLineNo">148</span><a name="line.148"></a>
+<span class="sourceLineNo">149</span>  public static class TestTableSnapshotMapper<a name="line.149"></a>
+<span class="sourceLineNo">150</span>    extends TableMapper&lt;ImmutableBytesWritable, NullWritable&gt; {<a name="line.150"></a>
+<span class="sourceLineNo">151</span>    @Override<a name="line.151"></a>
+<span class="sourceLineNo">152</span>    protected void map(ImmutableBytesWritable key, Result value,<a name="line.152"></a>
+<span class="sourceLineNo">153</span>        Context context) throws IOException, InterruptedException {<a name="line.153"></a>
+<span class="sourceLineNo">154</span>      // Validate a single row coming from the snapshot, and emit the row key<a name="line.154"></a>
+<span class="sourceLineNo">155</span>      verifyRowFromMap(key, value);<a name="line.155"></a>
+<span class="sourceLineNo">156</span>      context.write(key, NullWritable.get());<a name="line.156"></a>
+<span class="sourceLineNo">157</span>    }<a name="line.157"></a>
+<span class="sourceLineNo">158</span>  }<a name="line.158"></a>
+<span class="sourceLineNo">159</span><a name="line.159"></a>
+<span class="sourceLineNo">160</span>  public static class TestTableSnapshotReducer<a name="line.160"></a>
+<span class="sourceLineNo">161</span>    extends Reducer&lt;ImmutableBytesWritable, NullWritable, NullWritable, NullWritable&gt; {<a name="line.161"></a>
+<span class="sourceLineNo">162</span>    HBaseTestingUtil.SeenRowTracker rowTracker =<a name="line.162"></a>
+<span class="sourceLineNo">163</span>        new HBaseTestingUtil.SeenRowTracker(bbb, yyy);<a name="line.163"></a>
+<span class="sourceLineNo">164</span>    @Override<a name="line.164"></a>
+<span class="sourceLineNo">165</span>    protected void reduce(ImmutableBytesWritable key, Iterable&lt;NullWritable&gt; values,<a name="line.165"></a>
+<span class="sourceLineNo">166</span>       Context context) throws IOException, InterruptedException {<a name="line.166"></a>
+<span class="sourceLineNo">167</span>      rowTracker.addRow(key.get());<a name="line.167"></a>
+<span class="sourceLineNo">168</span>    }<a name="line.168"></a>
+<span class="sourceLineNo">169</span><a name="line.169"></a>
+<span class="sourceLineNo">170</span>    @Override<a name="line.170"></a>
+<span class="sourceLineNo">171</span>    protected void cleanup(Context context) throws IOException,<a name="line.171"></a>
+<span class="sourceLineNo">172</span>        InterruptedException {<a name="line.172"></a>
+<span class="sourceLineNo">173</span>      rowTracker.validate();<a name="line.173"></a>
+<span class="sourceLineNo">174</span>    }<a name="line.174"></a>
+<span class="sourceLineNo">175</span>  }<a name="line.175"></a>
+<span class="sourceLineNo">176</span><a name="line.176"></a>
+<span class="sourceLineNo">177</span>  @Test<a name="line.177"></a>
+<span class="sourceLineNo">178</span>  public void testInitTableSnapshotMapperJobConfig() throws Exception {<a name="line.178"></a>
+<span class="sourceLineNo">179</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.179"></a>
+<span class="sourceLineNo">180</span>    String snapshotName = "foo";<a name="line.180"></a>
+<span class="sourceLineNo">181</span><a name="line.181"></a>
+<span class="sourceLineNo">182</span>    try {<a name="line.182"></a>
+<span class="sourceLineNo">183</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 1);<a name="line.183"></a>
+<span class="sourceLineNo">184</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.184"></a>
+<span class="sourceLineNo">185</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.185"></a>
+<span class="sourceLineNo">186</span><a name="line.186"></a>
+<span class="sourceLineNo">187</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.187"></a>
+<span class="sourceLineNo">188</span>        new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.188"></a>
+<span class="sourceLineNo">189</span>        NullWritable.class, job, false, tmpTableDir);<a name="line.189"></a>
+<span class="sourceLineNo">190</span><a name="line.190"></a>
+<span class="sourceLineNo">191</span>      // TODO: would be better to examine directly the cache instance that results from this<a name="line.191"></a>
+<span class="sourceLineNo">192</span>      // config. Currently this is not possible because BlockCache initialization is static.<a name="line.192"></a>
+<span class="sourceLineNo">193</span>      Assert.assertEquals(<a name="line.193"></a>
+<span class="sourceLineNo">194</span>        "Snapshot job should be configured for default LruBlockCache.",<a name="line.194"></a>
+<span class="sourceLineNo">195</span>        HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT,<a name="line.195"></a>
+<span class="sourceLineNo">196</span>        job.getConfiguration().getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, -1), 0.01);<a name="line.196"></a>
+<span class="sourceLineNo">197</span>      Assert.assertEquals(<a name="line.197"></a>
+<span class="sourceLineNo">198</span>        "Snapshot job should not use BucketCache.",<a name="line.198"></a>
+<span class="sourceLineNo">199</span>        0, job.getConfiguration().getFloat("hbase.bucketcache.size", -1), 0.01);<a name="line.199"></a>
+<span class="sourceLineNo">200</span>    } finally {<a name="line.200"></a>
+<span class="sourceLineNo">201</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.201"></a>
+<span class="sourceLineNo">202</span>      UTIL.deleteTable(tableName);<a name="line.202"></a>
+<span class="sourceLineNo">203</span>    }<a name="line.203"></a>
+<span class="sourceLineNo">204</span>  }<a name="line.204"></a>
+<span class="sourceLineNo">205</span><a name="line.205"></a>
+<span class="sourceLineNo">206</span>  @Test<a name="line.206"></a>
+<span class="sourceLineNo">207</span>  public void testWithMockedMapReduceSingleRegionByRegionLocation() throws Exception {<a name="line.207"></a>
+<span class="sourceLineNo">208</span>    Configuration conf = UTIL.getConfiguration();<a name="line.208"></a>
+<span class="sourceLineNo">209</span>    conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION, true);<a name="line.209"></a>
+<span class="sourceLineNo">210</span>    try {<a name="line.210"></a>
+<span class="sourceLineNo">211</span>      testWithMockedMapReduce(UTIL, name.getMethodName() + "Snapshot", 1, 1, 1,<a name="line.211"></a>
+<span class="sourceLineNo">212</span>        true);<a name="line.212"></a>
+<span class="sourceLineNo">213</span>    } finally {<a name="line.213"></a>
+<span class="sourceLineNo">214</span>      conf.unset(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION);<a name="line.214"></a>
+<span class="sourceLineNo">215</span>    }<a name="line.215"></a>
+<span class="sourceLineNo">216</span>  }<a name="line.216"></a>
+<span class="sourceLineNo">217</span><a name="line.217"></a>
+<span class="sourceLineNo">218</span>  @Override<a name="line.218"></a>
+<span class="sourceLineNo">219</span>  public void testRestoreSnapshotDoesNotCreateBackRefLinksInit(TableName tableName,<a name="line.219"></a>
+<span class="sourceLineNo">220</span>      String snapshotName, Path tmpTableDir) throws Exception {<a name="line.220"></a>
+<span class="sourceLineNo">221</span>    Job job = new Job(UTIL.getConfiguration());<a name="line.221"></a>
+<span class="sourceLineNo">222</span>    TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.222"></a>
+<span class="sourceLineNo">223</span>      new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.223"></a>
+<span class="sourceLineNo">224</span>      NullWritable.class, job, false, tmpTableDir);<a name="line.224"></a>
+<span class="sourceLineNo">225</span>  }<a name="line.225"></a>
+<span class="sourceLineNo">226</span><a name="line.226"></a>
+<span class="sourceLineNo">227</span>  @Override<a name="line.227"></a>
+<span class="sourceLineNo">228</span>  public void testWithMockedMapReduce(HBaseTestingUtil util, String snapshotName,<a name="line.228"></a>
+<span class="sourceLineNo">229</span>      int numRegions, int numSplitsPerRegion, int expectedNumSplits, boolean setLocalityEnabledTo)<a name="line.229"></a>
+<span class="sourceLineNo">230</span>      throws Exception {<a name="line.230"></a>
+<span class="sourceLineNo">231</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.231"></a>
+<span class="sourceLineNo">232</span>    try {<a name="line.232"></a>
+<span class="sourceLineNo">233</span>      createTableAndSnapshot(<a name="line.233"></a>
+<span class="sourceLineNo">234</span>        util, tableName, snapshotName, getStartRow(), getEndRow(), numRegions);<a name="line.234"></a>
+<span class="sourceLineNo">235</span><a name="line.235"></a>
+<span class="sourceLineNo">236</span>      Configuration conf = util.getConfiguration();<a name="line.236"></a>
+<span class="sourceLineNo">237</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, setLocalityEnabledTo);<a name="line.237"></a>
+<span class="sourceLineNo">238</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.238"></a>
+<span class="sourceLineNo">239</span>        SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.239"></a>
+<span class="sourceLineNo">240</span>      Job job = new Job(conf);<a name="line.240"></a>
+<span class="sourceLineNo">241</span>      Path tmpTableDir = util.getDataTestDirOnTestFS(snapshotName);<a name="line.241"></a>
+<span class="sourceLineNo">242</span>      Scan scan = new Scan().withStartRow(getStartRow()).withStopRow(getEndRow()); // limit the scan<a name="line.242"></a>
+<span class="sourceLineNo">243</span><a name="line.243"></a>
+<span class="sourceLineNo">244</span>      if (numSplitsPerRegion &gt; 1) {<a name="line.244"></a>
+<span class="sourceLineNo">245</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.245"></a>
+<span class="sourceLineNo">246</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.246"></a>
+<span class="sourceLineNo">247</span>                NullWritable.class, job, false, tmpTableDir, new RegionSplitter.UniformSplit(),<a name="line.247"></a>
+<span class="sourceLineNo">248</span>                numSplitsPerRegion);<a name="line.248"></a>
+<span class="sourceLineNo">249</span>      } else {<a name="line.249"></a>
+<span class="sourceLineNo">250</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.250"></a>
+<span class="sourceLineNo">251</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.251"></a>
+<span class="sourceLineNo">252</span>                NullWritable.class, job, false, tmpTableDir);<a name="line.252"></a>
+<span class="sourceLineNo">253</span>      }<a name="line.253"></a>
+<span class="sourceLineNo">254</span><a name="line.254"></a>
+<span class="sourceLineNo">255</span>      verifyWithMockedMapReduce(job, numRegions, expectedNumSplits, getStartRow(), getEndRow());<a name="line.255"></a>
+<span class="sourceLineNo">256</span><a name="line.256"></a>
+<span class="sourceLineNo">257</span>    } finally {<a name="line.257"></a>
+<span class="sourceLineNo">258</span>      util.getAdmin().deleteSnapshot(snapshotName);<a name="line.258"></a>
+<span class="sourceLineNo">259</span>      util.deleteTable(tableName);<a name="line.259"></a>
+<span class="sourceLineNo">260</span>    }<a name="line.260"></a>
+<span class="sourceLineNo">261</span>  }<a name="line.261"></a>
+<span class="sourceLineNo">262</span><a name="line.262"></a>
+<span class="sourceLineNo">263</span>  @Test<a name="line.263"></a>
+<span class="sourceLineNo">264</span>  public void testWithMockedMapReduceWithSplitsPerRegion() throws Exception {<a name="line.264"></a>
+<span class="sourceLineNo">265</span>    String snapshotName = "testWithMockedMapReduceMultiRegion";<a name="line.265"></a>
+<span class="sourceLineNo">266</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.266"></a>
+<span class="sourceLineNo">267</span>    try {<a name="line.267"></a>
+<span class="sourceLineNo">268</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 10);<a name="line.268"></a>
+<span class="sourceLineNo">269</span><a name="line.269"></a>
+<span class="sourceLineNo">270</span>      Configuration conf = UTIL.getConfiguration();<a name="line.270"></a>
+<span class="sourceLineNo">271</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, false);<a name="line.271"></a>
+<span class="sourceLineNo">272</span>      Job job = new Job(conf);<a name="line.272"></a>
+<span class="sourceLineNo">273</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.273"></a>
+<span class="sourceLineNo">274</span>      // test scan with startRow and stopRow<a name="line.274"></a>
+<span class="sourceLineNo">275</span>      Scan scan = new Scan().withStartRow(bbc).withStopRow(yya);<a name="line.275"></a>
+<span class="sourceLineNo">276</span><a name="line.276"></a>
+<span class="sourceLineNo">277</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.277"></a>
+<span class="sourceLineNo">278</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.278"></a>
+<span class="sourceLineNo">279</span>        tmpTableDir, new RegionSplitter.UniformSplit(), 5);<a name="line.279"></a>
+<span class="sourceLineNo">280</span><a name="line.280"></a>
+<span class="sourceLineNo">281</span>      verifyWithMockedMapReduce(job, 10, 40, bbc, yya);<a name="line.281"></a>
+<span class="sourceLineNo">282</span>    } finally {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.283"></a>
+<span class="sourceLineNo">284</span>      UTIL.deleteTable(tableName);<a name="line.284"></a>
+<span class="sourceLineNo">285</span>    }<a name="line.285"></a>
+<span class="sourceLineNo">286</span>  }<a name="line.286"></a>
+<span class="sourceLineNo">287</span><a name="line.287"></a>
+<span class="sourceLineNo">288</span>  @Test<a name="line.288"></a>
+<span class="sourceLineNo">289</span>  public void testWithMockedMapReduceWithNoStartRowStopRow() throws Exception {<a name="line.289"></a>
+<span class="sourceLineNo">290</span>    String snapshotName = "testWithMockedMapReduceMultiRegion";<a name="line.290"></a>
+<span class="sourceLineNo">291</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.291"></a>
+<span class="sourceLineNo">292</span>    try {<a name="line.292"></a>
+<span class="sourceLineNo">293</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 10);<a name="line.293"></a>
+<span class="sourceLineNo">294</span><a name="line.294"></a>
+<span class="sourceLineNo">295</span>      Configuration conf = UTIL.getConfiguration();<a name="line.295"></a>
+<span class="sourceLineNo">296</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, false);<a name="line.296"></a>
+<span class="sourceLineNo">297</span>      Job job = new Job(conf);<a name="line.297"></a>
+<span class="sourceLineNo">298</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.298"></a>
+<span class="sourceLineNo">299</span>      // test scan without startRow and stopRow<a name="line.299"></a>
+<span class="sourceLineNo">300</span>      Scan scan2 = new Scan();<a name="line.300"></a>
+<span class="sourceLineNo">301</span><a name="line.301"></a>
+<span class="sourceLineNo">302</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan2,<a name="line.302"></a>
+<span class="sourceLineNo">303</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.303"></a>
+<span class="sourceLineNo">304</span>        tmpTableDir, new RegionSplitter.UniformSplit(), 5);<a name="line.304"></a>
 <span class="sourceLineNo">305</span><a name="line.305"></a>
-<span class="sourceLineNo">306</span>    } finally {<a name="line.306"></a>
-<span class="sourceLineNo">307</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.307"></a>
-<span class="sourceLineNo">308</span>      UTIL.deleteTable(tableName);<a name="line.308"></a>
-<span class="sourceLineNo">309</span>    }<a name="line.309"></a>
-<span class="sourceLineNo">310</span>  }<a name="line.310"></a>
-<span class="sourceLineNo">311</span><a name="line.311"></a>
-<span class="sourceLineNo">312</span>  @Test<a name="line.312"></a>
-<span class="sourceLineNo">313</span>  public void testScanLimit() throws Exception {<a name="line.313"></a>
-<span class="sourceLineNo">314</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.314"></a>
-<span class="sourceLineNo">315</span>    final String snapshotName = tableName + "Snapshot";<a name="line.315"></a>
-<span class="sourceLineNo">316</span>    Table table = null;<a name="line.316"></a>
-<span class="sourceLineNo">317</span>    try {<a name="line.317"></a>
-<span class="sourceLineNo">318</span>      UTIL.getConfiguration().setInt(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT, 10);<a name="line.318"></a>
-<span class="sourceLineNo">319</span>      if (UTIL.getAdmin().tableExists(tableName)) {<a name="line.319"></a>
-<span class="sourceLineNo">320</span>        UTIL.deleteTable(tableName);<a name="line.320"></a>
-<span class="sourceLineNo">321</span>      }<a name="line.321"></a>
-<span class="sourceLineNo">322</span><a name="line.322"></a>
-<span class="sourceLineNo">323</span>      UTIL.createTable(tableName, FAMILIES, new byte[][] { bbb, yyy });<a name="line.323"></a>
-<span class="sourceLineNo">324</span><a name="line.324"></a>
-<span class="sourceLineNo">325</span>      Admin admin = UTIL.getAdmin();<a name="line.325"></a>
-<span class="sourceLineNo">326</span><a name="line.326"></a>
-<span class="sourceLineNo">327</span>      int regionNum = admin.getRegions(tableName).size();<a name="line.327"></a>
-<span class="sourceLineNo">328</span>      // put some stuff in the table<a name="line.328"></a>
-<span class="sourceLineNo">329</span>      table = UTIL.getConnection().getTable(tableName);<a name="line.329"></a>
-<span class="sourceLineNo">330</span>      UTIL.loadTable(table, FAMILIES);<a name="line.330"></a>
-<span class="sourceLineNo">331</span><a name="line.331"></a>
-<span class="sourceLineNo">332</span>      Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.332"></a>
-<span class="sourceLineNo">333</span>      FileSystem fs = rootDir.getFileSystem(UTIL.getConfiguration());<a name="line.333"></a>
+<span class="sourceLineNo">306</span>      verifyWithMockedMapReduce(job, 10, 50, HConstants.EMPTY_START_ROW,<a name="line.306"></a>
+<span class="sourceLineNo">307</span>        HConstants.EMPTY_START_ROW);<a name="line.307"></a>
+<span class="sourceLineNo">308</span><a name="line.308"></a>
+<span class="sourceLineNo">309</span>    } finally {<a name="line.309"></a>
+<span class="sourceLineNo">310</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.310"></a>
+<span class="sourceLineNo">311</span>      UTIL.deleteTable(tableName);<a name="line.311"></a>
+<span class="sourceLineNo">312</span>    }<a name="line.312"></a>
+<span class="sourceLineNo">313</span>  }<a name="line.313"></a>
+<span class="sourceLineNo">314</span><a name="line.314"></a>
+<span class="sourceLineNo">315</span>  @Test<a name="line.315"></a>
+<span class="sourceLineNo">316</span>  public void testScanLimit() throws Exception {<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.317"></a>
+<span class="sourceLineNo">318</span>    final String snapshotName = tableName + "Snapshot";<a name="line.318"></a>
+<span class="sourceLineNo">319</span>    Table table = null;<a name="line.319"></a>
+<span class="sourceLineNo">320</span>    try {<a name="line.320"></a>
+<span class="sourceLineNo">321</span>      UTIL.getConfiguration().setInt(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT, 10);<a name="line.321"></a>
+<span class="sourceLineNo">322</span>      if (UTIL.getAdmin().tableExists(tableName)) {<a name="line.322"></a>
+<span class="sourceLineNo">323</span>        UTIL.deleteTable(tableName);<a name="line.323"></a>
+<span class="sourceLineNo">324</span>      }<a name="line.324"></a>
+<span class="sourceLineNo">325</span><a name="line.325"></a>
+<span class="sourceLineNo">326</span>      UTIL.createTable(tableName, FAMILIES, new byte[][] { bbb, yyy });<a name="line.326"></a>
+<span class="sourceLineNo">327</span><a name="line.327"></a>
+<span class="sourceLineNo">328</span>      Admin admin = UTIL.getAdmin();<a name="line.328"></a>
+<span class="sourceLineNo">329</span><a name="line.329"></a>
+<span class="sourceLineNo">330</span>      int regionNum = admin.getRegions(tableName).size();<a name="line.330"></a>
+<span class="sourceLineNo">331</span>      // put some stuff in the table<a name="line.331"></a>
+<span class="sourceLineNo">332</span>      table = UTIL.getConnection().getTable(tableName);<a name="line.332"></a>
+<span class="sourceLineNo">333</span>      UTIL.loadTable(table, FAMILIES);<a name="line.333"></a>
 <span class="sourceLineNo">334</span><a name="line.334"></a>
-<span class="sourceLineNo">335</span>      SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName, Arrays.asList(FAMILIES),<a name="line.335"></a>
-<span class="sourceLineNo">336</span>        null, snapshotName, rootDir, fs, true);<a name="line.336"></a>
+<span class="sourceLineNo">335</span>      Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.335"></a>
+<span class="sourceLineNo">336</span>      FileSystem fs = rootDir.getFileSystem(UTIL.getConfiguration());<a name="line.336"></a>
 <span class="sourceLineNo">337</span><a name="line.337"></a>
-<span class="sourceLineNo">338</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.338"></a>
-<span class="sourceLineNo">339</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.339"></a>
-<span class="sourceLineNo">340</span>      Scan scan = new Scan();<a name="line.340"></a>
-<span class="sourceLineNo">341</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.341"></a>
-<span class="sourceLineNo">342</span>        TestTableSnapshotInputFormat.class);<a name="line.342"></a>
-<span class="sourceLineNo">343</span><a name="line.343"></a>
-<span class="sourceLineNo">344</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.344"></a>
-<span class="sourceLineNo">345</span>        RowCounter.RowCounterMapper.class, NullWritable.class, NullWritable.class, job, true,<a name="line.345"></a>
-<span class="sourceLineNo">346</span>        tmpTableDir);<a name="line.346"></a>
-<span class="sourceLineNo">347</span>      Assert.assertTrue(job.waitForCompletion(true));<a name="line.347"></a>
-<span class="sourceLineNo">348</span>      Assert.assertEquals(10 * regionNum,<a name="line.348"></a>
-<span class="sourceLineNo">349</span>        job.getCounters().findCounter(RowCounter.RowCounterMapper.Counters.ROWS).getValue());<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    } finally {<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      if (table != null) {<a name="line.351"></a>
-<span class="sourceLineNo">352</span>        table.close();<a name="line.352"></a>
-<span class="sourceLineNo">353</span>      }<a name="line.353"></a>
-<span class="sourceLineNo">354</span>      UTIL.getConfiguration().unset(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT);<a name="line.354"></a>
-<span class="sourceLineNo">355</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.355"></a>
-<span class="sourceLineNo">356</span>      UTIL.deleteTable(tableName);<a name="line.356"></a>
-<span class="sourceLineNo">357</span>    }<a name="line.357"></a>
-<span class="sourceLineNo">358</span>  }<a name="line.358"></a>
-<span class="sourceLineNo">359</span><a name="line.359"></a>
-<span class="sourceLineNo">360</span>  @Test<a name="line.360"></a>
-<span class="sourceLineNo">361</span>  public void testNoDuplicateResultsWhenSplitting() throws Exception {<a name="line.361"></a>
-<span class="sourceLineNo">362</span>    TableName tableName = TableName.valueOf("testNoDuplicateResultsWhenSplitting");<a name="line.362"></a>
-<span class="sourceLineNo">363</span>    String snapshotName = "testSnapshotBug";<a name="line.363"></a>
-<span class="sourceLineNo">364</span>    try {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>      if (UTIL.getAdmin().tableExists(tableName)) {<a name="line.365"></a>
-<span class="sourceLineNo">366</span>        UTIL.deleteTable(tableName);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>      }<a name="line.367"></a>
-<span class="sourceLineNo">368</span><a name="line.368"></a>
-<span class="sourceLineNo">369</span>      UTIL.createTable(tableName, FAMILIES);<a name="line.369"></a>
-<span class="sourceLineNo">370</span>      Admin admin = UTIL.getAdmin();<a name="line.370"></a>
+<span class="sourceLineNo">338</span>      SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName, Arrays.asList(FAMILIES),<a name="line.338"></a>
+<span class="sourceLineNo">339</span>        null, snapshotName, rootDir, fs, true);<a name="line.339"></a>
+<span class="sourceLineNo">340</span><a name="line.340"></a>
+<span class="sourceLineNo">341</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.341"></a>
+<span class="sourceLineNo">342</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.342"></a>
+<span class="sourceLineNo">343</span>      Scan scan = new Scan();<a name="line.343"></a>
+<span class="sourceLineNo">344</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.344"></a>
+<span class="sourceLineNo">345</span>        TestTableSnapshotInputFormat.class);<a name="line.345"></a>
+<span class="sourceLineNo">346</span><a name="line.346"></a>
+<span class="sourceLineNo">347</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.347"></a>
+<span class="sourceLineNo">348</span>        RowCounter.RowCounterMapper.class, NullWritable.class, NullWritable.class, job, true,<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        tmpTableDir);<a name="line.349"></a>
+<span class="sourceLineNo">350</span>      Assert.assertTrue(job.waitForCompletion(true));<a name="line.350"></a>
+<span class="sourceLineNo">351</span>      Assert.assertEquals(10 * regionNum,<a name="line.351"></a>
+<span class="sourceLineNo">352</span>        job.getCounters().findCounter(RowCounter.RowCounterMapper.Counters.ROWS).getValue());<a name="line.352"></a>
+<span class="sourceLineNo">353</span>    } finally {<a name="line.353"></a>
+<span class="sourceLineNo">354</span>      if (table != null) {<a name="line.354"></a>
+<span class="sourceLineNo">355</span>        table.close();<a name="line.355"></a>
+<span class="sourceLineNo">356</span>      }<a name="line.356"></a>
+<span class="sourceLineNo">357</span>      UTIL.getConfiguration().unset(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT);<a name="line.357"></a>
+<span class="sourceLineNo">358</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.358"></a>
+<span class="sourceLineNo">359</span>      UTIL.deleteTable(tableName);<a name="line.359"></a>
+<span class="sourceLineNo">360</span>    }<a name="line.360"></a>
+<span class="sourceLineNo">361</span>  }<a name="line.361"></a>
+<span class="sourceLineNo">362</span><a name="line.362"></a>
+<span class="sourceLineNo">363</span>  @Test<a name="line.363"></a>
+<span class="sourceLineNo">364</span>  public void testNoDuplicateResultsWhenSplitting() throws Exception {<a name="line.364"></a>
+<span class="sourceLineNo">365</span>    TableName tableName = TableName.valueOf("testNoDuplicateResultsWhenSplitting");<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    String snapshotName = "testSnapshotBug";<a name="line.366"></a>
+<span class="sourceLineNo">367</span>    try {<a name="line.367"></a>
+<span class="sourceLineNo">368</span>      if (UTIL.getAdmin().tableExists(tableName)) {<a name="line.368"></a>
+<span class="sourceLineNo">369</span>        UTIL.deleteTable(tableName);<a name="line.369"></a>
+<span class="sourceLineNo">370</span>      }<a name="line.370"></a>
 <span class="sourceLineNo">371</span><a name="line.371"></a>
-<span class="sourceLineNo">372</span>      // put some stuff in the table<a name="line.372"></a>
-<span class="sourceLineNo">373</span>      Table table = UTIL.getConnection().getTable(tableName);<a name="line.373"></a>
-<span class="sourceLineNo">374</span>      UTIL.loadTable(table, FAMILIES);<a name="line.374"></a>
-<span class="sourceLineNo">375</span><a name="line.375"></a>
-<span class="sourceLineNo">376</span>      // split to 2 regions<a name="line.376"></a>
-<span class="sourceLineNo">377</span>      admin.split(tableName, Bytes.toBytes("eee"));<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      TestTableSnapshotScanner.blockUntilSplitFinished(UTIL, tableName, 2);<a name="line.378"></a>
-<span class="sourceLineNo">379</span><a name="line.379"></a>
-<span class="sourceLineNo">380</span>      Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      FileSystem fs = rootDir.getFileSystem(UTIL.getConfiguration());<a name="line.381"></a>
+<span class="sourceLineNo">372</span>      UTIL.createTable(tableName, FAMILIES);<a name="line.372"></a>
+<span class="sourceLineNo">373</span>      Admin admin = UTIL.getAdmin();<a name="line.373"></a>
+<span class="sourceLineNo">374</span><a name="line.374"></a>
+<span class="sourceLineNo">375</span>      // put some stuff in the table<a name="line.375"></a>
+<span class="sourceLineNo">376</span>      Table table = UTIL.getConnection().getTable(tableName);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>      UTIL.loadTable(table, FAMILIES);<a name="line.377"></a>
+<span class="sourceLineNo">378</span><a name="line.378"></a>
+<span class="sourceLineNo">379</span>      // split to 2 regions<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      admin.split(tableName, Bytes.toBytes("eee"));<a name="line.380"></a>
+<span class="sourceLineNo">381</span>      TestTableSnapshotScanner.blockUntilSplitFinished(UTIL, tableName, 2);<a name="line.381"></a>
 <span class="sourceLineNo">382</span><a name="line.382"></a>
-<span class="sourceLineNo">383</span>      SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName, Arrays.asList(FAMILIES),<a name="line.383"></a>
-<span class="sourceLineNo">384</span>        null, snapshotName, rootDir, fs, true);<a name="line.384"></a>
+<span class="sourceLineNo">383</span>      Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      FileSystem fs = rootDir.getFileSystem(UTIL.getConfiguration());<a name="line.384"></a>
 <span class="sourceLineNo">385</span><a name="line.385"></a>
-<span class="sourceLineNo">386</span>      // load different values<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      byte[] value = Bytes.toBytes("after_snapshot_value");<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      UTIL.loadTable(table, FAMILIES, value);<a name="line.388"></a>
-<span class="sourceLineNo">389</span><a name="line.389"></a>
-<span class="sourceLineNo">390</span>      // cause flush to create new files in the region<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      admin.flush(tableName);<a name="line.391"></a>
-<span class="sourceLineNo">392</span>      table.close();<a name="line.392"></a>
-<span class="sourceLineNo">393</span><a name="line.393"></a>
-<span class="sourceLineNo">394</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>      // limit the scan<a name="line.396"></a>
-<span class="sourceLineNo">397</span>      Scan scan = new Scan().withStartRow(getStartRow()).withStopRow(getEndRow());<a name="line.397"></a>
-<span class="sourceLineNo">398</span><a name="line.398"></a>
-<span class="sourceLineNo">399</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.399"></a>
-<span class="sourceLineNo">400</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.400"></a>
-<span class="sourceLineNo">401</span>        tmpTableDir);<a name="line.401"></a>
-<span class="sourceLineNo">402</span><a name="line.402"></a>
-<span class="sourceLineNo">403</span>      verifyWithMockedMapReduce(job, 2, 2, getStartRow(), getEndRow());<a name="line.403"></a>
-<span class="sourceLineNo">404</span>    } finally {<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      UTIL.deleteTable(tableName);<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    }<a name="line.407"></a>
-<span class="sourceLineNo">408</span>  }<a name="line.408"></a>
-<span class="sourceLineNo">409</span><a name="line.409"></a>
-<span class="sourceLineNo">410</span>  private void verifyWithMockedMapReduce(Job job, int numRegions, int expectedNumSplits,<a name="line.410"></a>
-<span class="sourceLineNo">411</span>      byte[] startRow, byte[] stopRow)<a name="line.411"></a>
-<span class="sourceLineNo">412</span>      throws IOException, InterruptedException {<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    TableSnapshotInputFormat tsif = new TableSnapshotInputFormat();<a name="line.413"></a>
-<span class="sourceLineNo">414</span>    List&lt;InputSplit&gt; splits = tsif.getSplits(job);<a name="line.414"></a>
-<span class="sourceLineNo">415</span><a name="line.415"></a>
-<span class="sourceLineNo">416</span>    Assert.assertEquals(expectedNumSplits, splits.size());<a name="line.416"></a>
-<span class="sourceLineNo">417</span><a name="line.417"></a>
-<span class="sourceLineNo">418</span>    HBaseTestingUtil.SeenRowTracker rowTracker = new HBaseTestingUtil.SeenRowTracker(startRow,<a name="line.418"></a>
-<span class="sourceLineNo">419</span>        stopRow.length &gt; 0 ? stopRow : Bytes.toBytes("\uffff"));<a name="line.419"></a>
-<span class="sourceLineNo">420</span><a name="line.420"></a>
-<span class="sourceLineNo">421</span>    boolean localityEnabled =<a name="line.421"></a>
-<span class="sourceLineNo">422</span>        job.getConfiguration().getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY,<a name="line.422"></a>
-<span class="sourceLineNo">423</span>                                          SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT);<a name="line.423"></a>
-<span class="sourceLineNo">424</span><a name="line.424"></a>
-<span class="sourceLineNo">425</span>    boolean byRegionLoc =<a name="line.425"></a>
-<span class="sourceLineNo">426</span>      job.getConfiguration().getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.426"></a>
-<span class="sourceLineNo">427</span>                                        SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.427"></a>
-<span class="sourceLineNo">428</span>    for (int i = 0; i &lt; splits.size(); i++) {<a name="line.428"></a>
-<span class="sourceLineNo">429</span>      // validate input split<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      InputSplit split = splits.get(i);<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      Assert.assertTrue(split instanceof TableSnapshotRegionSplit);<a name="line.431"></a>
-<span class="sourceLineNo">432</span>      TableSnapshotRegionSplit snapshotRegionSplit = (TableSnapshotRegionSplit) split;<a name="line.432"></a>
-<span class="sourceLineNo">433</span>      if (localityEnabled) {<a name="line.433"></a>
-<span class="sourceLineNo">434</span>        Assert.assertTrue(split.getLocations() != null &amp;&amp; split.getLocations().length != 0);<a name="line.434"></a>
-<span class="sourceLineNo">435</span>        if (byRegionLoc) {<a name="line.435"></a>
-<span class="sourceLineNo">436</span>          // When it uses region location from meta, the hostname will be "localhost",<a name="line.436"></a>
-<span class="sourceLineNo">437</span>          // the location from hdfs block location is "127.0.0.1".<a name="line.437"></a>
-<span class="sourceLineNo">438</span>          Assert.assertEquals(1, split.getLocations().length);<a name="line.438"></a>
-<span class="sourceLineNo">439</span>          Assert.assertTrue("Not using region location!",<a name="line.439"></a>
-<span class="sourceLineNo">440</span>            split.getLocations()[0].equals("localhost"));<a name="line.440"></a>
-<span class="sourceLineNo">441</span>        } else {<a name="line.441"></a>
-<span class="sourceLineNo">442</span>          Assert.assertTrue("Not using region location!",<a name="line.442"></a>
-<span class="sourceLineNo">443</span>            split.getLocations()[0].equals("127.0.0.1"));<a name="line.443"></a>
-<span class="sourceLineNo">444</span>        }<a name="line.444"></a>
-<span class="sourceLineNo">445</span>      } else {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>        Assert.assertTrue(split.getLocations() != null &amp;&amp; split.getLocations().length == 0);<a name="line.446"></a>
-<span class="sourceLineNo">447</span>      }<a name="line.447"></a>
+<span class="sourceLineNo">386</span>      SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName, Arrays.asList(FAMILIES),<a name="line.386"></a>
+<span class="sourceLineNo">387</span>        null, snapshotName, rootDir, fs, true);<a name="line.387"></a>
+<span class="sourceLineNo">388</span><a name="line.388"></a>
+<span class="sourceLineNo">389</span>      // load different values<a name="line.389"></a>
+<span class="sourceLineNo">390</span>      byte[] value = Bytes.toBytes("after_snapshot_value");<a name="line.390"></a>
+<span class="sourceLineNo">391</span>      UTIL.loadTable(table, FAMILIES, value);<a name="line.391"></a>
+<span class="sourceLineNo">392</span><a name="line.392"></a>
+<span class="sourceLineNo">393</span>      // cause flush to create new files in the region<a name="line.393"></a>
+<span class="sourceLineNo">394</span>      admin.flush(tableName);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>      table.close();<a name="line.395"></a>
+<span class="sourceLineNo">396</span><a name="line.396"></a>
+<span class="sourceLineNo">397</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.397"></a>
+<span class="sourceLineNo">398</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.398"></a>
+<span class="sourceLineNo">399</span>      // limit the scan<a name="line.399"></a>
+<span class="sourceLineNo">400</span>      Scan scan = new Scan().withStartRow(getStartRow()).withStopRow(getEndRow());<a name="line.400"></a>
+<span class="sourceLineNo">401</span><a name="line.401"></a>
+<span class="sourceLineNo">402</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.402"></a>
+<span class="sourceLineNo">403</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.403"></a>
+<span class="sourceLineNo">404</span>        tmpTableDir);<a name="line.404"></a>
+<span class="sourceLineNo">405</span><a name="line.405"></a>
+<span class="sourceLineNo">406</span>      verifyWithMockedMapReduce(job, 2, 2, getStartRow(), getEndRow());<a name="line.406"></a>
+<span class="sourceLineNo">407</span>    } finally {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.408"></a>
+<span class="sourceLineNo">409</span>      UTIL.deleteTable(tableName);<a name="line.409"></a>
+<span class="sourceLineNo">410</span>    }<a name="line.410"></a>
+<span class="sourceLineNo">411</span>  }<a name="line.411"></a>
+<span class="sourceLineNo">412</span><a name="line.412"></a>
+<span class="sourceLineNo">413</span>  @Test<a name="line.413"></a>
+<span class="sourceLineNo">414</span>  public void testScannerReadTypeConfiguration() throws IOException {<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    Configuration conf = new Configuration(false);<a name="line.415"></a>
+<span class="sourceLineNo">416</span>    // Explicitly set ReadTypes should persist<a name="line.416"></a>
+<span class="sourceLineNo">417</span>    for (ReadType readType : Arrays.asList(ReadType.PREAD, ReadType.STREAM)) {<a name="line.417"></a>
+<span class="sourceLineNo">418</span>      Scan scanWithReadType = new Scan();<a name="line.418"></a>
+<span class="sourceLineNo">419</span>      scanWithReadType.setReadType(readType);<a name="line.419"></a>
+<span class="sourceLineNo">420</span>      assertEquals(scanWithReadType.getReadType(),<a name="line.420"></a>
+<span class="sourceLineNo">421</span>          serializeAndReturn(conf, scanWithReadType).getReadType());<a name="line.421"></a>
+<span class="sourceLineNo">422</span>    }<a name="line.422"></a>
+<span class="sourceLineNo">423</span>    // We should only see the DEFAULT ReadType getting updated to STREAM.<a name="line.423"></a>
+<span class="sourceLineNo">424</span>    Scan scanWithoutReadType = new Scan();<a name="line.424"></a>
+<span class="sourceLineNo">425</span>    assertEquals(ReadType.DEFAULT, scanWithoutReadType.getReadType());<a name="line.425"></a>
+<span class="sourceLineNo">426</span>    assertEquals(ReadType.STREAM, serializeAndReturn(conf, scanWithoutReadType).getReadType());<a name="line.426"></a>
+<span class="sourceLineNo">427</span><a name="line.427"></a>
+<span class="sourceLineNo">428</span>    // We should still be able to force a certain ReadType when DEFAULT is given.<a name="line.428"></a>
+<span class="sourceLineNo">429</span>    conf.setEnum(SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE, ReadType.PREAD);<a name="line.429"></a>
+<span class="sourceLineNo">430</span>    assertEquals(ReadType.DEFAULT, scanWithoutReadType.getReadType());<a name="line.430"></a>
+<span class="sourceLineNo">431</span>    assertEquals(ReadType.PREAD, serializeAndReturn(conf, scanWithoutReadType).getReadType());<a name="line.431"></a>
+<span class="sourceLineNo">432</span>  }<a name="line.432"></a>
+<span class="sourceLineNo">433</span><a name="line.433"></a>
+<span class="sourceLineNo">434</span>  /**<a name="line.434"></a>
+<span class="sourceLineNo">435</span>   * Serializes and deserializes the given scan in the same manner that<a name="line.435"></a>
+<span class="sourceLineNo">436</span>   * TableSnapshotInputFormat does.<a name="line.436"></a>
+<span class="sourceLineNo">437</span>   */<a name="line.437"></a>
+<span class="sourceLineNo">438</span>  private Scan serializeAndReturn(Configuration conf, Scan s) throws IOException {<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    conf.set(TableInputFormat.SCAN, TableMapReduceUtil.convertScanToString(s));<a name="line.439"></a>
+<span class="sourceLineNo">440</span>    return TableSnapshotInputFormatImpl.extractScanFromConf(conf);<a name="line.440"></a>
+<span class="sourceLineNo">441</span>  }<a name="line.441"></a>
+<span class="sourceLineNo">442</span><a name="line.442"></a>
+<span class="sourceLineNo">443</span>  private void verifyWithMockedMapReduce(Job job, int numRegions, int expectedNumSplits,<a name="line.443"></a>
+<span class="sourceLineNo">444</span>      byte[] startRow, byte[] stopRow)<a name="line.444"></a>
+<span class="sourceLineNo">445</span>      throws IOException, InterruptedException {<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    TableSnapshotInputFormat tsif = new TableSnapshotInputFormat();<a name="line.446"></a>
+<span class="sourceLineNo">447</span>    List&lt;InputSplit&gt; splits = tsif.getSplits(job);<a name="line.447"></a>
 <span class="sourceLineNo">448</span><a name="line.448"></a>
-<span class="sourceLineNo">449</span>      Scan scan =<a name="line.449"></a>
-<span class="sourceLineNo">450</span>          TableMapReduceUtil.convertStringToScan(snapshotRegionSplit.getDelegate().getScan());<a name="line.450"></a>
-<span class="sourceLineNo">451</span>      if (startRow.length &gt; 0) {<a name="line.451"></a>
-<span class="sourceLineNo">452</span>        Assert.assertTrue(<a name="line.452"></a>
-<span class="sourceLineNo">453</span>          Bytes.toStringBinary(startRow) + " should &lt;= " + Bytes.toStringBinary(scan.getStartRow()),<a name="line.453"></a>
-<span class="sourceLineNo">454</span>          Bytes.compareTo(startRow, scan.getStartRow()) &lt;= 0);<a name="line.454"></a>
-<span class="sourceLineNo">455</span>      }<a name="line.455"></a>
-<span class="sourceLineNo">456</span>      if (stopRow.length &gt; 0) {<a name="line.456"></a>
-<span class="sourceLineNo">457</span>        Assert.assertTrue(<a name="line.457"></a>
-<span class="sourceLineNo">458</span>          Bytes.toStringBinary(stopRow) + " should &gt;= " + Bytes.toStringBinary(scan.getStopRow()),<a name="line.458"></a>
-<span class="sourceLineNo">459</span>          Bytes.compareTo(stopRow, scan.getStopRow()) &gt;= 0);<a name="line.459"></a>
-<span class="sourceLineNo">460</span>      }<a name="line.460"></a>
-<span class="sourceLineNo">461</span>      Assert.assertTrue("startRow should &lt; stopRow",<a name="line.461"></a>
-<span class="sourceLineNo">462</span>        Bytes.compareTo(scan.getStartRow(), scan.getStopRow()) &lt; 0);<a name="line.462"></a>
-<span class="sourceLineNo">463</span><a name="line.463"></a>
-<span class="sourceLineNo">464</span>      // validate record reader<a name="line.464"></a>
-<span class="sourceLineNo">465</span>      TaskAttemptContext taskAttemptContext = mock(TaskAttemptContext.class);<a name="line.465"></a>
-<span class="sourceLineNo">466</span>      when(taskAttemptContext.getConfiguration()).thenReturn(job.getConfiguration());<a name="line.466"></a>
-<span class="sourceLineNo">467</span>      RecordReader&lt;ImmutableBytesWritable, Result&gt; rr =<a name="line.467"></a>
-<span class="sourceLineNo">468</span>          tsif.createRecordReader(split, taskAttemptContext);<a name="line.468"></a>
-<span class="sourceLineNo">469</span>      rr.initialize(split, taskAttemptContext);<a name="line.469"></a>
-<span class="sourceLineNo">470</span><a name="line.470"></a>
-<span class="sourceLineNo">471</span>      // validate we can read all the data back<a name="line.471"></a>
-<span class="sourceLineNo">472</span>      while (rr.nextKeyValue()) {<a name="line.472"></a>
-<span class="sourceLineNo">473</span>        byte[] row = rr.getCurrentKey().get();<a name="line.473"></a>
-<span class="sourceLineNo">474</span>        verifyRowFromMap(rr.getCurrentKey(), rr.getCurrentValue());<a name="line.474"></a>
-<span class="sourceLineNo">475</span>        rowTracker.addRow(row);<a name="line.475"></a>
-<span class="sourceLineNo">476</span>      }<a name="line.476"></a>
-<span class="sourceLineNo">477</span><a name="line.477"></a>
-<span class="sourceLineNo">478</span>      rr.close();<a name="line.478"></a>
-<span class="sourceLineNo">479</span>    }<a name="line.479"></a>
-<span class="sourceLineNo">480</span><a name="line.480"></a>
-<span class="sourceLineNo">481</span>    // validate all rows are seen<a name="line.481"></a>
-<span class="sourceLineNo">482</span>    rowTracker.validate();<a name="line.482"></a>
-<span class="sourceLineNo">483</span>  }<a name="line.483"></a>
-<span class="sourceLineNo">484</span><a name="line.484"></a>
-<span class="sourceLineNo">485</span>  @Override<a name="line.485"></a>
-<span class="sourceLineNo">486</span>  protected void testWithMapReduceImpl(HBaseTestingUtil util, TableName tableName,<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      String snapshotName, Path tableDir, int numRegions, int numSplitsPerRegion,<a name="line.487"></a>
-<span class="sourceLineNo">488</span>      int expectedNumSplits, boolean shutdownCluster) throws Exception {<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    doTestWithMapReduce(util, tableName, snapshotName, getStartRow(), getEndRow(), tableDir,<a name="line.489"></a>
-<span class="sourceLineNo">490</span>      numRegions, numSplitsPerRegion, expectedNumSplits, shutdownCluster);<a name="line.490"></a>
-<span class="sourceLineNo">491</span>  }<a name="line.491"></a>
-<span class="sourceLineNo">492</span><a name="line.492"></a>
-<span class="sourceLineNo">493</span>  // this is also called by the IntegrationTestTableSnapshotInputFormat<a name="line.493"></a>
-<span class="sourceLineNo">494</span>  public static void doTestWithMapReduce(HBaseTestingUtil util, TableName tableName,<a name="line.494"></a>
-<span class="sourceLineNo">495</span>      String snapshotName, byte[] startRow, byte[] endRow, Path tableDir, int numRegions,<a name="line.495"></a>
-<span class="sourceLineNo">496</span>      int numSplitsPerRegion, int expectedNumSplits, boolean shutdownCluster) throws Exception {<a name="line.496"></a>
-<span class="sourceLineNo">497</span><a name="line.497"></a>
-<span class="sourceLineNo">498</span>    LOG.info("testing with MapReduce");<a name="line.498"></a>
-<span class="sourceLineNo">499</span><a name="line.499"></a>
-<span class="sourceLineNo">500</span>    LOG.info("create the table and snapshot");<a name="line.500"></a>
-<span class="sourceLineNo">501</span>    createTableAndSnapshot(util, tableName, snapshotName, startRow, endRow, numRegions);<a name="line.501"></a>
-<span class="sourceLineNo">502</span><a name="line.502"></a>
-<span class="sourceLineNo">503</span>    if (shutdownCluster) {<a name="line.503"></a>
-<span class="sourceLineNo">504</span>      LOG.info("shutting down hbase cluster.");<a name="line.504"></a>
-<span class="sourceLineNo">505</span>      util.shutdownMiniHBaseCluster();<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    }<a name="line.506"></a>
-<span class="sourceLineNo">507</span><a name="line.507"></a>
-<span class="sourceLineNo">508</span>    try {<a name="line.508"></a>
-<span class="sourceLineNo">509</span>      // create the job<a name="line.509"></a>
-<span class="sourceLineNo">510</span>      Job job = new Job(util.getConfiguration());<a name="line.510"></a>
-<span class="sourceLineNo">511</span>      Scan scan = new Scan().withStartRow(startRow).withStopRow(endRow); // limit the scan<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span>      job.setJarByClass(util.getClass());<a name="line.513"></a>
-<span class="sourceLineNo">514</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.514"></a>
-<span class="sourceLineNo">515</span>              TestTableSnapshotInputFormat.class);<a name="line.515"></a>
-<span class="sourceLineNo">516</span><a name="line.516"></a>
-<span class="sourceLineNo">517</span>      if (numSplitsPerRegion &gt; 1) {<a name="line.517"></a>
-<span class="sourceLineNo">518</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.518"></a>
-<span class="sourceLineNo">519</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.519"></a>
-<span class="sourceLineNo">520</span>                NullWritable.class, job, true, tableDir, new RegionSplitter.UniformSplit(),<a name="line.520"></a>
-<span class="sourceLineNo">521</span>                numSplitsPerRegion);<a name="line.521"></a>
-<span class="sourceLineNo">522</span>      } else {<a name="line.522"></a>
-<span class="sourceLineNo">523</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.523"></a>
-<span class="sourceLineNo">524</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.524"></a>
-<span class="sourceLineNo">525</span>                NullWritable.class, job, true, tableDir);<a name="line.525"></a>
-<span class="sourceLineNo">526</span>      }<a name="line.526"></a>
-<span class="sourceLineNo">527</span><a name="line.527"></a>
-<span class="sourceLineNo">528</span>      job.setReducerClass(TestTableSnapshotInputFormat.TestTableSnapshotReducer.class);<a name="line.528"></a>
-<span class="sourceLineNo">529</span>      job.setNumReduceTasks(1);<a name="line.529"></a>
-<span class="sourceLineNo">530</span>      job.setOutputFormatClass(NullOutputFormat.class);<a name="line.530"></a>
-<span class="sourceLineNo">531</span><a name="line.531"></a>
-<span class="sourceLineNo">532</span>      Assert.assertTrue(job.waitForCompletion(true));<a name="line.532"></a>
-<span class="sourceLineNo">533</span>    } finally {<a name="line.533"></a>
-<span class="sourceLineNo">534</span>      if (!shutdownCluster) {<a name="line.534"></a>
-<span class="sourceLineNo">535</span>        util.getAdmin().deleteSnapshot(snapshotName);<a name="line.535"></a>
-<span class="sourceLineNo">536</span>        util.deleteTable(tableName);<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      }<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    }<a name="line.538"></a>
-<span class="sourceLineNo">539</span>  }<a name="line.539"></a>
+<span class="sourceLineNo">449</span>    Assert.assertEquals(expectedNumSplits, splits.size());<a name="line.449"></a>
+<span class="sourceLineNo">450</span><a name="line.450"></a>
+<span class="sourceLineNo">451</span>    HBaseTestingUtil.SeenRowTracker rowTracker = new HBaseTestingUtil.SeenRowTracker(startRow,<a name="line.451"></a>
+<span class="sourceLineNo">452</span>        stopRow.length &gt; 0 ? stopRow : Bytes.toBytes("\uffff"));<a name="line.452"></a>
+<span class="sourceLineNo">453</span><a name="line.453"></a>
+<span class="sourceLineNo">454</span>    boolean localityEnabled =<a name="line.454"></a>
+<span class="sourceLineNo">455</span>        job.getConfiguration().getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY,<a name="line.455"></a>
+<span class="sourceLineNo">456</span>                                          SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT);<a name="line.456"></a>
+<span class="sourceLineNo">457</span><a name="line.457"></a>
+<span class="sourceLineNo">458</span>    boolean byRegionLoc =<a name="line.458"></a>
+<span class="sourceLineNo">459</span>      job.getConfiguration().getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.459"></a>
+<span class="sourceLineNo">460</span>                                        SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.460"></a>
+<span class="sourceLineNo">461</span>    for (int i = 0; i &lt; splits.size(); i++) {<a name="line.461"></a>
+<span class="sourceLineNo">462</span>      // validate input split<a name="line.462"></a>
+<span class="sourceLineNo">463</span>      InputSplit split = splits.get(i);<a name="line.463"></a>
+<span class="sourceLineNo">464</span>      Assert.assertTrue(split instanceof TableSnapshotRegionSplit);<a name="line.464"></a>
+<span class="sourceLineNo">465</span>      TableSnapshotRegionSplit snapshotRegionSplit = (TableSnapshotRegionSplit) split;<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      if (localityEnabled) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>        Assert.assertTrue(split.getLocations() != null &amp;&amp; split.getLocations().length != 0);<a name="line.467"></a>
+<span class="sourceLineNo">468</span>        if (byRegionLoc) {<a name="line.468"></a>
+<span class="sourceLineNo">469</span>          // When it uses region location from meta, the hostname will be "localhost",<a name="line.469"></a>
+<span class="sourceLineNo">470</span>          // the location from hdfs block location is "127.0.0.1".<a name="line.470"></a>
+<span class="sourceLineNo">471</span>          Assert.assertEquals(1, split.getLocations().length);<a name="line.471"></a>
+<span class="sourceLineNo">472</span>          Assert.assertTrue("Not using region location!",<a name="line.472"></a>
+<span class="sourceLineNo">473</span>            split.getLocations()[0].equals("localhost"));<a name="line.473"></a>
+<span class="sourceLineNo">474</span>        } else {<a name="line.474"></a>
+<span class="sourceLineNo">475</span>          Assert.assertTrue("Not using region location!",<a name="line.475"></a>
+<span class="sourceLineNo">476</span>            split.getLocations()[0].equals("127.0.0.1"));<a name="line.476"></a>
+<span class="sourceLineNo">477</span>        }<a name="line.477"></a>
+<span class="sourceLineNo">478</span>      } else {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>        Assert.assertTrue(split.getLocations() != null &amp;&amp; split.getLocations().length == 0);<a name="line.479"></a>
+<span class="sourceLineNo">480</span>      }<a name="line.480"></a>
+<span class="sourceLineNo">481</span><a name="line.481"></a>
+<span class="sourceLineNo">482</span>      Scan scan =<a name="line.482"></a>
+<span class="sourceLineNo">483</span>          TableMapReduceUtil.convertStringToScan(snapshotRegionSplit.getDelegate().getScan());<a name="line.483"></a>
+<span class="sourceLineNo">484</span>      if (startRow.length &gt; 0) {<a name="line.484"></a>
+<span class="sourceLineNo">485</span>        Assert.assertTrue(<a name="line.485"></a>
+<span class="sourceLineNo">486</span>          Bytes.toStringBinary(startRow) + " should &lt;= " + Bytes.toStringBinary(scan.getStartRow()),<a name="line.486"></a>
+<span class="sourceLineNo">487</span>          Bytes.compareTo(startRow, scan.getStartRow()) &lt;= 0);<a name="line.487"></a>
+<span class="sourceLineNo">488</span>      }<a name="line.488"></a>
+<span class="sourceLineNo">489</span>      if (stopRow.length &gt; 0) {<a name="line.489"></a>
+<span class="sourceLineNo">490</span>        Assert.assertTrue(<a name="line.490"></a>
+<span class="sourceLineNo">491</span>          Bytes.toStringBinary(stopRow) + " should &gt;= " + Bytes.toStringBinary(scan.getStopRow()),<a name="line.491"></a>
+<span class="sourceLineNo">492</span>          Bytes.compareTo(stopRow, scan.getStopRow()) &gt;= 0);<a name="line.492"></a>
+<span class="sourceLineNo">493</span>      }<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      Assert.assertTrue("startRow should &lt; stopRow",<a name="line.494"></a>
+<span class="sourceLineNo">495</span>        Bytes.compareTo(scan.getStartRow(), scan.getStopRow()) &lt; 0);<a name="line.495"></a>
+<span class="sourceLineNo">496</span><a name="line.496"></a>
+<span class="sourceLineNo">497</span>      // validate record reader<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      TaskAttemptContext taskAttemptContext = mock(TaskAttemptContext.class);<a name="line.498"></a>
+<span class="sourceLineNo">499</span>      when(taskAttemptContext.getConfiguration()).thenReturn(job.getConfiguration());<a name="line.499"></a>
+<span class="sourceLineNo">500</span>      RecordReader&lt;ImmutableBytesWritable, Result&gt; rr =<a name="line.500"></a>
+<span class="sourceLineNo">501</span>          tsif.createRecordReader(split, taskAttemptContext);<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      rr.initialize(split, taskAttemptContext);<a name="line.502"></a>
+<span class="sourceLineNo">503</span><a name="line.503"></a>
+<span class="sourceLineNo">504</span>      // validate we can read all the data back<a name="line.504"></a>
+<span class="sourceLineNo">505</span>      while (rr.nextKeyValue()) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span>        byte[] row = rr.getCurrentKey().get();<a name="line.506"></a>
+<span class="sourceLineNo">507</span>        verifyRowFromMap(rr.getCurrentKey(), rr.getCurrentValue());<a name="line.507"></a>
+<span class="sourceLineNo">508</span>        rowTracker.addRow(row);<a name="line.508"></a>
+<span class="sourceLineNo">509</span>      }<a name="line.509"></a>
+<span class="sourceLineNo">510</span><a name="line.510"></a>
+<span class="sourceLineNo">511</span>      rr.close();<a name="line.511"></a>
+<span class="sourceLineNo">512</span>    }<a name="line.512"></a>
+<span class="sourceLineNo">513</span><a name="line.513"></a>
+<span class="sourceLineNo">514</span>    // validate all rows are seen<a name="line.514"></a>
+<span class="sourceLineNo">515</span>    rowTracker.validate();<a name="line.515"></a>
+<span class="sourceLineNo">516</span>  }<a name="line.516"></a>
+<span class="sourceLineNo">517</span><a name="line.517"></a>
+<span class="sourceLineNo">518</span>  @Override<a name="line.518"></a>
+<span class="sourceLineNo">519</span>  protected void testWithMapReduceImpl(HBaseTestingUtil util, TableName tableName,<a name="line.519"></a>
+<span class="sourceLineNo">520</span>      String snapshotName, Path tableDir, int numRegions, int numSplitsPerRegion,<a name="line.520"></a>
+<span class="sourceLineNo">521</span>      int expectedNumSplits, boolean shutdownCluster) throws Exception {<a name="line.521"></a>
+<span class="sourceLineNo">522</span>    doTestWithMapReduce(util, tableName, snapshotName, getStartRow(), getEndRow(), tableDir,<a name="line.522"></a>
+<span class="sourceLineNo">523</span>      numRegions, numSplitsPerRegion, expectedNumSplits, shutdownCluster);<a name="line.523"></a>
+<span class="sourceLineNo">524</span>  }<a name="line.524"></a>
+<span class="sourceLineNo">525</span><a name="line.525"></a>
+<span class="sourceLineNo">526</span>  // this is also called by the IntegrationTestTableSnapshotInputFormat<a name="line.526"></a>
+<span class="sourceLineNo">527</span>  public static void doTestWithMapReduce(HBaseTestingUtil util, TableName tableName,<a name="line.527"></a>
+<span class="sourceLineNo">528</span>      String snapshotName, byte[] startRow, byte[] endRow, Path tableDir, int numRegions,<a name="line.528"></a>
+<span class="sourceLineNo">529</span>      int numSplitsPerRegion, int expectedNumSplits, boolean shutdownCluster) throws Exception {<a name="line.529"></a>
+<span class="sourceLineNo">530</span><a name="line.530"></a>
+<span class="sourceLineNo">531</span>    LOG.info("testing with MapReduce");<a name="line.531"></a>
+<span class="sourceLineNo">532</span><a name="line.532"></a>
+<span class="sourceLineNo">533</span>    LOG.info("create the table and snapshot");<a name="line.533"></a>
+<span class="sourceLineNo">534</span>    createTableAndSnapshot(util, tableName, snapshotName, startRow, endRow, numRegions);<a name="line.534"></a>
+<span class="sourceLineNo">535</span><a name="line.535"></a>
+<span class="sourceLineNo">536</span>    if (shutdownCluster) {<a name="line.536"></a>
+<span class="sourceLineNo">537</span>      LOG.info("shutting down hbase cluster.");<a name="line.537"></a>
+<span class="sourceLineNo">538</span>      util.shutdownMiniHBaseCluster();<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    }<a name="line.539"></a>
 <span class="sourceLineNo">540</span><a name="line.540"></a>
-<span class="sourceLineNo">541</span>  @Test<a name="line.541"></a>
-<span class="sourceLineNo">542</span>  public void testWithMapReduceMultipleMappersPerRegion() throws Exception {<a name="line.542"></a>
-<span class="sourceLineNo">543</span>    testWithMapReduce(UTIL, "testWithMapReduceMultiRegion", 10, 5, 50, false);<a name="line.543"></a>
-<span class="sourceLineNo">544</span>  }<a name="line.544"></a>
-<span class="sourceLineNo">545</span>}<a name="line.545"></a>
+<span class="sourceLineNo">541</span>    try {<a name="line.541"></a>
+<span class="sourceLineNo">542</span>      // create the job<a name="line.542"></a>
+<span class="sourceLineNo">543</span>      Job job = new Job(util.getConfiguration());<a name="line.543"></a>
+<span class="sourceLineNo">544</span>      Scan scan = new Scan().withStartRow(startRow).withStopRow(endRow); // limit the scan<a name="line.544"></a>
+<span class="sourceLineNo">545</span><a name="line.545"></a>
+<span class="sourceLineNo">546</span>      job.setJarByClass(util.getClass());<a name="line.546"></a>
+<span class="sourceLineNo">547</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.547"></a>
+<span class="sourceLineNo">548</span>              TestTableSnapshotInputFormat.class);<a name="line.548"></a>
+<span class="sourceLineNo">549</span><a name="line.549"></a>
+<span class="sourceLineNo">550</span>      if (numSplitsPerRegion &gt; 1) {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.551"></a>
+<span class="sourceLineNo">552</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.552"></a>
+<span class="sourceLineNo">553</span>                NullWritable.class, job, true, tableDir, new RegionSplitter.UniformSplit(),<a name="line.553"></a>
+<span class="sourceLineNo">554</span>                numSplitsPerRegion);<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      } else {<a name="line.555"></a>
+<span class="sourceLineNo">556</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.556"></a>
+<span class="sourceLineNo">557</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.557"></a>
+<span class="sourceLineNo">558</span>                NullWritable.class, job, true, tableDir);<a name="line.558"></a>
+<span class="sourceLineNo">559</span>      }<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>      job.setReducerClass(TestTableSnapshotInputFormat.TestTableSnapshotReducer.class);<a name="line.561"></a>
+<span class="sourceLineNo">562</span>      job.setNumReduceTasks(1);<a name="line.562"></a>
+<span class="sourceLineNo">563</span>      job.setOutputFormatClass(NullOutputFormat.class);<a name="line.563"></a>
+<span class="sourceLineNo">564</span><a name="line.564"></a>
+<span class="sourceLineNo">565</span>      Assert.assertTrue(job.waitForCompletion(true));<a name="line.565"></a>
+<span class="sourceLineNo">566</span>    } finally {<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      if (!shutdownCluster) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span>        util.getAdmin().deleteSnapshot(snapshotName);<a name="line.568"></a>
+<span class="sourceLineNo">569</span>        util.deleteTable(tableName);<a name="line.569"></a>
+<span class="sourceLineNo">570</span>      }<a name="line.570"></a>
+<span class="sourceLineNo">571</span>    }<a name="line.571"></a>
+<span class="sourceLineNo">572</span>  }<a name="line.572"></a>
+<span class="sourceLineNo">573</span><a name="line.573"></a>
+<span class="sourceLineNo">574</span>  @Test<a name="line.574"></a>
+<span class="sourceLineNo">575</span>  public void testWithMapReduceMultipleMappersPerRegion() throws Exception {<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    testWithMapReduce(UTIL, "testWithMapReduceMultiRegion", 10, 5, 50, false);<a name="line.576"></a>
+<span class="sourceLineNo">577</span>  }<a name="line.577"></a>
+<span class="sourceLineNo">578</span>}<a name="line.578"></a>
 
 
 
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotMapper.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotMapper.html
index 8d67eec..82673a9 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotMapper.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotMapper.html
@@ -30,527 +30,560 @@
 <span class="sourceLineNo">022</span>import static org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT;<a name="line.22"></a>
 <span class="sourceLineNo">023</span>import static org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION;<a name="line.23"></a>
 <span class="sourceLineNo">024</span>import static org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT;<a name="line.24"></a>
-<span class="sourceLineNo">025</span>import static org.mockito.Mockito.mock;<a name="line.25"></a>
-<span class="sourceLineNo">026</span>import static org.mockito.Mockito.when;<a name="line.26"></a>
-<span class="sourceLineNo">027</span><a name="line.27"></a>
-<span class="sourceLineNo">028</span>import java.io.IOException;<a name="line.28"></a>
-<span class="sourceLineNo">029</span>import java.util.Arrays;<a name="line.29"></a>
-<span class="sourceLineNo">030</span>import java.util.List;<a name="line.30"></a>
-<span class="sourceLineNo">031</span>import org.apache.hadoop.conf.Configuration;<a name="line.31"></a>
-<span class="sourceLineNo">032</span>import org.apache.hadoop.fs.FileSystem;<a name="line.32"></a>
-<span class="sourceLineNo">033</span>import org.apache.hadoop.fs.Path;<a name="line.33"></a>
-<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.34"></a>
-<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.HBaseTestingUtil;<a name="line.35"></a>
-<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.HConstants;<a name="line.36"></a>
-<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.HDFSBlocksDistribution;<a name="line.37"></a>
-<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.TableName;<a name="line.38"></a>
-<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.client.Admin;<a name="line.39"></a>
-<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.client.Result;<a name="line.40"></a>
-<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.client.Scan;<a name="line.41"></a>
-<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.client.Table;<a name="line.42"></a>
-<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.client.TestTableSnapshotScanner;<a name="line.43"></a>
-<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<a name="line.44"></a>
-<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormat.TableSnapshotRegionSplit;<a name="line.45"></a>
-<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.snapshot.SnapshotTestingUtils;<a name="line.46"></a>
-<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.testclassification.LargeTests;<a name="line.47"></a>
-<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.testclassification.VerySlowMapReduceTests;<a name="line.48"></a>
-<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.49"></a>
-<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.50"></a>
-<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.util.RegionSplitter;<a name="line.51"></a>
-<span class="sourceLineNo">052</span>import org.apache.hadoop.io.NullWritable;<a name="line.52"></a>
-<span class="sourceLineNo">053</span>import org.apache.hadoop.mapreduce.InputSplit;<a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.apache.hadoop.mapreduce.Job;<a name="line.54"></a>
-<span class="sourceLineNo">055</span>import org.apache.hadoop.mapreduce.RecordReader;<a name="line.55"></a>
-<span class="sourceLineNo">056</span>import org.apache.hadoop.mapreduce.Reducer;<a name="line.56"></a>
-<span class="sourceLineNo">057</span>import org.apache.hadoop.mapreduce.TaskAttemptContext;<a name="line.57"></a>
-<span class="sourceLineNo">058</span>import org.apache.hadoop.mapreduce.lib.output.NullOutputFormat;<a name="line.58"></a>
-<span class="sourceLineNo">059</span>import org.junit.Assert;<a name="line.59"></a>
-<span class="sourceLineNo">060</span>import org.junit.ClassRule;<a name="line.60"></a>
-<span class="sourceLineNo">061</span>import org.junit.Rule;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>import org.junit.Test;<a name="line.62"></a>
-<span class="sourceLineNo">063</span>import org.junit.experimental.categories.Category;<a name="line.63"></a>
-<span class="sourceLineNo">064</span>import org.junit.rules.TestName;<a name="line.64"></a>
-<span class="sourceLineNo">065</span>import org.slf4j.Logger;<a name="line.65"></a>
-<span class="sourceLineNo">066</span>import org.slf4j.LoggerFactory;<a name="line.66"></a>
-<span class="sourceLineNo">067</span><a name="line.67"></a>
-<span class="sourceLineNo">068</span>import org.apache.hbase.thirdparty.com.google.common.collect.Lists;<a name="line.68"></a>
-<span class="sourceLineNo">069</span><a name="line.69"></a>
-<span class="sourceLineNo">070</span>@Category({VerySlowMapReduceTests.class, LargeTests.class})<a name="line.70"></a>
-<span class="sourceLineNo">071</span>public class TestTableSnapshotInputFormat extends TableSnapshotInputFormatTestBase {<a name="line.71"></a>
+<span class="sourceLineNo">025</span>import static org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE;<a name="line.25"></a>
+<span class="sourceLineNo">026</span>import static org.junit.Assert.assertEquals;<a name="line.26"></a>
+<span class="sourceLineNo">027</span>import static org.mockito.Mockito.mock;<a name="line.27"></a>
+<span class="sourceLineNo">028</span>import static org.mockito.Mockito.when;<a name="line.28"></a>
+<span class="sourceLineNo">029</span><a name="line.29"></a>
+<span class="sourceLineNo">030</span>import java.io.IOException;<a name="line.30"></a>
+<span class="sourceLineNo">031</span>import java.util.Arrays;<a name="line.31"></a>
+<span class="sourceLineNo">032</span>import java.util.List;<a name="line.32"></a>
+<span class="sourceLineNo">033</span>import org.apache.hadoop.conf.Configuration;<a name="line.33"></a>
+<span class="sourceLineNo">034</span>import org.apache.hadoop.fs.FileSystem;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.fs.Path;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.HBaseTestingUtil;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.HConstants;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.HDFSBlocksDistribution;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.TableName;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.client.Admin;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.client.Result;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.client.Scan;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.client.Scan.ReadType;<a name="line.44"></a>
+<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.client.Table;<a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.client.TestTableSnapshotScanner;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormat.TableSnapshotRegionSplit;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.snapshot.SnapshotTestingUtils;<a name="line.49"></a>
+<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.testclassification.LargeTests;<a name="line.50"></a>
+<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.testclassification.VerySlowMapReduceTests;<a name="line.51"></a>
+<span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.52"></a>
+<span class="sourceLineNo">053</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.53"></a>
+<span class="sourceLineNo">054</span>import org.apache.hadoop.hbase.util.RegionSplitter;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>import org.apache.hadoop.io.NullWritable;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>import org.apache.hadoop.mapreduce.InputSplit;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>import org.apache.hadoop.mapreduce.Job;<a name="line.57"></a>
+<span class="sourceLineNo">058</span>import org.apache.hadoop.mapreduce.RecordReader;<a name="line.58"></a>
+<span class="sourceLineNo">059</span>import org.apache.hadoop.mapreduce.Reducer;<a name="line.59"></a>
+<span class="sourceLineNo">060</span>import org.apache.hadoop.mapreduce.TaskAttemptContext;<a name="line.60"></a>
+<span class="sourceLineNo">061</span>import org.apache.hadoop.mapreduce.lib.output.NullOutputFormat;<a name="line.61"></a>
+<span class="sourceLineNo">062</span>import org.junit.Assert;<a name="line.62"></a>
+<span class="sourceLineNo">063</span>import org.junit.ClassRule;<a name="line.63"></a>
+<span class="sourceLineNo">064</span>import org.junit.Rule;<a name="line.64"></a>
+<span class="sourceLineNo">065</span>import org.junit.Test;<a name="line.65"></a>
+<span class="sourceLineNo">066</span>import org.junit.experimental.categories.Category;<a name="line.66"></a>
+<span class="sourceLineNo">067</span>import org.junit.rules.TestName;<a name="line.67"></a>
+<span class="sourceLineNo">068</span>import org.slf4j.Logger;<a name="line.68"></a>
+<span class="sourceLineNo">069</span>import org.slf4j.LoggerFactory;<a name="line.69"></a>
+<span class="sourceLineNo">070</span><a name="line.70"></a>
+<span class="sourceLineNo">071</span>import org.apache.hbase.thirdparty.com.google.common.collect.Lists;<a name="line.71"></a>
 <span class="sourceLineNo">072</span><a name="line.72"></a>
-<span class="sourceLineNo">073</span>  @ClassRule<a name="line.73"></a>
-<span class="sourceLineNo">074</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.74"></a>
-<span class="sourceLineNo">075</span>      HBaseClassTestRule.forClass(TestTableSnapshotInputFormat.class);<a name="line.75"></a>
-<span class="sourceLineNo">076</span><a name="line.76"></a>
-<span class="sourceLineNo">077</span>  private static final Logger LOG = LoggerFactory.getLogger(TestTableSnapshotInputFormat.class);<a name="line.77"></a>
-<span class="sourceLineNo">078</span><a name="line.78"></a>
-<span class="sourceLineNo">079</span>  private static final byte[] bbb = Bytes.toBytes("bbb");<a name="line.79"></a>
-<span class="sourceLineNo">080</span>  private static final byte[] yyy = Bytes.toBytes("yyy");<a name="line.80"></a>
-<span class="sourceLineNo">081</span>  private static final byte[] bbc = Bytes.toBytes("bbc");<a name="line.81"></a>
-<span class="sourceLineNo">082</span>  private static final byte[] yya = Bytes.toBytes("yya");<a name="line.82"></a>
-<span class="sourceLineNo">083</span><a name="line.83"></a>
-<span class="sourceLineNo">084</span>  @Rule<a name="line.84"></a>
-<span class="sourceLineNo">085</span>  public TestName name = new TestName();<a name="line.85"></a>
+<span class="sourceLineNo">073</span>@Category({VerySlowMapReduceTests.class, LargeTests.class})<a name="line.73"></a>
+<span class="sourceLineNo">074</span>public class TestTableSnapshotInputFormat extends TableSnapshotInputFormatTestBase {<a name="line.74"></a>
+<span class="sourceLineNo">075</span><a name="line.75"></a>
+<span class="sourceLineNo">076</span>  @ClassRule<a name="line.76"></a>
+<span class="sourceLineNo">077</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.77"></a>
+<span class="sourceLineNo">078</span>      HBaseClassTestRule.forClass(TestTableSnapshotInputFormat.class);<a name="line.78"></a>
+<span class="sourceLineNo">079</span><a name="line.79"></a>
+<span class="sourceLineNo">080</span>  private static final Logger LOG = LoggerFactory.getLogger(TestTableSnapshotInputFormat.class);<a name="line.80"></a>
+<span class="sourceLineNo">081</span><a name="line.81"></a>
+<span class="sourceLineNo">082</span>  private static final byte[] bbb = Bytes.toBytes("bbb");<a name="line.82"></a>
+<span class="sourceLineNo">083</span>  private static final byte[] yyy = Bytes.toBytes("yyy");<a name="line.83"></a>
+<span class="sourceLineNo">084</span>  private static final byte[] bbc = Bytes.toBytes("bbc");<a name="line.84"></a>
+<span class="sourceLineNo">085</span>  private static final byte[] yya = Bytes.toBytes("yya");<a name="line.85"></a>
 <span class="sourceLineNo">086</span><a name="line.86"></a>
-<span class="sourceLineNo">087</span>  @Override<a name="line.87"></a>
-<span class="sourceLineNo">088</span>  protected byte[] getStartRow() {<a name="line.88"></a>
-<span class="sourceLineNo">089</span>    return bbb;<a name="line.89"></a>
-<span class="sourceLineNo">090</span>  }<a name="line.90"></a>
-<span class="sourceLineNo">091</span><a name="line.91"></a>
-<span class="sourceLineNo">092</span>  @Override<a name="line.92"></a>
-<span class="sourceLineNo">093</span>  protected byte[] getEndRow() {<a name="line.93"></a>
-<span class="sourceLineNo">094</span>    return yyy;<a name="line.94"></a>
-<span class="sourceLineNo">095</span>  }<a name="line.95"></a>
-<span class="sourceLineNo">096</span><a name="line.96"></a>
-<span class="sourceLineNo">097</span><a name="line.97"></a>
-<span class="sourceLineNo">098</span>  @Test<a name="line.98"></a>
-<span class="sourceLineNo">099</span>  public void testGetBestLocations() throws IOException {<a name="line.99"></a>
-<span class="sourceLineNo">100</span>    TableSnapshotInputFormatImpl tsif = new TableSnapshotInputFormatImpl();<a name="line.100"></a>
-<span class="sourceLineNo">101</span>    Configuration conf = UTIL.getConfiguration();<a name="line.101"></a>
-<span class="sourceLineNo">102</span><a name="line.102"></a>
-<span class="sourceLineNo">103</span>    HDFSBlocksDistribution blockDistribution = new HDFSBlocksDistribution();<a name="line.103"></a>
-<span class="sourceLineNo">104</span>    Assert.assertEquals(null,<a name="line.104"></a>
-<span class="sourceLineNo">105</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.105"></a>
-<span class="sourceLineNo">106</span><a name="line.106"></a>
-<span class="sourceLineNo">107</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 1);<a name="line.107"></a>
-<span class="sourceLineNo">108</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.108"></a>
-<span class="sourceLineNo">109</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.109"></a>
-<span class="sourceLineNo">110</span><a name="line.110"></a>
-<span class="sourceLineNo">111</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 1);<a name="line.111"></a>
-<span class="sourceLineNo">112</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.112"></a>
-<span class="sourceLineNo">113</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.113"></a>
-<span class="sourceLineNo">114</span><a name="line.114"></a>
-<span class="sourceLineNo">115</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 1);<a name="line.115"></a>
-<span class="sourceLineNo">116</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.116"></a>
-<span class="sourceLineNo">117</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.117"></a>
-<span class="sourceLineNo">118</span><a name="line.118"></a>
-<span class="sourceLineNo">119</span>    blockDistribution = new HDFSBlocksDistribution();<a name="line.119"></a>
-<span class="sourceLineNo">120</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 10);<a name="line.120"></a>
-<span class="sourceLineNo">121</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 7);<a name="line.121"></a>
-<span class="sourceLineNo">122</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h3"}, 5);<a name="line.122"></a>
-<span class="sourceLineNo">123</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h4"}, 1);<a name="line.123"></a>
-<span class="sourceLineNo">124</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.124"></a>
-<span class="sourceLineNo">125</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.125"></a>
-<span class="sourceLineNo">126</span><a name="line.126"></a>
-<span class="sourceLineNo">127</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 2);<a name="line.127"></a>
-<span class="sourceLineNo">128</span>    Assert.assertEquals(Lists.newArrayList("h1", "h2"),<a name="line.128"></a>
-<span class="sourceLineNo">129</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.129"></a>
-<span class="sourceLineNo">130</span><a name="line.130"></a>
-<span class="sourceLineNo">131</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 3);<a name="line.131"></a>
-<span class="sourceLineNo">132</span>    Assert.assertEquals(Lists.newArrayList("h2", "h1"),<a name="line.132"></a>
-<span class="sourceLineNo">133</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.133"></a>
-<span class="sourceLineNo">134</span><a name="line.134"></a>
-<span class="sourceLineNo">135</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h3"}, 6);<a name="line.135"></a>
-<span class="sourceLineNo">136</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h4"}, 9);<a name="line.136"></a>
+<span class="sourceLineNo">087</span>  @Rule<a name="line.87"></a>
+<span class="sourceLineNo">088</span>  public TestName name = new TestName();<a name="line.88"></a>
+<span class="sourceLineNo">089</span><a name="line.89"></a>
+<span class="sourceLineNo">090</span>  @Override<a name="line.90"></a>
+<span class="sourceLineNo">091</span>  protected byte[] getStartRow() {<a name="line.91"></a>
+<span class="sourceLineNo">092</span>    return bbb;<a name="line.92"></a>
+<span class="sourceLineNo">093</span>  }<a name="line.93"></a>
+<span class="sourceLineNo">094</span><a name="line.94"></a>
+<span class="sourceLineNo">095</span>  @Override<a name="line.95"></a>
+<span class="sourceLineNo">096</span>  protected byte[] getEndRow() {<a name="line.96"></a>
+<span class="sourceLineNo">097</span>    return yyy;<a name="line.97"></a>
+<span class="sourceLineNo">098</span>  }<a name="line.98"></a>
+<span class="sourceLineNo">099</span><a name="line.99"></a>
+<span class="sourceLineNo">100</span><a name="line.100"></a>
+<span class="sourceLineNo">101</span>  @Test<a name="line.101"></a>
+<span class="sourceLineNo">102</span>  public void testGetBestLocations() throws IOException {<a name="line.102"></a>
+<span class="sourceLineNo">103</span>    TableSnapshotInputFormatImpl tsif = new TableSnapshotInputFormatImpl();<a name="line.103"></a>
+<span class="sourceLineNo">104</span>    Configuration conf = UTIL.getConfiguration();<a name="line.104"></a>
+<span class="sourceLineNo">105</span><a name="line.105"></a>
+<span class="sourceLineNo">106</span>    HDFSBlocksDistribution blockDistribution = new HDFSBlocksDistribution();<a name="line.106"></a>
+<span class="sourceLineNo">107</span>    Assert.assertEquals(null,<a name="line.107"></a>
+<span class="sourceLineNo">108</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.108"></a>
+<span class="sourceLineNo">109</span><a name="line.109"></a>
+<span class="sourceLineNo">110</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 1);<a name="line.110"></a>
+<span class="sourceLineNo">111</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.111"></a>
+<span class="sourceLineNo">112</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.112"></a>
+<span class="sourceLineNo">113</span><a name="line.113"></a>
+<span class="sourceLineNo">114</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 1);<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.115"></a>
+<span class="sourceLineNo">116</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.116"></a>
+<span class="sourceLineNo">117</span><a name="line.117"></a>
+<span class="sourceLineNo">118</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 1);<a name="line.118"></a>
+<span class="sourceLineNo">119</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.119"></a>
+<span class="sourceLineNo">120</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.120"></a>
+<span class="sourceLineNo">121</span><a name="line.121"></a>
+<span class="sourceLineNo">122</span>    blockDistribution = new HDFSBlocksDistribution();<a name="line.122"></a>
+<span class="sourceLineNo">123</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 10);<a name="line.123"></a>
+<span class="sourceLineNo">124</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 7);<a name="line.124"></a>
+<span class="sourceLineNo">125</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h3"}, 5);<a name="line.125"></a>
+<span class="sourceLineNo">126</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h4"}, 1);<a name="line.126"></a>
+<span class="sourceLineNo">127</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.127"></a>
+<span class="sourceLineNo">128</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.128"></a>
+<span class="sourceLineNo">129</span><a name="line.129"></a>
+<span class="sourceLineNo">130</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 2);<a name="line.130"></a>
+<span class="sourceLineNo">131</span>    Assert.assertEquals(Lists.newArrayList("h1", "h2"),<a name="line.131"></a>
+<span class="sourceLineNo">132</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.132"></a>
+<span class="sourceLineNo">133</span><a name="line.133"></a>
+<span class="sourceLineNo">134</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 3);<a name="line.134"></a>
+<span class="sourceLineNo">135</span>    Assert.assertEquals(Lists.newArrayList("h2", "h1"),<a name="line.135"></a>
+<span class="sourceLineNo">136</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.136"></a>
 <span class="sourceLineNo">137</span><a name="line.137"></a>
-<span class="sourceLineNo">138</span>    Assert.assertEquals(Lists.newArrayList("h2", "h3", "h4"),<a name="line.138"></a>
-<span class="sourceLineNo">139</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.139"></a>
-<span class="sourceLineNo">140</span>  }<a name="line.140"></a>
-<span class="sourceLineNo">141</span><a name="line.141"></a>
-<span class="sourceLineNo">142</span>  public static enum TestTableSnapshotCounters {<a name="line.142"></a>
-<span class="sourceLineNo">143</span>    VALIDATION_ERROR<a name="line.143"></a>
-<span class="sourceLineNo">144</span>  }<a name="line.144"></a>
-<span class="sourceLineNo">145</span><a name="line.145"></a>
-<span class="sourceLineNo">146</span>  public static class TestTableSnapshotMapper<a name="line.146"></a>
-<span class="sourceLineNo">147</span>    extends TableMapper&lt;ImmutableBytesWritable, NullWritable&gt; {<a name="line.147"></a>
-<span class="sourceLineNo">148</span>    @Override<a name="line.148"></a>
-<span class="sourceLineNo">149</span>    protected void map(ImmutableBytesWritable key, Result value,<a name="line.149"></a>
-<span class="sourceLineNo">150</span>        Context context) throws IOException, InterruptedException {<a name="line.150"></a>
-<span class="sourceLineNo">151</span>      // Validate a single row coming from the snapshot, and emit the row key<a name="line.151"></a>
-<span class="sourceLineNo">152</span>      verifyRowFromMap(key, value);<a name="line.152"></a>
-<span class="sourceLineNo">153</span>      context.write(key, NullWritable.get());<a name="line.153"></a>
-<span class="sourceLineNo">154</span>    }<a name="line.154"></a>
-<span class="sourceLineNo">155</span>  }<a name="line.155"></a>
-<span class="sourceLineNo">156</span><a name="line.156"></a>
-<span class="sourceLineNo">157</span>  public static class TestTableSnapshotReducer<a name="line.157"></a>
-<span class="sourceLineNo">158</span>    extends Reducer&lt;ImmutableBytesWritable, NullWritable, NullWritable, NullWritable&gt; {<a name="line.158"></a>
-<span class="sourceLineNo">159</span>    HBaseTestingUtil.SeenRowTracker rowTracker =<a name="line.159"></a>
-<span class="sourceLineNo">160</span>        new HBaseTestingUtil.SeenRowTracker(bbb, yyy);<a name="line.160"></a>
-<span class="sourceLineNo">161</span>    @Override<a name="line.161"></a>
-<span class="sourceLineNo">162</span>    protected void reduce(ImmutableBytesWritable key, Iterable&lt;NullWritable&gt; values,<a name="line.162"></a>
-<span class="sourceLineNo">163</span>       Context context) throws IOException, InterruptedException {<a name="line.163"></a>
-<span class="sourceLineNo">164</span>      rowTracker.addRow(key.get());<a name="line.164"></a>
-<span class="sourceLineNo">165</span>    }<a name="line.165"></a>
-<span class="sourceLineNo">166</span><a name="line.166"></a>
-<span class="sourceLineNo">167</span>    @Override<a name="line.167"></a>
-<span class="sourceLineNo">168</span>    protected void cleanup(Context context) throws IOException,<a name="line.168"></a>
-<span class="sourceLineNo">169</span>        InterruptedException {<a name="line.169"></a>
-<span class="sourceLineNo">170</span>      rowTracker.validate();<a name="line.170"></a>
-<span class="sourceLineNo">171</span>    }<a name="line.171"></a>
-<span class="sourceLineNo">172</span>  }<a name="line.172"></a>
-<span class="sourceLineNo">173</span><a name="line.173"></a>
-<span class="sourceLineNo">174</span>  @Test<a name="line.174"></a>
-<span class="sourceLineNo">175</span>  public void testInitTableSnapshotMapperJobConfig() throws Exception {<a name="line.175"></a>
-<span class="sourceLineNo">176</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.176"></a>
-<span class="sourceLineNo">177</span>    String snapshotName = "foo";<a name="line.177"></a>
-<span class="sourceLineNo">178</span><a name="line.178"></a>
-<span class="sourceLineNo">179</span>    try {<a name="line.179"></a>
-<span class="sourceLineNo">180</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 1);<a name="line.180"></a>
-<span class="sourceLineNo">181</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.181"></a>
-<span class="sourceLineNo">182</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.182"></a>
-<span class="sourceLineNo">183</span><a name="line.183"></a>
-<span class="sourceLineNo">184</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.184"></a>
-<span class="sourceLineNo">185</span>        new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.185"></a>
-<span class="sourceLineNo">186</span>        NullWritable.class, job, false, tmpTableDir);<a name="line.186"></a>
-<span class="sourceLineNo">187</span><a name="line.187"></a>
-<span class="sourceLineNo">188</span>      // TODO: would be better to examine directly the cache instance that results from this<a name="line.188"></a>
-<span class="sourceLineNo">189</span>      // config. Currently this is not possible because BlockCache initialization is static.<a name="line.189"></a>
-<span class="sourceLineNo">190</span>      Assert.assertEquals(<a name="line.190"></a>
-<span class="sourceLineNo">191</span>        "Snapshot job should be configured for default LruBlockCache.",<a name="line.191"></a>
-<span class="sourceLineNo">192</span>        HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT,<a name="line.192"></a>
-<span class="sourceLineNo">193</span>        job.getConfiguration().getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, -1), 0.01);<a name="line.193"></a>
-<span class="sourceLineNo">194</span>      Assert.assertEquals(<a name="line.194"></a>
-<span class="sourceLineNo">195</span>        "Snapshot job should not use BucketCache.",<a name="line.195"></a>
-<span class="sourceLineNo">196</span>        0, job.getConfiguration().getFloat("hbase.bucketcache.size", -1), 0.01);<a name="line.196"></a>
-<span class="sourceLineNo">197</span>    } finally {<a name="line.197"></a>
-<span class="sourceLineNo">198</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.198"></a>
-<span class="sourceLineNo">199</span>      UTIL.deleteTable(tableName);<a name="line.199"></a>
-<span class="sourceLineNo">200</span>    }<a name="line.200"></a>
-<span class="sourceLineNo">201</span>  }<a name="line.201"></a>
-<span class="sourceLineNo">202</span><a name="line.202"></a>
-<span class="sourceLineNo">203</span>  @Test<a name="line.203"></a>
-<span class="sourceLineNo">204</span>  public void testWithMockedMapReduceSingleRegionByRegionLocation() throws Exception {<a name="line.204"></a>
-<span class="sourceLineNo">205</span>    Configuration conf = UTIL.getConfiguration();<a name="line.205"></a>
-<span class="sourceLineNo">206</span>    conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION, true);<a name="line.206"></a>
-<span class="sourceLineNo">207</span>    try {<a name="line.207"></a>
-<span class="sourceLineNo">208</span>      testWithMockedMapReduce(UTIL, name.getMethodName() + "Snapshot", 1, 1, 1,<a name="line.208"></a>
-<span class="sourceLineNo">209</span>        true);<a name="line.209"></a>
-<span class="sourceLineNo">210</span>    } finally {<a name="line.210"></a>
-<span class="sourceLineNo">211</span>      conf.unset(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION);<a name="line.211"></a>
-<span class="sourceLineNo">212</span>    }<a name="line.212"></a>
-<span class="sourceLineNo">213</span>  }<a name="line.213"></a>
-<span class="sourceLineNo">214</span><a name="line.214"></a>
-<span class="sourceLineNo">215</span>  @Override<a name="line.215"></a>
-<span class="sourceLineNo">216</span>  public void testRestoreSnapshotDoesNotCreateBackRefLinksInit(TableName tableName,<a name="line.216"></a>
-<span class="sourceLineNo">217</span>      String snapshotName, Path tmpTableDir) throws Exception {<a name="line.217"></a>
-<span class="sourceLineNo">218</span>    Job job = new Job(UTIL.getConfiguration());<a name="line.218"></a>
-<span class="sourceLineNo">219</span>    TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.219"></a>
-<span class="sourceLineNo">220</span>      new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.220"></a>
-<span class="sourceLineNo">221</span>      NullWritable.class, job, false, tmpTableDir);<a name="line.221"></a>
-<span class="sourceLineNo">222</span>  }<a name="line.222"></a>
-<span class="sourceLineNo">223</span><a name="line.223"></a>
-<span class="sourceLineNo">224</span>  @Override<a name="line.224"></a>
-<span class="sourceLineNo">225</span>  public void testWithMockedMapReduce(HBaseTestingUtil util, String snapshotName,<a name="line.225"></a>
-<span class="sourceLineNo">226</span>      int numRegions, int numSplitsPerRegion, int expectedNumSplits, boolean setLocalityEnabledTo)<a name="line.226"></a>
-<span class="sourceLineNo">227</span>      throws Exception {<a name="line.227"></a>
-<span class="sourceLineNo">228</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.228"></a>
-<span class="sourceLineNo">229</span>    try {<a name="line.229"></a>
-<span class="sourceLineNo">230</span>      createTableAndSnapshot(<a name="line.230"></a>
-<span class="sourceLineNo">231</span>        util, tableName, snapshotName, getStartRow(), getEndRow(), numRegions);<a name="line.231"></a>
-<span class="sourceLineNo">232</span><a name="line.232"></a>
-<span class="sourceLineNo">233</span>      Configuration conf = util.getConfiguration();<a name="line.233"></a>
-<span class="sourceLineNo">234</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, setLocalityEnabledTo);<a name="line.234"></a>
-<span class="sourceLineNo">235</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.235"></a>
-<span class="sourceLineNo">236</span>        SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.236"></a>
-<span class="sourceLineNo">237</span>      Job job = new Job(conf);<a name="line.237"></a>
-<span class="sourceLineNo">238</span>      Path tmpTableDir = util.getDataTestDirOnTestFS(snapshotName);<a name="line.238"></a>
-<span class="sourceLineNo">239</span>      Scan scan = new Scan().withStartRow(getStartRow()).withStopRow(getEndRow()); // limit the scan<a name="line.239"></a>
-<span class="sourceLineNo">240</span><a name="line.240"></a>
-<span class="sourceLineNo">241</span>      if (numSplitsPerRegion &gt; 1) {<a name="line.241"></a>
-<span class="sourceLineNo">242</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.242"></a>
-<span class="sourceLineNo">243</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.243"></a>
-<span class="sourceLineNo">244</span>                NullWritable.class, job, false, tmpTableDir, new RegionSplitter.UniformSplit(),<a name="line.244"></a>
-<span class="sourceLineNo">245</span>                numSplitsPerRegion);<a name="line.245"></a>
-<span class="sourceLineNo">246</span>      } else {<a name="line.246"></a>
-<span class="sourceLineNo">247</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.247"></a>
-<span class="sourceLineNo">248</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.248"></a>
-<span class="sourceLineNo">249</span>                NullWritable.class, job, false, tmpTableDir);<a name="line.249"></a>
-<span class="sourceLineNo">250</span>      }<a name="line.250"></a>
-<span class="sourceLineNo">251</span><a name="line.251"></a>
-<span class="sourceLineNo">252</span>      verifyWithMockedMapReduce(job, numRegions, expectedNumSplits, getStartRow(), getEndRow());<a name="line.252"></a>
-<span class="sourceLineNo">253</span><a name="line.253"></a>
-<span class="sourceLineNo">254</span>    } finally {<a name="line.254"></a>
-<span class="sourceLineNo">255</span>      util.getAdmin().deleteSnapshot(snapshotName);<a name="line.255"></a>
-<span class="sourceLineNo">256</span>      util.deleteTable(tableName);<a name="line.256"></a>
-<span class="sourceLineNo">257</span>    }<a name="line.257"></a>
-<span class="sourceLineNo">258</span>  }<a name="line.258"></a>
-<span class="sourceLineNo">259</span><a name="line.259"></a>
-<span class="sourceLineNo">260</span>  @Test<a name="line.260"></a>
-<span class="sourceLineNo">261</span>  public void testWithMockedMapReduceWithSplitsPerRegion() throws Exception {<a name="line.261"></a>
-<span class="sourceLineNo">262</span>    String snapshotName = "testWithMockedMapReduceMultiRegion";<a name="line.262"></a>
-<span class="sourceLineNo">263</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.263"></a>
-<span class="sourceLineNo">264</span>    try {<a name="line.264"></a>
-<span class="sourceLineNo">265</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 10);<a name="line.265"></a>
-<span class="sourceLineNo">266</span><a name="line.266"></a>
-<span class="sourceLineNo">267</span>      Configuration conf = UTIL.getConfiguration();<a name="line.267"></a>
-<span class="sourceLineNo">268</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, false);<a name="line.268"></a>
-<span class="sourceLineNo">269</span>      Job job = new Job(conf);<a name="line.269"></a>
-<span class="sourceLineNo">270</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.270"></a>
-<span class="sourceLineNo">271</span>      // test scan with startRow and stopRow<a name="line.271"></a>
-<span class="sourceLineNo">272</span>      Scan scan = new Scan().withStartRow(bbc).withStopRow(yya);<a name="line.272"></a>
-<span class="sourceLineNo">273</span><a name="line.273"></a>
-<span class="sourceLineNo">274</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.274"></a>
-<span class="sourceLineNo">275</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.275"></a>
-<span class="sourceLineNo">276</span>        tmpTableDir, new RegionSplitter.UniformSplit(), 5);<a name="line.276"></a>
-<span class="sourceLineNo">277</span><a name="line.277"></a>
-<span class="sourceLineNo">278</span>      verifyWithMockedMapReduce(job, 10, 40, bbc, yya);<a name="line.278"></a>
-<span class="sourceLineNo">279</span>    } finally {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.280"></a>
-<span class="sourceLineNo">281</span>      UTIL.deleteTable(tableName);<a name="line.281"></a>
-<span class="sourceLineNo">282</span>    }<a name="line.282"></a>
-<span class="sourceLineNo">283</span>  }<a name="line.283"></a>
-<span class="sourceLineNo">284</span><a name="line.284"></a>
-<span class="sourceLineNo">285</span>  @Test<a name="line.285"></a>
-<span class="sourceLineNo">286</span>  public void testWithMockedMapReduceWithNoStartRowStopRow() throws Exception {<a name="line.286"></a>
-<span class="sourceLineNo">287</span>    String snapshotName = "testWithMockedMapReduceMultiRegion";<a name="line.287"></a>
-<span class="sourceLineNo">288</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.288"></a>
-<span class="sourceLineNo">289</span>    try {<a name="line.289"></a>
-<span class="sourceLineNo">290</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 10);<a name="line.290"></a>
-<span class="sourceLineNo">291</span><a name="line.291"></a>
-<span class="sourceLineNo">292</span>      Configuration conf = UTIL.getConfiguration();<a name="line.292"></a>
-<span class="sourceLineNo">293</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, false);<a name="line.293"></a>
-<span class="sourceLineNo">294</span>      Job job = new Job(conf);<a name="line.294"></a>
-<span class="sourceLineNo">295</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.295"></a>
-<span class="sourceLineNo">296</span>      // test scan without startRow and stopRow<a name="line.296"></a>
-<span class="sourceLineNo">297</span>      Scan scan2 = new Scan();<a name="line.297"></a>
-<span class="sourceLineNo">298</span><a name="line.298"></a>
-<span class="sourceLineNo">299</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan2,<a name="line.299"></a>
-<span class="sourceLineNo">300</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.300"></a>
-<span class="sourceLineNo">301</span>        tmpTableDir, new RegionSplitter.UniformSplit(), 5);<a name="line.301"></a>
-<span class="sourceLineNo">302</span><a name="line.302"></a>
-<span class="sourceLineNo">303</span>      verifyWithMockedMapReduce(job, 10, 50, HConstants.EMPTY_START_ROW,<a name="line.303"></a>
-<span class="sourceLineNo">304</span>        HConstants.EMPTY_START_ROW);<a name="line.304"></a>
+<span class="sourceLineNo">138</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h3"}, 6);<a name="line.138"></a>
+<span class="sourceLineNo">139</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h4"}, 9);<a name="line.139"></a>
+<span class="sourceLineNo">140</span><a name="line.140"></a>
+<span class="sourceLineNo">141</span>    Assert.assertEquals(Lists.newArrayList("h2", "h3", "h4"),<a name="line.141"></a>
+<span class="sourceLineNo">142</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.142"></a>
+<span class="sourceLineNo">143</span>  }<a name="line.143"></a>
+<span class="sourceLineNo">144</span><a name="line.144"></a>
+<span class="sourceLineNo">145</span>  public static enum TestTableSnapshotCounters {<a name="line.145"></a>
+<span class="sourceLineNo">146</span>    VALIDATION_ERROR<a name="line.146"></a>
+<span class="sourceLineNo">147</span>  }<a name="line.147"></a>
+<span class="sourceLineNo">148</span><a name="line.148"></a>
+<span class="sourceLineNo">149</span>  public static class TestTableSnapshotMapper<a name="line.149"></a>
+<span class="sourceLineNo">150</span>    extends TableMapper&lt;ImmutableBytesWritable, NullWritable&gt; {<a name="line.150"></a>
+<span class="sourceLineNo">151</span>    @Override<a name="line.151"></a>
+<span class="sourceLineNo">152</span>    protected void map(ImmutableBytesWritable key, Result value,<a name="line.152"></a>
+<span class="sourceLineNo">153</span>        Context context) throws IOException, InterruptedException {<a name="line.153"></a>
+<span class="sourceLineNo">154</span>      // Validate a single row coming from the snapshot, and emit the row key<a name="line.154"></a>
+<span class="sourceLineNo">155</span>      verifyRowFromMap(key, value);<a name="line.155"></a>
+<span class="sourceLineNo">156</span>      context.write(key, NullWritable.get());<a name="line.156"></a>
+<span class="sourceLineNo">157</span>    }<a name="line.157"></a>
+<span class="sourceLineNo">158</span>  }<a name="line.158"></a>
+<span class="sourceLineNo">159</span><a name="line.159"></a>
+<span class="sourceLineNo">160</span>  public static class TestTableSnapshotReducer<a name="line.160"></a>
+<span class="sourceLineNo">161</span>    extends Reducer&lt;ImmutableBytesWritable, NullWritable, NullWritable, NullWritable&gt; {<a name="line.161"></a>
+<span class="sourceLineNo">162</span>    HBaseTestingUtil.SeenRowTracker rowTracker =<a name="line.162"></a>
+<span class="sourceLineNo">163</span>        new HBaseTestingUtil.SeenRowTracker(bbb, yyy);<a name="line.163"></a>
+<span class="sourceLineNo">164</span>    @Override<a name="line.164"></a>
+<span class="sourceLineNo">165</span>    protected void reduce(ImmutableBytesWritable key, Iterable&lt;NullWritable&gt; values,<a name="line.165"></a>
+<span class="sourceLineNo">166</span>       Context context) throws IOException, InterruptedException {<a name="line.166"></a>
+<span class="sourceLineNo">167</span>      rowTracker.addRow(key.get());<a name="line.167"></a>
+<span class="sourceLineNo">168</span>    }<a name="line.168"></a>
+<span class="sourceLineNo">169</span><a name="line.169"></a>
+<span class="sourceLineNo">170</span>    @Override<a name="line.170"></a>
+<span class="sourceLineNo">171</span>    protected void cleanup(Context context) throws IOException,<a name="line.171"></a>
+<span class="sourceLineNo">172</span>        InterruptedException {<a name="line.172"></a>
+<span class="sourceLineNo">173</span>      rowTracker.validate();<a name="line.173"></a>
+<span class="sourceLineNo">174</span>    }<a name="line.174"></a>
+<span class="sourceLineNo">175</span>  }<a name="line.175"></a>
+<span class="sourceLineNo">176</span><a name="line.176"></a>
+<span class="sourceLineNo">177</span>  @Test<a name="line.177"></a>
+<span class="sourceLineNo">178</span>  public void testInitTableSnapshotMapperJobConfig() throws Exception {<a name="line.178"></a>
+<span class="sourceLineNo">179</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.179"></a>
+<span class="sourceLineNo">180</span>    String snapshotName = "foo";<a name="line.180"></a>
+<span class="sourceLineNo">181</span><a name="line.181"></a>
+<span class="sourceLineNo">182</span>    try {<a name="line.182"></a>
+<span class="sourceLineNo">183</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 1);<a name="line.183"></a>
+<span class="sourceLineNo">184</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.184"></a>
+<span class="sourceLineNo">185</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.185"></a>
+<span class="sourceLineNo">186</span><a name="line.186"></a>
+<span class="sourceLineNo">187</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.187"></a>
+<span class="sourceLineNo">188</span>        new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.188"></a>
+<span class="sourceLineNo">189</span>        NullWritable.class, job, false, tmpTableDir);<a name="line.189"></a>
+<span class="sourceLineNo">190</span><a name="line.190"></a>
+<span class="sourceLineNo">191</span>      // TODO: would be better to examine directly the cache instance that results from this<a name="line.191"></a>
+<span class="sourceLineNo">192</span>      // config. Currently this is not possible because BlockCache initialization is static.<a name="line.192"></a>
+<span class="sourceLineNo">193</span>      Assert.assertEquals(<a name="line.193"></a>
+<span class="sourceLineNo">194</span>        "Snapshot job should be configured for default LruBlockCache.",<a name="line.194"></a>
+<span class="sourceLineNo">195</span>        HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT,<a name="line.195"></a>
+<span class="sourceLineNo">196</span>        job.getConfiguration().getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, -1), 0.01);<a name="line.196"></a>
+<span class="sourceLineNo">197</span>      Assert.assertEquals(<a name="line.197"></a>
+<span class="sourceLineNo">198</span>        "Snapshot job should not use BucketCache.",<a name="line.198"></a>
+<span class="sourceLineNo">199</span>        0, job.getConfiguration().getFloat("hbase.bucketcache.size", -1), 0.01);<a name="line.199"></a>
+<span class="sourceLineNo">200</span>    } finally {<a name="line.200"></a>
+<span class="sourceLineNo">201</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.201"></a>
+<span class="sourceLineNo">202</span>      UTIL.deleteTable(tableName);<a name="line.202"></a>
+<span class="sourceLineNo">203</span>    }<a name="line.203"></a>
+<span class="sourceLineNo">204</span>  }<a name="line.204"></a>
+<span class="sourceLineNo">205</span><a name="line.205"></a>
+<span class="sourceLineNo">206</span>  @Test<a name="line.206"></a>
+<span class="sourceLineNo">207</span>  public void testWithMockedMapReduceSingleRegionByRegionLocation() throws Exception {<a name="line.207"></a>
+<span class="sourceLineNo">208</span>    Configuration conf = UTIL.getConfiguration();<a name="line.208"></a>
+<span class="sourceLineNo">209</span>    conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION, true);<a name="line.209"></a>
+<span class="sourceLineNo">210</span>    try {<a name="line.210"></a>
+<span class="sourceLineNo">211</span>      testWithMockedMapReduce(UTIL, name.getMethodName() + "Snapshot", 1, 1, 1,<a name="line.211"></a>
+<span class="sourceLineNo">212</span>        true);<a name="line.212"></a>
+<span class="sourceLineNo">213</span>    } finally {<a name="line.213"></a>
+<span class="sourceLineNo">214</span>      conf.unset(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION);<a name="line.214"></a>
+<span class="sourceLineNo">215</span>    }<a name="line.215"></a>
+<span class="sourceLineNo">216</span>  }<a name="line.216"></a>
+<span class="sourceLineNo">217</span><a name="line.217"></a>
+<span class="sourceLineNo">218</span>  @Override<a name="line.218"></a>
+<span class="sourceLineNo">219</span>  public void testRestoreSnapshotDoesNotCreateBackRefLinksInit(TableName tableName,<a name="line.219"></a>
+<span class="sourceLineNo">220</span>      String snapshotName, Path tmpTableDir) throws Exception {<a name="line.220"></a>
+<span class="sourceLineNo">221</span>    Job job = new Job(UTIL.getConfiguration());<a name="line.221"></a>
+<span class="sourceLineNo">222</span>    TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.222"></a>
+<span class="sourceLineNo">223</span>      new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.223"></a>
+<span class="sourceLineNo">224</span>      NullWritable.class, job, false, tmpTableDir);<a name="line.224"></a>
+<span class="sourceLineNo">225</span>  }<a name="line.225"></a>
+<span class="sourceLineNo">226</span><a name="line.226"></a>
+<span class="sourceLineNo">227</span>  @Override<a name="line.227"></a>
+<span class="sourceLineNo">228</span>  public void testWithMockedMapReduce(HBaseTestingUtil util, String snapshotName,<a name="line.228"></a>
+<span class="sourceLineNo">229</span>      int numRegions, int numSplitsPerRegion, int expectedNumSplits, boolean setLocalityEnabledTo)<a name="line.229"></a>
+<span class="sourceLineNo">230</span>      throws Exception {<a name="line.230"></a>
+<span class="sourceLineNo">231</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.231"></a>
+<span class="sourceLineNo">232</span>    try {<a name="line.232"></a>
+<span class="sourceLineNo">233</span>      createTableAndSnapshot(<a name="line.233"></a>
+<span class="sourceLineNo">234</span>        util, tableName, snapshotName, getStartRow(), getEndRow(), numRegions);<a name="line.234"></a>
+<span class="sourceLineNo">235</span><a name="line.235"></a>
+<span class="sourceLineNo">236</span>      Configuration conf = util.getConfiguration();<a name="line.236"></a>
+<span class="sourceLineNo">237</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, setLocalityEnabledTo);<a name="line.237"></a>
+<span class="sourceLineNo">238</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.238"></a>
+<span class="sourceLineNo">239</span>        SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.239"></a>
+<span class="sourceLineNo">240</span>      Job job = new Job(conf);<a name="line.240"></a>
+<span class="sourceLineNo">241</span>      Path tmpTableDir = util.getDataTestDirOnTestFS(snapshotName);<a name="line.241"></a>
+<span class="sourceLineNo">242</span>      Scan scan = new Scan().withStartRow(getStartRow()).withStopRow(getEndRow()); // limit the scan<a name="line.242"></a>
+<span class="sourceLineNo">243</span><a name="line.243"></a>
+<span class="sourceLineNo">244</span>      if (numSplitsPerRegion &gt; 1) {<a name="line.244"></a>
+<span class="sourceLineNo">245</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.245"></a>
+<span class="sourceLineNo">246</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.246"></a>
+<span class="sourceLineNo">247</span>                NullWritable.class, job, false, tmpTableDir, new RegionSplitter.UniformSplit(),<a name="line.247"></a>
+<span class="sourceLineNo">248</span>                numSplitsPerRegion);<a name="line.248"></a>
+<span class="sourceLineNo">249</span>      } else {<a name="line.249"></a>
+<span class="sourceLineNo">250</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.250"></a>
+<span class="sourceLineNo">251</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.251"></a>
+<span class="sourceLineNo">252</span>                NullWritable.class, job, false, tmpTableDir);<a name="line.252"></a>
+<span class="sourceLineNo">253</span>      }<a name="line.253"></a>
+<span class="sourceLineNo">254</span><a name="line.254"></a>
+<span class="sourceLineNo">255</span>      verifyWithMockedMapReduce(job, numRegions, expectedNumSplits, getStartRow(), getEndRow());<a name="line.255"></a>
+<span class="sourceLineNo">256</span><a name="line.256"></a>
+<span class="sourceLineNo">257</span>    } finally {<a name="line.257"></a>
+<span class="sourceLineNo">258</span>      util.getAdmin().deleteSnapshot(snapshotName);<a name="line.258"></a>
+<span class="sourceLineNo">259</span>      util.deleteTable(tableName);<a name="line.259"></a>
+<span class="sourceLineNo">260</span>    }<a name="line.260"></a>
+<span class="sourceLineNo">261</span>  }<a name="line.261"></a>
+<span class="sourceLineNo">262</span><a name="line.262"></a>
+<span class="sourceLineNo">263</span>  @Test<a name="line.263"></a>
+<span class="sourceLineNo">264</span>  public void testWithMockedMapReduceWithSplitsPerRegion() throws Exception {<a name="line.264"></a>
+<span class="sourceLineNo">265</span>    String snapshotName = "testWithMockedMapReduceMultiRegion";<a name="line.265"></a>
+<span class="sourceLineNo">266</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.266"></a>
+<span class="sourceLineNo">267</span>    try {<a name="line.267"></a>
+<span class="sourceLineNo">268</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 10);<a name="line.268"></a>
+<span class="sourceLineNo">269</span><a name="line.269"></a>
+<span class="sourceLineNo">270</span>      Configuration conf = UTIL.getConfiguration();<a name="line.270"></a>
+<span class="sourceLineNo">271</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, false);<a name="line.271"></a>
+<span class="sourceLineNo">272</span>      Job job = new Job(conf);<a name="line.272"></a>
+<span class="sourceLineNo">273</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.273"></a>
+<span class="sourceLineNo">274</span>      // test scan with startRow and stopRow<a name="line.274"></a>
+<span class="sourceLineNo">275</span>      Scan scan = new Scan().withStartRow(bbc).withStopRow(yya);<a name="line.275"></a>
+<span class="sourceLineNo">276</span><a name="line.276"></a>
+<span class="sourceLineNo">277</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.277"></a>
+<span class="sourceLineNo">278</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.278"></a>
+<span class="sourceLineNo">279</span>        tmpTableDir, new RegionSplitter.UniformSplit(), 5);<a name="line.279"></a>
+<span class="sourceLineNo">280</span><a name="line.280"></a>
+<span class="sourceLineNo">281</span>      verifyWithMockedMapReduce(job, 10, 40, bbc, yya);<a name="line.281"></a>
+<span class="sourceLineNo">282</span>    } finally {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.283"></a>
+<span class="sourceLineNo">284</span>      UTIL.deleteTable(tableName);<a name="line.284"></a>
+<span class="sourceLineNo">285</span>    }<a name="line.285"></a>
+<span class="sourceLineNo">286</span>  }<a name="line.286"></a>
+<span class="sourceLineNo">287</span><a name="line.287"></a>
+<span class="sourceLineNo">288</span>  @Test<a name="line.288"></a>
+<span class="sourceLineNo">289</span>  public void testWithMockedMapReduceWithNoStartRowStopRow() throws Exception {<a name="line.289"></a>
+<span class="sourceLineNo">290</span>    String snapshotName = "testWithMockedMapReduceMultiRegion";<a name="line.290"></a>
+<span class="sourceLineNo">291</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.291"></a>
+<span class="sourceLineNo">292</span>    try {<a name="line.292"></a>
+<span class="sourceLineNo">293</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 10);<a name="line.293"></a>
+<span class="sourceLineNo">294</span><a name="line.294"></a>
+<span class="sourceLineNo">295</span>      Configuration conf = UTIL.getConfiguration();<a name="line.295"></a>
+<span class="sourceLineNo">296</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, false);<a name="line.296"></a>
+<span class="sourceLineNo">297</span>      Job job = new Job(conf);<a name="line.297"></a>
+<span class="sourceLineNo">298</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.298"></a>
+<span class="sourceLineNo">299</span>      // test scan without startRow and stopRow<a name="line.299"></a>
+<span class="sourceLineNo">300</span>      Scan scan2 = new Scan();<a name="line.300"></a>
+<span class="sourceLineNo">301</span><a name="line.301"></a>
+<span class="sourceLineNo">302</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan2,<a name="line.302"></a>
+<span class="sourceLineNo">303</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.303"></a>
+<span class="sourceLineNo">304</span>        tmpTableDir, new RegionSplitter.UniformSplit(), 5);<a name="line.304"></a>
 <span class="sourceLineNo">305</span><a name="line.305"></a>
-<span class="sourceLineNo">306</span>    } finally {<a name="line.306"></a>
-<span class="sourceLineNo">307</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.307"></a>
-<span class="sourceLineNo">308</span>      UTIL.deleteTable(tableName);<a name="line.308"></a>
-<span class="sourceLineNo">309</span>    }<a name="line.309"></a>
-<span class="sourceLineNo">310</span>  }<a name="line.310"></a>
-<span class="sourceLineNo">311</span><a name="line.311"></a>
-<span class="sourceLineNo">312</span>  @Test<a name="line.312"></a>
-<span class="sourceLineNo">313</span>  public void testScanLimit() throws Exception {<a name="line.313"></a>
-<span class="sourceLineNo">314</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.314"></a>
-<span class="sourceLineNo">315</span>    final String snapshotName = tableName + "Snapshot";<a name="line.315"></a>
-<span class="sourceLineNo">316</span>    Table table = null;<a name="line.316"></a>
-<span class="sourceLineNo">317</span>    try {<a name="line.317"></a>
-<span class="sourceLineNo">318</span>      UTIL.getConfiguration().setInt(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT, 10);<a name="line.318"></a>
-<span class="sourceLineNo">319</span>      if (UTIL.getAdmin().tableExists(tableName)) {<a name="line.319"></a>
-<span class="sourceLineNo">320</span>        UTIL.deleteTable(tableName);<a name="line.320"></a>
-<span class="sourceLineNo">321</span>      }<a name="line.321"></a>
-<span class="sourceLineNo">322</span><a name="line.322"></a>
-<span class="sourceLineNo">323</span>      UTIL.createTable(tableName, FAMILIES, new byte[][] { bbb, yyy });<a name="line.323"></a>
-<span class="sourceLineNo">324</span><a name="line.324"></a>
-<span class="sourceLineNo">325</span>      Admin admin = UTIL.getAdmin();<a name="line.325"></a>
-<span class="sourceLineNo">326</span><a name="line.326"></a>
-<span class="sourceLineNo">327</span>      int regionNum = admin.getRegions(tableName).size();<a name="line.327"></a>
-<span class="sourceLineNo">328</span>      // put some stuff in the table<a name="line.328"></a>
-<span class="sourceLineNo">329</span>      table = UTIL.getConnection().getTable(tableName);<a name="line.329"></a>
-<span class="sourceLineNo">330</span>      UTIL.loadTable(table, FAMILIES);<a name="line.330"></a>
-<span class="sourceLineNo">331</span><a name="line.331"></a>
-<span class="sourceLineNo">332</span>      Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.332"></a>
-<span class="sourceLineNo">333</span>      FileSystem fs = rootDir.getFileSystem(UTIL.getConfiguration());<a name="line.333"></a>
+<span class="sourceLineNo">306</span>      verifyWithMockedMapReduce(job, 10, 50, HConstants.EMPTY_START_ROW,<a name="line.306"></a>
+<span class="sourceLineNo">307</span>        HConstants.EMPTY_START_ROW);<a name="line.307"></a>
+<span class="sourceLineNo">308</span><a name="line.308"></a>
+<span class="sourceLineNo">309</span>    } finally {<a name="line.309"></a>
+<span class="sourceLineNo">310</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.310"></a>
+<span class="sourceLineNo">311</span>      UTIL.deleteTable(tableName);<a name="line.311"></a>
+<span class="sourceLineNo">312</span>    }<a name="line.312"></a>
+<span class="sourceLineNo">313</span>  }<a name="line.313"></a>
+<span class="sourceLineNo">314</span><a name="line.314"></a>
+<span class="sourceLineNo">315</span>  @Test<a name="line.315"></a>
+<span class="sourceLineNo">316</span>  public void testScanLimit() throws Exception {<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.317"></a>
+<span class="sourceLineNo">318</span>    final String snapshotName = tableName + "Snapshot";<a name="line.318"></a>
+<span class="sourceLineNo">319</span>    Table table = null;<a name="line.319"></a>
+<span class="sourceLineNo">320</span>    try {<a name="line.320"></a>
+<span class="sourceLineNo">321</span>      UTIL.getConfiguration().setInt(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT, 10);<a name="line.321"></a>
+<span class="sourceLineNo">322</span>      if (UTIL.getAdmin().tableExists(tableName)) {<a name="line.322"></a>
+<span class="sourceLineNo">323</span>        UTIL.deleteTable(tableName);<a name="line.323"></a>
+<span class="sourceLineNo">324</span>      }<a name="line.324"></a>
+<span class="sourceLineNo">325</span><a name="line.325"></a>
+<span class="sourceLineNo">326</span>      UTIL.createTable(tableName, FAMILIES, new byte[][] { bbb, yyy });<a name="line.326"></a>
+<span class="sourceLineNo">327</span><a name="line.327"></a>
+<span class="sourceLineNo">328</span>      Admin admin = UTIL.getAdmin();<a name="line.328"></a>
+<span class="sourceLineNo">329</span><a name="line.329"></a>
+<span class="sourceLineNo">330</span>      int regionNum = admin.getRegions(tableName).size();<a name="line.330"></a>
+<span class="sourceLineNo">331</span>      // put some stuff in the table<a name="line.331"></a>
+<span class="sourceLineNo">332</span>      table = UTIL.getConnection().getTable(tableName);<a name="line.332"></a>
+<span class="sourceLineNo">333</span>      UTIL.loadTable(table, FAMILIES);<a name="line.333"></a>
 <span class="sourceLineNo">334</span><a name="line.334"></a>
-<span class="sourceLineNo">335</span>      SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName, Arrays.asList(FAMILIES),<a name="line.335"></a>
-<span class="sourceLineNo">336</span>        null, snapshotName, rootDir, fs, true);<a name="line.336"></a>
+<span class="sourceLineNo">335</span>      Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.335"></a>
+<span class="sourceLineNo">336</span>      FileSystem fs = rootDir.getFileSystem(UTIL.getConfiguration());<a name="line.336"></a>
 <span class="sourceLineNo">337</span><a name="line.337"></a>
-<span class="sourceLineNo">338</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.338"></a>
-<span class="sourceLineNo">339</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.339"></a>
-<span class="sourceLineNo">340</span>      Scan scan = new Scan();<a name="line.340"></a>
-<span class="sourceLineNo">341</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.341"></a>
-<span class="sourceLineNo">342</span>        TestTableSnapshotInputFormat.class);<a name="line.342"></a>
-<span class="sourceLineNo">343</span><a name="line.343"></a>
-<span class="sourceLineNo">344</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.344"></a>
-<span class="sourceLineNo">345</span>        RowCounter.RowCounterMapper.class, NullWritable.class, NullWritable.class, job, true,<a name="line.345"></a>
-<span class="sourceLineNo">346</span>        tmpTableDir);<a name="line.346"></a>
-<span class="sourceLineNo">347</span>      Assert.assertTrue(job.waitForCompletion(true));<a name="line.347"></a>
-<span class="sourceLineNo">348</span>      Assert.assertEquals(10 * regionNum,<a name="line.348"></a>
-<span class="sourceLineNo">349</span>        job.getCounters().findCounter(RowCounter.RowCounterMapper.Counters.ROWS).getValue());<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    } finally {<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      if (table != null) {<a name="line.351"></a>
-<span class="sourceLineNo">352</span>        table.close();<a name="line.352"></a>
-<span class="sourceLineNo">353</span>      }<a name="line.353"></a>
-<span class="sourceLineNo">354</span>      UTIL.getConfiguration().unset(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT);<a name="line.354"></a>
-<span class="sourceLineNo">355</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.355"></a>
-<span class="sourceLineNo">356</span>      UTIL.deleteTable(tableName);<a name="line.356"></a>
-<span class="sourceLineNo">357</span>    }<a name="line.357"></a>
-<span class="sourceLineNo">358</span>  }<a name="line.358"></a>
-<span class="sourceLineNo">359</span><a name="line.359"></a>
-<span class="sourceLineNo">360</span>  @Test<a name="line.360"></a>
-<span class="sourceLineNo">361</span>  public void testNoDuplicateResultsWhenSplitting() throws Exception {<a name="line.361"></a>
-<span class="sourceLineNo">362</span>    TableName tableName = TableName.valueOf("testNoDuplicateResultsWhenSplitting");<a name="line.362"></a>
-<span class="sourceLineNo">363</span>    String snapshotName = "testSnapshotBug";<a name="line.363"></a>
-<span class="sourceLineNo">364</span>    try {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>      if (UTIL.getAdmin().tableExists(tableName)) {<a name="line.365"></a>
-<span class="sourceLineNo">366</span>        UTIL.deleteTable(tableName);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>      }<a name="line.367"></a>
-<span class="sourceLineNo">368</span><a name="line.368"></a>
-<span class="sourceLineNo">369</span>      UTIL.createTable(tableName, FAMILIES);<a name="line.369"></a>
-<span class="sourceLineNo">370</span>      Admin admin = UTIL.getAdmin();<a name="line.370"></a>
+<span class="sourceLineNo">338</span>      SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName, Arrays.asList(FAMILIES),<a name="line.338"></a>
+<span class="sourceLineNo">339</span>        null, snapshotName, rootDir, fs, true);<a name="line.339"></a>
+<span class="sourceLineNo">340</span><a name="line.340"></a>
+<span class="sourceLineNo">341</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.341"></a>
+<span class="sourceLineNo">342</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.342"></a>
+<span class="sourceLineNo">343</span>      Scan scan = new Scan();<a name="line.343"></a>
+<span class="sourceLineNo">344</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.344"></a>
+<span class="sourceLineNo">345</span>        TestTableSnapshotInputFormat.class);<a name="line.345"></a>
+<span class="sourceLineNo">346</span><a name="line.346"></a>
+<span class="sourceLineNo">347</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.347"></a>
+<span class="sourceLineNo">348</span>        RowCounter.RowCounterMapper.class, NullWritable.class, NullWritable.class, job, true,<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        tmpTableDir);<a name="line.349"></a>
+<span class="sourceLineNo">350</span>      Assert.assertTrue(job.waitForCompletion(true));<a name="line.350"></a>
+<span class="sourceLineNo">351</span>      Assert.assertEquals(10 * regionNum,<a name="line.351"></a>
+<span class="sourceLineNo">352</span>        job.getCounters().findCounter(RowCounter.RowCounterMapper.Counters.ROWS).getValue());<a name="line.352"></a>
+<span class="sourceLineNo">353</span>    } finally {<a name="line.353"></a>
+<span class="sourceLineNo">354</span>      if (table != null) {<a name="line.354"></a>
+<span class="sourceLineNo">355</span>        table.close();<a name="line.355"></a>
+<span class="sourceLineNo">356</span>      }<a name="line.356"></a>
+<span class="sourceLineNo">357</span>      UTIL.getConfiguration().unset(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT);<a name="line.357"></a>
+<span class="sourceLineNo">358</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.358"></a>
+<span class="sourceLineNo">359</span>      UTIL.deleteTable(tableName);<a name="line.359"></a>
+<span class="sourceLineNo">360</span>    }<a name="line.360"></a>
+<span class="sourceLineNo">361</span>  }<a name="line.361"></a>
+<span class="sourceLineNo">362</span><a name="line.362"></a>
+<span class="sourceLineNo">363</span>  @Test<a name="line.363"></a>
+<span class="sourceLineNo">364</span>  public void testNoDuplicateResultsWhenSplitting() throws Exception {<a name="line.364"></a>
+<span class="sourceLineNo">365</span>    TableName tableName = TableName.valueOf("testNoDuplicateResultsWhenSplitting");<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    String snapshotName = "testSnapshotBug";<a name="line.366"></a>
+<span class="sourceLineNo">367</span>    try {<a name="line.367"></a>
+<span class="sourceLineNo">368</span>      if (UTIL.getAdmin().tableExists(tableName)) {<a name="line.368"></a>
+<span class="sourceLineNo">369</span>        UTIL.deleteTable(tableName);<a name="line.369"></a>
+<span class="sourceLineNo">370</span>      }<a name="line.370"></a>
 <span class="sourceLineNo">371</span><a name="line.371"></a>
-<span class="sourceLineNo">372</span>      // put some stuff in the table<a name="line.372"></a>
-<span class="sourceLineNo">373</span>      Table table = UTIL.getConnection().getTable(tableName);<a name="line.373"></a>
-<span class="sourceLineNo">374</span>      UTIL.loadTable(table, FAMILIES);<a name="line.374"></a>
-<span class="sourceLineNo">375</span><a name="line.375"></a>
-<span class="sourceLineNo">376</span>      // split to 2 regions<a name="line.376"></a>
-<span class="sourceLineNo">377</span>      admin.split(tableName, Bytes.toBytes("eee"));<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      TestTableSnapshotScanner.blockUntilSplitFinished(UTIL, tableName, 2);<a name="line.378"></a>
-<span class="sourceLineNo">379</span><a name="line.379"></a>
-<span class="sourceLineNo">380</span>      Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      FileSystem fs = rootDir.getFileSystem(UTIL.getConfiguration());<a name="line.381"></a>
+<span class="sourceLineNo">372</span>      UTIL.createTable(tableName, FAMILIES);<a name="line.372"></a>
+<span class="sourceLineNo">373</span>      Admin admin = UTIL.getAdmin();<a name="line.373"></a>
+<span class="sourceLineNo">374</span><a name="line.374"></a>
+<span class="sourceLineNo">375</span>      // put some stuff in the table<a name="line.375"></a>
+<span class="sourceLineNo">376</span>      Table table = UTIL.getConnection().getTable(tableName);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>      UTIL.loadTable(table, FAMILIES);<a name="line.377"></a>
+<span class="sourceLineNo">378</span><a name="line.378"></a>
+<span class="sourceLineNo">379</span>      // split to 2 regions<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      admin.split(tableName, Bytes.toBytes("eee"));<a name="line.380"></a>
+<span class="sourceLineNo">381</span>      TestTableSnapshotScanner.blockUntilSplitFinished(UTIL, tableName, 2);<a name="line.381"></a>
 <span class="sourceLineNo">382</span><a name="line.382"></a>
-<span class="sourceLineNo">383</span>      SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName, Arrays.asList(FAMILIES),<a name="line.383"></a>
-<span class="sourceLineNo">384</span>        null, snapshotName, rootDir, fs, true);<a name="line.384"></a>
+<span class="sourceLineNo">383</span>      Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      FileSystem fs = rootDir.getFileSystem(UTIL.getConfiguration());<a name="line.384"></a>
 <span class="sourceLineNo">385</span><a name="line.385"></a>
-<span class="sourceLineNo">386</span>      // load different values<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      byte[] value = Bytes.toBytes("after_snapshot_value");<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      UTIL.loadTable(table, FAMILIES, value);<a name="line.388"></a>
-<span class="sourceLineNo">389</span><a name="line.389"></a>
-<span class="sourceLineNo">390</span>      // cause flush to create new files in the region<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      admin.flush(tableName);<a name="line.391"></a>
-<span class="sourceLineNo">392</span>      table.close();<a name="line.392"></a>
-<span class="sourceLineNo">393</span><a name="line.393"></a>
-<span class="sourceLineNo">394</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>      // limit the scan<a name="line.396"></a>
-<span class="sourceLineNo">397</span>      Scan scan = new Scan().withStartRow(getStartRow()).withStopRow(getEndRow());<a name="line.397"></a>
-<span class="sourceLineNo">398</span><a name="line.398"></a>
-<span class="sourceLineNo">399</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.399"></a>
-<span class="sourceLineNo">400</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.400"></a>
-<span class="sourceLineNo">401</span>        tmpTableDir);<a name="line.401"></a>
-<span class="sourceLineNo">402</span><a name="line.402"></a>
-<span class="sourceLineNo">403</span>      verifyWithMockedMapReduce(job, 2, 2, getStartRow(), getEndRow());<a name="line.403"></a>
-<span class="sourceLineNo">404</span>    } finally {<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      UTIL.deleteTable(tableName);<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    }<a name="line.407"></a>
-<span class="sourceLineNo">408</span>  }<a name="line.408"></a>
-<span class="sourceLineNo">409</span><a name="line.409"></a>
-<span class="sourceLineNo">410</span>  private void verifyWithMockedMapReduce(Job job, int numRegions, int expectedNumSplits,<a name="line.410"></a>
-<span class="sourceLineNo">411</span>      byte[] startRow, byte[] stopRow)<a name="line.411"></a>
-<span class="sourceLineNo">412</span>      throws IOException, InterruptedException {<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    TableSnapshotInputFormat tsif = new TableSnapshotInputFormat();<a name="line.413"></a>
-<span class="sourceLineNo">414</span>    List&lt;InputSplit&gt; splits = tsif.getSplits(job);<a name="line.414"></a>
-<span class="sourceLineNo">415</span><a name="line.415"></a>
-<span class="sourceLineNo">416</span>    Assert.assertEquals(expectedNumSplits, splits.size());<a name="line.416"></a>
-<span class="sourceLineNo">417</span><a name="line.417"></a>
-<span class="sourceLineNo">418</span>    HBaseTestingUtil.SeenRowTracker rowTracker = new HBaseTestingUtil.SeenRowTracker(startRow,<a name="line.418"></a>
-<span class="sourceLineNo">419</span>        stopRow.length &gt; 0 ? stopRow : Bytes.toBytes("\uffff"));<a name="line.419"></a>
-<span class="sourceLineNo">420</span><a name="line.420"></a>
-<span class="sourceLineNo">421</span>    boolean localityEnabled =<a name="line.421"></a>
-<span class="sourceLineNo">422</span>        job.getConfiguration().getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY,<a name="line.422"></a>
-<span class="sourceLineNo">423</span>                                          SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT);<a name="line.423"></a>
-<span class="sourceLineNo">424</span><a name="line.424"></a>
-<span class="sourceLineNo">425</span>    boolean byRegionLoc =<a name="line.425"></a>
-<span class="sourceLineNo">426</span>      job.getConfiguration().getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.426"></a>
-<span class="sourceLineNo">427</span>                                        SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.427"></a>
-<span class="sourceLineNo">428</span>    for (int i = 0; i &lt; splits.size(); i++) {<a name="line.428"></a>
-<span class="sourceLineNo">429</span>      // validate input split<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      InputSplit split = splits.get(i);<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      Assert.assertTrue(split instanceof TableSnapshotRegionSplit);<a name="line.431"></a>
-<span class="sourceLineNo">432</span>      TableSnapshotRegionSplit snapshotRegionSplit = (TableSnapshotRegionSplit) split;<a name="line.432"></a>
-<span class="sourceLineNo">433</span>      if (localityEnabled) {<a name="line.433"></a>
-<span class="sourceLineNo">434</span>        Assert.assertTrue(split.getLocations() != null &amp;&amp; split.getLocations().length != 0);<a name="line.434"></a>
-<span class="sourceLineNo">435</span>        if (byRegionLoc) {<a name="line.435"></a>
-<span class="sourceLineNo">436</span>          // When it uses region location from meta, the hostname will be "localhost",<a name="line.436"></a>
-<span class="sourceLineNo">437</span>          // the location from hdfs block location is "127.0.0.1".<a name="line.437"></a>
-<span class="sourceLineNo">438</span>          Assert.assertEquals(1, split.getLocations().length);<a name="line.438"></a>
-<span class="sourceLineNo">439</span>          Assert.assertTrue("Not using region location!",<a name="line.439"></a>
-<span class="sourceLineNo">440</span>            split.getLocations()[0].equals("localhost"));<a name="line.440"></a>
-<span class="sourceLineNo">441</span>        } else {<a name="line.441"></a>
-<span class="sourceLineNo">442</span>          Assert.assertTrue("Not using region location!",<a name="line.442"></a>
-<span class="sourceLineNo">443</span>            split.getLocations()[0].equals("127.0.0.1"));<a name="line.443"></a>
-<span class="sourceLineNo">444</span>        }<a name="line.444"></a>
-<span class="sourceLineNo">445</span>      } else {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>        Assert.assertTrue(split.getLocations() != null &amp;&amp; split.getLocations().length == 0);<a name="line.446"></a>
-<span class="sourceLineNo">447</span>      }<a name="line.447"></a>
+<span class="sourceLineNo">386</span>      SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName, Arrays.asList(FAMILIES),<a name="line.386"></a>
+<span class="sourceLineNo">387</span>        null, snapshotName, rootDir, fs, true);<a name="line.387"></a>
+<span class="sourceLineNo">388</span><a name="line.388"></a>
+<span class="sourceLineNo">389</span>      // load different values<a name="line.389"></a>
+<span class="sourceLineNo">390</span>      byte[] value = Bytes.toBytes("after_snapshot_value");<a name="line.390"></a>
+<span class="sourceLineNo">391</span>      UTIL.loadTable(table, FAMILIES, value);<a name="line.391"></a>
+<span class="sourceLineNo">392</span><a name="line.392"></a>
+<span class="sourceLineNo">393</span>      // cause flush to create new files in the region<a name="line.393"></a>
+<span class="sourceLineNo">394</span>      admin.flush(tableName);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>      table.close();<a name="line.395"></a>
+<span class="sourceLineNo">396</span><a name="line.396"></a>
+<span class="sourceLineNo">397</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.397"></a>
+<span class="sourceLineNo">398</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.398"></a>
+<span class="sourceLineNo">399</span>      // limit the scan<a name="line.399"></a>
+<span class="sourceLineNo">400</span>      Scan scan = new Scan().withStartRow(getStartRow()).withStopRow(getEndRow());<a name="line.400"></a>
+<span class="sourceLineNo">401</span><a name="line.401"></a>
+<span class="sourceLineNo">402</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.402"></a>
+<span class="sourceLineNo">403</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.403"></a>
+<span class="sourceLineNo">404</span>        tmpTableDir);<a name="line.404"></a>
+<span class="sourceLineNo">405</span><a name="line.405"></a>
+<span class="sourceLineNo">406</span>      verifyWithMockedMapReduce(job, 2, 2, getStartRow(), getEndRow());<a name="line.406"></a>
+<span class="sourceLineNo">407</span>    } finally {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.408"></a>
+<span class="sourceLineNo">409</span>      UTIL.deleteTable(tableName);<a name="line.409"></a>
+<span class="sourceLineNo">410</span>    }<a name="line.410"></a>
+<span class="sourceLineNo">411</span>  }<a name="line.411"></a>
+<span class="sourceLineNo">412</span><a name="line.412"></a>
+<span class="sourceLineNo">413</span>  @Test<a name="line.413"></a>
+<span class="sourceLineNo">414</span>  public void testScannerReadTypeConfiguration() throws IOException {<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    Configuration conf = new Configuration(false);<a name="line.415"></a>
+<span class="sourceLineNo">416</span>    // Explicitly set ReadTypes should persist<a name="line.416"></a>
+<span class="sourceLineNo">417</span>    for (ReadType readType : Arrays.asList(ReadType.PREAD, ReadType.STREAM)) {<a name="line.417"></a>
+<span class="sourceLineNo">418</span>      Scan scanWithReadType = new Scan();<a name="line.418"></a>
+<span class="sourceLineNo">419</span>      scanWithReadType.setReadType(readType);<a name="line.419"></a>
+<span class="sourceLineNo">420</span>      assertEquals(scanWithReadType.getReadType(),<a name="line.420"></a>
+<span class="sourceLineNo">421</span>          serializeAndReturn(conf, scanWithReadType).getReadType());<a name="line.421"></a>
+<span class="sourceLineNo">422</span>    }<a name="line.422"></a>
+<span class="sourceLineNo">423</span>    // We should only see the DEFAULT ReadType getting updated to STREAM.<a name="line.423"></a>
+<span class="sourceLineNo">424</span>    Scan scanWithoutReadType = new Scan();<a name="line.424"></a>
+<span class="sourceLineNo">425</span>    assertEquals(ReadType.DEFAULT, scanWithoutReadType.getReadType());<a name="line.425"></a>
+<span class="sourceLineNo">426</span>    assertEquals(ReadType.STREAM, serializeAndReturn(conf, scanWithoutReadType).getReadType());<a name="line.426"></a>
+<span class="sourceLineNo">427</span><a name="line.427"></a>
+<span class="sourceLineNo">428</span>    // We should still be able to force a certain ReadType when DEFAULT is given.<a name="line.428"></a>
+<span class="sourceLineNo">429</span>    conf.setEnum(SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE, ReadType.PREAD);<a name="line.429"></a>
+<span class="sourceLineNo">430</span>    assertEquals(ReadType.DEFAULT, scanWithoutReadType.getReadType());<a name="line.430"></a>
+<span class="sourceLineNo">431</span>    assertEquals(ReadType.PREAD, serializeAndReturn(conf, scanWithoutReadType).getReadType());<a name="line.431"></a>
+<span class="sourceLineNo">432</span>  }<a name="line.432"></a>
+<span class="sourceLineNo">433</span><a name="line.433"></a>
+<span class="sourceLineNo">434</span>  /**<a name="line.434"></a>
+<span class="sourceLineNo">435</span>   * Serializes and deserializes the given scan in the same manner that<a name="line.435"></a>
+<span class="sourceLineNo">436</span>   * TableSnapshotInputFormat does.<a name="line.436"></a>
+<span class="sourceLineNo">437</span>   */<a name="line.437"></a>
+<span class="sourceLineNo">438</span>  private Scan serializeAndReturn(Configuration conf, Scan s) throws IOException {<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    conf.set(TableInputFormat.SCAN, TableMapReduceUtil.convertScanToString(s));<a name="line.439"></a>
+<span class="sourceLineNo">440</span>    return TableSnapshotInputFormatImpl.extractScanFromConf(conf);<a name="line.440"></a>
+<span class="sourceLineNo">441</span>  }<a name="line.441"></a>
+<span class="sourceLineNo">442</span><a name="line.442"></a>
+<span class="sourceLineNo">443</span>  private void verifyWithMockedMapReduce(Job job, int numRegions, int expectedNumSplits,<a name="line.443"></a>
+<span class="sourceLineNo">444</span>      byte[] startRow, byte[] stopRow)<a name="line.444"></a>
+<span class="sourceLineNo">445</span>      throws IOException, InterruptedException {<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    TableSnapshotInputFormat tsif = new TableSnapshotInputFormat();<a name="line.446"></a>
+<span class="sourceLineNo">447</span>    List&lt;InputSplit&gt; splits = tsif.getSplits(job);<a name="line.447"></a>
 <span class="sourceLineNo">448</span><a name="line.448"></a>
-<span class="sourceLineNo">449</span>      Scan scan =<a name="line.449"></a>
-<span class="sourceLineNo">450</span>          TableMapReduceUtil.convertStringToScan(snapshotRegionSplit.getDelegate().getScan());<a name="line.450"></a>
-<span class="sourceLineNo">451</span>      if (startRow.length &gt; 0) {<a name="line.451"></a>
-<span class="sourceLineNo">452</span>        Assert.assertTrue(<a name="line.452"></a>
-<span class="sourceLineNo">453</span>          Bytes.toStringBinary(startRow) + " should &lt;= " + Bytes.toStringBinary(scan.getStartRow()),<a name="line.453"></a>
-<span class="sourceLineNo">454</span>          Bytes.compareTo(startRow, scan.getStartRow()) &lt;= 0);<a name="line.454"></a>
-<span class="sourceLineNo">455</span>      }<a name="line.455"></a>
-<span class="sourceLineNo">456</span>      if (stopRow.length &gt; 0) {<a name="line.456"></a>
-<span class="sourceLineNo">457</span>        Assert.assertTrue(<a name="line.457"></a>
-<span class="sourceLineNo">458</span>          Bytes.toStringBinary(stopRow) + " should &gt;= " + Bytes.toStringBinary(scan.getStopRow()),<a name="line.458"></a>
-<span class="sourceLineNo">459</span>          Bytes.compareTo(stopRow, scan.getStopRow()) &gt;= 0);<a name="line.459"></a>
-<span class="sourceLineNo">460</span>      }<a name="line.460"></a>
-<span class="sourceLineNo">461</span>      Assert.assertTrue("startRow should &lt; stopRow",<a name="line.461"></a>
-<span class="sourceLineNo">462</span>        Bytes.compareTo(scan.getStartRow(), scan.getStopRow()) &lt; 0);<a name="line.462"></a>
-<span class="sourceLineNo">463</span><a name="line.463"></a>
-<span class="sourceLineNo">464</span>      // validate record reader<a name="line.464"></a>
-<span class="sourceLineNo">465</span>      TaskAttemptContext taskAttemptContext = mock(TaskAttemptContext.class);<a name="line.465"></a>
-<span class="sourceLineNo">466</span>      when(taskAttemptContext.getConfiguration()).thenReturn(job.getConfiguration());<a name="line.466"></a>
-<span class="sourceLineNo">467</span>      RecordReader&lt;ImmutableBytesWritable, Result&gt; rr =<a name="line.467"></a>
-<span class="sourceLineNo">468</span>          tsif.createRecordReader(split, taskAttemptContext);<a name="line.468"></a>
-<span class="sourceLineNo">469</span>      rr.initialize(split, taskAttemptContext);<a name="line.469"></a>
-<span class="sourceLineNo">470</span><a name="line.470"></a>
-<span class="sourceLineNo">471</span>      // validate we can read all the data back<a name="line.471"></a>
-<span class="sourceLineNo">472</span>      while (rr.nextKeyValue()) {<a name="line.472"></a>
-<span class="sourceLineNo">473</span>        byte[] row = rr.getCurrentKey().get();<a name="line.473"></a>
-<span class="sourceLineNo">474</span>        verifyRowFromMap(rr.getCurrentKey(), rr.getCurrentValue());<a name="line.474"></a>
-<span class="sourceLineNo">475</span>        rowTracker.addRow(row);<a name="line.475"></a>
-<span class="sourceLineNo">476</span>      }<a name="line.476"></a>
-<span class="sourceLineNo">477</span><a name="line.477"></a>
-<span class="sourceLineNo">478</span>      rr.close();<a name="line.478"></a>
-<span class="sourceLineNo">479</span>    }<a name="line.479"></a>
-<span class="sourceLineNo">480</span><a name="line.480"></a>
-<span class="sourceLineNo">481</span>    // validate all rows are seen<a name="line.481"></a>
-<span class="sourceLineNo">482</span>    rowTracker.validate();<a name="line.482"></a>
-<span class="sourceLineNo">483</span>  }<a name="line.483"></a>
-<span class="sourceLineNo">484</span><a name="line.484"></a>
-<span class="sourceLineNo">485</span>  @Override<a name="line.485"></a>
-<span class="sourceLineNo">486</span>  protected void testWithMapReduceImpl(HBaseTestingUtil util, TableName tableName,<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      String snapshotName, Path tableDir, int numRegions, int numSplitsPerRegion,<a name="line.487"></a>
-<span class="sourceLineNo">488</span>      int expectedNumSplits, boolean shutdownCluster) throws Exception {<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    doTestWithMapReduce(util, tableName, snapshotName, getStartRow(), getEndRow(), tableDir,<a name="line.489"></a>
-<span class="sourceLineNo">490</span>      numRegions, numSplitsPerRegion, expectedNumSplits, shutdownCluster);<a name="line.490"></a>
-<span class="sourceLineNo">491</span>  }<a name="line.491"></a>
-<span class="sourceLineNo">492</span><a name="line.492"></a>
-<span class="sourceLineNo">493</span>  // this is also called by the IntegrationTestTableSnapshotInputFormat<a name="line.493"></a>
-<span class="sourceLineNo">494</span>  public static void doTestWithMapReduce(HBaseTestingUtil util, TableName tableName,<a name="line.494"></a>
-<span class="sourceLineNo">495</span>      String snapshotName, byte[] startRow, byte[] endRow, Path tableDir, int numRegions,<a name="line.495"></a>
-<span class="sourceLineNo">496</span>      int numSplitsPerRegion, int expectedNumSplits, boolean shutdownCluster) throws Exception {<a name="line.496"></a>
-<span class="sourceLineNo">497</span><a name="line.497"></a>
-<span class="sourceLineNo">498</span>    LOG.info("testing with MapReduce");<a name="line.498"></a>
-<span class="sourceLineNo">499</span><a name="line.499"></a>
-<span class="sourceLineNo">500</span>    LOG.info("create the table and snapshot");<a name="line.500"></a>
-<span class="sourceLineNo">501</span>    createTableAndSnapshot(util, tableName, snapshotName, startRow, endRow, numRegions);<a name="line.501"></a>
-<span class="sourceLineNo">502</span><a name="line.502"></a>
-<span class="sourceLineNo">503</span>    if (shutdownCluster) {<a name="line.503"></a>
-<span class="sourceLineNo">504</span>      LOG.info("shutting down hbase cluster.");<a name="line.504"></a>
-<span class="sourceLineNo">505</span>      util.shutdownMiniHBaseCluster();<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    }<a name="line.506"></a>
-<span class="sourceLineNo">507</span><a name="line.507"></a>
-<span class="sourceLineNo">508</span>    try {<a name="line.508"></a>
-<span class="sourceLineNo">509</span>      // create the job<a name="line.509"></a>
-<span class="sourceLineNo">510</span>      Job job = new Job(util.getConfiguration());<a name="line.510"></a>
-<span class="sourceLineNo">511</span>      Scan scan = new Scan().withStartRow(startRow).withStopRow(endRow); // limit the scan<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span>      job.setJarByClass(util.getClass());<a name="line.513"></a>
-<span class="sourceLineNo">514</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.514"></a>
-<span class="sourceLineNo">515</span>              TestTableSnapshotInputFormat.class);<a name="line.515"></a>
-<span class="sourceLineNo">516</span><a name="line.516"></a>
-<span class="sourceLineNo">517</span>      if (numSplitsPerRegion &gt; 1) {<a name="line.517"></a>
-<span class="sourceLineNo">518</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.518"></a>
-<span class="sourceLineNo">519</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.519"></a>
-<span class="sourceLineNo">520</span>                NullWritable.class, job, true, tableDir, new RegionSplitter.UniformSplit(),<a name="line.520"></a>
-<span class="sourceLineNo">521</span>                numSplitsPerRegion);<a name="line.521"></a>
-<span class="sourceLineNo">522</span>      } else {<a name="line.522"></a>
-<span class="sourceLineNo">523</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.523"></a>
-<span class="sourceLineNo">524</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.524"></a>
-<span class="sourceLineNo">525</span>                NullWritable.class, job, true, tableDir);<a name="line.525"></a>
-<span class="sourceLineNo">526</span>      }<a name="line.526"></a>
-<span class="sourceLineNo">527</span><a name="line.527"></a>
-<span class="sourceLineNo">528</span>      job.setReducerClass(TestTableSnapshotInputFormat.TestTableSnapshotReducer.class);<a name="line.528"></a>
-<span class="sourceLineNo">529</span>      job.setNumReduceTasks(1);<a name="line.529"></a>
-<span class="sourceLineNo">530</span>      job.setOutputFormatClass(NullOutputFormat.class);<a name="line.530"></a>
-<span class="sourceLineNo">531</span><a name="line.531"></a>
-<span class="sourceLineNo">532</span>      Assert.assertTrue(job.waitForCompletion(true));<a name="line.532"></a>
-<span class="sourceLineNo">533</span>    } finally {<a name="line.533"></a>
-<span class="sourceLineNo">534</span>      if (!shutdownCluster) {<a name="line.534"></a>
-<span class="sourceLineNo">535</span>        util.getAdmin().deleteSnapshot(snapshotName);<a name="line.535"></a>
-<span class="sourceLineNo">536</span>        util.deleteTable(tableName);<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      }<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    }<a name="line.538"></a>
-<span class="sourceLineNo">539</span>  }<a name="line.539"></a>
+<span class="sourceLineNo">449</span>    Assert.assertEquals(expectedNumSplits, splits.size());<a name="line.449"></a>
+<span class="sourceLineNo">450</span><a name="line.450"></a>
+<span class="sourceLineNo">451</span>    HBaseTestingUtil.SeenRowTracker rowTracker = new HBaseTestingUtil.SeenRowTracker(startRow,<a name="line.451"></a>
+<span class="sourceLineNo">452</span>        stopRow.length &gt; 0 ? stopRow : Bytes.toBytes("\uffff"));<a name="line.452"></a>
+<span class="sourceLineNo">453</span><a name="line.453"></a>
+<span class="sourceLineNo">454</span>    boolean localityEnabled =<a name="line.454"></a>
+<span class="sourceLineNo">455</span>        job.getConfiguration().getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY,<a name="line.455"></a>
+<span class="sourceLineNo">456</span>                                          SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT);<a name="line.456"></a>
+<span class="sourceLineNo">457</span><a name="line.457"></a>
+<span class="sourceLineNo">458</span>    boolean byRegionLoc =<a name="line.458"></a>
+<span class="sourceLineNo">459</span>      job.getConfiguration().getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.459"></a>
+<span class="sourceLineNo">460</span>                                        SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.460"></a>
+<span class="sourceLineNo">461</span>    for (int i = 0; i &lt; splits.size(); i++) {<a name="line.461"></a>
+<span class="sourceLineNo">462</span>      // validate input split<a name="line.462"></a>
+<span class="sourceLineNo">463</span>      InputSplit split = splits.get(i);<a name="line.463"></a>
+<span class="sourceLineNo">464</span>      Assert.assertTrue(split instanceof TableSnapshotRegionSplit);<a name="line.464"></a>
+<span class="sourceLineNo">465</span>      TableSnapshotRegionSplit snapshotRegionSplit = (TableSnapshotRegionSplit) split;<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      if (localityEnabled) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>        Assert.assertTrue(split.getLocations() != null &amp;&amp; split.getLocations().length != 0);<a name="line.467"></a>
+<span class="sourceLineNo">468</span>        if (byRegionLoc) {<a name="line.468"></a>
+<span class="sourceLineNo">469</span>          // When it uses region location from meta, the hostname will be "localhost",<a name="line.469"></a>
+<span class="sourceLineNo">470</span>          // the location from hdfs block location is "127.0.0.1".<a name="line.470"></a>
+<span class="sourceLineNo">471</span>          Assert.assertEquals(1, split.getLocations().length);<a name="line.471"></a>
+<span class="sourceLineNo">472</span>          Assert.assertTrue("Not using region location!",<a name="line.472"></a>
+<span class="sourceLineNo">473</span>            split.getLocations()[0].equals("localhost"));<a name="line.473"></a>
+<span class="sourceLineNo">474</span>        } else {<a name="line.474"></a>
+<span class="sourceLineNo">475</span>          Assert.assertTrue("Not using region location!",<a name="line.475"></a>
+<span class="sourceLineNo">476</span>            split.getLocations()[0].equals("127.0.0.1"));<a name="line.476"></a>
+<span class="sourceLineNo">477</span>        }<a name="line.477"></a>
+<span class="sourceLineNo">478</span>      } else {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>        Assert.assertTrue(split.getLocations() != null &amp;&amp; split.getLocations().length == 0);<a name="line.479"></a>
+<span class="sourceLineNo">480</span>      }<a name="line.480"></a>
+<span class="sourceLineNo">481</span><a name="line.481"></a>
+<span class="sourceLineNo">482</span>      Scan scan =<a name="line.482"></a>
+<span class="sourceLineNo">483</span>          TableMapReduceUtil.convertStringToScan(snapshotRegionSplit.getDelegate().getScan());<a name="line.483"></a>
+<span class="sourceLineNo">484</span>      if (startRow.length &gt; 0) {<a name="line.484"></a>
+<span class="sourceLineNo">485</span>        Assert.assertTrue(<a name="line.485"></a>
+<span class="sourceLineNo">486</span>          Bytes.toStringBinary(startRow) + " should &lt;= " + Bytes.toStringBinary(scan.getStartRow()),<a name="line.486"></a>
+<span class="sourceLineNo">487</span>          Bytes.compareTo(startRow, scan.getStartRow()) &lt;= 0);<a name="line.487"></a>
+<span class="sourceLineNo">488</span>      }<a name="line.488"></a>
+<span class="sourceLineNo">489</span>      if (stopRow.length &gt; 0) {<a name="line.489"></a>
+<span class="sourceLineNo">490</span>        Assert.assertTrue(<a name="line.490"></a>
+<span class="sourceLineNo">491</span>          Bytes.toStringBinary(stopRow) + " should &gt;= " + Bytes.toStringBinary(scan.getStopRow()),<a name="line.491"></a>
+<span class="sourceLineNo">492</span>          Bytes.compareTo(stopRow, scan.getStopRow()) &gt;= 0);<a name="line.492"></a>
+<span class="sourceLineNo">493</span>      }<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      Assert.assertTrue("startRow should &lt; stopRow",<a name="line.494"></a>
+<span class="sourceLineNo">495</span>        Bytes.compareTo(scan.getStartRow(), scan.getStopRow()) &lt; 0);<a name="line.495"></a>
+<span class="sourceLineNo">496</span><a name="line.496"></a>
+<span class="sourceLineNo">497</span>      // validate record reader<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      TaskAttemptContext taskAttemptContext = mock(TaskAttemptContext.class);<a name="line.498"></a>
+<span class="sourceLineNo">499</span>      when(taskAttemptContext.getConfiguration()).thenReturn(job.getConfiguration());<a name="line.499"></a>
+<span class="sourceLineNo">500</span>      RecordReader&lt;ImmutableBytesWritable, Result&gt; rr =<a name="line.500"></a>
+<span class="sourceLineNo">501</span>          tsif.createRecordReader(split, taskAttemptContext);<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      rr.initialize(split, taskAttemptContext);<a name="line.502"></a>
+<span class="sourceLineNo">503</span><a name="line.503"></a>
+<span class="sourceLineNo">504</span>      // validate we can read all the data back<a name="line.504"></a>
+<span class="sourceLineNo">505</span>      while (rr.nextKeyValue()) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span>        byte[] row = rr.getCurrentKey().get();<a name="line.506"></a>
+<span class="sourceLineNo">507</span>        verifyRowFromMap(rr.getCurrentKey(), rr.getCurrentValue());<a name="line.507"></a>
+<span class="sourceLineNo">508</span>        rowTracker.addRow(row);<a name="line.508"></a>
+<span class="sourceLineNo">509</span>      }<a name="line.509"></a>
+<span class="sourceLineNo">510</span><a name="line.510"></a>
+<span class="sourceLineNo">511</span>      rr.close();<a name="line.511"></a>
+<span class="sourceLineNo">512</span>    }<a name="line.512"></a>
+<span class="sourceLineNo">513</span><a name="line.513"></a>
+<span class="sourceLineNo">514</span>    // validate all rows are seen<a name="line.514"></a>
+<span class="sourceLineNo">515</span>    rowTracker.validate();<a name="line.515"></a>
+<span class="sourceLineNo">516</span>  }<a name="line.516"></a>
+<span class="sourceLineNo">517</span><a name="line.517"></a>
+<span class="sourceLineNo">518</span>  @Override<a name="line.518"></a>
+<span class="sourceLineNo">519</span>  protected void testWithMapReduceImpl(HBaseTestingUtil util, TableName tableName,<a name="line.519"></a>
+<span class="sourceLineNo">520</span>      String snapshotName, Path tableDir, int numRegions, int numSplitsPerRegion,<a name="line.520"></a>
+<span class="sourceLineNo">521</span>      int expectedNumSplits, boolean shutdownCluster) throws Exception {<a name="line.521"></a>
+<span class="sourceLineNo">522</span>    doTestWithMapReduce(util, tableName, snapshotName, getStartRow(), getEndRow(), tableDir,<a name="line.522"></a>
+<span class="sourceLineNo">523</span>      numRegions, numSplitsPerRegion, expectedNumSplits, shutdownCluster);<a name="line.523"></a>
+<span class="sourceLineNo">524</span>  }<a name="line.524"></a>
+<span class="sourceLineNo">525</span><a name="line.525"></a>
+<span class="sourceLineNo">526</span>  // this is also called by the IntegrationTestTableSnapshotInputFormat<a name="line.526"></a>
+<span class="sourceLineNo">527</span>  public static void doTestWithMapReduce(HBaseTestingUtil util, TableName tableName,<a name="line.527"></a>
+<span class="sourceLineNo">528</span>      String snapshotName, byte[] startRow, byte[] endRow, Path tableDir, int numRegions,<a name="line.528"></a>
+<span class="sourceLineNo">529</span>      int numSplitsPerRegion, int expectedNumSplits, boolean shutdownCluster) throws Exception {<a name="line.529"></a>
+<span class="sourceLineNo">530</span><a name="line.530"></a>
+<span class="sourceLineNo">531</span>    LOG.info("testing with MapReduce");<a name="line.531"></a>
+<span class="sourceLineNo">532</span><a name="line.532"></a>
+<span class="sourceLineNo">533</span>    LOG.info("create the table and snapshot");<a name="line.533"></a>
+<span class="sourceLineNo">534</span>    createTableAndSnapshot(util, tableName, snapshotName, startRow, endRow, numRegions);<a name="line.534"></a>
+<span class="sourceLineNo">535</span><a name="line.535"></a>
+<span class="sourceLineNo">536</span>    if (shutdownCluster) {<a name="line.536"></a>
+<span class="sourceLineNo">537</span>      LOG.info("shutting down hbase cluster.");<a name="line.537"></a>
+<span class="sourceLineNo">538</span>      util.shutdownMiniHBaseCluster();<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    }<a name="line.539"></a>
 <span class="sourceLineNo">540</span><a name="line.540"></a>
-<span class="sourceLineNo">541</span>  @Test<a name="line.541"></a>
-<span class="sourceLineNo">542</span>  public void testWithMapReduceMultipleMappersPerRegion() throws Exception {<a name="line.542"></a>
-<span class="sourceLineNo">543</span>    testWithMapReduce(UTIL, "testWithMapReduceMultiRegion", 10, 5, 50, false);<a name="line.543"></a>
-<span class="sourceLineNo">544</span>  }<a name="line.544"></a>
-<span class="sourceLineNo">545</span>}<a name="line.545"></a>
+<span class="sourceLineNo">541</span>    try {<a name="line.541"></a>
+<span class="sourceLineNo">542</span>      // create the job<a name="line.542"></a>
+<span class="sourceLineNo">543</span>      Job job = new Job(util.getConfiguration());<a name="line.543"></a>
+<span class="sourceLineNo">544</span>      Scan scan = new Scan().withStartRow(startRow).withStopRow(endRow); // limit the scan<a name="line.544"></a>
+<span class="sourceLineNo">545</span><a name="line.545"></a>
+<span class="sourceLineNo">546</span>      job.setJarByClass(util.getClass());<a name="line.546"></a>
+<span class="sourceLineNo">547</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.547"></a>
+<span class="sourceLineNo">548</span>              TestTableSnapshotInputFormat.class);<a name="line.548"></a>
+<span class="sourceLineNo">549</span><a name="line.549"></a>
+<span class="sourceLineNo">550</span>      if (numSplitsPerRegion &gt; 1) {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.551"></a>
+<span class="sourceLineNo">552</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.552"></a>
+<span class="sourceLineNo">553</span>                NullWritable.class, job, true, tableDir, new RegionSplitter.UniformSplit(),<a name="line.553"></a>
+<span class="sourceLineNo">554</span>                numSplitsPerRegion);<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      } else {<a name="line.555"></a>
+<span class="sourceLineNo">556</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.556"></a>
+<span class="sourceLineNo">557</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.557"></a>
+<span class="sourceLineNo">558</span>                NullWritable.class, job, true, tableDir);<a name="line.558"></a>
+<span class="sourceLineNo">559</span>      }<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>      job.setReducerClass(TestTableSnapshotInputFormat.TestTableSnapshotReducer.class);<a name="line.561"></a>
+<span class="sourceLineNo">562</span>      job.setNumReduceTasks(1);<a name="line.562"></a>
+<span class="sourceLineNo">563</span>      job.setOutputFormatClass(NullOutputFormat.class);<a name="line.563"></a>
+<span class="sourceLineNo">564</span><a name="line.564"></a>
+<span class="sourceLineNo">565</span>      Assert.assertTrue(job.waitForCompletion(true));<a name="line.565"></a>
+<span class="sourceLineNo">566</span>    } finally {<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      if (!shutdownCluster) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span>        util.getAdmin().deleteSnapshot(snapshotName);<a name="line.568"></a>
+<span class="sourceLineNo">569</span>        util.deleteTable(tableName);<a name="line.569"></a>
+<span class="sourceLineNo">570</span>      }<a name="line.570"></a>
+<span class="sourceLineNo">571</span>    }<a name="line.571"></a>
+<span class="sourceLineNo">572</span>  }<a name="line.572"></a>
+<span class="sourceLineNo">573</span><a name="line.573"></a>
+<span class="sourceLineNo">574</span>  @Test<a name="line.574"></a>
+<span class="sourceLineNo">575</span>  public void testWithMapReduceMultipleMappersPerRegion() throws Exception {<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    testWithMapReduce(UTIL, "testWithMapReduceMultiRegion", 10, 5, 50, false);<a name="line.576"></a>
+<span class="sourceLineNo">577</span>  }<a name="line.577"></a>
+<span class="sourceLineNo">578</span>}<a name="line.578"></a>
 
 
 
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotReducer.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotReducer.html
index 8d67eec..82673a9 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotReducer.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.TestTableSnapshotReducer.html
@@ -30,527 +30,560 @@
 <span class="sourceLineNo">022</span>import static org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT;<a name="line.22"></a>
 <span class="sourceLineNo">023</span>import static org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION;<a name="line.23"></a>
 <span class="sourceLineNo">024</span>import static org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT;<a name="line.24"></a>
-<span class="sourceLineNo">025</span>import static org.mockito.Mockito.mock;<a name="line.25"></a>
-<span class="sourceLineNo">026</span>import static org.mockito.Mockito.when;<a name="line.26"></a>
-<span class="sourceLineNo">027</span><a name="line.27"></a>
-<span class="sourceLineNo">028</span>import java.io.IOException;<a name="line.28"></a>
-<span class="sourceLineNo">029</span>import java.util.Arrays;<a name="line.29"></a>
-<span class="sourceLineNo">030</span>import java.util.List;<a name="line.30"></a>
-<span class="sourceLineNo">031</span>import org.apache.hadoop.conf.Configuration;<a name="line.31"></a>
-<span class="sourceLineNo">032</span>import org.apache.hadoop.fs.FileSystem;<a name="line.32"></a>
-<span class="sourceLineNo">033</span>import org.apache.hadoop.fs.Path;<a name="line.33"></a>
-<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.34"></a>
-<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.HBaseTestingUtil;<a name="line.35"></a>
-<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.HConstants;<a name="line.36"></a>
-<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.HDFSBlocksDistribution;<a name="line.37"></a>
-<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.TableName;<a name="line.38"></a>
-<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.client.Admin;<a name="line.39"></a>
-<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.client.Result;<a name="line.40"></a>
-<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.client.Scan;<a name="line.41"></a>
-<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.client.Table;<a name="line.42"></a>
-<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.client.TestTableSnapshotScanner;<a name="line.43"></a>
-<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<a name="line.44"></a>
-<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormat.TableSnapshotRegionSplit;<a name="line.45"></a>
-<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.snapshot.SnapshotTestingUtils;<a name="line.46"></a>
-<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.testclassification.LargeTests;<a name="line.47"></a>
-<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.testclassification.VerySlowMapReduceTests;<a name="line.48"></a>
-<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.49"></a>
-<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.50"></a>
-<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.util.RegionSplitter;<a name="line.51"></a>
-<span class="sourceLineNo">052</span>import org.apache.hadoop.io.NullWritable;<a name="line.52"></a>
-<span class="sourceLineNo">053</span>import org.apache.hadoop.mapreduce.InputSplit;<a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.apache.hadoop.mapreduce.Job;<a name="line.54"></a>
-<span class="sourceLineNo">055</span>import org.apache.hadoop.mapreduce.RecordReader;<a name="line.55"></a>
-<span class="sourceLineNo">056</span>import org.apache.hadoop.mapreduce.Reducer;<a name="line.56"></a>
-<span class="sourceLineNo">057</span>import org.apache.hadoop.mapreduce.TaskAttemptContext;<a name="line.57"></a>
-<span class="sourceLineNo">058</span>import org.apache.hadoop.mapreduce.lib.output.NullOutputFormat;<a name="line.58"></a>
-<span class="sourceLineNo">059</span>import org.junit.Assert;<a name="line.59"></a>
-<span class="sourceLineNo">060</span>import org.junit.ClassRule;<a name="line.60"></a>
-<span class="sourceLineNo">061</span>import org.junit.Rule;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>import org.junit.Test;<a name="line.62"></a>
-<span class="sourceLineNo">063</span>import org.junit.experimental.categories.Category;<a name="line.63"></a>
-<span class="sourceLineNo">064</span>import org.junit.rules.TestName;<a name="line.64"></a>
-<span class="sourceLineNo">065</span>import org.slf4j.Logger;<a name="line.65"></a>
-<span class="sourceLineNo">066</span>import org.slf4j.LoggerFactory;<a name="line.66"></a>
-<span class="sourceLineNo">067</span><a name="line.67"></a>
-<span class="sourceLineNo">068</span>import org.apache.hbase.thirdparty.com.google.common.collect.Lists;<a name="line.68"></a>
-<span class="sourceLineNo">069</span><a name="line.69"></a>
-<span class="sourceLineNo">070</span>@Category({VerySlowMapReduceTests.class, LargeTests.class})<a name="line.70"></a>
-<span class="sourceLineNo">071</span>public class TestTableSnapshotInputFormat extends TableSnapshotInputFormatTestBase {<a name="line.71"></a>
+<span class="sourceLineNo">025</span>import static org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE;<a name="line.25"></a>
+<span class="sourceLineNo">026</span>import static org.junit.Assert.assertEquals;<a name="line.26"></a>
+<span class="sourceLineNo">027</span>import static org.mockito.Mockito.mock;<a name="line.27"></a>
+<span class="sourceLineNo">028</span>import static org.mockito.Mockito.when;<a name="line.28"></a>
+<span class="sourceLineNo">029</span><a name="line.29"></a>
+<span class="sourceLineNo">030</span>import java.io.IOException;<a name="line.30"></a>
+<span class="sourceLineNo">031</span>import java.util.Arrays;<a name="line.31"></a>
+<span class="sourceLineNo">032</span>import java.util.List;<a name="line.32"></a>
+<span class="sourceLineNo">033</span>import org.apache.hadoop.conf.Configuration;<a name="line.33"></a>
+<span class="sourceLineNo">034</span>import org.apache.hadoop.fs.FileSystem;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.fs.Path;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.HBaseTestingUtil;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.HConstants;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.HDFSBlocksDistribution;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.TableName;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.client.Admin;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.client.Result;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.client.Scan;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.client.Scan.ReadType;<a name="line.44"></a>
+<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.client.Table;<a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.client.TestTableSnapshotScanner;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormat.TableSnapshotRegionSplit;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.snapshot.SnapshotTestingUtils;<a name="line.49"></a>
+<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.testclassification.LargeTests;<a name="line.50"></a>
+<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.testclassification.VerySlowMapReduceTests;<a name="line.51"></a>
+<span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.52"></a>
+<span class="sourceLineNo">053</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.53"></a>
+<span class="sourceLineNo">054</span>import org.apache.hadoop.hbase.util.RegionSplitter;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>import org.apache.hadoop.io.NullWritable;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>import org.apache.hadoop.mapreduce.InputSplit;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>import org.apache.hadoop.mapreduce.Job;<a name="line.57"></a>
+<span class="sourceLineNo">058</span>import org.apache.hadoop.mapreduce.RecordReader;<a name="line.58"></a>
+<span class="sourceLineNo">059</span>import org.apache.hadoop.mapreduce.Reducer;<a name="line.59"></a>
+<span class="sourceLineNo">060</span>import org.apache.hadoop.mapreduce.TaskAttemptContext;<a name="line.60"></a>
+<span class="sourceLineNo">061</span>import org.apache.hadoop.mapreduce.lib.output.NullOutputFormat;<a name="line.61"></a>
+<span class="sourceLineNo">062</span>import org.junit.Assert;<a name="line.62"></a>
+<span class="sourceLineNo">063</span>import org.junit.ClassRule;<a name="line.63"></a>
+<span class="sourceLineNo">064</span>import org.junit.Rule;<a name="line.64"></a>
+<span class="sourceLineNo">065</span>import org.junit.Test;<a name="line.65"></a>
+<span class="sourceLineNo">066</span>import org.junit.experimental.categories.Category;<a name="line.66"></a>
+<span class="sourceLineNo">067</span>import org.junit.rules.TestName;<a name="line.67"></a>
+<span class="sourceLineNo">068</span>import org.slf4j.Logger;<a name="line.68"></a>
+<span class="sourceLineNo">069</span>import org.slf4j.LoggerFactory;<a name="line.69"></a>
+<span class="sourceLineNo">070</span><a name="line.70"></a>
+<span class="sourceLineNo">071</span>import org.apache.hbase.thirdparty.com.google.common.collect.Lists;<a name="line.71"></a>
 <span class="sourceLineNo">072</span><a name="line.72"></a>
-<span class="sourceLineNo">073</span>  @ClassRule<a name="line.73"></a>
-<span class="sourceLineNo">074</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.74"></a>
-<span class="sourceLineNo">075</span>      HBaseClassTestRule.forClass(TestTableSnapshotInputFormat.class);<a name="line.75"></a>
-<span class="sourceLineNo">076</span><a name="line.76"></a>
-<span class="sourceLineNo">077</span>  private static final Logger LOG = LoggerFactory.getLogger(TestTableSnapshotInputFormat.class);<a name="line.77"></a>
-<span class="sourceLineNo">078</span><a name="line.78"></a>
-<span class="sourceLineNo">079</span>  private static final byte[] bbb = Bytes.toBytes("bbb");<a name="line.79"></a>
-<span class="sourceLineNo">080</span>  private static final byte[] yyy = Bytes.toBytes("yyy");<a name="line.80"></a>
-<span class="sourceLineNo">081</span>  private static final byte[] bbc = Bytes.toBytes("bbc");<a name="line.81"></a>
-<span class="sourceLineNo">082</span>  private static final byte[] yya = Bytes.toBytes("yya");<a name="line.82"></a>
-<span class="sourceLineNo">083</span><a name="line.83"></a>
-<span class="sourceLineNo">084</span>  @Rule<a name="line.84"></a>
-<span class="sourceLineNo">085</span>  public TestName name = new TestName();<a name="line.85"></a>
+<span class="sourceLineNo">073</span>@Category({VerySlowMapReduceTests.class, LargeTests.class})<a name="line.73"></a>
+<span class="sourceLineNo">074</span>public class TestTableSnapshotInputFormat extends TableSnapshotInputFormatTestBase {<a name="line.74"></a>
+<span class="sourceLineNo">075</span><a name="line.75"></a>
+<span class="sourceLineNo">076</span>  @ClassRule<a name="line.76"></a>
+<span class="sourceLineNo">077</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.77"></a>
+<span class="sourceLineNo">078</span>      HBaseClassTestRule.forClass(TestTableSnapshotInputFormat.class);<a name="line.78"></a>
+<span class="sourceLineNo">079</span><a name="line.79"></a>
+<span class="sourceLineNo">080</span>  private static final Logger LOG = LoggerFactory.getLogger(TestTableSnapshotInputFormat.class);<a name="line.80"></a>
+<span class="sourceLineNo">081</span><a name="line.81"></a>
+<span class="sourceLineNo">082</span>  private static final byte[] bbb = Bytes.toBytes("bbb");<a name="line.82"></a>
+<span class="sourceLineNo">083</span>  private static final byte[] yyy = Bytes.toBytes("yyy");<a name="line.83"></a>
+<span class="sourceLineNo">084</span>  private static final byte[] bbc = Bytes.toBytes("bbc");<a name="line.84"></a>
+<span class="sourceLineNo">085</span>  private static final byte[] yya = Bytes.toBytes("yya");<a name="line.85"></a>
 <span class="sourceLineNo">086</span><a name="line.86"></a>
-<span class="sourceLineNo">087</span>  @Override<a name="line.87"></a>
-<span class="sourceLineNo">088</span>  protected byte[] getStartRow() {<a name="line.88"></a>
-<span class="sourceLineNo">089</span>    return bbb;<a name="line.89"></a>
-<span class="sourceLineNo">090</span>  }<a name="line.90"></a>
-<span class="sourceLineNo">091</span><a name="line.91"></a>
-<span class="sourceLineNo">092</span>  @Override<a name="line.92"></a>
-<span class="sourceLineNo">093</span>  protected byte[] getEndRow() {<a name="line.93"></a>
-<span class="sourceLineNo">094</span>    return yyy;<a name="line.94"></a>
-<span class="sourceLineNo">095</span>  }<a name="line.95"></a>
-<span class="sourceLineNo">096</span><a name="line.96"></a>
-<span class="sourceLineNo">097</span><a name="line.97"></a>
-<span class="sourceLineNo">098</span>  @Test<a name="line.98"></a>
-<span class="sourceLineNo">099</span>  public void testGetBestLocations() throws IOException {<a name="line.99"></a>
-<span class="sourceLineNo">100</span>    TableSnapshotInputFormatImpl tsif = new TableSnapshotInputFormatImpl();<a name="line.100"></a>
-<span class="sourceLineNo">101</span>    Configuration conf = UTIL.getConfiguration();<a name="line.101"></a>
-<span class="sourceLineNo">102</span><a name="line.102"></a>
-<span class="sourceLineNo">103</span>    HDFSBlocksDistribution blockDistribution = new HDFSBlocksDistribution();<a name="line.103"></a>
-<span class="sourceLineNo">104</span>    Assert.assertEquals(null,<a name="line.104"></a>
-<span class="sourceLineNo">105</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.105"></a>
-<span class="sourceLineNo">106</span><a name="line.106"></a>
-<span class="sourceLineNo">107</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 1);<a name="line.107"></a>
-<span class="sourceLineNo">108</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.108"></a>
-<span class="sourceLineNo">109</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.109"></a>
-<span class="sourceLineNo">110</span><a name="line.110"></a>
-<span class="sourceLineNo">111</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 1);<a name="line.111"></a>
-<span class="sourceLineNo">112</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.112"></a>
-<span class="sourceLineNo">113</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.113"></a>
-<span class="sourceLineNo">114</span><a name="line.114"></a>
-<span class="sourceLineNo">115</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 1);<a name="line.115"></a>
-<span class="sourceLineNo">116</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.116"></a>
-<span class="sourceLineNo">117</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.117"></a>
-<span class="sourceLineNo">118</span><a name="line.118"></a>
-<span class="sourceLineNo">119</span>    blockDistribution = new HDFSBlocksDistribution();<a name="line.119"></a>
-<span class="sourceLineNo">120</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 10);<a name="line.120"></a>
-<span class="sourceLineNo">121</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 7);<a name="line.121"></a>
-<span class="sourceLineNo">122</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h3"}, 5);<a name="line.122"></a>
-<span class="sourceLineNo">123</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h4"}, 1);<a name="line.123"></a>
-<span class="sourceLineNo">124</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.124"></a>
-<span class="sourceLineNo">125</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.125"></a>
-<span class="sourceLineNo">126</span><a name="line.126"></a>
-<span class="sourceLineNo">127</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 2);<a name="line.127"></a>
-<span class="sourceLineNo">128</span>    Assert.assertEquals(Lists.newArrayList("h1", "h2"),<a name="line.128"></a>
-<span class="sourceLineNo">129</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.129"></a>
-<span class="sourceLineNo">130</span><a name="line.130"></a>
-<span class="sourceLineNo">131</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 3);<a name="line.131"></a>
-<span class="sourceLineNo">132</span>    Assert.assertEquals(Lists.newArrayList("h2", "h1"),<a name="line.132"></a>
-<span class="sourceLineNo">133</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.133"></a>
-<span class="sourceLineNo">134</span><a name="line.134"></a>
-<span class="sourceLineNo">135</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h3"}, 6);<a name="line.135"></a>
-<span class="sourceLineNo">136</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h4"}, 9);<a name="line.136"></a>
+<span class="sourceLineNo">087</span>  @Rule<a name="line.87"></a>
+<span class="sourceLineNo">088</span>  public TestName name = new TestName();<a name="line.88"></a>
+<span class="sourceLineNo">089</span><a name="line.89"></a>
+<span class="sourceLineNo">090</span>  @Override<a name="line.90"></a>
+<span class="sourceLineNo">091</span>  protected byte[] getStartRow() {<a name="line.91"></a>
+<span class="sourceLineNo">092</span>    return bbb;<a name="line.92"></a>
+<span class="sourceLineNo">093</span>  }<a name="line.93"></a>
+<span class="sourceLineNo">094</span><a name="line.94"></a>
+<span class="sourceLineNo">095</span>  @Override<a name="line.95"></a>
+<span class="sourceLineNo">096</span>  protected byte[] getEndRow() {<a name="line.96"></a>
+<span class="sourceLineNo">097</span>    return yyy;<a name="line.97"></a>
+<span class="sourceLineNo">098</span>  }<a name="line.98"></a>
+<span class="sourceLineNo">099</span><a name="line.99"></a>
+<span class="sourceLineNo">100</span><a name="line.100"></a>
+<span class="sourceLineNo">101</span>  @Test<a name="line.101"></a>
+<span class="sourceLineNo">102</span>  public void testGetBestLocations() throws IOException {<a name="line.102"></a>
+<span class="sourceLineNo">103</span>    TableSnapshotInputFormatImpl tsif = new TableSnapshotInputFormatImpl();<a name="line.103"></a>
+<span class="sourceLineNo">104</span>    Configuration conf = UTIL.getConfiguration();<a name="line.104"></a>
+<span class="sourceLineNo">105</span><a name="line.105"></a>
+<span class="sourceLineNo">106</span>    HDFSBlocksDistribution blockDistribution = new HDFSBlocksDistribution();<a name="line.106"></a>
+<span class="sourceLineNo">107</span>    Assert.assertEquals(null,<a name="line.107"></a>
+<span class="sourceLineNo">108</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.108"></a>
+<span class="sourceLineNo">109</span><a name="line.109"></a>
+<span class="sourceLineNo">110</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 1);<a name="line.110"></a>
+<span class="sourceLineNo">111</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.111"></a>
+<span class="sourceLineNo">112</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.112"></a>
+<span class="sourceLineNo">113</span><a name="line.113"></a>
+<span class="sourceLineNo">114</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 1);<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.115"></a>
+<span class="sourceLineNo">116</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.116"></a>
+<span class="sourceLineNo">117</span><a name="line.117"></a>
+<span class="sourceLineNo">118</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 1);<a name="line.118"></a>
+<span class="sourceLineNo">119</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.119"></a>
+<span class="sourceLineNo">120</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.120"></a>
+<span class="sourceLineNo">121</span><a name="line.121"></a>
+<span class="sourceLineNo">122</span>    blockDistribution = new HDFSBlocksDistribution();<a name="line.122"></a>
+<span class="sourceLineNo">123</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 10);<a name="line.123"></a>
+<span class="sourceLineNo">124</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 7);<a name="line.124"></a>
+<span class="sourceLineNo">125</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h3"}, 5);<a name="line.125"></a>
+<span class="sourceLineNo">126</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h4"}, 1);<a name="line.126"></a>
+<span class="sourceLineNo">127</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.127"></a>
+<span class="sourceLineNo">128</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.128"></a>
+<span class="sourceLineNo">129</span><a name="line.129"></a>
+<span class="sourceLineNo">130</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 2);<a name="line.130"></a>
+<span class="sourceLineNo">131</span>    Assert.assertEquals(Lists.newArrayList("h1", "h2"),<a name="line.131"></a>
+<span class="sourceLineNo">132</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.132"></a>
+<span class="sourceLineNo">133</span><a name="line.133"></a>
+<span class="sourceLineNo">134</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 3);<a name="line.134"></a>
+<span class="sourceLineNo">135</span>    Assert.assertEquals(Lists.newArrayList("h2", "h1"),<a name="line.135"></a>
+<span class="sourceLineNo">136</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.136"></a>
 <span class="sourceLineNo">137</span><a name="line.137"></a>
-<span class="sourceLineNo">138</span>    Assert.assertEquals(Lists.newArrayList("h2", "h3", "h4"),<a name="line.138"></a>
-<span class="sourceLineNo">139</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.139"></a>
-<span class="sourceLineNo">140</span>  }<a name="line.140"></a>
-<span class="sourceLineNo">141</span><a name="line.141"></a>
-<span class="sourceLineNo">142</span>  public static enum TestTableSnapshotCounters {<a name="line.142"></a>
-<span class="sourceLineNo">143</span>    VALIDATION_ERROR<a name="line.143"></a>
-<span class="sourceLineNo">144</span>  }<a name="line.144"></a>
-<span class="sourceLineNo">145</span><a name="line.145"></a>
-<span class="sourceLineNo">146</span>  public static class TestTableSnapshotMapper<a name="line.146"></a>
-<span class="sourceLineNo">147</span>    extends TableMapper&lt;ImmutableBytesWritable, NullWritable&gt; {<a name="line.147"></a>
-<span class="sourceLineNo">148</span>    @Override<a name="line.148"></a>
-<span class="sourceLineNo">149</span>    protected void map(ImmutableBytesWritable key, Result value,<a name="line.149"></a>
-<span class="sourceLineNo">150</span>        Context context) throws IOException, InterruptedException {<a name="line.150"></a>
-<span class="sourceLineNo">151</span>      // Validate a single row coming from the snapshot, and emit the row key<a name="line.151"></a>
-<span class="sourceLineNo">152</span>      verifyRowFromMap(key, value);<a name="line.152"></a>
-<span class="sourceLineNo">153</span>      context.write(key, NullWritable.get());<a name="line.153"></a>
-<span class="sourceLineNo">154</span>    }<a name="line.154"></a>
-<span class="sourceLineNo">155</span>  }<a name="line.155"></a>
-<span class="sourceLineNo">156</span><a name="line.156"></a>
-<span class="sourceLineNo">157</span>  public static class TestTableSnapshotReducer<a name="line.157"></a>
-<span class="sourceLineNo">158</span>    extends Reducer&lt;ImmutableBytesWritable, NullWritable, NullWritable, NullWritable&gt; {<a name="line.158"></a>
-<span class="sourceLineNo">159</span>    HBaseTestingUtil.SeenRowTracker rowTracker =<a name="line.159"></a>
-<span class="sourceLineNo">160</span>        new HBaseTestingUtil.SeenRowTracker(bbb, yyy);<a name="line.160"></a>
-<span class="sourceLineNo">161</span>    @Override<a name="line.161"></a>
-<span class="sourceLineNo">162</span>    protected void reduce(ImmutableBytesWritable key, Iterable&lt;NullWritable&gt; values,<a name="line.162"></a>
-<span class="sourceLineNo">163</span>       Context context) throws IOException, InterruptedException {<a name="line.163"></a>
-<span class="sourceLineNo">164</span>      rowTracker.addRow(key.get());<a name="line.164"></a>
-<span class="sourceLineNo">165</span>    }<a name="line.165"></a>
-<span class="sourceLineNo">166</span><a name="line.166"></a>
-<span class="sourceLineNo">167</span>    @Override<a name="line.167"></a>
-<span class="sourceLineNo">168</span>    protected void cleanup(Context context) throws IOException,<a name="line.168"></a>
-<span class="sourceLineNo">169</span>        InterruptedException {<a name="line.169"></a>
-<span class="sourceLineNo">170</span>      rowTracker.validate();<a name="line.170"></a>
-<span class="sourceLineNo">171</span>    }<a name="line.171"></a>
-<span class="sourceLineNo">172</span>  }<a name="line.172"></a>
-<span class="sourceLineNo">173</span><a name="line.173"></a>
-<span class="sourceLineNo">174</span>  @Test<a name="line.174"></a>
-<span class="sourceLineNo">175</span>  public void testInitTableSnapshotMapperJobConfig() throws Exception {<a name="line.175"></a>
-<span class="sourceLineNo">176</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.176"></a>
-<span class="sourceLineNo">177</span>    String snapshotName = "foo";<a name="line.177"></a>
-<span class="sourceLineNo">178</span><a name="line.178"></a>
-<span class="sourceLineNo">179</span>    try {<a name="line.179"></a>
-<span class="sourceLineNo">180</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 1);<a name="line.180"></a>
-<span class="sourceLineNo">181</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.181"></a>
-<span class="sourceLineNo">182</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.182"></a>
-<span class="sourceLineNo">183</span><a name="line.183"></a>
-<span class="sourceLineNo">184</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.184"></a>
-<span class="sourceLineNo">185</span>        new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.185"></a>
-<span class="sourceLineNo">186</span>        NullWritable.class, job, false, tmpTableDir);<a name="line.186"></a>
-<span class="sourceLineNo">187</span><a name="line.187"></a>
-<span class="sourceLineNo">188</span>      // TODO: would be better to examine directly the cache instance that results from this<a name="line.188"></a>
-<span class="sourceLineNo">189</span>      // config. Currently this is not possible because BlockCache initialization is static.<a name="line.189"></a>
-<span class="sourceLineNo">190</span>      Assert.assertEquals(<a name="line.190"></a>
-<span class="sourceLineNo">191</span>        "Snapshot job should be configured for default LruBlockCache.",<a name="line.191"></a>
-<span class="sourceLineNo">192</span>        HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT,<a name="line.192"></a>
-<span class="sourceLineNo">193</span>        job.getConfiguration().getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, -1), 0.01);<a name="line.193"></a>
-<span class="sourceLineNo">194</span>      Assert.assertEquals(<a name="line.194"></a>
-<span class="sourceLineNo">195</span>        "Snapshot job should not use BucketCache.",<a name="line.195"></a>
-<span class="sourceLineNo">196</span>        0, job.getConfiguration().getFloat("hbase.bucketcache.size", -1), 0.01);<a name="line.196"></a>
-<span class="sourceLineNo">197</span>    } finally {<a name="line.197"></a>
-<span class="sourceLineNo">198</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.198"></a>
-<span class="sourceLineNo">199</span>      UTIL.deleteTable(tableName);<a name="line.199"></a>
-<span class="sourceLineNo">200</span>    }<a name="line.200"></a>
-<span class="sourceLineNo">201</span>  }<a name="line.201"></a>
-<span class="sourceLineNo">202</span><a name="line.202"></a>
-<span class="sourceLineNo">203</span>  @Test<a name="line.203"></a>
-<span class="sourceLineNo">204</span>  public void testWithMockedMapReduceSingleRegionByRegionLocation() throws Exception {<a name="line.204"></a>
-<span class="sourceLineNo">205</span>    Configuration conf = UTIL.getConfiguration();<a name="line.205"></a>
-<span class="sourceLineNo">206</span>    conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION, true);<a name="line.206"></a>
-<span class="sourceLineNo">207</span>    try {<a name="line.207"></a>
-<span class="sourceLineNo">208</span>      testWithMockedMapReduce(UTIL, name.getMethodName() + "Snapshot", 1, 1, 1,<a name="line.208"></a>
-<span class="sourceLineNo">209</span>        true);<a name="line.209"></a>
-<span class="sourceLineNo">210</span>    } finally {<a name="line.210"></a>
-<span class="sourceLineNo">211</span>      conf.unset(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION);<a name="line.211"></a>
-<span class="sourceLineNo">212</span>    }<a name="line.212"></a>
-<span class="sourceLineNo">213</span>  }<a name="line.213"></a>
-<span class="sourceLineNo">214</span><a name="line.214"></a>
-<span class="sourceLineNo">215</span>  @Override<a name="line.215"></a>
-<span class="sourceLineNo">216</span>  public void testRestoreSnapshotDoesNotCreateBackRefLinksInit(TableName tableName,<a name="line.216"></a>
-<span class="sourceLineNo">217</span>      String snapshotName, Path tmpTableDir) throws Exception {<a name="line.217"></a>
-<span class="sourceLineNo">218</span>    Job job = new Job(UTIL.getConfiguration());<a name="line.218"></a>
-<span class="sourceLineNo">219</span>    TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.219"></a>
-<span class="sourceLineNo">220</span>      new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.220"></a>
-<span class="sourceLineNo">221</span>      NullWritable.class, job, false, tmpTableDir);<a name="line.221"></a>
-<span class="sourceLineNo">222</span>  }<a name="line.222"></a>
-<span class="sourceLineNo">223</span><a name="line.223"></a>
-<span class="sourceLineNo">224</span>  @Override<a name="line.224"></a>
-<span class="sourceLineNo">225</span>  public void testWithMockedMapReduce(HBaseTestingUtil util, String snapshotName,<a name="line.225"></a>
-<span class="sourceLineNo">226</span>      int numRegions, int numSplitsPerRegion, int expectedNumSplits, boolean setLocalityEnabledTo)<a name="line.226"></a>
-<span class="sourceLineNo">227</span>      throws Exception {<a name="line.227"></a>
-<span class="sourceLineNo">228</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.228"></a>
-<span class="sourceLineNo">229</span>    try {<a name="line.229"></a>
-<span class="sourceLineNo">230</span>      createTableAndSnapshot(<a name="line.230"></a>
-<span class="sourceLineNo">231</span>        util, tableName, snapshotName, getStartRow(), getEndRow(), numRegions);<a name="line.231"></a>
-<span class="sourceLineNo">232</span><a name="line.232"></a>
-<span class="sourceLineNo">233</span>      Configuration conf = util.getConfiguration();<a name="line.233"></a>
-<span class="sourceLineNo">234</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, setLocalityEnabledTo);<a name="line.234"></a>
-<span class="sourceLineNo">235</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.235"></a>
-<span class="sourceLineNo">236</span>        SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.236"></a>
-<span class="sourceLineNo">237</span>      Job job = new Job(conf);<a name="line.237"></a>
-<span class="sourceLineNo">238</span>      Path tmpTableDir = util.getDataTestDirOnTestFS(snapshotName);<a name="line.238"></a>
-<span class="sourceLineNo">239</span>      Scan scan = new Scan().withStartRow(getStartRow()).withStopRow(getEndRow()); // limit the scan<a name="line.239"></a>
-<span class="sourceLineNo">240</span><a name="line.240"></a>
-<span class="sourceLineNo">241</span>      if (numSplitsPerRegion &gt; 1) {<a name="line.241"></a>
-<span class="sourceLineNo">242</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.242"></a>
-<span class="sourceLineNo">243</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.243"></a>
-<span class="sourceLineNo">244</span>                NullWritable.class, job, false, tmpTableDir, new RegionSplitter.UniformSplit(),<a name="line.244"></a>
-<span class="sourceLineNo">245</span>                numSplitsPerRegion);<a name="line.245"></a>
-<span class="sourceLineNo">246</span>      } else {<a name="line.246"></a>
-<span class="sourceLineNo">247</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.247"></a>
-<span class="sourceLineNo">248</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.248"></a>
-<span class="sourceLineNo">249</span>                NullWritable.class, job, false, tmpTableDir);<a name="line.249"></a>
-<span class="sourceLineNo">250</span>      }<a name="line.250"></a>
-<span class="sourceLineNo">251</span><a name="line.251"></a>
-<span class="sourceLineNo">252</span>      verifyWithMockedMapReduce(job, numRegions, expectedNumSplits, getStartRow(), getEndRow());<a name="line.252"></a>
-<span class="sourceLineNo">253</span><a name="line.253"></a>
-<span class="sourceLineNo">254</span>    } finally {<a name="line.254"></a>
-<span class="sourceLineNo">255</span>      util.getAdmin().deleteSnapshot(snapshotName);<a name="line.255"></a>
-<span class="sourceLineNo">256</span>      util.deleteTable(tableName);<a name="line.256"></a>
-<span class="sourceLineNo">257</span>    }<a name="line.257"></a>
-<span class="sourceLineNo">258</span>  }<a name="line.258"></a>
-<span class="sourceLineNo">259</span><a name="line.259"></a>
-<span class="sourceLineNo">260</span>  @Test<a name="line.260"></a>
-<span class="sourceLineNo">261</span>  public void testWithMockedMapReduceWithSplitsPerRegion() throws Exception {<a name="line.261"></a>
-<span class="sourceLineNo">262</span>    String snapshotName = "testWithMockedMapReduceMultiRegion";<a name="line.262"></a>
-<span class="sourceLineNo">263</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.263"></a>
-<span class="sourceLineNo">264</span>    try {<a name="line.264"></a>
-<span class="sourceLineNo">265</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 10);<a name="line.265"></a>
-<span class="sourceLineNo">266</span><a name="line.266"></a>
-<span class="sourceLineNo">267</span>      Configuration conf = UTIL.getConfiguration();<a name="line.267"></a>
-<span class="sourceLineNo">268</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, false);<a name="line.268"></a>
-<span class="sourceLineNo">269</span>      Job job = new Job(conf);<a name="line.269"></a>
-<span class="sourceLineNo">270</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.270"></a>
-<span class="sourceLineNo">271</span>      // test scan with startRow and stopRow<a name="line.271"></a>
-<span class="sourceLineNo">272</span>      Scan scan = new Scan().withStartRow(bbc).withStopRow(yya);<a name="line.272"></a>
-<span class="sourceLineNo">273</span><a name="line.273"></a>
-<span class="sourceLineNo">274</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.274"></a>
-<span class="sourceLineNo">275</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.275"></a>
-<span class="sourceLineNo">276</span>        tmpTableDir, new RegionSplitter.UniformSplit(), 5);<a name="line.276"></a>
-<span class="sourceLineNo">277</span><a name="line.277"></a>
-<span class="sourceLineNo">278</span>      verifyWithMockedMapReduce(job, 10, 40, bbc, yya);<a name="line.278"></a>
-<span class="sourceLineNo">279</span>    } finally {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.280"></a>
-<span class="sourceLineNo">281</span>      UTIL.deleteTable(tableName);<a name="line.281"></a>
-<span class="sourceLineNo">282</span>    }<a name="line.282"></a>
-<span class="sourceLineNo">283</span>  }<a name="line.283"></a>
-<span class="sourceLineNo">284</span><a name="line.284"></a>
-<span class="sourceLineNo">285</span>  @Test<a name="line.285"></a>
-<span class="sourceLineNo">286</span>  public void testWithMockedMapReduceWithNoStartRowStopRow() throws Exception {<a name="line.286"></a>
-<span class="sourceLineNo">287</span>    String snapshotName = "testWithMockedMapReduceMultiRegion";<a name="line.287"></a>
-<span class="sourceLineNo">288</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.288"></a>
-<span class="sourceLineNo">289</span>    try {<a name="line.289"></a>
-<span class="sourceLineNo">290</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 10);<a name="line.290"></a>
-<span class="sourceLineNo">291</span><a name="line.291"></a>
-<span class="sourceLineNo">292</span>      Configuration conf = UTIL.getConfiguration();<a name="line.292"></a>
-<span class="sourceLineNo">293</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, false);<a name="line.293"></a>
-<span class="sourceLineNo">294</span>      Job job = new Job(conf);<a name="line.294"></a>
-<span class="sourceLineNo">295</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.295"></a>
-<span class="sourceLineNo">296</span>      // test scan without startRow and stopRow<a name="line.296"></a>
-<span class="sourceLineNo">297</span>      Scan scan2 = new Scan();<a name="line.297"></a>
-<span class="sourceLineNo">298</span><a name="line.298"></a>
-<span class="sourceLineNo">299</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan2,<a name="line.299"></a>
-<span class="sourceLineNo">300</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.300"></a>
-<span class="sourceLineNo">301</span>        tmpTableDir, new RegionSplitter.UniformSplit(), 5);<a name="line.301"></a>
-<span class="sourceLineNo">302</span><a name="line.302"></a>
-<span class="sourceLineNo">303</span>      verifyWithMockedMapReduce(job, 10, 50, HConstants.EMPTY_START_ROW,<a name="line.303"></a>
-<span class="sourceLineNo">304</span>        HConstants.EMPTY_START_ROW);<a name="line.304"></a>
+<span class="sourceLineNo">138</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h3"}, 6);<a name="line.138"></a>
+<span class="sourceLineNo">139</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h4"}, 9);<a name="line.139"></a>
+<span class="sourceLineNo">140</span><a name="line.140"></a>
+<span class="sourceLineNo">141</span>    Assert.assertEquals(Lists.newArrayList("h2", "h3", "h4"),<a name="line.141"></a>
+<span class="sourceLineNo">142</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.142"></a>
+<span class="sourceLineNo">143</span>  }<a name="line.143"></a>
+<span class="sourceLineNo">144</span><a name="line.144"></a>
+<span class="sourceLineNo">145</span>  public static enum TestTableSnapshotCounters {<a name="line.145"></a>
+<span class="sourceLineNo">146</span>    VALIDATION_ERROR<a name="line.146"></a>
+<span class="sourceLineNo">147</span>  }<a name="line.147"></a>
+<span class="sourceLineNo">148</span><a name="line.148"></a>
+<span class="sourceLineNo">149</span>  public static class TestTableSnapshotMapper<a name="line.149"></a>
+<span class="sourceLineNo">150</span>    extends TableMapper&lt;ImmutableBytesWritable, NullWritable&gt; {<a name="line.150"></a>
+<span class="sourceLineNo">151</span>    @Override<a name="line.151"></a>
+<span class="sourceLineNo">152</span>    protected void map(ImmutableBytesWritable key, Result value,<a name="line.152"></a>
+<span class="sourceLineNo">153</span>        Context context) throws IOException, InterruptedException {<a name="line.153"></a>
+<span class="sourceLineNo">154</span>      // Validate a single row coming from the snapshot, and emit the row key<a name="line.154"></a>
+<span class="sourceLineNo">155</span>      verifyRowFromMap(key, value);<a name="line.155"></a>
+<span class="sourceLineNo">156</span>      context.write(key, NullWritable.get());<a name="line.156"></a>
+<span class="sourceLineNo">157</span>    }<a name="line.157"></a>
+<span class="sourceLineNo">158</span>  }<a name="line.158"></a>
+<span class="sourceLineNo">159</span><a name="line.159"></a>
+<span class="sourceLineNo">160</span>  public static class TestTableSnapshotReducer<a name="line.160"></a>
+<span class="sourceLineNo">161</span>    extends Reducer&lt;ImmutableBytesWritable, NullWritable, NullWritable, NullWritable&gt; {<a name="line.161"></a>
+<span class="sourceLineNo">162</span>    HBaseTestingUtil.SeenRowTracker rowTracker =<a name="line.162"></a>
+<span class="sourceLineNo">163</span>        new HBaseTestingUtil.SeenRowTracker(bbb, yyy);<a name="line.163"></a>
+<span class="sourceLineNo">164</span>    @Override<a name="line.164"></a>
+<span class="sourceLineNo">165</span>    protected void reduce(ImmutableBytesWritable key, Iterable&lt;NullWritable&gt; values,<a name="line.165"></a>
+<span class="sourceLineNo">166</span>       Context context) throws IOException, InterruptedException {<a name="line.166"></a>
+<span class="sourceLineNo">167</span>      rowTracker.addRow(key.get());<a name="line.167"></a>
+<span class="sourceLineNo">168</span>    }<a name="line.168"></a>
+<span class="sourceLineNo">169</span><a name="line.169"></a>
+<span class="sourceLineNo">170</span>    @Override<a name="line.170"></a>
+<span class="sourceLineNo">171</span>    protected void cleanup(Context context) throws IOException,<a name="line.171"></a>
+<span class="sourceLineNo">172</span>        InterruptedException {<a name="line.172"></a>
+<span class="sourceLineNo">173</span>      rowTracker.validate();<a name="line.173"></a>
+<span class="sourceLineNo">174</span>    }<a name="line.174"></a>
+<span class="sourceLineNo">175</span>  }<a name="line.175"></a>
+<span class="sourceLineNo">176</span><a name="line.176"></a>
+<span class="sourceLineNo">177</span>  @Test<a name="line.177"></a>
+<span class="sourceLineNo">178</span>  public void testInitTableSnapshotMapperJobConfig() throws Exception {<a name="line.178"></a>
+<span class="sourceLineNo">179</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.179"></a>
+<span class="sourceLineNo">180</span>    String snapshotName = "foo";<a name="line.180"></a>
+<span class="sourceLineNo">181</span><a name="line.181"></a>
+<span class="sourceLineNo">182</span>    try {<a name="line.182"></a>
+<span class="sourceLineNo">183</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 1);<a name="line.183"></a>
+<span class="sourceLineNo">184</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.184"></a>
+<span class="sourceLineNo">185</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.185"></a>
+<span class="sourceLineNo">186</span><a name="line.186"></a>
+<span class="sourceLineNo">187</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.187"></a>
+<span class="sourceLineNo">188</span>        new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.188"></a>
+<span class="sourceLineNo">189</span>        NullWritable.class, job, false, tmpTableDir);<a name="line.189"></a>
+<span class="sourceLineNo">190</span><a name="line.190"></a>
+<span class="sourceLineNo">191</span>      // TODO: would be better to examine directly the cache instance that results from this<a name="line.191"></a>
+<span class="sourceLineNo">192</span>      // config. Currently this is not possible because BlockCache initialization is static.<a name="line.192"></a>
+<span class="sourceLineNo">193</span>      Assert.assertEquals(<a name="line.193"></a>
+<span class="sourceLineNo">194</span>        "Snapshot job should be configured for default LruBlockCache.",<a name="line.194"></a>
+<span class="sourceLineNo">195</span>        HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT,<a name="line.195"></a>
+<span class="sourceLineNo">196</span>        job.getConfiguration().getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, -1), 0.01);<a name="line.196"></a>
+<span class="sourceLineNo">197</span>      Assert.assertEquals(<a name="line.197"></a>
+<span class="sourceLineNo">198</span>        "Snapshot job should not use BucketCache.",<a name="line.198"></a>
+<span class="sourceLineNo">199</span>        0, job.getConfiguration().getFloat("hbase.bucketcache.size", -1), 0.01);<a name="line.199"></a>
+<span class="sourceLineNo">200</span>    } finally {<a name="line.200"></a>
+<span class="sourceLineNo">201</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.201"></a>
+<span class="sourceLineNo">202</span>      UTIL.deleteTable(tableName);<a name="line.202"></a>
+<span class="sourceLineNo">203</span>    }<a name="line.203"></a>
+<span class="sourceLineNo">204</span>  }<a name="line.204"></a>
+<span class="sourceLineNo">205</span><a name="line.205"></a>
+<span class="sourceLineNo">206</span>  @Test<a name="line.206"></a>
+<span class="sourceLineNo">207</span>  public void testWithMockedMapReduceSingleRegionByRegionLocation() throws Exception {<a name="line.207"></a>
+<span class="sourceLineNo">208</span>    Configuration conf = UTIL.getConfiguration();<a name="line.208"></a>
+<span class="sourceLineNo">209</span>    conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION, true);<a name="line.209"></a>
+<span class="sourceLineNo">210</span>    try {<a name="line.210"></a>
+<span class="sourceLineNo">211</span>      testWithMockedMapReduce(UTIL, name.getMethodName() + "Snapshot", 1, 1, 1,<a name="line.211"></a>
+<span class="sourceLineNo">212</span>        true);<a name="line.212"></a>
+<span class="sourceLineNo">213</span>    } finally {<a name="line.213"></a>
+<span class="sourceLineNo">214</span>      conf.unset(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION);<a name="line.214"></a>
+<span class="sourceLineNo">215</span>    }<a name="line.215"></a>
+<span class="sourceLineNo">216</span>  }<a name="line.216"></a>
+<span class="sourceLineNo">217</span><a name="line.217"></a>
+<span class="sourceLineNo">218</span>  @Override<a name="line.218"></a>
+<span class="sourceLineNo">219</span>  public void testRestoreSnapshotDoesNotCreateBackRefLinksInit(TableName tableName,<a name="line.219"></a>
+<span class="sourceLineNo">220</span>      String snapshotName, Path tmpTableDir) throws Exception {<a name="line.220"></a>
+<span class="sourceLineNo">221</span>    Job job = new Job(UTIL.getConfiguration());<a name="line.221"></a>
+<span class="sourceLineNo">222</span>    TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.222"></a>
+<span class="sourceLineNo">223</span>      new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.223"></a>
+<span class="sourceLineNo">224</span>      NullWritable.class, job, false, tmpTableDir);<a name="line.224"></a>
+<span class="sourceLineNo">225</span>  }<a name="line.225"></a>
+<span class="sourceLineNo">226</span><a name="line.226"></a>
+<span class="sourceLineNo">227</span>  @Override<a name="line.227"></a>
+<span class="sourceLineNo">228</span>  public void testWithMockedMapReduce(HBaseTestingUtil util, String snapshotName,<a name="line.228"></a>
+<span class="sourceLineNo">229</span>      int numRegions, int numSplitsPerRegion, int expectedNumSplits, boolean setLocalityEnabledTo)<a name="line.229"></a>
+<span class="sourceLineNo">230</span>      throws Exception {<a name="line.230"></a>
+<span class="sourceLineNo">231</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.231"></a>
+<span class="sourceLineNo">232</span>    try {<a name="line.232"></a>
+<span class="sourceLineNo">233</span>      createTableAndSnapshot(<a name="line.233"></a>
+<span class="sourceLineNo">234</span>        util, tableName, snapshotName, getStartRow(), getEndRow(), numRegions);<a name="line.234"></a>
+<span class="sourceLineNo">235</span><a name="line.235"></a>
+<span class="sourceLineNo">236</span>      Configuration conf = util.getConfiguration();<a name="line.236"></a>
+<span class="sourceLineNo">237</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, setLocalityEnabledTo);<a name="line.237"></a>
+<span class="sourceLineNo">238</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.238"></a>
+<span class="sourceLineNo">239</span>        SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.239"></a>
+<span class="sourceLineNo">240</span>      Job job = new Job(conf);<a name="line.240"></a>
+<span class="sourceLineNo">241</span>      Path tmpTableDir = util.getDataTestDirOnTestFS(snapshotName);<a name="line.241"></a>
+<span class="sourceLineNo">242</span>      Scan scan = new Scan().withStartRow(getStartRow()).withStopRow(getEndRow()); // limit the scan<a name="line.242"></a>
+<span class="sourceLineNo">243</span><a name="line.243"></a>
+<span class="sourceLineNo">244</span>      if (numSplitsPerRegion &gt; 1) {<a name="line.244"></a>
+<span class="sourceLineNo">245</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.245"></a>
+<span class="sourceLineNo">246</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.246"></a>
+<span class="sourceLineNo">247</span>                NullWritable.class, job, false, tmpTableDir, new RegionSplitter.UniformSplit(),<a name="line.247"></a>
+<span class="sourceLineNo">248</span>                numSplitsPerRegion);<a name="line.248"></a>
+<span class="sourceLineNo">249</span>      } else {<a name="line.249"></a>
+<span class="sourceLineNo">250</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.250"></a>
+<span class="sourceLineNo">251</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.251"></a>
+<span class="sourceLineNo">252</span>                NullWritable.class, job, false, tmpTableDir);<a name="line.252"></a>
+<span class="sourceLineNo">253</span>      }<a name="line.253"></a>
+<span class="sourceLineNo">254</span><a name="line.254"></a>
+<span class="sourceLineNo">255</span>      verifyWithMockedMapReduce(job, numRegions, expectedNumSplits, getStartRow(), getEndRow());<a name="line.255"></a>
+<span class="sourceLineNo">256</span><a name="line.256"></a>
+<span class="sourceLineNo">257</span>    } finally {<a name="line.257"></a>
+<span class="sourceLineNo">258</span>      util.getAdmin().deleteSnapshot(snapshotName);<a name="line.258"></a>
+<span class="sourceLineNo">259</span>      util.deleteTable(tableName);<a name="line.259"></a>
+<span class="sourceLineNo">260</span>    }<a name="line.260"></a>
+<span class="sourceLineNo">261</span>  }<a name="line.261"></a>
+<span class="sourceLineNo">262</span><a name="line.262"></a>
+<span class="sourceLineNo">263</span>  @Test<a name="line.263"></a>
+<span class="sourceLineNo">264</span>  public void testWithMockedMapReduceWithSplitsPerRegion() throws Exception {<a name="line.264"></a>
+<span class="sourceLineNo">265</span>    String snapshotName = "testWithMockedMapReduceMultiRegion";<a name="line.265"></a>
+<span class="sourceLineNo">266</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.266"></a>
+<span class="sourceLineNo">267</span>    try {<a name="line.267"></a>
+<span class="sourceLineNo">268</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 10);<a name="line.268"></a>
+<span class="sourceLineNo">269</span><a name="line.269"></a>
+<span class="sourceLineNo">270</span>      Configuration conf = UTIL.getConfiguration();<a name="line.270"></a>
+<span class="sourceLineNo">271</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, false);<a name="line.271"></a>
+<span class="sourceLineNo">272</span>      Job job = new Job(conf);<a name="line.272"></a>
+<span class="sourceLineNo">273</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.273"></a>
+<span class="sourceLineNo">274</span>      // test scan with startRow and stopRow<a name="line.274"></a>
+<span class="sourceLineNo">275</span>      Scan scan = new Scan().withStartRow(bbc).withStopRow(yya);<a name="line.275"></a>
+<span class="sourceLineNo">276</span><a name="line.276"></a>
+<span class="sourceLineNo">277</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.277"></a>
+<span class="sourceLineNo">278</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.278"></a>
+<span class="sourceLineNo">279</span>        tmpTableDir, new RegionSplitter.UniformSplit(), 5);<a name="line.279"></a>
+<span class="sourceLineNo">280</span><a name="line.280"></a>
+<span class="sourceLineNo">281</span>      verifyWithMockedMapReduce(job, 10, 40, bbc, yya);<a name="line.281"></a>
+<span class="sourceLineNo">282</span>    } finally {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.283"></a>
+<span class="sourceLineNo">284</span>      UTIL.deleteTable(tableName);<a name="line.284"></a>
+<span class="sourceLineNo">285</span>    }<a name="line.285"></a>
+<span class="sourceLineNo">286</span>  }<a name="line.286"></a>
+<span class="sourceLineNo">287</span><a name="line.287"></a>
+<span class="sourceLineNo">288</span>  @Test<a name="line.288"></a>
+<span class="sourceLineNo">289</span>  public void testWithMockedMapReduceWithNoStartRowStopRow() throws Exception {<a name="line.289"></a>
+<span class="sourceLineNo">290</span>    String snapshotName = "testWithMockedMapReduceMultiRegion";<a name="line.290"></a>
+<span class="sourceLineNo">291</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.291"></a>
+<span class="sourceLineNo">292</span>    try {<a name="line.292"></a>
+<span class="sourceLineNo">293</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 10);<a name="line.293"></a>
+<span class="sourceLineNo">294</span><a name="line.294"></a>
+<span class="sourceLineNo">295</span>      Configuration conf = UTIL.getConfiguration();<a name="line.295"></a>
+<span class="sourceLineNo">296</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, false);<a name="line.296"></a>
+<span class="sourceLineNo">297</span>      Job job = new Job(conf);<a name="line.297"></a>
+<span class="sourceLineNo">298</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.298"></a>
+<span class="sourceLineNo">299</span>      // test scan without startRow and stopRow<a name="line.299"></a>
+<span class="sourceLineNo">300</span>      Scan scan2 = new Scan();<a name="line.300"></a>
+<span class="sourceLineNo">301</span><a name="line.301"></a>
+<span class="sourceLineNo">302</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan2,<a name="line.302"></a>
+<span class="sourceLineNo">303</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.303"></a>
+<span class="sourceLineNo">304</span>        tmpTableDir, new RegionSplitter.UniformSplit(), 5);<a name="line.304"></a>
 <span class="sourceLineNo">305</span><a name="line.305"></a>
-<span class="sourceLineNo">306</span>    } finally {<a name="line.306"></a>
-<span class="sourceLineNo">307</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.307"></a>
-<span class="sourceLineNo">308</span>      UTIL.deleteTable(tableName);<a name="line.308"></a>
-<span class="sourceLineNo">309</span>    }<a name="line.309"></a>
-<span class="sourceLineNo">310</span>  }<a name="line.310"></a>
-<span class="sourceLineNo">311</span><a name="line.311"></a>
-<span class="sourceLineNo">312</span>  @Test<a name="line.312"></a>
-<span class="sourceLineNo">313</span>  public void testScanLimit() throws Exception {<a name="line.313"></a>
-<span class="sourceLineNo">314</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.314"></a>
-<span class="sourceLineNo">315</span>    final String snapshotName = tableName + "Snapshot";<a name="line.315"></a>
-<span class="sourceLineNo">316</span>    Table table = null;<a name="line.316"></a>
-<span class="sourceLineNo">317</span>    try {<a name="line.317"></a>
-<span class="sourceLineNo">318</span>      UTIL.getConfiguration().setInt(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT, 10);<a name="line.318"></a>
-<span class="sourceLineNo">319</span>      if (UTIL.getAdmin().tableExists(tableName)) {<a name="line.319"></a>
-<span class="sourceLineNo">320</span>        UTIL.deleteTable(tableName);<a name="line.320"></a>
-<span class="sourceLineNo">321</span>      }<a name="line.321"></a>
-<span class="sourceLineNo">322</span><a name="line.322"></a>
-<span class="sourceLineNo">323</span>      UTIL.createTable(tableName, FAMILIES, new byte[][] { bbb, yyy });<a name="line.323"></a>
-<span class="sourceLineNo">324</span><a name="line.324"></a>
-<span class="sourceLineNo">325</span>      Admin admin = UTIL.getAdmin();<a name="line.325"></a>
-<span class="sourceLineNo">326</span><a name="line.326"></a>
-<span class="sourceLineNo">327</span>      int regionNum = admin.getRegions(tableName).size();<a name="line.327"></a>
-<span class="sourceLineNo">328</span>      // put some stuff in the table<a name="line.328"></a>
-<span class="sourceLineNo">329</span>      table = UTIL.getConnection().getTable(tableName);<a name="line.329"></a>
-<span class="sourceLineNo">330</span>      UTIL.loadTable(table, FAMILIES);<a name="line.330"></a>
-<span class="sourceLineNo">331</span><a name="line.331"></a>
-<span class="sourceLineNo">332</span>      Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.332"></a>
-<span class="sourceLineNo">333</span>      FileSystem fs = rootDir.getFileSystem(UTIL.getConfiguration());<a name="line.333"></a>
+<span class="sourceLineNo">306</span>      verifyWithMockedMapReduce(job, 10, 50, HConstants.EMPTY_START_ROW,<a name="line.306"></a>
+<span class="sourceLineNo">307</span>        HConstants.EMPTY_START_ROW);<a name="line.307"></a>
+<span class="sourceLineNo">308</span><a name="line.308"></a>
+<span class="sourceLineNo">309</span>    } finally {<a name="line.309"></a>
+<span class="sourceLineNo">310</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.310"></a>
+<span class="sourceLineNo">311</span>      UTIL.deleteTable(tableName);<a name="line.311"></a>
+<span class="sourceLineNo">312</span>    }<a name="line.312"></a>
+<span class="sourceLineNo">313</span>  }<a name="line.313"></a>
+<span class="sourceLineNo">314</span><a name="line.314"></a>
+<span class="sourceLineNo">315</span>  @Test<a name="line.315"></a>
+<span class="sourceLineNo">316</span>  public void testScanLimit() throws Exception {<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.317"></a>
+<span class="sourceLineNo">318</span>    final String snapshotName = tableName + "Snapshot";<a name="line.318"></a>
+<span class="sourceLineNo">319</span>    Table table = null;<a name="line.319"></a>
+<span class="sourceLineNo">320</span>    try {<a name="line.320"></a>
+<span class="sourceLineNo">321</span>      UTIL.getConfiguration().setInt(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT, 10);<a name="line.321"></a>
+<span class="sourceLineNo">322</span>      if (UTIL.getAdmin().tableExists(tableName)) {<a name="line.322"></a>
+<span class="sourceLineNo">323</span>        UTIL.deleteTable(tableName);<a name="line.323"></a>
+<span class="sourceLineNo">324</span>      }<a name="line.324"></a>
+<span class="sourceLineNo">325</span><a name="line.325"></a>
+<span class="sourceLineNo">326</span>      UTIL.createTable(tableName, FAMILIES, new byte[][] { bbb, yyy });<a name="line.326"></a>
+<span class="sourceLineNo">327</span><a name="line.327"></a>
+<span class="sourceLineNo">328</span>      Admin admin = UTIL.getAdmin();<a name="line.328"></a>
+<span class="sourceLineNo">329</span><a name="line.329"></a>
+<span class="sourceLineNo">330</span>      int regionNum = admin.getRegions(tableName).size();<a name="line.330"></a>
+<span class="sourceLineNo">331</span>      // put some stuff in the table<a name="line.331"></a>
+<span class="sourceLineNo">332</span>      table = UTIL.getConnection().getTable(tableName);<a name="line.332"></a>
+<span class="sourceLineNo">333</span>      UTIL.loadTable(table, FAMILIES);<a name="line.333"></a>
 <span class="sourceLineNo">334</span><a name="line.334"></a>
-<span class="sourceLineNo">335</span>      SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName, Arrays.asList(FAMILIES),<a name="line.335"></a>
-<span class="sourceLineNo">336</span>        null, snapshotName, rootDir, fs, true);<a name="line.336"></a>
+<span class="sourceLineNo">335</span>      Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.335"></a>
+<span class="sourceLineNo">336</span>      FileSystem fs = rootDir.getFileSystem(UTIL.getConfiguration());<a name="line.336"></a>
 <span class="sourceLineNo">337</span><a name="line.337"></a>
-<span class="sourceLineNo">338</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.338"></a>
-<span class="sourceLineNo">339</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.339"></a>
-<span class="sourceLineNo">340</span>      Scan scan = new Scan();<a name="line.340"></a>
-<span class="sourceLineNo">341</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.341"></a>
-<span class="sourceLineNo">342</span>        TestTableSnapshotInputFormat.class);<a name="line.342"></a>
-<span class="sourceLineNo">343</span><a name="line.343"></a>
-<span class="sourceLineNo">344</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.344"></a>
-<span class="sourceLineNo">345</span>        RowCounter.RowCounterMapper.class, NullWritable.class, NullWritable.class, job, true,<a name="line.345"></a>
-<span class="sourceLineNo">346</span>        tmpTableDir);<a name="line.346"></a>
-<span class="sourceLineNo">347</span>      Assert.assertTrue(job.waitForCompletion(true));<a name="line.347"></a>
-<span class="sourceLineNo">348</span>      Assert.assertEquals(10 * regionNum,<a name="line.348"></a>
-<span class="sourceLineNo">349</span>        job.getCounters().findCounter(RowCounter.RowCounterMapper.Counters.ROWS).getValue());<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    } finally {<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      if (table != null) {<a name="line.351"></a>
-<span class="sourceLineNo">352</span>        table.close();<a name="line.352"></a>
-<span class="sourceLineNo">353</span>      }<a name="line.353"></a>
-<span class="sourceLineNo">354</span>      UTIL.getConfiguration().unset(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT);<a name="line.354"></a>
-<span class="sourceLineNo">355</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.355"></a>
-<span class="sourceLineNo">356</span>      UTIL.deleteTable(tableName);<a name="line.356"></a>
-<span class="sourceLineNo">357</span>    }<a name="line.357"></a>
-<span class="sourceLineNo">358</span>  }<a name="line.358"></a>
-<span class="sourceLineNo">359</span><a name="line.359"></a>
-<span class="sourceLineNo">360</span>  @Test<a name="line.360"></a>
-<span class="sourceLineNo">361</span>  public void testNoDuplicateResultsWhenSplitting() throws Exception {<a name="line.361"></a>
-<span class="sourceLineNo">362</span>    TableName tableName = TableName.valueOf("testNoDuplicateResultsWhenSplitting");<a name="line.362"></a>
-<span class="sourceLineNo">363</span>    String snapshotName = "testSnapshotBug";<a name="line.363"></a>
-<span class="sourceLineNo">364</span>    try {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>      if (UTIL.getAdmin().tableExists(tableName)) {<a name="line.365"></a>
-<span class="sourceLineNo">366</span>        UTIL.deleteTable(tableName);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>      }<a name="line.367"></a>
-<span class="sourceLineNo">368</span><a name="line.368"></a>
-<span class="sourceLineNo">369</span>      UTIL.createTable(tableName, FAMILIES);<a name="line.369"></a>
-<span class="sourceLineNo">370</span>      Admin admin = UTIL.getAdmin();<a name="line.370"></a>
+<span class="sourceLineNo">338</span>      SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName, Arrays.asList(FAMILIES),<a name="line.338"></a>
+<span class="sourceLineNo">339</span>        null, snapshotName, rootDir, fs, true);<a name="line.339"></a>
+<span class="sourceLineNo">340</span><a name="line.340"></a>
+<span class="sourceLineNo">341</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.341"></a>
+<span class="sourceLineNo">342</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.342"></a>
+<span class="sourceLineNo">343</span>      Scan scan = new Scan();<a name="line.343"></a>
+<span class="sourceLineNo">344</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.344"></a>
+<span class="sourceLineNo">345</span>        TestTableSnapshotInputFormat.class);<a name="line.345"></a>
+<span class="sourceLineNo">346</span><a name="line.346"></a>
+<span class="sourceLineNo">347</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.347"></a>
+<span class="sourceLineNo">348</span>        RowCounter.RowCounterMapper.class, NullWritable.class, NullWritable.class, job, true,<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        tmpTableDir);<a name="line.349"></a>
+<span class="sourceLineNo">350</span>      Assert.assertTrue(job.waitForCompletion(true));<a name="line.350"></a>
+<span class="sourceLineNo">351</span>      Assert.assertEquals(10 * regionNum,<a name="line.351"></a>
+<span class="sourceLineNo">352</span>        job.getCounters().findCounter(RowCounter.RowCounterMapper.Counters.ROWS).getValue());<a name="line.352"></a>
+<span class="sourceLineNo">353</span>    } finally {<a name="line.353"></a>
+<span class="sourceLineNo">354</span>      if (table != null) {<a name="line.354"></a>
+<span class="sourceLineNo">355</span>        table.close();<a name="line.355"></a>
+<span class="sourceLineNo">356</span>      }<a name="line.356"></a>
+<span class="sourceLineNo">357</span>      UTIL.getConfiguration().unset(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT);<a name="line.357"></a>
+<span class="sourceLineNo">358</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.358"></a>
+<span class="sourceLineNo">359</span>      UTIL.deleteTable(tableName);<a name="line.359"></a>
+<span class="sourceLineNo">360</span>    }<a name="line.360"></a>
+<span class="sourceLineNo">361</span>  }<a name="line.361"></a>
+<span class="sourceLineNo">362</span><a name="line.362"></a>
+<span class="sourceLineNo">363</span>  @Test<a name="line.363"></a>
+<span class="sourceLineNo">364</span>  public void testNoDuplicateResultsWhenSplitting() throws Exception {<a name="line.364"></a>
+<span class="sourceLineNo">365</span>    TableName tableName = TableName.valueOf("testNoDuplicateResultsWhenSplitting");<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    String snapshotName = "testSnapshotBug";<a name="line.366"></a>
+<span class="sourceLineNo">367</span>    try {<a name="line.367"></a>
+<span class="sourceLineNo">368</span>      if (UTIL.getAdmin().tableExists(tableName)) {<a name="line.368"></a>
+<span class="sourceLineNo">369</span>        UTIL.deleteTable(tableName);<a name="line.369"></a>
+<span class="sourceLineNo">370</span>      }<a name="line.370"></a>
 <span class="sourceLineNo">371</span><a name="line.371"></a>
-<span class="sourceLineNo">372</span>      // put some stuff in the table<a name="line.372"></a>
-<span class="sourceLineNo">373</span>      Table table = UTIL.getConnection().getTable(tableName);<a name="line.373"></a>
-<span class="sourceLineNo">374</span>      UTIL.loadTable(table, FAMILIES);<a name="line.374"></a>
-<span class="sourceLineNo">375</span><a name="line.375"></a>
-<span class="sourceLineNo">376</span>      // split to 2 regions<a name="line.376"></a>
-<span class="sourceLineNo">377</span>      admin.split(tableName, Bytes.toBytes("eee"));<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      TestTableSnapshotScanner.blockUntilSplitFinished(UTIL, tableName, 2);<a name="line.378"></a>
-<span class="sourceLineNo">379</span><a name="line.379"></a>
-<span class="sourceLineNo">380</span>      Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      FileSystem fs = rootDir.getFileSystem(UTIL.getConfiguration());<a name="line.381"></a>
+<span class="sourceLineNo">372</span>      UTIL.createTable(tableName, FAMILIES);<a name="line.372"></a>
+<span class="sourceLineNo">373</span>      Admin admin = UTIL.getAdmin();<a name="line.373"></a>
+<span class="sourceLineNo">374</span><a name="line.374"></a>
+<span class="sourceLineNo">375</span>      // put some stuff in the table<a name="line.375"></a>
+<span class="sourceLineNo">376</span>      Table table = UTIL.getConnection().getTable(tableName);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>      UTIL.loadTable(table, FAMILIES);<a name="line.377"></a>
+<span class="sourceLineNo">378</span><a name="line.378"></a>
+<span class="sourceLineNo">379</span>      // split to 2 regions<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      admin.split(tableName, Bytes.toBytes("eee"));<a name="line.380"></a>
+<span class="sourceLineNo">381</span>      TestTableSnapshotScanner.blockUntilSplitFinished(UTIL, tableName, 2);<a name="line.381"></a>
 <span class="sourceLineNo">382</span><a name="line.382"></a>
-<span class="sourceLineNo">383</span>      SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName, Arrays.asList(FAMILIES),<a name="line.383"></a>
-<span class="sourceLineNo">384</span>        null, snapshotName, rootDir, fs, true);<a name="line.384"></a>
+<span class="sourceLineNo">383</span>      Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      FileSystem fs = rootDir.getFileSystem(UTIL.getConfiguration());<a name="line.384"></a>
 <span class="sourceLineNo">385</span><a name="line.385"></a>
-<span class="sourceLineNo">386</span>      // load different values<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      byte[] value = Bytes.toBytes("after_snapshot_value");<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      UTIL.loadTable(table, FAMILIES, value);<a name="line.388"></a>
-<span class="sourceLineNo">389</span><a name="line.389"></a>
-<span class="sourceLineNo">390</span>      // cause flush to create new files in the region<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      admin.flush(tableName);<a name="line.391"></a>
-<span class="sourceLineNo">392</span>      table.close();<a name="line.392"></a>
-<span class="sourceLineNo">393</span><a name="line.393"></a>
-<span class="sourceLineNo">394</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>      // limit the scan<a name="line.396"></a>
-<span class="sourceLineNo">397</span>      Scan scan = new Scan().withStartRow(getStartRow()).withStopRow(getEndRow());<a name="line.397"></a>
-<span class="sourceLineNo">398</span><a name="line.398"></a>
-<span class="sourceLineNo">399</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.399"></a>
-<span class="sourceLineNo">400</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.400"></a>
-<span class="sourceLineNo">401</span>        tmpTableDir);<a name="line.401"></a>
-<span class="sourceLineNo">402</span><a name="line.402"></a>
-<span class="sourceLineNo">403</span>      verifyWithMockedMapReduce(job, 2, 2, getStartRow(), getEndRow());<a name="line.403"></a>
-<span class="sourceLineNo">404</span>    } finally {<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      UTIL.deleteTable(tableName);<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    }<a name="line.407"></a>
-<span class="sourceLineNo">408</span>  }<a name="line.408"></a>
-<span class="sourceLineNo">409</span><a name="line.409"></a>
-<span class="sourceLineNo">410</span>  private void verifyWithMockedMapReduce(Job job, int numRegions, int expectedNumSplits,<a name="line.410"></a>
-<span class="sourceLineNo">411</span>      byte[] startRow, byte[] stopRow)<a name="line.411"></a>
-<span class="sourceLineNo">412</span>      throws IOException, InterruptedException {<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    TableSnapshotInputFormat tsif = new TableSnapshotInputFormat();<a name="line.413"></a>
-<span class="sourceLineNo">414</span>    List&lt;InputSplit&gt; splits = tsif.getSplits(job);<a name="line.414"></a>
-<span class="sourceLineNo">415</span><a name="line.415"></a>
-<span class="sourceLineNo">416</span>    Assert.assertEquals(expectedNumSplits, splits.size());<a name="line.416"></a>
-<span class="sourceLineNo">417</span><a name="line.417"></a>
-<span class="sourceLineNo">418</span>    HBaseTestingUtil.SeenRowTracker rowTracker = new HBaseTestingUtil.SeenRowTracker(startRow,<a name="line.418"></a>
-<span class="sourceLineNo">419</span>        stopRow.length &gt; 0 ? stopRow : Bytes.toBytes("\uffff"));<a name="line.419"></a>
-<span class="sourceLineNo">420</span><a name="line.420"></a>
-<span class="sourceLineNo">421</span>    boolean localityEnabled =<a name="line.421"></a>
-<span class="sourceLineNo">422</span>        job.getConfiguration().getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY,<a name="line.422"></a>
-<span class="sourceLineNo">423</span>                                          SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT);<a name="line.423"></a>
-<span class="sourceLineNo">424</span><a name="line.424"></a>
-<span class="sourceLineNo">425</span>    boolean byRegionLoc =<a name="line.425"></a>
-<span class="sourceLineNo">426</span>      job.getConfiguration().getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.426"></a>
-<span class="sourceLineNo">427</span>                                        SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.427"></a>
-<span class="sourceLineNo">428</span>    for (int i = 0; i &lt; splits.size(); i++) {<a name="line.428"></a>
-<span class="sourceLineNo">429</span>      // validate input split<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      InputSplit split = splits.get(i);<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      Assert.assertTrue(split instanceof TableSnapshotRegionSplit);<a name="line.431"></a>
-<span class="sourceLineNo">432</span>      TableSnapshotRegionSplit snapshotRegionSplit = (TableSnapshotRegionSplit) split;<a name="line.432"></a>
-<span class="sourceLineNo">433</span>      if (localityEnabled) {<a name="line.433"></a>
-<span class="sourceLineNo">434</span>        Assert.assertTrue(split.getLocations() != null &amp;&amp; split.getLocations().length != 0);<a name="line.434"></a>
-<span class="sourceLineNo">435</span>        if (byRegionLoc) {<a name="line.435"></a>
-<span class="sourceLineNo">436</span>          // When it uses region location from meta, the hostname will be "localhost",<a name="line.436"></a>
-<span class="sourceLineNo">437</span>          // the location from hdfs block location is "127.0.0.1".<a name="line.437"></a>
-<span class="sourceLineNo">438</span>          Assert.assertEquals(1, split.getLocations().length);<a name="line.438"></a>
-<span class="sourceLineNo">439</span>          Assert.assertTrue("Not using region location!",<a name="line.439"></a>
-<span class="sourceLineNo">440</span>            split.getLocations()[0].equals("localhost"));<a name="line.440"></a>
-<span class="sourceLineNo">441</span>        } else {<a name="line.441"></a>
-<span class="sourceLineNo">442</span>          Assert.assertTrue("Not using region location!",<a name="line.442"></a>
-<span class="sourceLineNo">443</span>            split.getLocations()[0].equals("127.0.0.1"));<a name="line.443"></a>
-<span class="sourceLineNo">444</span>        }<a name="line.444"></a>
-<span class="sourceLineNo">445</span>      } else {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>        Assert.assertTrue(split.getLocations() != null &amp;&amp; split.getLocations().length == 0);<a name="line.446"></a>
-<span class="sourceLineNo">447</span>      }<a name="line.447"></a>
+<span class="sourceLineNo">386</span>      SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName, Arrays.asList(FAMILIES),<a name="line.386"></a>
+<span class="sourceLineNo">387</span>        null, snapshotName, rootDir, fs, true);<a name="line.387"></a>
+<span class="sourceLineNo">388</span><a name="line.388"></a>
+<span class="sourceLineNo">389</span>      // load different values<a name="line.389"></a>
+<span class="sourceLineNo">390</span>      byte[] value = Bytes.toBytes("after_snapshot_value");<a name="line.390"></a>
+<span class="sourceLineNo">391</span>      UTIL.loadTable(table, FAMILIES, value);<a name="line.391"></a>
+<span class="sourceLineNo">392</span><a name="line.392"></a>
+<span class="sourceLineNo">393</span>      // cause flush to create new files in the region<a name="line.393"></a>
+<span class="sourceLineNo">394</span>      admin.flush(tableName);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>      table.close();<a name="line.395"></a>
+<span class="sourceLineNo">396</span><a name="line.396"></a>
+<span class="sourceLineNo">397</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.397"></a>
+<span class="sourceLineNo">398</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.398"></a>
+<span class="sourceLineNo">399</span>      // limit the scan<a name="line.399"></a>
+<span class="sourceLineNo">400</span>      Scan scan = new Scan().withStartRow(getStartRow()).withStopRow(getEndRow());<a name="line.400"></a>
+<span class="sourceLineNo">401</span><a name="line.401"></a>
+<span class="sourceLineNo">402</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.402"></a>
+<span class="sourceLineNo">403</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.403"></a>
+<span class="sourceLineNo">404</span>        tmpTableDir);<a name="line.404"></a>
+<span class="sourceLineNo">405</span><a name="line.405"></a>
+<span class="sourceLineNo">406</span>      verifyWithMockedMapReduce(job, 2, 2, getStartRow(), getEndRow());<a name="line.406"></a>
+<span class="sourceLineNo">407</span>    } finally {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.408"></a>
+<span class="sourceLineNo">409</span>      UTIL.deleteTable(tableName);<a name="line.409"></a>
+<span class="sourceLineNo">410</span>    }<a name="line.410"></a>
+<span class="sourceLineNo">411</span>  }<a name="line.411"></a>
+<span class="sourceLineNo">412</span><a name="line.412"></a>
+<span class="sourceLineNo">413</span>  @Test<a name="line.413"></a>
+<span class="sourceLineNo">414</span>  public void testScannerReadTypeConfiguration() throws IOException {<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    Configuration conf = new Configuration(false);<a name="line.415"></a>
+<span class="sourceLineNo">416</span>    // Explicitly set ReadTypes should persist<a name="line.416"></a>
+<span class="sourceLineNo">417</span>    for (ReadType readType : Arrays.asList(ReadType.PREAD, ReadType.STREAM)) {<a name="line.417"></a>
+<span class="sourceLineNo">418</span>      Scan scanWithReadType = new Scan();<a name="line.418"></a>
+<span class="sourceLineNo">419</span>      scanWithReadType.setReadType(readType);<a name="line.419"></a>
+<span class="sourceLineNo">420</span>      assertEquals(scanWithReadType.getReadType(),<a name="line.420"></a>
+<span class="sourceLineNo">421</span>          serializeAndReturn(conf, scanWithReadType).getReadType());<a name="line.421"></a>
+<span class="sourceLineNo">422</span>    }<a name="line.422"></a>
+<span class="sourceLineNo">423</span>    // We should only see the DEFAULT ReadType getting updated to STREAM.<a name="line.423"></a>
+<span class="sourceLineNo">424</span>    Scan scanWithoutReadType = new Scan();<a name="line.424"></a>
+<span class="sourceLineNo">425</span>    assertEquals(ReadType.DEFAULT, scanWithoutReadType.getReadType());<a name="line.425"></a>
+<span class="sourceLineNo">426</span>    assertEquals(ReadType.STREAM, serializeAndReturn(conf, scanWithoutReadType).getReadType());<a name="line.426"></a>
+<span class="sourceLineNo">427</span><a name="line.427"></a>
+<span class="sourceLineNo">428</span>    // We should still be able to force a certain ReadType when DEFAULT is given.<a name="line.428"></a>
+<span class="sourceLineNo">429</span>    conf.setEnum(SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE, ReadType.PREAD);<a name="line.429"></a>
+<span class="sourceLineNo">430</span>    assertEquals(ReadType.DEFAULT, scanWithoutReadType.getReadType());<a name="line.430"></a>
+<span class="sourceLineNo">431</span>    assertEquals(ReadType.PREAD, serializeAndReturn(conf, scanWithoutReadType).getReadType());<a name="line.431"></a>
+<span class="sourceLineNo">432</span>  }<a name="line.432"></a>
+<span class="sourceLineNo">433</span><a name="line.433"></a>
+<span class="sourceLineNo">434</span>  /**<a name="line.434"></a>
+<span class="sourceLineNo">435</span>   * Serializes and deserializes the given scan in the same manner that<a name="line.435"></a>
+<span class="sourceLineNo">436</span>   * TableSnapshotInputFormat does.<a name="line.436"></a>
+<span class="sourceLineNo">437</span>   */<a name="line.437"></a>
+<span class="sourceLineNo">438</span>  private Scan serializeAndReturn(Configuration conf, Scan s) throws IOException {<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    conf.set(TableInputFormat.SCAN, TableMapReduceUtil.convertScanToString(s));<a name="line.439"></a>
+<span class="sourceLineNo">440</span>    return TableSnapshotInputFormatImpl.extractScanFromConf(conf);<a name="line.440"></a>
+<span class="sourceLineNo">441</span>  }<a name="line.441"></a>
+<span class="sourceLineNo">442</span><a name="line.442"></a>
+<span class="sourceLineNo">443</span>  private void verifyWithMockedMapReduce(Job job, int numRegions, int expectedNumSplits,<a name="line.443"></a>
+<span class="sourceLineNo">444</span>      byte[] startRow, byte[] stopRow)<a name="line.444"></a>
+<span class="sourceLineNo">445</span>      throws IOException, InterruptedException {<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    TableSnapshotInputFormat tsif = new TableSnapshotInputFormat();<a name="line.446"></a>
+<span class="sourceLineNo">447</span>    List&lt;InputSplit&gt; splits = tsif.getSplits(job);<a name="line.447"></a>
 <span class="sourceLineNo">448</span><a name="line.448"></a>
-<span class="sourceLineNo">449</span>      Scan scan =<a name="line.449"></a>
-<span class="sourceLineNo">450</span>          TableMapReduceUtil.convertStringToScan(snapshotRegionSplit.getDelegate().getScan());<a name="line.450"></a>
-<span class="sourceLineNo">451</span>      if (startRow.length &gt; 0) {<a name="line.451"></a>
-<span class="sourceLineNo">452</span>        Assert.assertTrue(<a name="line.452"></a>
-<span class="sourceLineNo">453</span>          Bytes.toStringBinary(startRow) + " should &lt;= " + Bytes.toStringBinary(scan.getStartRow()),<a name="line.453"></a>
-<span class="sourceLineNo">454</span>          Bytes.compareTo(startRow, scan.getStartRow()) &lt;= 0);<a name="line.454"></a>
-<span class="sourceLineNo">455</span>      }<a name="line.455"></a>
-<span class="sourceLineNo">456</span>      if (stopRow.length &gt; 0) {<a name="line.456"></a>
-<span class="sourceLineNo">457</span>        Assert.assertTrue(<a name="line.457"></a>
-<span class="sourceLineNo">458</span>          Bytes.toStringBinary(stopRow) + " should &gt;= " + Bytes.toStringBinary(scan.getStopRow()),<a name="line.458"></a>
-<span class="sourceLineNo">459</span>          Bytes.compareTo(stopRow, scan.getStopRow()) &gt;= 0);<a name="line.459"></a>
-<span class="sourceLineNo">460</span>      }<a name="line.460"></a>
-<span class="sourceLineNo">461</span>      Assert.assertTrue("startRow should &lt; stopRow",<a name="line.461"></a>
-<span class="sourceLineNo">462</span>        Bytes.compareTo(scan.getStartRow(), scan.getStopRow()) &lt; 0);<a name="line.462"></a>
-<span class="sourceLineNo">463</span><a name="line.463"></a>
-<span class="sourceLineNo">464</span>      // validate record reader<a name="line.464"></a>
-<span class="sourceLineNo">465</span>      TaskAttemptContext taskAttemptContext = mock(TaskAttemptContext.class);<a name="line.465"></a>
-<span class="sourceLineNo">466</span>      when(taskAttemptContext.getConfiguration()).thenReturn(job.getConfiguration());<a name="line.466"></a>
-<span class="sourceLineNo">467</span>      RecordReader&lt;ImmutableBytesWritable, Result&gt; rr =<a name="line.467"></a>
-<span class="sourceLineNo">468</span>          tsif.createRecordReader(split, taskAttemptContext);<a name="line.468"></a>
-<span class="sourceLineNo">469</span>      rr.initialize(split, taskAttemptContext);<a name="line.469"></a>
-<span class="sourceLineNo">470</span><a name="line.470"></a>
-<span class="sourceLineNo">471</span>      // validate we can read all the data back<a name="line.471"></a>
-<span class="sourceLineNo">472</span>      while (rr.nextKeyValue()) {<a name="line.472"></a>
-<span class="sourceLineNo">473</span>        byte[] row = rr.getCurrentKey().get();<a name="line.473"></a>
-<span class="sourceLineNo">474</span>        verifyRowFromMap(rr.getCurrentKey(), rr.getCurrentValue());<a name="line.474"></a>
-<span class="sourceLineNo">475</span>        rowTracker.addRow(row);<a name="line.475"></a>
-<span class="sourceLineNo">476</span>      }<a name="line.476"></a>
-<span class="sourceLineNo">477</span><a name="line.477"></a>
-<span class="sourceLineNo">478</span>      rr.close();<a name="line.478"></a>
-<span class="sourceLineNo">479</span>    }<a name="line.479"></a>
-<span class="sourceLineNo">480</span><a name="line.480"></a>
-<span class="sourceLineNo">481</span>    // validate all rows are seen<a name="line.481"></a>
-<span class="sourceLineNo">482</span>    rowTracker.validate();<a name="line.482"></a>
-<span class="sourceLineNo">483</span>  }<a name="line.483"></a>
-<span class="sourceLineNo">484</span><a name="line.484"></a>
-<span class="sourceLineNo">485</span>  @Override<a name="line.485"></a>
-<span class="sourceLineNo">486</span>  protected void testWithMapReduceImpl(HBaseTestingUtil util, TableName tableName,<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      String snapshotName, Path tableDir, int numRegions, int numSplitsPerRegion,<a name="line.487"></a>
-<span class="sourceLineNo">488</span>      int expectedNumSplits, boolean shutdownCluster) throws Exception {<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    doTestWithMapReduce(util, tableName, snapshotName, getStartRow(), getEndRow(), tableDir,<a name="line.489"></a>
-<span class="sourceLineNo">490</span>      numRegions, numSplitsPerRegion, expectedNumSplits, shutdownCluster);<a name="line.490"></a>
-<span class="sourceLineNo">491</span>  }<a name="line.491"></a>
-<span class="sourceLineNo">492</span><a name="line.492"></a>
-<span class="sourceLineNo">493</span>  // this is also called by the IntegrationTestTableSnapshotInputFormat<a name="line.493"></a>
-<span class="sourceLineNo">494</span>  public static void doTestWithMapReduce(HBaseTestingUtil util, TableName tableName,<a name="line.494"></a>
-<span class="sourceLineNo">495</span>      String snapshotName, byte[] startRow, byte[] endRow, Path tableDir, int numRegions,<a name="line.495"></a>
-<span class="sourceLineNo">496</span>      int numSplitsPerRegion, int expectedNumSplits, boolean shutdownCluster) throws Exception {<a name="line.496"></a>
-<span class="sourceLineNo">497</span><a name="line.497"></a>
-<span class="sourceLineNo">498</span>    LOG.info("testing with MapReduce");<a name="line.498"></a>
-<span class="sourceLineNo">499</span><a name="line.499"></a>
-<span class="sourceLineNo">500</span>    LOG.info("create the table and snapshot");<a name="line.500"></a>
-<span class="sourceLineNo">501</span>    createTableAndSnapshot(util, tableName, snapshotName, startRow, endRow, numRegions);<a name="line.501"></a>
-<span class="sourceLineNo">502</span><a name="line.502"></a>
-<span class="sourceLineNo">503</span>    if (shutdownCluster) {<a name="line.503"></a>
-<span class="sourceLineNo">504</span>      LOG.info("shutting down hbase cluster.");<a name="line.504"></a>
-<span class="sourceLineNo">505</span>      util.shutdownMiniHBaseCluster();<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    }<a name="line.506"></a>
-<span class="sourceLineNo">507</span><a name="line.507"></a>
-<span class="sourceLineNo">508</span>    try {<a name="line.508"></a>
-<span class="sourceLineNo">509</span>      // create the job<a name="line.509"></a>
-<span class="sourceLineNo">510</span>      Job job = new Job(util.getConfiguration());<a name="line.510"></a>
-<span class="sourceLineNo">511</span>      Scan scan = new Scan().withStartRow(startRow).withStopRow(endRow); // limit the scan<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span>      job.setJarByClass(util.getClass());<a name="line.513"></a>
-<span class="sourceLineNo">514</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.514"></a>
-<span class="sourceLineNo">515</span>              TestTableSnapshotInputFormat.class);<a name="line.515"></a>
-<span class="sourceLineNo">516</span><a name="line.516"></a>
-<span class="sourceLineNo">517</span>      if (numSplitsPerRegion &gt; 1) {<a name="line.517"></a>
-<span class="sourceLineNo">518</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.518"></a>
-<span class="sourceLineNo">519</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.519"></a>
-<span class="sourceLineNo">520</span>                NullWritable.class, job, true, tableDir, new RegionSplitter.UniformSplit(),<a name="line.520"></a>
-<span class="sourceLineNo">521</span>                numSplitsPerRegion);<a name="line.521"></a>
-<span class="sourceLineNo">522</span>      } else {<a name="line.522"></a>
-<span class="sourceLineNo">523</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.523"></a>
-<span class="sourceLineNo">524</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.524"></a>
-<span class="sourceLineNo">525</span>                NullWritable.class, job, true, tableDir);<a name="line.525"></a>
-<span class="sourceLineNo">526</span>      }<a name="line.526"></a>
-<span class="sourceLineNo">527</span><a name="line.527"></a>
-<span class="sourceLineNo">528</span>      job.setReducerClass(TestTableSnapshotInputFormat.TestTableSnapshotReducer.class);<a name="line.528"></a>
-<span class="sourceLineNo">529</span>      job.setNumReduceTasks(1);<a name="line.529"></a>
-<span class="sourceLineNo">530</span>      job.setOutputFormatClass(NullOutputFormat.class);<a name="line.530"></a>
-<span class="sourceLineNo">531</span><a name="line.531"></a>
-<span class="sourceLineNo">532</span>      Assert.assertTrue(job.waitForCompletion(true));<a name="line.532"></a>
-<span class="sourceLineNo">533</span>    } finally {<a name="line.533"></a>
-<span class="sourceLineNo">534</span>      if (!shutdownCluster) {<a name="line.534"></a>
-<span class="sourceLineNo">535</span>        util.getAdmin().deleteSnapshot(snapshotName);<a name="line.535"></a>
-<span class="sourceLineNo">536</span>        util.deleteTable(tableName);<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      }<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    }<a name="line.538"></a>
-<span class="sourceLineNo">539</span>  }<a name="line.539"></a>
+<span class="sourceLineNo">449</span>    Assert.assertEquals(expectedNumSplits, splits.size());<a name="line.449"></a>
+<span class="sourceLineNo">450</span><a name="line.450"></a>
+<span class="sourceLineNo">451</span>    HBaseTestingUtil.SeenRowTracker rowTracker = new HBaseTestingUtil.SeenRowTracker(startRow,<a name="line.451"></a>
+<span class="sourceLineNo">452</span>        stopRow.length &gt; 0 ? stopRow : Bytes.toBytes("\uffff"));<a name="line.452"></a>
+<span class="sourceLineNo">453</span><a name="line.453"></a>
+<span class="sourceLineNo">454</span>    boolean localityEnabled =<a name="line.454"></a>
+<span class="sourceLineNo">455</span>        job.getConfiguration().getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY,<a name="line.455"></a>
+<span class="sourceLineNo">456</span>                                          SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT);<a name="line.456"></a>
+<span class="sourceLineNo">457</span><a name="line.457"></a>
+<span class="sourceLineNo">458</span>    boolean byRegionLoc =<a name="line.458"></a>
+<span class="sourceLineNo">459</span>      job.getConfiguration().getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.459"></a>
+<span class="sourceLineNo">460</span>                                        SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.460"></a>
+<span class="sourceLineNo">461</span>    for (int i = 0; i &lt; splits.size(); i++) {<a name="line.461"></a>
+<span class="sourceLineNo">462</span>      // validate input split<a name="line.462"></a>
+<span class="sourceLineNo">463</span>      InputSplit split = splits.get(i);<a name="line.463"></a>
+<span class="sourceLineNo">464</span>      Assert.assertTrue(split instanceof TableSnapshotRegionSplit);<a name="line.464"></a>
+<span class="sourceLineNo">465</span>      TableSnapshotRegionSplit snapshotRegionSplit = (TableSnapshotRegionSplit) split;<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      if (localityEnabled) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>        Assert.assertTrue(split.getLocations() != null &amp;&amp; split.getLocations().length != 0);<a name="line.467"></a>
+<span class="sourceLineNo">468</span>        if (byRegionLoc) {<a name="line.468"></a>
+<span class="sourceLineNo">469</span>          // When it uses region location from meta, the hostname will be "localhost",<a name="line.469"></a>
+<span class="sourceLineNo">470</span>          // the location from hdfs block location is "127.0.0.1".<a name="line.470"></a>
+<span class="sourceLineNo">471</span>          Assert.assertEquals(1, split.getLocations().length);<a name="line.471"></a>
+<span class="sourceLineNo">472</span>          Assert.assertTrue("Not using region location!",<a name="line.472"></a>
+<span class="sourceLineNo">473</span>            split.getLocations()[0].equals("localhost"));<a name="line.473"></a>
+<span class="sourceLineNo">474</span>        } else {<a name="line.474"></a>
+<span class="sourceLineNo">475</span>          Assert.assertTrue("Not using region location!",<a name="line.475"></a>
+<span class="sourceLineNo">476</span>            split.getLocations()[0].equals("127.0.0.1"));<a name="line.476"></a>
+<span class="sourceLineNo">477</span>        }<a name="line.477"></a>
+<span class="sourceLineNo">478</span>      } else {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>        Assert.assertTrue(split.getLocations() != null &amp;&amp; split.getLocations().length == 0);<a name="line.479"></a>
+<span class="sourceLineNo">480</span>      }<a name="line.480"></a>
+<span class="sourceLineNo">481</span><a name="line.481"></a>
+<span class="sourceLineNo">482</span>      Scan scan =<a name="line.482"></a>
+<span class="sourceLineNo">483</span>          TableMapReduceUtil.convertStringToScan(snapshotRegionSplit.getDelegate().getScan());<a name="line.483"></a>
+<span class="sourceLineNo">484</span>      if (startRow.length &gt; 0) {<a name="line.484"></a>
+<span class="sourceLineNo">485</span>        Assert.assertTrue(<a name="line.485"></a>
+<span class="sourceLineNo">486</span>          Bytes.toStringBinary(startRow) + " should &lt;= " + Bytes.toStringBinary(scan.getStartRow()),<a name="line.486"></a>
+<span class="sourceLineNo">487</span>          Bytes.compareTo(startRow, scan.getStartRow()) &lt;= 0);<a name="line.487"></a>
+<span class="sourceLineNo">488</span>      }<a name="line.488"></a>
+<span class="sourceLineNo">489</span>      if (stopRow.length &gt; 0) {<a name="line.489"></a>
+<span class="sourceLineNo">490</span>        Assert.assertTrue(<a name="line.490"></a>
+<span class="sourceLineNo">491</span>          Bytes.toStringBinary(stopRow) + " should &gt;= " + Bytes.toStringBinary(scan.getStopRow()),<a name="line.491"></a>
+<span class="sourceLineNo">492</span>          Bytes.compareTo(stopRow, scan.getStopRow()) &gt;= 0);<a name="line.492"></a>
+<span class="sourceLineNo">493</span>      }<a name="line.493"></a>
+<span class="sourceLineNo">494</span>      Assert.assertTrue("startRow should &lt; stopRow",<a name="line.494"></a>
+<span class="sourceLineNo">495</span>        Bytes.compareTo(scan.getStartRow(), scan.getStopRow()) &lt; 0);<a name="line.495"></a>
+<span class="sourceLineNo">496</span><a name="line.496"></a>
+<span class="sourceLineNo">497</span>      // validate record reader<a name="line.497"></a>
+<span class="sourceLineNo">498</span>      TaskAttemptContext taskAttemptContext = mock(TaskAttemptContext.class);<a name="line.498"></a>
+<span class="sourceLineNo">499</span>      when(taskAttemptContext.getConfiguration()).thenReturn(job.getConfiguration());<a name="line.499"></a>
+<span class="sourceLineNo">500</span>      RecordReader&lt;ImmutableBytesWritable, Result&gt; rr =<a name="line.500"></a>
+<span class="sourceLineNo">501</span>          tsif.createRecordReader(split, taskAttemptContext);<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      rr.initialize(split, taskAttemptContext);<a name="line.502"></a>
+<span class="sourceLineNo">503</span><a name="line.503"></a>
+<span class="sourceLineNo">504</span>      // validate we can read all the data back<a name="line.504"></a>
+<span class="sourceLineNo">505</span>      while (rr.nextKeyValue()) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span>        byte[] row = rr.getCurrentKey().get();<a name="line.506"></a>
+<span class="sourceLineNo">507</span>        verifyRowFromMap(rr.getCurrentKey(), rr.getCurrentValue());<a name="line.507"></a>
+<span class="sourceLineNo">508</span>        rowTracker.addRow(row);<a name="line.508"></a>
+<span class="sourceLineNo">509</span>      }<a name="line.509"></a>
+<span class="sourceLineNo">510</span><a name="line.510"></a>
+<span class="sourceLineNo">511</span>      rr.close();<a name="line.511"></a>
+<span class="sourceLineNo">512</span>    }<a name="line.512"></a>
+<span class="sourceLineNo">513</span><a name="line.513"></a>
+<span class="sourceLineNo">514</span>    // validate all rows are seen<a name="line.514"></a>
+<span class="sourceLineNo">515</span>    rowTracker.validate();<a name="line.515"></a>
+<span class="sourceLineNo">516</span>  }<a name="line.516"></a>
+<span class="sourceLineNo">517</span><a name="line.517"></a>
+<span class="sourceLineNo">518</span>  @Override<a name="line.518"></a>
+<span class="sourceLineNo">519</span>  protected void testWithMapReduceImpl(HBaseTestingUtil util, TableName tableName,<a name="line.519"></a>
+<span class="sourceLineNo">520</span>      String snapshotName, Path tableDir, int numRegions, int numSplitsPerRegion,<a name="line.520"></a>
+<span class="sourceLineNo">521</span>      int expectedNumSplits, boolean shutdownCluster) throws Exception {<a name="line.521"></a>
+<span class="sourceLineNo">522</span>    doTestWithMapReduce(util, tableName, snapshotName, getStartRow(), getEndRow(), tableDir,<a name="line.522"></a>
+<span class="sourceLineNo">523</span>      numRegions, numSplitsPerRegion, expectedNumSplits, shutdownCluster);<a name="line.523"></a>
+<span class="sourceLineNo">524</span>  }<a name="line.524"></a>
+<span class="sourceLineNo">525</span><a name="line.525"></a>
+<span class="sourceLineNo">526</span>  // this is also called by the IntegrationTestTableSnapshotInputFormat<a name="line.526"></a>
+<span class="sourceLineNo">527</span>  public static void doTestWithMapReduce(HBaseTestingUtil util, TableName tableName,<a name="line.527"></a>
+<span class="sourceLineNo">528</span>      String snapshotName, byte[] startRow, byte[] endRow, Path tableDir, int numRegions,<a name="line.528"></a>
+<span class="sourceLineNo">529</span>      int numSplitsPerRegion, int expectedNumSplits, boolean shutdownCluster) throws Exception {<a name="line.529"></a>
+<span class="sourceLineNo">530</span><a name="line.530"></a>
+<span class="sourceLineNo">531</span>    LOG.info("testing with MapReduce");<a name="line.531"></a>
+<span class="sourceLineNo">532</span><a name="line.532"></a>
+<span class="sourceLineNo">533</span>    LOG.info("create the table and snapshot");<a name="line.533"></a>
+<span class="sourceLineNo">534</span>    createTableAndSnapshot(util, tableName, snapshotName, startRow, endRow, numRegions);<a name="line.534"></a>
+<span class="sourceLineNo">535</span><a name="line.535"></a>
+<span class="sourceLineNo">536</span>    if (shutdownCluster) {<a name="line.536"></a>
+<span class="sourceLineNo">537</span>      LOG.info("shutting down hbase cluster.");<a name="line.537"></a>
+<span class="sourceLineNo">538</span>      util.shutdownMiniHBaseCluster();<a name="line.538"></a>
+<span class="sourceLineNo">539</span>    }<a name="line.539"></a>
 <span class="sourceLineNo">540</span><a name="line.540"></a>
-<span class="sourceLineNo">541</span>  @Test<a name="line.541"></a>
-<span class="sourceLineNo">542</span>  public void testWithMapReduceMultipleMappersPerRegion() throws Exception {<a name="line.542"></a>
-<span class="sourceLineNo">543</span>    testWithMapReduce(UTIL, "testWithMapReduceMultiRegion", 10, 5, 50, false);<a name="line.543"></a>
-<span class="sourceLineNo">544</span>  }<a name="line.544"></a>
-<span class="sourceLineNo">545</span>}<a name="line.545"></a>
+<span class="sourceLineNo">541</span>    try {<a name="line.541"></a>
+<span class="sourceLineNo">542</span>      // create the job<a name="line.542"></a>
+<span class="sourceLineNo">543</span>      Job job = new Job(util.getConfiguration());<a name="line.543"></a>
+<span class="sourceLineNo">544</span>      Scan scan = new Scan().withStartRow(startRow).withStopRow(endRow); // limit the scan<a name="line.544"></a>
+<span class="sourceLineNo">545</span><a name="line.545"></a>
+<span class="sourceLineNo">546</span>      job.setJarByClass(util.getClass());<a name="line.546"></a>
+<span class="sourceLineNo">547</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.547"></a>
+<span class="sourceLineNo">548</span>              TestTableSnapshotInputFormat.class);<a name="line.548"></a>
+<span class="sourceLineNo">549</span><a name="line.549"></a>
+<span class="sourceLineNo">550</span>      if (numSplitsPerRegion &gt; 1) {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.551"></a>
+<span class="sourceLineNo">552</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.552"></a>
+<span class="sourceLineNo">553</span>                NullWritable.class, job, true, tableDir, new RegionSplitter.UniformSplit(),<a name="line.553"></a>
+<span class="sourceLineNo">554</span>                numSplitsPerRegion);<a name="line.554"></a>
+<span class="sourceLineNo">555</span>      } else {<a name="line.555"></a>
+<span class="sourceLineNo">556</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.556"></a>
+<span class="sourceLineNo">557</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.557"></a>
+<span class="sourceLineNo">558</span>                NullWritable.class, job, true, tableDir);<a name="line.558"></a>
+<span class="sourceLineNo">559</span>      }<a name="line.559"></a>
+<span class="sourceLineNo">560</span><a name="line.560"></a>
+<span class="sourceLineNo">561</span>      job.setReducerClass(TestTableSnapshotInputFormat.TestTableSnapshotReducer.class);<a name="line.561"></a>
+<span class="sourceLineNo">562</span>      job.setNumReduceTasks(1);<a name="line.562"></a>
+<span class="sourceLineNo">563</span>      job.setOutputFormatClass(NullOutputFormat.class);<a name="line.563"></a>
+<span class="sourceLineNo">564</span><a name="line.564"></a>
+<span class="sourceLineNo">565</span>      Assert.assertTrue(job.waitForCompletion(true));<a name="line.565"></a>
+<span class="sourceLineNo">566</span>    } finally {<a name="line.566"></a>
+<span class="sourceLineNo">567</span>      if (!shutdownCluster) {<a name="line.567"></a>
+<span class="sourceLineNo">568</span>        util.getAdmin().deleteSnapshot(snapshotName);<a name="line.568"></a>
+<span class="sourceLineNo">569</span>        util.deleteTable(tableName);<a name="line.569"></a>
+<span class="sourceLineNo">570</span>      }<a name="line.570"></a>
+<span class="sourceLineNo">571</span>    }<a name="line.571"></a>
+<span class="sourceLineNo">572</span>  }<a name="line.572"></a>
+<span class="sourceLineNo">573</span><a name="line.573"></a>
+<span class="sourceLineNo">574</span>  @Test<a name="line.574"></a>
+<span class="sourceLineNo">575</span>  public void testWithMapReduceMultipleMappersPerRegion() throws Exception {<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    testWithMapReduce(UTIL, "testWithMapReduceMultiRegion", 10, 5, 50, false);<a name="line.576"></a>
+<span class="sourceLineNo">577</span>  }<a name="line.577"></a>
+<span class="sourceLineNo">578</span>}<a name="line.578"></a>
 
 
 
diff --git a/testdevapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html b/testdevapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html
index 8d67eec..82673a9 100644
--- a/testdevapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html
+++ b/testdevapidocs/src-html/org/apache/hadoop/hbase/mapreduce/TestTableSnapshotInputFormat.html
@@ -30,527 +30,560 @@
 <span class="sourceLineNo">022</span>import static org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT;<a name="line.22"></a>
 <span class="sourceLineNo">023</span>import static org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION;<a name="line.23"></a>
 <span class="sourceLineNo">024</span>import static org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT;<a name="line.24"></a>
-<span class="sourceLineNo">025</span>import static org.mockito.Mockito.mock;<a name="line.25"></a>
-<span class="sourceLineNo">026</span>import static org.mockito.Mockito.when;<a name="line.26"></a>
-<span class="sourceLineNo">027</span><a name="line.27"></a>
-<span class="sourceLineNo">028</span>import java.io.IOException;<a name="line.28"></a>
-<span class="sourceLineNo">029</span>import java.util.Arrays;<a name="line.29"></a>
-<span class="sourceLineNo">030</span>import java.util.List;<a name="line.30"></a>
-<span class="sourceLineNo">031</span>import org.apache.hadoop.conf.Configuration;<a name="line.31"></a>
-<span class="sourceLineNo">032</span>import org.apache.hadoop.fs.FileSystem;<a name="line.32"></a>
-<span class="sourceLineNo">033</span>import org.apache.hadoop.fs.Path;<a name="line.33"></a>
-<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.34"></a>
-<span class="sourceLineNo">035</span>import org.apache.hadoop.hbase.HBaseTestingUtil;<a name="line.35"></a>
-<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.HConstants;<a name="line.36"></a>
-<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.HDFSBlocksDistribution;<a name="line.37"></a>
-<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.TableName;<a name="line.38"></a>
-<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.client.Admin;<a name="line.39"></a>
-<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.client.Result;<a name="line.40"></a>
-<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.client.Scan;<a name="line.41"></a>
-<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.client.Table;<a name="line.42"></a>
-<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.client.TestTableSnapshotScanner;<a name="line.43"></a>
-<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<a name="line.44"></a>
-<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormat.TableSnapshotRegionSplit;<a name="line.45"></a>
-<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.snapshot.SnapshotTestingUtils;<a name="line.46"></a>
-<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.testclassification.LargeTests;<a name="line.47"></a>
-<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.testclassification.VerySlowMapReduceTests;<a name="line.48"></a>
-<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.49"></a>
-<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.50"></a>
-<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.util.RegionSplitter;<a name="line.51"></a>
-<span class="sourceLineNo">052</span>import org.apache.hadoop.io.NullWritable;<a name="line.52"></a>
-<span class="sourceLineNo">053</span>import org.apache.hadoop.mapreduce.InputSplit;<a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.apache.hadoop.mapreduce.Job;<a name="line.54"></a>
-<span class="sourceLineNo">055</span>import org.apache.hadoop.mapreduce.RecordReader;<a name="line.55"></a>
-<span class="sourceLineNo">056</span>import org.apache.hadoop.mapreduce.Reducer;<a name="line.56"></a>
-<span class="sourceLineNo">057</span>import org.apache.hadoop.mapreduce.TaskAttemptContext;<a name="line.57"></a>
-<span class="sourceLineNo">058</span>import org.apache.hadoop.mapreduce.lib.output.NullOutputFormat;<a name="line.58"></a>
-<span class="sourceLineNo">059</span>import org.junit.Assert;<a name="line.59"></a>
-<span class="sourceLineNo">060</span>import org.junit.ClassRule;<a name="line.60"></a>
-<span class="sourceLineNo">061</span>import org.junit.Rule;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>import org.junit.Test;<a name="line.62"></a>
-<span class="sourceLineNo">063</span>import org.junit.experimental.categories.Category;<a name="line.63"></a>
-<span class="sourceLineNo">064</span>import org.junit.rules.TestName;<a name="line.64"></a>
-<span class="sourceLineNo">065</span>import org.slf4j.Logger;<a name="line.65"></a>
-<span class="sourceLineNo">066</span>import org.slf4j.LoggerFactory;<a name="line.66"></a>
-<span class="sourceLineNo">067</span><a name="line.67"></a>
-<span class="sourceLineNo">068</span>import org.apache.hbase.thirdparty.com.google.common.collect.Lists;<a name="line.68"></a>
-<span class="sourceLineNo">069</span><a name="line.69"></a>
-<span class="sourceLineNo">070</span>@Category({VerySlowMapReduceTests.class, LargeTests.class})<a name="line.70"></a>
-<span class="sourceLineNo">071</span>public class TestTableSnapshotInputFormat extends TableSnapshotInputFormatTestBase {<a name="line.71"></a>
+<span class="sourceLineNo">025</span>import static org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormatImpl.SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE;<a name="line.25"></a>
+<span class="sourceLineNo">026</span>import static org.junit.Assert.assertEquals;<a name="line.26"></a>
+<span class="sourceLineNo">027</span>import static org.mockito.Mockito.mock;<a name="line.27"></a>
+<span class="sourceLineNo">028</span>import static org.mockito.Mockito.when;<a name="line.28"></a>
+<span class="sourceLineNo">029</span><a name="line.29"></a>
+<span class="sourceLineNo">030</span>import java.io.IOException;<a name="line.30"></a>
+<span class="sourceLineNo">031</span>import java.util.Arrays;<a name="line.31"></a>
+<span class="sourceLineNo">032</span>import java.util.List;<a name="line.32"></a>
+<span class="sourceLineNo">033</span>import org.apache.hadoop.conf.Configuration;<a name="line.33"></a>
+<span class="sourceLineNo">034</span>import org.apache.hadoop.fs.FileSystem;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.fs.Path;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.hbase.HBaseClassTestRule;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.hbase.HBaseTestingUtil;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.hadoop.hbase.HConstants;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.apache.hadoop.hbase.HDFSBlocksDistribution;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.apache.hadoop.hbase.TableName;<a name="line.40"></a>
+<span class="sourceLineNo">041</span>import org.apache.hadoop.hbase.client.Admin;<a name="line.41"></a>
+<span class="sourceLineNo">042</span>import org.apache.hadoop.hbase.client.Result;<a name="line.42"></a>
+<span class="sourceLineNo">043</span>import org.apache.hadoop.hbase.client.Scan;<a name="line.43"></a>
+<span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.client.Scan.ReadType;<a name="line.44"></a>
+<span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.client.Table;<a name="line.45"></a>
+<span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.client.TestTableSnapshotScanner;<a name="line.46"></a>
+<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.mapreduce.TableSnapshotInputFormat.TableSnapshotRegionSplit;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.snapshot.SnapshotTestingUtils;<a name="line.49"></a>
+<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.testclassification.LargeTests;<a name="line.50"></a>
+<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.testclassification.VerySlowMapReduceTests;<a name="line.51"></a>
+<span class="sourceLineNo">052</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.52"></a>
+<span class="sourceLineNo">053</span>import org.apache.hadoop.hbase.util.CommonFSUtils;<a name="line.53"></a>
+<span class="sourceLineNo">054</span>import org.apache.hadoop.hbase.util.RegionSplitter;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>import org.apache.hadoop.io.NullWritable;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>import org.apache.hadoop.mapreduce.InputSplit;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>import org.apache.hadoop.mapreduce.Job;<a name="line.57"></a>
+<span class="sourceLineNo">058</span>import org.apache.hadoop.mapreduce.RecordReader;<a name="line.58"></a>
+<span class="sourceLineNo">059</span>import org.apache.hadoop.mapreduce.Reducer;<a name="line.59"></a>
+<span class="sourceLineNo">060</span>import org.apache.hadoop.mapreduce.TaskAttemptContext;<a name="line.60"></a>
+<span class="sourceLineNo">061</span>import org.apache.hadoop.mapreduce.lib.output.NullOutputFormat;<a name="line.61"></a>
+<span class="sourceLineNo">062</span>import org.junit.Assert;<a name="line.62"></a>
+<span class="sourceLineNo">063</span>import org.junit.ClassRule;<a name="line.63"></a>
+<span class="sourceLineNo">064</span>import org.junit.Rule;<a name="line.64"></a>
+<span class="sourceLineNo">065</span>import org.junit.Test;<a name="line.65"></a>
+<span class="sourceLineNo">066</span>import org.junit.experimental.categories.Category;<a name="line.66"></a>
+<span class="sourceLineNo">067</span>import org.junit.rules.TestName;<a name="line.67"></a>
+<span class="sourceLineNo">068</span>import org.slf4j.Logger;<a name="line.68"></a>
+<span class="sourceLineNo">069</span>import org.slf4j.LoggerFactory;<a name="line.69"></a>
+<span class="sourceLineNo">070</span><a name="line.70"></a>
+<span class="sourceLineNo">071</span>import org.apache.hbase.thirdparty.com.google.common.collect.Lists;<a name="line.71"></a>
 <span class="sourceLineNo">072</span><a name="line.72"></a>
-<span class="sourceLineNo">073</span>  @ClassRule<a name="line.73"></a>
-<span class="sourceLineNo">074</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.74"></a>
-<span class="sourceLineNo">075</span>      HBaseClassTestRule.forClass(TestTableSnapshotInputFormat.class);<a name="line.75"></a>
-<span class="sourceLineNo">076</span><a name="line.76"></a>
-<span class="sourceLineNo">077</span>  private static final Logger LOG = LoggerFactory.getLogger(TestTableSnapshotInputFormat.class);<a name="line.77"></a>
-<span class="sourceLineNo">078</span><a name="line.78"></a>
-<span class="sourceLineNo">079</span>  private static final byte[] bbb = Bytes.toBytes("bbb");<a name="line.79"></a>
-<span class="sourceLineNo">080</span>  private static final byte[] yyy = Bytes.toBytes("yyy");<a name="line.80"></a>
-<span class="sourceLineNo">081</span>  private static final byte[] bbc = Bytes.toBytes("bbc");<a name="line.81"></a>
-<span class="sourceLineNo">082</span>  private static final byte[] yya = Bytes.toBytes("yya");<a name="line.82"></a>
-<span class="sourceLineNo">083</span><a name="line.83"></a>
-<span class="sourceLineNo">084</span>  @Rule<a name="line.84"></a>
-<span class="sourceLineNo">085</span>  public TestName name = new TestName();<a name="line.85"></a>
+<span class="sourceLineNo">073</span>@Category({VerySlowMapReduceTests.class, LargeTests.class})<a name="line.73"></a>
+<span class="sourceLineNo">074</span>public class TestTableSnapshotInputFormat extends TableSnapshotInputFormatTestBase {<a name="line.74"></a>
+<span class="sourceLineNo">075</span><a name="line.75"></a>
+<span class="sourceLineNo">076</span>  @ClassRule<a name="line.76"></a>
+<span class="sourceLineNo">077</span>  public static final HBaseClassTestRule CLASS_RULE =<a name="line.77"></a>
+<span class="sourceLineNo">078</span>      HBaseClassTestRule.forClass(TestTableSnapshotInputFormat.class);<a name="line.78"></a>
+<span class="sourceLineNo">079</span><a name="line.79"></a>
+<span class="sourceLineNo">080</span>  private static final Logger LOG = LoggerFactory.getLogger(TestTableSnapshotInputFormat.class);<a name="line.80"></a>
+<span class="sourceLineNo">081</span><a name="line.81"></a>
+<span class="sourceLineNo">082</span>  private static final byte[] bbb = Bytes.toBytes("bbb");<a name="line.82"></a>
+<span class="sourceLineNo">083</span>  private static final byte[] yyy = Bytes.toBytes("yyy");<a name="line.83"></a>
+<span class="sourceLineNo">084</span>  private static final byte[] bbc = Bytes.toBytes("bbc");<a name="line.84"></a>
+<span class="sourceLineNo">085</span>  private static final byte[] yya = Bytes.toBytes("yya");<a name="line.85"></a>
 <span class="sourceLineNo">086</span><a name="line.86"></a>
-<span class="sourceLineNo">087</span>  @Override<a name="line.87"></a>
-<span class="sourceLineNo">088</span>  protected byte[] getStartRow() {<a name="line.88"></a>
-<span class="sourceLineNo">089</span>    return bbb;<a name="line.89"></a>
-<span class="sourceLineNo">090</span>  }<a name="line.90"></a>
-<span class="sourceLineNo">091</span><a name="line.91"></a>
-<span class="sourceLineNo">092</span>  @Override<a name="line.92"></a>
-<span class="sourceLineNo">093</span>  protected byte[] getEndRow() {<a name="line.93"></a>
-<span class="sourceLineNo">094</span>    return yyy;<a name="line.94"></a>
-<span class="sourceLineNo">095</span>  }<a name="line.95"></a>
-<span class="sourceLineNo">096</span><a name="line.96"></a>
-<span class="sourceLineNo">097</span><a name="line.97"></a>
-<span class="sourceLineNo">098</span>  @Test<a name="line.98"></a>
-<span class="sourceLineNo">099</span>  public void testGetBestLocations() throws IOException {<a name="line.99"></a>
-<span class="sourceLineNo">100</span>    TableSnapshotInputFormatImpl tsif = new TableSnapshotInputFormatImpl();<a name="line.100"></a>
-<span class="sourceLineNo">101</span>    Configuration conf = UTIL.getConfiguration();<a name="line.101"></a>
-<span class="sourceLineNo">102</span><a name="line.102"></a>
-<span class="sourceLineNo">103</span>    HDFSBlocksDistribution blockDistribution = new HDFSBlocksDistribution();<a name="line.103"></a>
-<span class="sourceLineNo">104</span>    Assert.assertEquals(null,<a name="line.104"></a>
-<span class="sourceLineNo">105</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.105"></a>
-<span class="sourceLineNo">106</span><a name="line.106"></a>
-<span class="sourceLineNo">107</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 1);<a name="line.107"></a>
-<span class="sourceLineNo">108</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.108"></a>
-<span class="sourceLineNo">109</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.109"></a>
-<span class="sourceLineNo">110</span><a name="line.110"></a>
-<span class="sourceLineNo">111</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 1);<a name="line.111"></a>
-<span class="sourceLineNo">112</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.112"></a>
-<span class="sourceLineNo">113</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.113"></a>
-<span class="sourceLineNo">114</span><a name="line.114"></a>
-<span class="sourceLineNo">115</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 1);<a name="line.115"></a>
-<span class="sourceLineNo">116</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.116"></a>
-<span class="sourceLineNo">117</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.117"></a>
-<span class="sourceLineNo">118</span><a name="line.118"></a>
-<span class="sourceLineNo">119</span>    blockDistribution = new HDFSBlocksDistribution();<a name="line.119"></a>
-<span class="sourceLineNo">120</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 10);<a name="line.120"></a>
-<span class="sourceLineNo">121</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 7);<a name="line.121"></a>
-<span class="sourceLineNo">122</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h3"}, 5);<a name="line.122"></a>
-<span class="sourceLineNo">123</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h4"}, 1);<a name="line.123"></a>
-<span class="sourceLineNo">124</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.124"></a>
-<span class="sourceLineNo">125</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.125"></a>
-<span class="sourceLineNo">126</span><a name="line.126"></a>
-<span class="sourceLineNo">127</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 2);<a name="line.127"></a>
-<span class="sourceLineNo">128</span>    Assert.assertEquals(Lists.newArrayList("h1", "h2"),<a name="line.128"></a>
-<span class="sourceLineNo">129</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.129"></a>
-<span class="sourceLineNo">130</span><a name="line.130"></a>
-<span class="sourceLineNo">131</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 3);<a name="line.131"></a>
-<span class="sourceLineNo">132</span>    Assert.assertEquals(Lists.newArrayList("h2", "h1"),<a name="line.132"></a>
-<span class="sourceLineNo">133</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.133"></a>
-<span class="sourceLineNo">134</span><a name="line.134"></a>
-<span class="sourceLineNo">135</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h3"}, 6);<a name="line.135"></a>
-<span class="sourceLineNo">136</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h4"}, 9);<a name="line.136"></a>
+<span class="sourceLineNo">087</span>  @Rule<a name="line.87"></a>
+<span class="sourceLineNo">088</span>  public TestName name = new TestName();<a name="line.88"></a>
+<span class="sourceLineNo">089</span><a name="line.89"></a>
+<span class="sourceLineNo">090</span>  @Override<a name="line.90"></a>
+<span class="sourceLineNo">091</span>  protected byte[] getStartRow() {<a name="line.91"></a>
+<span class="sourceLineNo">092</span>    return bbb;<a name="line.92"></a>
+<span class="sourceLineNo">093</span>  }<a name="line.93"></a>
+<span class="sourceLineNo">094</span><a name="line.94"></a>
+<span class="sourceLineNo">095</span>  @Override<a name="line.95"></a>
+<span class="sourceLineNo">096</span>  protected byte[] getEndRow() {<a name="line.96"></a>
+<span class="sourceLineNo">097</span>    return yyy;<a name="line.97"></a>
+<span class="sourceLineNo">098</span>  }<a name="line.98"></a>
+<span class="sourceLineNo">099</span><a name="line.99"></a>
+<span class="sourceLineNo">100</span><a name="line.100"></a>
+<span class="sourceLineNo">101</span>  @Test<a name="line.101"></a>
+<span class="sourceLineNo">102</span>  public void testGetBestLocations() throws IOException {<a name="line.102"></a>
+<span class="sourceLineNo">103</span>    TableSnapshotInputFormatImpl tsif = new TableSnapshotInputFormatImpl();<a name="line.103"></a>
+<span class="sourceLineNo">104</span>    Configuration conf = UTIL.getConfiguration();<a name="line.104"></a>
+<span class="sourceLineNo">105</span><a name="line.105"></a>
+<span class="sourceLineNo">106</span>    HDFSBlocksDistribution blockDistribution = new HDFSBlocksDistribution();<a name="line.106"></a>
+<span class="sourceLineNo">107</span>    Assert.assertEquals(null,<a name="line.107"></a>
+<span class="sourceLineNo">108</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.108"></a>
+<span class="sourceLineNo">109</span><a name="line.109"></a>
+<span class="sourceLineNo">110</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 1);<a name="line.110"></a>
+<span class="sourceLineNo">111</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.111"></a>
+<span class="sourceLineNo">112</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.112"></a>
+<span class="sourceLineNo">113</span><a name="line.113"></a>
+<span class="sourceLineNo">114</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 1);<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.115"></a>
+<span class="sourceLineNo">116</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.116"></a>
+<span class="sourceLineNo">117</span><a name="line.117"></a>
+<span class="sourceLineNo">118</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 1);<a name="line.118"></a>
+<span class="sourceLineNo">119</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.119"></a>
+<span class="sourceLineNo">120</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.120"></a>
+<span class="sourceLineNo">121</span><a name="line.121"></a>
+<span class="sourceLineNo">122</span>    blockDistribution = new HDFSBlocksDistribution();<a name="line.122"></a>
+<span class="sourceLineNo">123</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h1"}, 10);<a name="line.123"></a>
+<span class="sourceLineNo">124</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 7);<a name="line.124"></a>
+<span class="sourceLineNo">125</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h3"}, 5);<a name="line.125"></a>
+<span class="sourceLineNo">126</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h4"}, 1);<a name="line.126"></a>
+<span class="sourceLineNo">127</span>    Assert.assertEquals(Lists.newArrayList("h1"),<a name="line.127"></a>
+<span class="sourceLineNo">128</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.128"></a>
+<span class="sourceLineNo">129</span><a name="line.129"></a>
+<span class="sourceLineNo">130</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 2);<a name="line.130"></a>
+<span class="sourceLineNo">131</span>    Assert.assertEquals(Lists.newArrayList("h1", "h2"),<a name="line.131"></a>
+<span class="sourceLineNo">132</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.132"></a>
+<span class="sourceLineNo">133</span><a name="line.133"></a>
+<span class="sourceLineNo">134</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h2"}, 3);<a name="line.134"></a>
+<span class="sourceLineNo">135</span>    Assert.assertEquals(Lists.newArrayList("h2", "h1"),<a name="line.135"></a>
+<span class="sourceLineNo">136</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.136"></a>
 <span class="sourceLineNo">137</span><a name="line.137"></a>
-<span class="sourceLineNo">138</span>    Assert.assertEquals(Lists.newArrayList("h2", "h3", "h4"),<a name="line.138"></a>
-<span class="sourceLineNo">139</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.139"></a>
-<span class="sourceLineNo">140</span>  }<a name="line.140"></a>
-<span class="sourceLineNo">141</span><a name="line.141"></a>
-<span class="sourceLineNo">142</span>  public static enum TestTableSnapshotCounters {<a name="line.142"></a>
-<span class="sourceLineNo">143</span>    VALIDATION_ERROR<a name="line.143"></a>
-<span class="sourceLineNo">144</span>  }<a name="line.144"></a>
-<span class="sourceLineNo">145</span><a name="line.145"></a>
-<span class="sourceLineNo">146</span>  public static class TestTableSnapshotMapper<a name="line.146"></a>
-<span class="sourceLineNo">147</span>    extends TableMapper&lt;ImmutableBytesWritable, NullWritable&gt; {<a name="line.147"></a>
-<span class="sourceLineNo">148</span>    @Override<a name="line.148"></a>
-<span class="sourceLineNo">149</span>    protected void map(ImmutableBytesWritable key, Result value,<a name="line.149"></a>
-<span class="sourceLineNo">150</span>        Context context) throws IOException, InterruptedException {<a name="line.150"></a>
-<span class="sourceLineNo">151</span>      // Validate a single row coming from the snapshot, and emit the row key<a name="line.151"></a>
-<span class="sourceLineNo">152</span>      verifyRowFromMap(key, value);<a name="line.152"></a>
-<span class="sourceLineNo">153</span>      context.write(key, NullWritable.get());<a name="line.153"></a>
-<span class="sourceLineNo">154</span>    }<a name="line.154"></a>
-<span class="sourceLineNo">155</span>  }<a name="line.155"></a>
-<span class="sourceLineNo">156</span><a name="line.156"></a>
-<span class="sourceLineNo">157</span>  public static class TestTableSnapshotReducer<a name="line.157"></a>
-<span class="sourceLineNo">158</span>    extends Reducer&lt;ImmutableBytesWritable, NullWritable, NullWritable, NullWritable&gt; {<a name="line.158"></a>
-<span class="sourceLineNo">159</span>    HBaseTestingUtil.SeenRowTracker rowTracker =<a name="line.159"></a>
-<span class="sourceLineNo">160</span>        new HBaseTestingUtil.SeenRowTracker(bbb, yyy);<a name="line.160"></a>
-<span class="sourceLineNo">161</span>    @Override<a name="line.161"></a>
-<span class="sourceLineNo">162</span>    protected void reduce(ImmutableBytesWritable key, Iterable&lt;NullWritable&gt; values,<a name="line.162"></a>
-<span class="sourceLineNo">163</span>       Context context) throws IOException, InterruptedException {<a name="line.163"></a>
-<span class="sourceLineNo">164</span>      rowTracker.addRow(key.get());<a name="line.164"></a>
-<span class="sourceLineNo">165</span>    }<a name="line.165"></a>
-<span class="sourceLineNo">166</span><a name="line.166"></a>
-<span class="sourceLineNo">167</span>    @Override<a name="line.167"></a>
-<span class="sourceLineNo">168</span>    protected void cleanup(Context context) throws IOException,<a name="line.168"></a>
-<span class="sourceLineNo">169</span>        InterruptedException {<a name="line.169"></a>
-<span class="sourceLineNo">170</span>      rowTracker.validate();<a name="line.170"></a>
-<span class="sourceLineNo">171</span>    }<a name="line.171"></a>
-<span class="sourceLineNo">172</span>  }<a name="line.172"></a>
-<span class="sourceLineNo">173</span><a name="line.173"></a>
-<span class="sourceLineNo">174</span>  @Test<a name="line.174"></a>
-<span class="sourceLineNo">175</span>  public void testInitTableSnapshotMapperJobConfig() throws Exception {<a name="line.175"></a>
-<span class="sourceLineNo">176</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.176"></a>
-<span class="sourceLineNo">177</span>    String snapshotName = "foo";<a name="line.177"></a>
-<span class="sourceLineNo">178</span><a name="line.178"></a>
-<span class="sourceLineNo">179</span>    try {<a name="line.179"></a>
-<span class="sourceLineNo">180</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 1);<a name="line.180"></a>
-<span class="sourceLineNo">181</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.181"></a>
-<span class="sourceLineNo">182</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.182"></a>
-<span class="sourceLineNo">183</span><a name="line.183"></a>
-<span class="sourceLineNo">184</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.184"></a>
-<span class="sourceLineNo">185</span>        new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.185"></a>
-<span class="sourceLineNo">186</span>        NullWritable.class, job, false, tmpTableDir);<a name="line.186"></a>
-<span class="sourceLineNo">187</span><a name="line.187"></a>
-<span class="sourceLineNo">188</span>      // TODO: would be better to examine directly the cache instance that results from this<a name="line.188"></a>
-<span class="sourceLineNo">189</span>      // config. Currently this is not possible because BlockCache initialization is static.<a name="line.189"></a>
-<span class="sourceLineNo">190</span>      Assert.assertEquals(<a name="line.190"></a>
-<span class="sourceLineNo">191</span>        "Snapshot job should be configured for default LruBlockCache.",<a name="line.191"></a>
-<span class="sourceLineNo">192</span>        HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT,<a name="line.192"></a>
-<span class="sourceLineNo">193</span>        job.getConfiguration().getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, -1), 0.01);<a name="line.193"></a>
-<span class="sourceLineNo">194</span>      Assert.assertEquals(<a name="line.194"></a>
-<span class="sourceLineNo">195</span>        "Snapshot job should not use BucketCache.",<a name="line.195"></a>
-<span class="sourceLineNo">196</span>        0, job.getConfiguration().getFloat("hbase.bucketcache.size", -1), 0.01);<a name="line.196"></a>
-<span class="sourceLineNo">197</span>    } finally {<a name="line.197"></a>
-<span class="sourceLineNo">198</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.198"></a>
-<span class="sourceLineNo">199</span>      UTIL.deleteTable(tableName);<a name="line.199"></a>
-<span class="sourceLineNo">200</span>    }<a name="line.200"></a>
-<span class="sourceLineNo">201</span>  }<a name="line.201"></a>
-<span class="sourceLineNo">202</span><a name="line.202"></a>
-<span class="sourceLineNo">203</span>  @Test<a name="line.203"></a>
-<span class="sourceLineNo">204</span>  public void testWithMockedMapReduceSingleRegionByRegionLocation() throws Exception {<a name="line.204"></a>
-<span class="sourceLineNo">205</span>    Configuration conf = UTIL.getConfiguration();<a name="line.205"></a>
-<span class="sourceLineNo">206</span>    conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION, true);<a name="line.206"></a>
-<span class="sourceLineNo">207</span>    try {<a name="line.207"></a>
-<span class="sourceLineNo">208</span>      testWithMockedMapReduce(UTIL, name.getMethodName() + "Snapshot", 1, 1, 1,<a name="line.208"></a>
-<span class="sourceLineNo">209</span>        true);<a name="line.209"></a>
-<span class="sourceLineNo">210</span>    } finally {<a name="line.210"></a>
-<span class="sourceLineNo">211</span>      conf.unset(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION);<a name="line.211"></a>
-<span class="sourceLineNo">212</span>    }<a name="line.212"></a>
-<span class="sourceLineNo">213</span>  }<a name="line.213"></a>
-<span class="sourceLineNo">214</span><a name="line.214"></a>
-<span class="sourceLineNo">215</span>  @Override<a name="line.215"></a>
-<span class="sourceLineNo">216</span>  public void testRestoreSnapshotDoesNotCreateBackRefLinksInit(TableName tableName,<a name="line.216"></a>
-<span class="sourceLineNo">217</span>      String snapshotName, Path tmpTableDir) throws Exception {<a name="line.217"></a>
-<span class="sourceLineNo">218</span>    Job job = new Job(UTIL.getConfiguration());<a name="line.218"></a>
-<span class="sourceLineNo">219</span>    TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.219"></a>
-<span class="sourceLineNo">220</span>      new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.220"></a>
-<span class="sourceLineNo">221</span>      NullWritable.class, job, false, tmpTableDir);<a name="line.221"></a>
-<span class="sourceLineNo">222</span>  }<a name="line.222"></a>
-<span class="sourceLineNo">223</span><a name="line.223"></a>
-<span class="sourceLineNo">224</span>  @Override<a name="line.224"></a>
-<span class="sourceLineNo">225</span>  public void testWithMockedMapReduce(HBaseTestingUtil util, String snapshotName,<a name="line.225"></a>
-<span class="sourceLineNo">226</span>      int numRegions, int numSplitsPerRegion, int expectedNumSplits, boolean setLocalityEnabledTo)<a name="line.226"></a>
-<span class="sourceLineNo">227</span>      throws Exception {<a name="line.227"></a>
-<span class="sourceLineNo">228</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.228"></a>
-<span class="sourceLineNo">229</span>    try {<a name="line.229"></a>
-<span class="sourceLineNo">230</span>      createTableAndSnapshot(<a name="line.230"></a>
-<span class="sourceLineNo">231</span>        util, tableName, snapshotName, getStartRow(), getEndRow(), numRegions);<a name="line.231"></a>
-<span class="sourceLineNo">232</span><a name="line.232"></a>
-<span class="sourceLineNo">233</span>      Configuration conf = util.getConfiguration();<a name="line.233"></a>
-<span class="sourceLineNo">234</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, setLocalityEnabledTo);<a name="line.234"></a>
-<span class="sourceLineNo">235</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.235"></a>
-<span class="sourceLineNo">236</span>        SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.236"></a>
-<span class="sourceLineNo">237</span>      Job job = new Job(conf);<a name="line.237"></a>
-<span class="sourceLineNo">238</span>      Path tmpTableDir = util.getDataTestDirOnTestFS(snapshotName);<a name="line.238"></a>
-<span class="sourceLineNo">239</span>      Scan scan = new Scan().withStartRow(getStartRow()).withStopRow(getEndRow()); // limit the scan<a name="line.239"></a>
-<span class="sourceLineNo">240</span><a name="line.240"></a>
-<span class="sourceLineNo">241</span>      if (numSplitsPerRegion &gt; 1) {<a name="line.241"></a>
-<span class="sourceLineNo">242</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.242"></a>
-<span class="sourceLineNo">243</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.243"></a>
-<span class="sourceLineNo">244</span>                NullWritable.class, job, false, tmpTableDir, new RegionSplitter.UniformSplit(),<a name="line.244"></a>
-<span class="sourceLineNo">245</span>                numSplitsPerRegion);<a name="line.245"></a>
-<span class="sourceLineNo">246</span>      } else {<a name="line.246"></a>
-<span class="sourceLineNo">247</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.247"></a>
-<span class="sourceLineNo">248</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.248"></a>
-<span class="sourceLineNo">249</span>                NullWritable.class, job, false, tmpTableDir);<a name="line.249"></a>
-<span class="sourceLineNo">250</span>      }<a name="line.250"></a>
-<span class="sourceLineNo">251</span><a name="line.251"></a>
-<span class="sourceLineNo">252</span>      verifyWithMockedMapReduce(job, numRegions, expectedNumSplits, getStartRow(), getEndRow());<a name="line.252"></a>
-<span class="sourceLineNo">253</span><a name="line.253"></a>
-<span class="sourceLineNo">254</span>    } finally {<a name="line.254"></a>
-<span class="sourceLineNo">255</span>      util.getAdmin().deleteSnapshot(snapshotName);<a name="line.255"></a>
-<span class="sourceLineNo">256</span>      util.deleteTable(tableName);<a name="line.256"></a>
-<span class="sourceLineNo">257</span>    }<a name="line.257"></a>
-<span class="sourceLineNo">258</span>  }<a name="line.258"></a>
-<span class="sourceLineNo">259</span><a name="line.259"></a>
-<span class="sourceLineNo">260</span>  @Test<a name="line.260"></a>
-<span class="sourceLineNo">261</span>  public void testWithMockedMapReduceWithSplitsPerRegion() throws Exception {<a name="line.261"></a>
-<span class="sourceLineNo">262</span>    String snapshotName = "testWithMockedMapReduceMultiRegion";<a name="line.262"></a>
-<span class="sourceLineNo">263</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.263"></a>
-<span class="sourceLineNo">264</span>    try {<a name="line.264"></a>
-<span class="sourceLineNo">265</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 10);<a name="line.265"></a>
-<span class="sourceLineNo">266</span><a name="line.266"></a>
-<span class="sourceLineNo">267</span>      Configuration conf = UTIL.getConfiguration();<a name="line.267"></a>
-<span class="sourceLineNo">268</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, false);<a name="line.268"></a>
-<span class="sourceLineNo">269</span>      Job job = new Job(conf);<a name="line.269"></a>
-<span class="sourceLineNo">270</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.270"></a>
-<span class="sourceLineNo">271</span>      // test scan with startRow and stopRow<a name="line.271"></a>
-<span class="sourceLineNo">272</span>      Scan scan = new Scan().withStartRow(bbc).withStopRow(yya);<a name="line.272"></a>
-<span class="sourceLineNo">273</span><a name="line.273"></a>
-<span class="sourceLineNo">274</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.274"></a>
-<span class="sourceLineNo">275</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.275"></a>
-<span class="sourceLineNo">276</span>        tmpTableDir, new RegionSplitter.UniformSplit(), 5);<a name="line.276"></a>
-<span class="sourceLineNo">277</span><a name="line.277"></a>
-<span class="sourceLineNo">278</span>      verifyWithMockedMapReduce(job, 10, 40, bbc, yya);<a name="line.278"></a>
-<span class="sourceLineNo">279</span>    } finally {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.280"></a>
-<span class="sourceLineNo">281</span>      UTIL.deleteTable(tableName);<a name="line.281"></a>
-<span class="sourceLineNo">282</span>    }<a name="line.282"></a>
-<span class="sourceLineNo">283</span>  }<a name="line.283"></a>
-<span class="sourceLineNo">284</span><a name="line.284"></a>
-<span class="sourceLineNo">285</span>  @Test<a name="line.285"></a>
-<span class="sourceLineNo">286</span>  public void testWithMockedMapReduceWithNoStartRowStopRow() throws Exception {<a name="line.286"></a>
-<span class="sourceLineNo">287</span>    String snapshotName = "testWithMockedMapReduceMultiRegion";<a name="line.287"></a>
-<span class="sourceLineNo">288</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.288"></a>
-<span class="sourceLineNo">289</span>    try {<a name="line.289"></a>
-<span class="sourceLineNo">290</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 10);<a name="line.290"></a>
-<span class="sourceLineNo">291</span><a name="line.291"></a>
-<span class="sourceLineNo">292</span>      Configuration conf = UTIL.getConfiguration();<a name="line.292"></a>
-<span class="sourceLineNo">293</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, false);<a name="line.293"></a>
-<span class="sourceLineNo">294</span>      Job job = new Job(conf);<a name="line.294"></a>
-<span class="sourceLineNo">295</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.295"></a>
-<span class="sourceLineNo">296</span>      // test scan without startRow and stopRow<a name="line.296"></a>
-<span class="sourceLineNo">297</span>      Scan scan2 = new Scan();<a name="line.297"></a>
-<span class="sourceLineNo">298</span><a name="line.298"></a>
-<span class="sourceLineNo">299</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan2,<a name="line.299"></a>
-<span class="sourceLineNo">300</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.300"></a>
-<span class="sourceLineNo">301</span>        tmpTableDir, new RegionSplitter.UniformSplit(), 5);<a name="line.301"></a>
-<span class="sourceLineNo">302</span><a name="line.302"></a>
-<span class="sourceLineNo">303</span>      verifyWithMockedMapReduce(job, 10, 50, HConstants.EMPTY_START_ROW,<a name="line.303"></a>
-<span class="sourceLineNo">304</span>        HConstants.EMPTY_START_ROW);<a name="line.304"></a>
+<span class="sourceLineNo">138</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h3"}, 6);<a name="line.138"></a>
+<span class="sourceLineNo">139</span>    blockDistribution.addHostsAndBlockWeight(new String[] {"h4"}, 9);<a name="line.139"></a>
+<span class="sourceLineNo">140</span><a name="line.140"></a>
+<span class="sourceLineNo">141</span>    Assert.assertEquals(Lists.newArrayList("h2", "h3", "h4"),<a name="line.141"></a>
+<span class="sourceLineNo">142</span>      TableSnapshotInputFormatImpl.getBestLocations(conf, blockDistribution));<a name="line.142"></a>
+<span class="sourceLineNo">143</span>  }<a name="line.143"></a>
+<span class="sourceLineNo">144</span><a name="line.144"></a>
+<span class="sourceLineNo">145</span>  public static enum TestTableSnapshotCounters {<a name="line.145"></a>
+<span class="sourceLineNo">146</span>    VALIDATION_ERROR<a name="line.146"></a>
+<span class="sourceLineNo">147</span>  }<a name="line.147"></a>
+<span class="sourceLineNo">148</span><a name="line.148"></a>
+<span class="sourceLineNo">149</span>  public static class TestTableSnapshotMapper<a name="line.149"></a>
+<span class="sourceLineNo">150</span>    extends TableMapper&lt;ImmutableBytesWritable, NullWritable&gt; {<a name="line.150"></a>
+<span class="sourceLineNo">151</span>    @Override<a name="line.151"></a>
+<span class="sourceLineNo">152</span>    protected void map(ImmutableBytesWritable key, Result value,<a name="line.152"></a>
+<span class="sourceLineNo">153</span>        Context context) throws IOException, InterruptedException {<a name="line.153"></a>
+<span class="sourceLineNo">154</span>      // Validate a single row coming from the snapshot, and emit the row key<a name="line.154"></a>
+<span class="sourceLineNo">155</span>      verifyRowFromMap(key, value);<a name="line.155"></a>
+<span class="sourceLineNo">156</span>      context.write(key, NullWritable.get());<a name="line.156"></a>
+<span class="sourceLineNo">157</span>    }<a name="line.157"></a>
+<span class="sourceLineNo">158</span>  }<a name="line.158"></a>
+<span class="sourceLineNo">159</span><a name="line.159"></a>
+<span class="sourceLineNo">160</span>  public static class TestTableSnapshotReducer<a name="line.160"></a>
+<span class="sourceLineNo">161</span>    extends Reducer&lt;ImmutableBytesWritable, NullWritable, NullWritable, NullWritable&gt; {<a name="line.161"></a>
+<span class="sourceLineNo">162</span>    HBaseTestingUtil.SeenRowTracker rowTracker =<a name="line.162"></a>
+<span class="sourceLineNo">163</span>        new HBaseTestingUtil.SeenRowTracker(bbb, yyy);<a name="line.163"></a>
+<span class="sourceLineNo">164</span>    @Override<a name="line.164"></a>
+<span class="sourceLineNo">165</span>    protected void reduce(ImmutableBytesWritable key, Iterable&lt;NullWritable&gt; values,<a name="line.165"></a>
+<span class="sourceLineNo">166</span>       Context context) throws IOException, InterruptedException {<a name="line.166"></a>
+<span class="sourceLineNo">167</span>      rowTracker.addRow(key.get());<a name="line.167"></a>
+<span class="sourceLineNo">168</span>    }<a name="line.168"></a>
+<span class="sourceLineNo">169</span><a name="line.169"></a>
+<span class="sourceLineNo">170</span>    @Override<a name="line.170"></a>
+<span class="sourceLineNo">171</span>    protected void cleanup(Context context) throws IOException,<a name="line.171"></a>
+<span class="sourceLineNo">172</span>        InterruptedException {<a name="line.172"></a>
+<span class="sourceLineNo">173</span>      rowTracker.validate();<a name="line.173"></a>
+<span class="sourceLineNo">174</span>    }<a name="line.174"></a>
+<span class="sourceLineNo">175</span>  }<a name="line.175"></a>
+<span class="sourceLineNo">176</span><a name="line.176"></a>
+<span class="sourceLineNo">177</span>  @Test<a name="line.177"></a>
+<span class="sourceLineNo">178</span>  public void testInitTableSnapshotMapperJobConfig() throws Exception {<a name="line.178"></a>
+<span class="sourceLineNo">179</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.179"></a>
+<span class="sourceLineNo">180</span>    String snapshotName = "foo";<a name="line.180"></a>
+<span class="sourceLineNo">181</span><a name="line.181"></a>
+<span class="sourceLineNo">182</span>    try {<a name="line.182"></a>
+<span class="sourceLineNo">183</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 1);<a name="line.183"></a>
+<span class="sourceLineNo">184</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.184"></a>
+<span class="sourceLineNo">185</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.185"></a>
+<span class="sourceLineNo">186</span><a name="line.186"></a>
+<span class="sourceLineNo">187</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.187"></a>
+<span class="sourceLineNo">188</span>        new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.188"></a>
+<span class="sourceLineNo">189</span>        NullWritable.class, job, false, tmpTableDir);<a name="line.189"></a>
+<span class="sourceLineNo">190</span><a name="line.190"></a>
+<span class="sourceLineNo">191</span>      // TODO: would be better to examine directly the cache instance that results from this<a name="line.191"></a>
+<span class="sourceLineNo">192</span>      // config. Currently this is not possible because BlockCache initialization is static.<a name="line.192"></a>
+<span class="sourceLineNo">193</span>      Assert.assertEquals(<a name="line.193"></a>
+<span class="sourceLineNo">194</span>        "Snapshot job should be configured for default LruBlockCache.",<a name="line.194"></a>
+<span class="sourceLineNo">195</span>        HConstants.HFILE_BLOCK_CACHE_SIZE_DEFAULT,<a name="line.195"></a>
+<span class="sourceLineNo">196</span>        job.getConfiguration().getFloat(HConstants.HFILE_BLOCK_CACHE_SIZE_KEY, -1), 0.01);<a name="line.196"></a>
+<span class="sourceLineNo">197</span>      Assert.assertEquals(<a name="line.197"></a>
+<span class="sourceLineNo">198</span>        "Snapshot job should not use BucketCache.",<a name="line.198"></a>
+<span class="sourceLineNo">199</span>        0, job.getConfiguration().getFloat("hbase.bucketcache.size", -1), 0.01);<a name="line.199"></a>
+<span class="sourceLineNo">200</span>    } finally {<a name="line.200"></a>
+<span class="sourceLineNo">201</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.201"></a>
+<span class="sourceLineNo">202</span>      UTIL.deleteTable(tableName);<a name="line.202"></a>
+<span class="sourceLineNo">203</span>    }<a name="line.203"></a>
+<span class="sourceLineNo">204</span>  }<a name="line.204"></a>
+<span class="sourceLineNo">205</span><a name="line.205"></a>
+<span class="sourceLineNo">206</span>  @Test<a name="line.206"></a>
+<span class="sourceLineNo">207</span>  public void testWithMockedMapReduceSingleRegionByRegionLocation() throws Exception {<a name="line.207"></a>
+<span class="sourceLineNo">208</span>    Configuration conf = UTIL.getConfiguration();<a name="line.208"></a>
+<span class="sourceLineNo">209</span>    conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION, true);<a name="line.209"></a>
+<span class="sourceLineNo">210</span>    try {<a name="line.210"></a>
+<span class="sourceLineNo">211</span>      testWithMockedMapReduce(UTIL, name.getMethodName() + "Snapshot", 1, 1, 1,<a name="line.211"></a>
+<span class="sourceLineNo">212</span>        true);<a name="line.212"></a>
+<span class="sourceLineNo">213</span>    } finally {<a name="line.213"></a>
+<span class="sourceLineNo">214</span>      conf.unset(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION);<a name="line.214"></a>
+<span class="sourceLineNo">215</span>    }<a name="line.215"></a>
+<span class="sourceLineNo">216</span>  }<a name="line.216"></a>
+<span class="sourceLineNo">217</span><a name="line.217"></a>
+<span class="sourceLineNo">218</span>  @Override<a name="line.218"></a>
+<span class="sourceLineNo">219</span>  public void testRestoreSnapshotDoesNotCreateBackRefLinksInit(TableName tableName,<a name="line.219"></a>
+<span class="sourceLineNo">220</span>      String snapshotName, Path tmpTableDir) throws Exception {<a name="line.220"></a>
+<span class="sourceLineNo">221</span>    Job job = new Job(UTIL.getConfiguration());<a name="line.221"></a>
+<span class="sourceLineNo">222</span>    TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.222"></a>
+<span class="sourceLineNo">223</span>      new Scan(), TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.223"></a>
+<span class="sourceLineNo">224</span>      NullWritable.class, job, false, tmpTableDir);<a name="line.224"></a>
+<span class="sourceLineNo">225</span>  }<a name="line.225"></a>
+<span class="sourceLineNo">226</span><a name="line.226"></a>
+<span class="sourceLineNo">227</span>  @Override<a name="line.227"></a>
+<span class="sourceLineNo">228</span>  public void testWithMockedMapReduce(HBaseTestingUtil util, String snapshotName,<a name="line.228"></a>
+<span class="sourceLineNo">229</span>      int numRegions, int numSplitsPerRegion, int expectedNumSplits, boolean setLocalityEnabledTo)<a name="line.229"></a>
+<span class="sourceLineNo">230</span>      throws Exception {<a name="line.230"></a>
+<span class="sourceLineNo">231</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.231"></a>
+<span class="sourceLineNo">232</span>    try {<a name="line.232"></a>
+<span class="sourceLineNo">233</span>      createTableAndSnapshot(<a name="line.233"></a>
+<span class="sourceLineNo">234</span>        util, tableName, snapshotName, getStartRow(), getEndRow(), numRegions);<a name="line.234"></a>
+<span class="sourceLineNo">235</span><a name="line.235"></a>
+<span class="sourceLineNo">236</span>      Configuration conf = util.getConfiguration();<a name="line.236"></a>
+<span class="sourceLineNo">237</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, setLocalityEnabledTo);<a name="line.237"></a>
+<span class="sourceLineNo">238</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.238"></a>
+<span class="sourceLineNo">239</span>        SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.239"></a>
+<span class="sourceLineNo">240</span>      Job job = new Job(conf);<a name="line.240"></a>
+<span class="sourceLineNo">241</span>      Path tmpTableDir = util.getDataTestDirOnTestFS(snapshotName);<a name="line.241"></a>
+<span class="sourceLineNo">242</span>      Scan scan = new Scan().withStartRow(getStartRow()).withStopRow(getEndRow()); // limit the scan<a name="line.242"></a>
+<span class="sourceLineNo">243</span><a name="line.243"></a>
+<span class="sourceLineNo">244</span>      if (numSplitsPerRegion &gt; 1) {<a name="line.244"></a>
+<span class="sourceLineNo">245</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.245"></a>
+<span class="sourceLineNo">246</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.246"></a>
+<span class="sourceLineNo">247</span>                NullWritable.class, job, false, tmpTableDir, new RegionSplitter.UniformSplit(),<a name="line.247"></a>
+<span class="sourceLineNo">248</span>                numSplitsPerRegion);<a name="line.248"></a>
+<span class="sourceLineNo">249</span>      } else {<a name="line.249"></a>
+<span class="sourceLineNo">250</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.250"></a>
+<span class="sourceLineNo">251</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.251"></a>
+<span class="sourceLineNo">252</span>                NullWritable.class, job, false, tmpTableDir);<a name="line.252"></a>
+<span class="sourceLineNo">253</span>      }<a name="line.253"></a>
+<span class="sourceLineNo">254</span><a name="line.254"></a>
+<span class="sourceLineNo">255</span>      verifyWithMockedMapReduce(job, numRegions, expectedNumSplits, getStartRow(), getEndRow());<a name="line.255"></a>
+<span class="sourceLineNo">256</span><a name="line.256"></a>
+<span class="sourceLineNo">257</span>    } finally {<a name="line.257"></a>
+<span class="sourceLineNo">258</span>      util.getAdmin().deleteSnapshot(snapshotName);<a name="line.258"></a>
+<span class="sourceLineNo">259</span>      util.deleteTable(tableName);<a name="line.259"></a>
+<span class="sourceLineNo">260</span>    }<a name="line.260"></a>
+<span class="sourceLineNo">261</span>  }<a name="line.261"></a>
+<span class="sourceLineNo">262</span><a name="line.262"></a>
+<span class="sourceLineNo">263</span>  @Test<a name="line.263"></a>
+<span class="sourceLineNo">264</span>  public void testWithMockedMapReduceWithSplitsPerRegion() throws Exception {<a name="line.264"></a>
+<span class="sourceLineNo">265</span>    String snapshotName = "testWithMockedMapReduceMultiRegion";<a name="line.265"></a>
+<span class="sourceLineNo">266</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.266"></a>
+<span class="sourceLineNo">267</span>    try {<a name="line.267"></a>
+<span class="sourceLineNo">268</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 10);<a name="line.268"></a>
+<span class="sourceLineNo">269</span><a name="line.269"></a>
+<span class="sourceLineNo">270</span>      Configuration conf = UTIL.getConfiguration();<a name="line.270"></a>
+<span class="sourceLineNo">271</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, false);<a name="line.271"></a>
+<span class="sourceLineNo">272</span>      Job job = new Job(conf);<a name="line.272"></a>
+<span class="sourceLineNo">273</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.273"></a>
+<span class="sourceLineNo">274</span>      // test scan with startRow and stopRow<a name="line.274"></a>
+<span class="sourceLineNo">275</span>      Scan scan = new Scan().withStartRow(bbc).withStopRow(yya);<a name="line.275"></a>
+<span class="sourceLineNo">276</span><a name="line.276"></a>
+<span class="sourceLineNo">277</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.277"></a>
+<span class="sourceLineNo">278</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.278"></a>
+<span class="sourceLineNo">279</span>        tmpTableDir, new RegionSplitter.UniformSplit(), 5);<a name="line.279"></a>
+<span class="sourceLineNo">280</span><a name="line.280"></a>
+<span class="sourceLineNo">281</span>      verifyWithMockedMapReduce(job, 10, 40, bbc, yya);<a name="line.281"></a>
+<span class="sourceLineNo">282</span>    } finally {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.283"></a>
+<span class="sourceLineNo">284</span>      UTIL.deleteTable(tableName);<a name="line.284"></a>
+<span class="sourceLineNo">285</span>    }<a name="line.285"></a>
+<span class="sourceLineNo">286</span>  }<a name="line.286"></a>
+<span class="sourceLineNo">287</span><a name="line.287"></a>
+<span class="sourceLineNo">288</span>  @Test<a name="line.288"></a>
+<span class="sourceLineNo">289</span>  public void testWithMockedMapReduceWithNoStartRowStopRow() throws Exception {<a name="line.289"></a>
+<span class="sourceLineNo">290</span>    String snapshotName = "testWithMockedMapReduceMultiRegion";<a name="line.290"></a>
+<span class="sourceLineNo">291</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.291"></a>
+<span class="sourceLineNo">292</span>    try {<a name="line.292"></a>
+<span class="sourceLineNo">293</span>      createTableAndSnapshot(UTIL, tableName, snapshotName, getStartRow(), getEndRow(), 10);<a name="line.293"></a>
+<span class="sourceLineNo">294</span><a name="line.294"></a>
+<span class="sourceLineNo">295</span>      Configuration conf = UTIL.getConfiguration();<a name="line.295"></a>
+<span class="sourceLineNo">296</span>      conf.setBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY, false);<a name="line.296"></a>
+<span class="sourceLineNo">297</span>      Job job = new Job(conf);<a name="line.297"></a>
+<span class="sourceLineNo">298</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.298"></a>
+<span class="sourceLineNo">299</span>      // test scan without startRow and stopRow<a name="line.299"></a>
+<span class="sourceLineNo">300</span>      Scan scan2 = new Scan();<a name="line.300"></a>
+<span class="sourceLineNo">301</span><a name="line.301"></a>
+<span class="sourceLineNo">302</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan2,<a name="line.302"></a>
+<span class="sourceLineNo">303</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.303"></a>
+<span class="sourceLineNo">304</span>        tmpTableDir, new RegionSplitter.UniformSplit(), 5);<a name="line.304"></a>
 <span class="sourceLineNo">305</span><a name="line.305"></a>
-<span class="sourceLineNo">306</span>    } finally {<a name="line.306"></a>
-<span class="sourceLineNo">307</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.307"></a>
-<span class="sourceLineNo">308</span>      UTIL.deleteTable(tableName);<a name="line.308"></a>
-<span class="sourceLineNo">309</span>    }<a name="line.309"></a>
-<span class="sourceLineNo">310</span>  }<a name="line.310"></a>
-<span class="sourceLineNo">311</span><a name="line.311"></a>
-<span class="sourceLineNo">312</span>  @Test<a name="line.312"></a>
-<span class="sourceLineNo">313</span>  public void testScanLimit() throws Exception {<a name="line.313"></a>
-<span class="sourceLineNo">314</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.314"></a>
-<span class="sourceLineNo">315</span>    final String snapshotName = tableName + "Snapshot";<a name="line.315"></a>
-<span class="sourceLineNo">316</span>    Table table = null;<a name="line.316"></a>
-<span class="sourceLineNo">317</span>    try {<a name="line.317"></a>
-<span class="sourceLineNo">318</span>      UTIL.getConfiguration().setInt(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT, 10);<a name="line.318"></a>
-<span class="sourceLineNo">319</span>      if (UTIL.getAdmin().tableExists(tableName)) {<a name="line.319"></a>
-<span class="sourceLineNo">320</span>        UTIL.deleteTable(tableName);<a name="line.320"></a>
-<span class="sourceLineNo">321</span>      }<a name="line.321"></a>
-<span class="sourceLineNo">322</span><a name="line.322"></a>
-<span class="sourceLineNo">323</span>      UTIL.createTable(tableName, FAMILIES, new byte[][] { bbb, yyy });<a name="line.323"></a>
-<span class="sourceLineNo">324</span><a name="line.324"></a>
-<span class="sourceLineNo">325</span>      Admin admin = UTIL.getAdmin();<a name="line.325"></a>
-<span class="sourceLineNo">326</span><a name="line.326"></a>
-<span class="sourceLineNo">327</span>      int regionNum = admin.getRegions(tableName).size();<a name="line.327"></a>
-<span class="sourceLineNo">328</span>      // put some stuff in the table<a name="line.328"></a>
-<span class="sourceLineNo">329</span>      table = UTIL.getConnection().getTable(tableName);<a name="line.329"></a>
-<span class="sourceLineNo">330</span>      UTIL.loadTable(table, FAMILIES);<a name="line.330"></a>
-<span class="sourceLineNo">331</span><a name="line.331"></a>
-<span class="sourceLineNo">332</span>      Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.332"></a>
-<span class="sourceLineNo">333</span>      FileSystem fs = rootDir.getFileSystem(UTIL.getConfiguration());<a name="line.333"></a>
+<span class="sourceLineNo">306</span>      verifyWithMockedMapReduce(job, 10, 50, HConstants.EMPTY_START_ROW,<a name="line.306"></a>
+<span class="sourceLineNo">307</span>        HConstants.EMPTY_START_ROW);<a name="line.307"></a>
+<span class="sourceLineNo">308</span><a name="line.308"></a>
+<span class="sourceLineNo">309</span>    } finally {<a name="line.309"></a>
+<span class="sourceLineNo">310</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.310"></a>
+<span class="sourceLineNo">311</span>      UTIL.deleteTable(tableName);<a name="line.311"></a>
+<span class="sourceLineNo">312</span>    }<a name="line.312"></a>
+<span class="sourceLineNo">313</span>  }<a name="line.313"></a>
+<span class="sourceLineNo">314</span><a name="line.314"></a>
+<span class="sourceLineNo">315</span>  @Test<a name="line.315"></a>
+<span class="sourceLineNo">316</span>  public void testScanLimit() throws Exception {<a name="line.316"></a>
+<span class="sourceLineNo">317</span>    final TableName tableName = TableName.valueOf(name.getMethodName());<a name="line.317"></a>
+<span class="sourceLineNo">318</span>    final String snapshotName = tableName + "Snapshot";<a name="line.318"></a>
+<span class="sourceLineNo">319</span>    Table table = null;<a name="line.319"></a>
+<span class="sourceLineNo">320</span>    try {<a name="line.320"></a>
+<span class="sourceLineNo">321</span>      UTIL.getConfiguration().setInt(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT, 10);<a name="line.321"></a>
+<span class="sourceLineNo">322</span>      if (UTIL.getAdmin().tableExists(tableName)) {<a name="line.322"></a>
+<span class="sourceLineNo">323</span>        UTIL.deleteTable(tableName);<a name="line.323"></a>
+<span class="sourceLineNo">324</span>      }<a name="line.324"></a>
+<span class="sourceLineNo">325</span><a name="line.325"></a>
+<span class="sourceLineNo">326</span>      UTIL.createTable(tableName, FAMILIES, new byte[][] { bbb, yyy });<a name="line.326"></a>
+<span class="sourceLineNo">327</span><a name="line.327"></a>
+<span class="sourceLineNo">328</span>      Admin admin = UTIL.getAdmin();<a name="line.328"></a>
+<span class="sourceLineNo">329</span><a name="line.329"></a>
+<span class="sourceLineNo">330</span>      int regionNum = admin.getRegions(tableName).size();<a name="line.330"></a>
+<span class="sourceLineNo">331</span>      // put some stuff in the table<a name="line.331"></a>
+<span class="sourceLineNo">332</span>      table = UTIL.getConnection().getTable(tableName);<a name="line.332"></a>
+<span class="sourceLineNo">333</span>      UTIL.loadTable(table, FAMILIES);<a name="line.333"></a>
 <span class="sourceLineNo">334</span><a name="line.334"></a>
-<span class="sourceLineNo">335</span>      SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName, Arrays.asList(FAMILIES),<a name="line.335"></a>
-<span class="sourceLineNo">336</span>        null, snapshotName, rootDir, fs, true);<a name="line.336"></a>
+<span class="sourceLineNo">335</span>      Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.335"></a>
+<span class="sourceLineNo">336</span>      FileSystem fs = rootDir.getFileSystem(UTIL.getConfiguration());<a name="line.336"></a>
 <span class="sourceLineNo">337</span><a name="line.337"></a>
-<span class="sourceLineNo">338</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.338"></a>
-<span class="sourceLineNo">339</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.339"></a>
-<span class="sourceLineNo">340</span>      Scan scan = new Scan();<a name="line.340"></a>
-<span class="sourceLineNo">341</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.341"></a>
-<span class="sourceLineNo">342</span>        TestTableSnapshotInputFormat.class);<a name="line.342"></a>
-<span class="sourceLineNo">343</span><a name="line.343"></a>
-<span class="sourceLineNo">344</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.344"></a>
-<span class="sourceLineNo">345</span>        RowCounter.RowCounterMapper.class, NullWritable.class, NullWritable.class, job, true,<a name="line.345"></a>
-<span class="sourceLineNo">346</span>        tmpTableDir);<a name="line.346"></a>
-<span class="sourceLineNo">347</span>      Assert.assertTrue(job.waitForCompletion(true));<a name="line.347"></a>
-<span class="sourceLineNo">348</span>      Assert.assertEquals(10 * regionNum,<a name="line.348"></a>
-<span class="sourceLineNo">349</span>        job.getCounters().findCounter(RowCounter.RowCounterMapper.Counters.ROWS).getValue());<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    } finally {<a name="line.350"></a>
-<span class="sourceLineNo">351</span>      if (table != null) {<a name="line.351"></a>
-<span class="sourceLineNo">352</span>        table.close();<a name="line.352"></a>
-<span class="sourceLineNo">353</span>      }<a name="line.353"></a>
-<span class="sourceLineNo">354</span>      UTIL.getConfiguration().unset(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT);<a name="line.354"></a>
-<span class="sourceLineNo">355</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.355"></a>
-<span class="sourceLineNo">356</span>      UTIL.deleteTable(tableName);<a name="line.356"></a>
-<span class="sourceLineNo">357</span>    }<a name="line.357"></a>
-<span class="sourceLineNo">358</span>  }<a name="line.358"></a>
-<span class="sourceLineNo">359</span><a name="line.359"></a>
-<span class="sourceLineNo">360</span>  @Test<a name="line.360"></a>
-<span class="sourceLineNo">361</span>  public void testNoDuplicateResultsWhenSplitting() throws Exception {<a name="line.361"></a>
-<span class="sourceLineNo">362</span>    TableName tableName = TableName.valueOf("testNoDuplicateResultsWhenSplitting");<a name="line.362"></a>
-<span class="sourceLineNo">363</span>    String snapshotName = "testSnapshotBug";<a name="line.363"></a>
-<span class="sourceLineNo">364</span>    try {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>      if (UTIL.getAdmin().tableExists(tableName)) {<a name="line.365"></a>
-<span class="sourceLineNo">366</span>        UTIL.deleteTable(tableName);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>      }<a name="line.367"></a>
-<span class="sourceLineNo">368</span><a name="line.368"></a>
-<span class="sourceLineNo">369</span>      UTIL.createTable(tableName, FAMILIES);<a name="line.369"></a>
-<span class="sourceLineNo">370</span>      Admin admin = UTIL.getAdmin();<a name="line.370"></a>
+<span class="sourceLineNo">338</span>      SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName, Arrays.asList(FAMILIES),<a name="line.338"></a>
+<span class="sourceLineNo">339</span>        null, snapshotName, rootDir, fs, true);<a name="line.339"></a>
+<span class="sourceLineNo">340</span><a name="line.340"></a>
+<span class="sourceLineNo">341</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.341"></a>
+<span class="sourceLineNo">342</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.342"></a>
+<span class="sourceLineNo">343</span>      Scan scan = new Scan();<a name="line.343"></a>
+<span class="sourceLineNo">344</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.344"></a>
+<span class="sourceLineNo">345</span>        TestTableSnapshotInputFormat.class);<a name="line.345"></a>
+<span class="sourceLineNo">346</span><a name="line.346"></a>
+<span class="sourceLineNo">347</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.347"></a>
+<span class="sourceLineNo">348</span>        RowCounter.RowCounterMapper.class, NullWritable.class, NullWritable.class, job, true,<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        tmpTableDir);<a name="line.349"></a>
+<span class="sourceLineNo">350</span>      Assert.assertTrue(job.waitForCompletion(true));<a name="line.350"></a>
+<span class="sourceLineNo">351</span>      Assert.assertEquals(10 * regionNum,<a name="line.351"></a>
+<span class="sourceLineNo">352</span>        job.getCounters().findCounter(RowCounter.RowCounterMapper.Counters.ROWS).getValue());<a name="line.352"></a>
+<span class="sourceLineNo">353</span>    } finally {<a name="line.353"></a>
+<span class="sourceLineNo">354</span>      if (table != null) {<a name="line.354"></a>
+<span class="sourceLineNo">355</span>        table.close();<a name="line.355"></a>
+<span class="sourceLineNo">356</span>      }<a name="line.356"></a>
+<span class="sourceLineNo">357</span>      UTIL.getConfiguration().unset(SNAPSHOT_INPUTFORMAT_ROW_LIMIT_PER_INPUTSPLIT);<a name="line.357"></a>
+<span class="sourceLineNo">358</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.358"></a>
+<span class="sourceLineNo">359</span>      UTIL.deleteTable(tableName);<a name="line.359"></a>
+<span class="sourceLineNo">360</span>    }<a name="line.360"></a>
+<span class="sourceLineNo">361</span>  }<a name="line.361"></a>
+<span class="sourceLineNo">362</span><a name="line.362"></a>
+<span class="sourceLineNo">363</span>  @Test<a name="line.363"></a>
+<span class="sourceLineNo">364</span>  public void testNoDuplicateResultsWhenSplitting() throws Exception {<a name="line.364"></a>
+<span class="sourceLineNo">365</span>    TableName tableName = TableName.valueOf("testNoDuplicateResultsWhenSplitting");<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    String snapshotName = "testSnapshotBug";<a name="line.366"></a>
+<span class="sourceLineNo">367</span>    try {<a name="line.367"></a>
+<span class="sourceLineNo">368</span>      if (UTIL.getAdmin().tableExists(tableName)) {<a name="line.368"></a>
+<span class="sourceLineNo">369</span>        UTIL.deleteTable(tableName);<a name="line.369"></a>
+<span class="sourceLineNo">370</span>      }<a name="line.370"></a>
 <span class="sourceLineNo">371</span><a name="line.371"></a>
-<span class="sourceLineNo">372</span>      // put some stuff in the table<a name="line.372"></a>
-<span class="sourceLineNo">373</span>      Table table = UTIL.getConnection().getTable(tableName);<a name="line.373"></a>
-<span class="sourceLineNo">374</span>      UTIL.loadTable(table, FAMILIES);<a name="line.374"></a>
-<span class="sourceLineNo">375</span><a name="line.375"></a>
-<span class="sourceLineNo">376</span>      // split to 2 regions<a name="line.376"></a>
-<span class="sourceLineNo">377</span>      admin.split(tableName, Bytes.toBytes("eee"));<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      TestTableSnapshotScanner.blockUntilSplitFinished(UTIL, tableName, 2);<a name="line.378"></a>
-<span class="sourceLineNo">379</span><a name="line.379"></a>
-<span class="sourceLineNo">380</span>      Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      FileSystem fs = rootDir.getFileSystem(UTIL.getConfiguration());<a name="line.381"></a>
+<span class="sourceLineNo">372</span>      UTIL.createTable(tableName, FAMILIES);<a name="line.372"></a>
+<span class="sourceLineNo">373</span>      Admin admin = UTIL.getAdmin();<a name="line.373"></a>
+<span class="sourceLineNo">374</span><a name="line.374"></a>
+<span class="sourceLineNo">375</span>      // put some stuff in the table<a name="line.375"></a>
+<span class="sourceLineNo">376</span>      Table table = UTIL.getConnection().getTable(tableName);<a name="line.376"></a>
+<span class="sourceLineNo">377</span>      UTIL.loadTable(table, FAMILIES);<a name="line.377"></a>
+<span class="sourceLineNo">378</span><a name="line.378"></a>
+<span class="sourceLineNo">379</span>      // split to 2 regions<a name="line.379"></a>
+<span class="sourceLineNo">380</span>      admin.split(tableName, Bytes.toBytes("eee"));<a name="line.380"></a>
+<span class="sourceLineNo">381</span>      TestTableSnapshotScanner.blockUntilSplitFinished(UTIL, tableName, 2);<a name="line.381"></a>
 <span class="sourceLineNo">382</span><a name="line.382"></a>
-<span class="sourceLineNo">383</span>      SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName, Arrays.asList(FAMILIES),<a name="line.383"></a>
-<span class="sourceLineNo">384</span>        null, snapshotName, rootDir, fs, true);<a name="line.384"></a>
+<span class="sourceLineNo">383</span>      Path rootDir = CommonFSUtils.getRootDir(UTIL.getConfiguration());<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      FileSystem fs = rootDir.getFileSystem(UTIL.getConfiguration());<a name="line.384"></a>
 <span class="sourceLineNo">385</span><a name="line.385"></a>
-<span class="sourceLineNo">386</span>      // load different values<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      byte[] value = Bytes.toBytes("after_snapshot_value");<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      UTIL.loadTable(table, FAMILIES, value);<a name="line.388"></a>
-<span class="sourceLineNo">389</span><a name="line.389"></a>
-<span class="sourceLineNo">390</span>      // cause flush to create new files in the region<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      admin.flush(tableName);<a name="line.391"></a>
-<span class="sourceLineNo">392</span>      table.close();<a name="line.392"></a>
-<span class="sourceLineNo">393</span><a name="line.393"></a>
-<span class="sourceLineNo">394</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.395"></a>
-<span class="sourceLineNo">396</span>      // limit the scan<a name="line.396"></a>
-<span class="sourceLineNo">397</span>      Scan scan = new Scan().withStartRow(getStartRow()).withStopRow(getEndRow());<a name="line.397"></a>
-<span class="sourceLineNo">398</span><a name="line.398"></a>
-<span class="sourceLineNo">399</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.399"></a>
-<span class="sourceLineNo">400</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.400"></a>
-<span class="sourceLineNo">401</span>        tmpTableDir);<a name="line.401"></a>
-<span class="sourceLineNo">402</span><a name="line.402"></a>
-<span class="sourceLineNo">403</span>      verifyWithMockedMapReduce(job, 2, 2, getStartRow(), getEndRow());<a name="line.403"></a>
-<span class="sourceLineNo">404</span>    } finally {<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      UTIL.deleteTable(tableName);<a name="line.406"></a>
-<span class="sourceLineNo">407</span>    }<a name="line.407"></a>
-<span class="sourceLineNo">408</span>  }<a name="line.408"></a>
-<span class="sourceLineNo">409</span><a name="line.409"></a>
-<span class="sourceLineNo">410</span>  private void verifyWithMockedMapReduce(Job job, int numRegions, int expectedNumSplits,<a name="line.410"></a>
-<span class="sourceLineNo">411</span>      byte[] startRow, byte[] stopRow)<a name="line.411"></a>
-<span class="sourceLineNo">412</span>      throws IOException, InterruptedException {<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    TableSnapshotInputFormat tsif = new TableSnapshotInputFormat();<a name="line.413"></a>
-<span class="sourceLineNo">414</span>    List&lt;InputSplit&gt; splits = tsif.getSplits(job);<a name="line.414"></a>
-<span class="sourceLineNo">415</span><a name="line.415"></a>
-<span class="sourceLineNo">416</span>    Assert.assertEquals(expectedNumSplits, splits.size());<a name="line.416"></a>
-<span class="sourceLineNo">417</span><a name="line.417"></a>
-<span class="sourceLineNo">418</span>    HBaseTestingUtil.SeenRowTracker rowTracker = new HBaseTestingUtil.SeenRowTracker(startRow,<a name="line.418"></a>
-<span class="sourceLineNo">419</span>        stopRow.length &gt; 0 ? stopRow : Bytes.toBytes("\uffff"));<a name="line.419"></a>
-<span class="sourceLineNo">420</span><a name="line.420"></a>
-<span class="sourceLineNo">421</span>    boolean localityEnabled =<a name="line.421"></a>
-<span class="sourceLineNo">422</span>        job.getConfiguration().getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY,<a name="line.422"></a>
-<span class="sourceLineNo">423</span>                                          SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT);<a name="line.423"></a>
-<span class="sourceLineNo">424</span><a name="line.424"></a>
-<span class="sourceLineNo">425</span>    boolean byRegionLoc =<a name="line.425"></a>
-<span class="sourceLineNo">426</span>      job.getConfiguration().getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.426"></a>
-<span class="sourceLineNo">427</span>                                        SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.427"></a>
-<span class="sourceLineNo">428</span>    for (int i = 0; i &lt; splits.size(); i++) {<a name="line.428"></a>
-<span class="sourceLineNo">429</span>      // validate input split<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      InputSplit split = splits.get(i);<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      Assert.assertTrue(split instanceof TableSnapshotRegionSplit);<a name="line.431"></a>
-<span class="sourceLineNo">432</span>      TableSnapshotRegionSplit snapshotRegionSplit = (TableSnapshotRegionSplit) split;<a name="line.432"></a>
-<span class="sourceLineNo">433</span>      if (localityEnabled) {<a name="line.433"></a>
-<span class="sourceLineNo">434</span>        Assert.assertTrue(split.getLocations() != null &amp;&amp; split.getLocations().length != 0);<a name="line.434"></a>
-<span class="sourceLineNo">435</span>        if (byRegionLoc) {<a name="line.435"></a>
-<span class="sourceLineNo">436</span>          // When it uses region location from meta, the hostname will be "localhost",<a name="line.436"></a>
-<span class="sourceLineNo">437</span>          // the location from hdfs block location is "127.0.0.1".<a name="line.437"></a>
-<span class="sourceLineNo">438</span>          Assert.assertEquals(1, split.getLocations().length);<a name="line.438"></a>
-<span class="sourceLineNo">439</span>          Assert.assertTrue("Not using region location!",<a name="line.439"></a>
-<span class="sourceLineNo">440</span>            split.getLocations()[0].equals("localhost"));<a name="line.440"></a>
-<span class="sourceLineNo">441</span>        } else {<a name="line.441"></a>
-<span class="sourceLineNo">442</span>          Assert.assertTrue("Not using region location!",<a name="line.442"></a>
-<span class="sourceLineNo">443</span>            split.getLocations()[0].equals("127.0.0.1"));<a name="line.443"></a>
-<span class="sourceLineNo">444</span>        }<a name="line.444"></a>
-<span class="sourceLineNo">445</span>      } else {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>        Assert.assertTrue(split.getLocations() != null &amp;&amp; split.getLocations().length == 0);<a name="line.446"></a>
-<span class="sourceLineNo">447</span>      }<a name="line.447"></a>
+<span class="sourceLineNo">386</span>      SnapshotTestingUtils.createSnapshotAndValidate(admin, tableName, Arrays.asList(FAMILIES),<a name="line.386"></a>
+<span class="sourceLineNo">387</span>        null, snapshotName, rootDir, fs, true);<a name="line.387"></a>
+<span class="sourceLineNo">388</span><a name="line.388"></a>
+<span class="sourceLineNo">389</span>      // load different values<a name="line.389"></a>
+<span class="sourceLineNo">390</span>      byte[] value = Bytes.toBytes("after_snapshot_value");<a name="line.390"></a>
+<span class="sourceLineNo">391</span>      UTIL.loadTable(table, FAMILIES, value);<a name="line.391"></a>
+<span class="sourceLineNo">392</span><a name="line.392"></a>
+<span class="sourceLineNo">393</span>      // cause flush to create new files in the region<a name="line.393"></a>
+<span class="sourceLineNo">394</span>      admin.flush(tableName);<a name="line.394"></a>
+<span class="sourceLineNo">395</span>      table.close();<a name="line.395"></a>
+<span class="sourceLineNo">396</span><a name="line.396"></a>
+<span class="sourceLineNo">397</span>      Job job = new Job(UTIL.getConfiguration());<a name="line.397"></a>
+<span class="sourceLineNo">398</span>      Path tmpTableDir = UTIL.getDataTestDirOnTestFS(snapshotName);<a name="line.398"></a>
+<span class="sourceLineNo">399</span>      // limit the scan<a name="line.399"></a>
+<span class="sourceLineNo">400</span>      Scan scan = new Scan().withStartRow(getStartRow()).withStopRow(getEndRow());<a name="line.400"></a>
+<span class="sourceLineNo">401</span><a name="line.401"></a>
+<span class="sourceLineNo">402</span>      TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName, scan,<a name="line.402"></a>
+<span class="sourceLineNo">403</span>        TestTableSnapshotMapper.class, ImmutableBytesWritable.class, NullWritable.class, job, false,<a name="line.403"></a>
+<span class="sourceLineNo">404</span>        tmpTableDir);<a name="line.404"></a>
+<span class="sourceLineNo">405</span><a name="line.405"></a>
+<span class="sourceLineNo">406</span>      verifyWithMockedMapReduce(job, 2, 2, getStartRow(), getEndRow());<a name="line.406"></a>
+<span class="sourceLineNo">407</span>    } finally {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>      UTIL.getAdmin().deleteSnapshot(snapshotName);<a name="line.408"></a>
+<span class="sourceLineNo">409</span>      UTIL.deleteTable(tableName);<a name="line.409"></a>
+<span class="sourceLineNo">410</span>    }<a name="line.410"></a>
+<span class="sourceLineNo">411</span>  }<a name="line.411"></a>
+<span class="sourceLineNo">412</span><a name="line.412"></a>
+<span class="sourceLineNo">413</span>  @Test<a name="line.413"></a>
+<span class="sourceLineNo">414</span>  public void testScannerReadTypeConfiguration() throws IOException {<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    Configuration conf = new Configuration(false);<a name="line.415"></a>
+<span class="sourceLineNo">416</span>    // Explicitly set ReadTypes should persist<a name="line.416"></a>
+<span class="sourceLineNo">417</span>    for (ReadType readType : Arrays.asList(ReadType.PREAD, ReadType.STREAM)) {<a name="line.417"></a>
+<span class="sourceLineNo">418</span>      Scan scanWithReadType = new Scan();<a name="line.418"></a>
+<span class="sourceLineNo">419</span>      scanWithReadType.setReadType(readType);<a name="line.419"></a>
+<span class="sourceLineNo">420</span>      assertEquals(scanWithReadType.getReadType(),<a name="line.420"></a>
+<span class="sourceLineNo">421</span>          serializeAndReturn(conf, scanWithReadType).getReadType());<a name="line.421"></a>
+<span class="sourceLineNo">422</span>    }<a name="line.422"></a>
+<span class="sourceLineNo">423</span>    // We should only see the DEFAULT ReadType getting updated to STREAM.<a name="line.423"></a>
+<span class="sourceLineNo">424</span>    Scan scanWithoutReadType = new Scan();<a name="line.424"></a>
+<span class="sourceLineNo">425</span>    assertEquals(ReadType.DEFAULT, scanWithoutReadType.getReadType());<a name="line.425"></a>
+<span class="sourceLineNo">426</span>    assertEquals(ReadType.STREAM, serializeAndReturn(conf, scanWithoutReadType).getReadType());<a name="line.426"></a>
+<span class="sourceLineNo">427</span><a name="line.427"></a>
+<span class="sourceLineNo">428</span>    // We should still be able to force a certain ReadType when DEFAULT is given.<a name="line.428"></a>
+<span class="sourceLineNo">429</span>    conf.setEnum(SNAPSHOT_INPUTFORMAT_SCANNER_READTYPE, ReadType.PREAD);<a name="line.429"></a>
+<span class="sourceLineNo">430</span>    assertEquals(ReadType.DEFAULT, scanWithoutReadType.getReadType());<a name="line.430"></a>
+<span class="sourceLineNo">431</span>    assertEquals(ReadType.PREAD, serializeAndReturn(conf, scanWithoutReadType).getReadType());<a name="line.431"></a>
+<span class="sourceLineNo">432</span>  }<a name="line.432"></a>
+<span class="sourceLineNo">433</span><a name="line.433"></a>
+<span class="sourceLineNo">434</span>  /**<a name="line.434"></a>
+<span class="sourceLineNo">435</span>   * Serializes and deserializes the given scan in the same manner that<a name="line.435"></a>
+<span class="sourceLineNo">436</span>   * TableSnapshotInputFormat does.<a name="line.436"></a>
+<span class="sourceLineNo">437</span>   */<a name="line.437"></a>
+<span class="sourceLineNo">438</span>  private Scan serializeAndReturn(Configuration conf, Scan s) throws IOException {<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    conf.set(TableInputFormat.SCAN, TableMapReduceUtil.convertScanToString(s));<a name="line.439"></a>
+<span class="sourceLineNo">440</span>    return TableSnapshotInputFormatImpl.extractScanFromConf(conf);<a name="line.440"></a>
+<span class="sourceLineNo">441</span>  }<a name="line.441"></a>
+<span class="sourceLineNo">442</span><a name="line.442"></a>
+<span class="sourceLineNo">443</span>  private void verifyWithMockedMapReduce(Job job, int numRegions, int expectedNumSplits,<a name="line.443"></a>
+<span class="sourceLineNo">444</span>      byte[] startRow, byte[] stopRow)<a name="line.444"></a>
+<span class="sourceLineNo">445</span>      throws IOException, InterruptedException {<a name="line.445"></a>
+<span class="sourceLineNo">446</span>    TableSnapshotInputFormat tsif = new TableSnapshotInputFormat();<a name="line.446"></a>
+<span class="sourceLineNo">447</span>    List&lt;InputSplit&gt; splits = tsif.getSplits(job);<a name="line.447"></a>
 <span class="sourceLineNo">448</span><a name="line.448"></a>
-<span class="sourceLineNo">449</span>      Scan scan =<a name="line.449"></a>
-<span class="sourceLineNo">450</span>          TableMapReduceUtil.convertStringToScan(snapshotRegionSplit.getDelegate().getScan());<a name="line.450"></a>
-<span class="sourceLineNo">451</span>      if (startRow.length &gt; 0) {<a name="line.451"></a>
-<span class="sourceLineNo">452</span>        Assert.assertTrue(<a name="line.452"></a>
-<span class="sourceLineNo">453</span>          Bytes.toStringBinary(startRow) + " should &lt;= " + Bytes.toStringBinary(scan.getStartRow()),<a name="line.453"></a>
-<span class="sourceLineNo">454</span>          Bytes.compareTo(startRow, scan.getStartRow()) &lt;= 0);<a name="line.454"></a>
-<span class="sourceLineNo">455</span>      }<a name="line.455"></a>
-<span class="sourceLineNo">456</span>      if (stopRow.length &gt; 0) {<a name="line.456"></a>
-<span class="sourceLineNo">457</span>        Assert.assertTrue(<a name="line.457"></a>
-<span class="sourceLineNo">458</span>          Bytes.toStringBinary(stopRow) + " should &gt;= " + Bytes.toStringBinary(scan.getStopRow()),<a name="line.458"></a>
-<span class="sourceLineNo">459</span>          Bytes.compareTo(stopRow, scan.getStopRow()) &gt;= 0);<a name="line.459"></a>
-<span class="sourceLineNo">460</span>      }<a name="line.460"></a>
-<span class="sourceLineNo">461</span>      Assert.assertTrue("startRow should &lt; stopRow",<a name="line.461"></a>
-<span class="sourceLineNo">462</span>        Bytes.compareTo(scan.getStartRow(), scan.getStopRow()) &lt; 0);<a name="line.462"></a>
-<span class="sourceLineNo">463</span><a name="line.463"></a>
-<span class="sourceLineNo">464</span>      // validate record reader<a name="line.464"></a>
-<span class="sourceLineNo">465</span>      TaskAttemptContext taskAttemptContext = mock(TaskAttemptContext.class);<a name="line.465"></a>
-<span class="sourceLineNo">466</span>      when(taskAttemptContext.getConfiguration()).thenReturn(job.getConfiguration());<a name="line.466"></a>
-<span class="sourceLineNo">467</span>      RecordReader&lt;ImmutableBytesWritable, Result&gt; rr =<a name="line.467"></a>
-<span class="sourceLineNo">468</span>          tsif.createRecordReader(split, taskAttemptContext);<a name="line.468"></a>
-<span class="sourceLineNo">469</span>      rr.initialize(split, taskAttemptContext);<a name="line.469"></a>
-<span class="sourceLineNo">470</span><a name="line.470"></a>
-<span class="sourceLineNo">471</span>      // validate we can read all the data back<a name="line.471"></a>
-<span class="sourceLineNo">472</span>      while (rr.nextKeyValue()) {<a name="line.472"></a>
-<span class="sourceLineNo">473</span>        byte[] row = rr.getCurrentKey().get();<a name="line.473"></a>
-<span class="sourceLineNo">474</span>        verifyRowFromMap(rr.getCurrentKey(), rr.getCurrentValue());<a name="line.474"></a>
-<span class="sourceLineNo">475</span>        rowTracker.addRow(row);<a name="line.475"></a>
-<span class="sourceLineNo">476</span>      }<a name="line.476"></a>
-<span class="sourceLineNo">477</span><a name="line.477"></a>
-<span class="sourceLineNo">478</span>      rr.close();<a name="line.478"></a>
-<span class="sourceLineNo">479</span>    }<a name="line.479"></a>
-<span class="sourceLineNo">480</span><a name="line.480"></a>
-<span class="sourceLineNo">481</span>    // validate all rows are seen<a name="line.481"></a>
-<span class="sourceLineNo">482</span>    rowTracker.validate();<a name="line.482"></a>
-<span class="sourceLineNo">483</span>  }<a name="line.483"></a>
-<span class="sourceLineNo">484</span><a name="line.484"></a>
-<span class="sourceLineNo">485</span>  @Override<a name="line.485"></a>
-<span class="sourceLineNo">486</span>  protected void testWithMapReduceImpl(HBaseTestingUtil util, TableName tableName,<a name="line.486"></a>
-<span class="sourceLineNo">487</span>      String snapshotName, Path tableDir, int numRegions, int numSplitsPerRegion,<a name="line.487"></a>
-<span class="sourceLineNo">488</span>      int expectedNumSplits, boolean shutdownCluster) throws Exception {<a name="line.488"></a>
-<span class="sourceLineNo">489</span>    doTestWithMapReduce(util, tableName, snapshotName, getStartRow(), getEndRow(), tableDir,<a name="line.489"></a>
-<span class="sourceLineNo">490</span>      numRegions, numSplitsPerRegion, expectedNumSplits, shutdownCluster);<a name="line.490"></a>
-<span class="sourceLineNo">491</span>  }<a name="line.491"></a>
-<span class="sourceLineNo">492</span><a name="line.492"></a>
-<span class="sourceLineNo">493</span>  // this is also called by the IntegrationTestTableSnapshotInputFormat<a name="line.493"></a>
-<span class="sourceLineNo">494</span>  public static void doTestWithMapReduce(HBaseTestingUtil util, TableName tableName,<a name="line.494"></a>
-<span class="sourceLineNo">495</span>      String snapshotName, byte[] startRow, byte[] endRow, Path tableDir, int numRegions,<a name="line.495"></a>
-<span class="sourceLineNo">496</span>      int numSplitsPerRegion, int expectedNumSplits, boolean shutdownCluster) throws Exception {<a name="line.496"></a>
-<span class="sourceLineNo">497</span><a name="line.497"></a>
-<span class="sourceLineNo">498</span>    LOG.info("testing with MapReduce");<a name="line.498"></a>
-<span class="sourceLineNo">499</span><a name="line.499"></a>
-<span class="sourceLineNo">500</span>    LOG.info("create the table and snapshot");<a name="line.500"></a>
-<span class="sourceLineNo">501</span>    createTableAndSnapshot(util, tableName, snapshotName, startRow, endRow, numRegions);<a name="line.501"></a>
-<span class="sourceLineNo">502</span><a name="line.502"></a>
-<span class="sourceLineNo">503</span>    if (shutdownCluster) {<a name="line.503"></a>
-<span class="sourceLineNo">504</span>      LOG.info("shutting down hbase cluster.");<a name="line.504"></a>
-<span class="sourceLineNo">505</span>      util.shutdownMiniHBaseCluster();<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    }<a name="line.506"></a>
-<span class="sourceLineNo">507</span><a name="line.507"></a>
-<span class="sourceLineNo">508</span>    try {<a name="line.508"></a>
-<span class="sourceLineNo">509</span>      // create the job<a name="line.509"></a>
-<span class="sourceLineNo">510</span>      Job job = new Job(util.getConfiguration());<a name="line.510"></a>
-<span class="sourceLineNo">511</span>      Scan scan = new Scan().withStartRow(startRow).withStopRow(endRow); // limit the scan<a name="line.511"></a>
-<span class="sourceLineNo">512</span><a name="line.512"></a>
-<span class="sourceLineNo">513</span>      job.setJarByClass(util.getClass());<a name="line.513"></a>
-<span class="sourceLineNo">514</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.514"></a>
-<span class="sourceLineNo">515</span>              TestTableSnapshotInputFormat.class);<a name="line.515"></a>
-<span class="sourceLineNo">516</span><a name="line.516"></a>
-<span class="sourceLineNo">517</span>      if (numSplitsPerRegion &gt; 1) {<a name="line.517"></a>
-<span class="sourceLineNo">518</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.518"></a>
-<span class="sourceLineNo">519</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.519"></a>
-<span class="sourceLineNo">520</span>                NullWritable.class, job, true, tableDir, new RegionSplitter.UniformSplit(),<a name="line.520"></a>
-<span class="sourceLineNo">521</span>                numSplitsPerRegion);<a name="line.521"></a>
-<span class="sourceLineNo">522</span>      } else {<a name="line.522"></a>
-<span class="sourceLineNo">523</span>        TableMapReduceUtil.initTableSnapshotMapperJob(snapshotName,<a name="line.523"></a>
-<span class="sourceLineNo">524</span>                scan, TestTableSnapshotMapper.class, ImmutableBytesWritable.class,<a name="line.524"></a>
-<span class="sourceLineNo">525</span>                NullWritable.class, job, true, tableDir);<a name="line.525"></a>
-<span class="sourceLineNo">526</span>      }<a name="line.526"></a>
-<span class="sourceLineNo">527</span><a name="line.527"></a>
-<span class="sourceLineNo">528</span>      job.setReducerClass(TestTableSnapshotInputFormat.TestTableSnapshotReducer.class);<a name="line.528"></a>
-<span class="sourceLineNo">529</span>      job.setNumReduceTasks(1);<a name="line.529"></a>
-<span class="sourceLineNo">530</span>      job.setOutputFormatClass(NullOutputFormat.class);<a name="line.530"></a>
-<span class="sourceLineNo">531</span><a name="line.531"></a>
-<span class="sourceLineNo">532</span>      Assert.assertTrue(job.waitForCompletion(true));<a name="line.532"></a>
-<span class="sourceLineNo">533</span>    } finally {<a name="line.533"></a>
-<span class="sourceLineNo">534</span>      if (!shutdownCluster) {<a name="line.534"></a>
-<span class="sourceLineNo">535</span>        util.getAdmin().deleteSnapshot(snapshotName);<a name="line.535"></a>
-<span class="sourceLineNo">536</span>        util.deleteTable(tableName);<a name="line.536"></a>
-<span class="sourceLineNo">537</span>      }<a name="line.537"></a>
-<span class="sourceLineNo">538</span>    }<a name="line.538"></a>
-<span class="sourceLineNo">539</span>  }<a name="line.539"></a>
+<span class="sourceLineNo">449</span>    Assert.assertEquals(expectedNumSplits, splits.size());<a name="line.449"></a>
+<span class="sourceLineNo">450</span><a name="line.450"></a>
+<span class="sourceLineNo">451</span>    HBaseTestingUtil.SeenRowTracker rowTracker = new HBaseTestingUtil.SeenRowTracker(startRow,<a name="line.451"></a>
+<span class="sourceLineNo">452</span>        stopRow.length &gt; 0 ? stopRow : Bytes.toBytes("\uffff"));<a name="line.452"></a>
+<span class="sourceLineNo">453</span><a name="line.453"></a>
+<span class="sourceLineNo">454</span>    boolean localityEnabled =<a name="line.454"></a>
+<span class="sourceLineNo">455</span>        job.getConfiguration().getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_KEY,<a name="line.455"></a>
+<span class="sourceLineNo">456</span>                                          SNAPSHOT_INPUTFORMAT_LOCALITY_ENABLED_DEFAULT);<a name="line.456"></a>
+<span class="sourceLineNo">457</span><a name="line.457"></a>
+<span class="sourceLineNo">458</span>    boolean byRegionLoc =<a name="line.458"></a>
+<span class="sourceLineNo">459</span>      job.getConfiguration().getBoolean(SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION,<a name="line.459"></a>
+<span class="sourceLineNo">460</span>                                        SNAPSHOT_INPUTFORMAT_LOCALITY_BY_REGION_LOCATION_DEFAULT);<a name="line.460"></a>
+<span class="sourceLineNo">461</span>    for (int i = 0; i &lt; splits.size(); i++) {<a name="line.461"></a>
+<span class="sourceLineNo">462</span>      // validate input split<a name="line.462"></a>
+<span class="sourceLineNo">463</span>      InputSplit split = splits.get(i);<a name="line.463"></a>
+<span class="sourceLineNo">464</span>      Assert.assertTrue(split instanceof TableSnapshotRegionSplit);<a name="line.464"></a>
+<span class="sourceLineNo">465</span>      TableSnapshotRegionSplit snapshotRegionSplit = (TableSnapshotRegionSplit) split;<a name="line.465"></a>
+<span class="sourceLineNo">466</span>      if (localityEnabled) {<a name="line.466"></a>
+<span class="sourceLineNo">467</span>        Assert.assertTrue(split.getLocations() != null &amp;&amp; split.getLocations().length != 0);<a name="line.467"></a>
+<span class="sourceLineNo">468</span>        if (byRegionLoc) {<a name="line.468"></a>
+<span class="sourceLineNo">469</span>          // When it uses region location from meta, the hostname will be "localhost",<a name="line.469"></a>
+<span class="sourceLineNo">470</span>          // the location from hdfs block location is "127.0.0.1".<a name="line.470"></a>
+<span class="sourceLineNo">471</span>          Assert.assertEquals(1, split.getLocations().length);<a name="line.471"></a>
+<span class="sourceLineNo">472</span>          Assert.assertTrue("Not using region location!",<a name="line.472"></a>
... 114 lines suppressed ...