hbase-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From git-site-r...@apache.org
Subject [hbase-site] branch asf-site updated: Published site at 335305e0cf1ae00b18d6e7fb26a0e3617a4481a6.
Date Tue, 01 Jun 2021 20:18:01 GMT
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 b7e95c1  Published site at 335305e0cf1ae00b18d6e7fb26a0e3617a4481a6.
b7e95c1 is described below

commit b7e95c19c8de8e3812d0a8b83c6c624951f77817
Author: jenkins <builds@apache.org>
AuthorDate: Tue Jun 1 20:17:36 2021 +0000

    Published site at 335305e0cf1ae00b18d6e7fb26a0e3617a4481a6.
---
 apache_hbase_reference_guide.pdf                   |     4 +-
 .../org/apache/hadoop/hbase/ScheduledChore.html    |    42 +-
 apidocs/org/apache/hadoop/hbase/client/Delete.html |     2 +-
 .../hadoop/hbase/mapred/TableRecordReaderImpl.html |    30 +-
 .../hadoop/hbase/mapreduce/HFileOutputFormat2.html |     8 +-
 .../apache/hadoop/hbase/mapreduce/ImportTsv.html   |    40 +-
 .../hbase/mapreduce/TableRecordReaderImpl.html     |    30 +-
 .../apache/hadoop/hbase/mapreduce/WALPlayer.html   |    26 +-
 .../apache/hadoop/hbase/rest/client/Client.html    |    88 +-
 .../hadoop/hbase/snapshot/ExportSnapshot.html      |    22 +-
 .../hbase/zookeeper/MiniZooKeeperCluster.html      |    30 +-
 .../org/apache/hadoop/hbase/ScheduledChore.html    |   666 +-
 .../org/apache/hadoop/hbase/client/Delete.html     |     2 +-
 .../hadoop/hbase/mapred/TableRecordReaderImpl.html |   435 +-
 .../hadoop/hbase/mapreduce/HFileOutputFormat2.html |  1066 +-
 .../apache/hadoop/hbase/mapreduce/ImportTsv.html   |  1487 +--
 .../hbase/mapreduce/TableRecordReaderImpl.html     |   611 +-
 .../apache/hadoop/hbase/mapreduce/WALPlayer.html   |   739 +-
 .../apache/hadoop/hbase/rest/client/Client.html    |  1581 +--
 .../hadoop/hbase/snapshot/ExportSnapshot.html      |  2183 ++--
 .../hbase/zookeeper/MiniZooKeeperCluster.html      |   790 +-
 book.html                                          |     2 +-
 checkstyle-aggregate.html                          | 11220 +++++++++----------
 checkstyle.rss                                     |    10 +-
 devapidocs/index-all.html                          |     4 +-
 .../org/apache/hadoop/hbase/HealthCheckChore.html  |    22 +-
 .../org/apache/hadoop/hbase/ScheduledChore.html    |    90 +-
 .../ServerMetricsBuilder.ServerMetricsImpl.html    |    68 +-
 .../apache/hadoop/hbase/ServerMetricsBuilder.html  |    80 +-
 .../hadoop/hbase/backup/impl/BackupManager.html    |    76 +-
 .../hadoop/hbase/client/ClientIdGenerator.html     |    12 +-
 .../org/apache/hadoop/hbase/client/Delete.html     |     2 +-
 .../hadoop/hbase/client/RegionInfoBuilder.html     |    46 +-
 .../example/ExampleMasterObserverWithMetrics.html  |    26 +-
 .../example/WriteHeavyIncrementObserver.html       |    34 +-
 .../apache/hadoop/hbase/hbtop/screen/Screen.html   |    26 +-
 .../hbase/hbtop/screen/top/TopScreenModel.html     |    68 +-
 .../hbase/hbtop/screen/top/TopScreenPresenter.html |    90 +-
 .../io/hfile/HFileBlock.BlockDeserializer.html     |     8 +-
 .../hbase/io/hfile/HFileBlock.BlockIterator.html   |     8 +-
 .../hbase/io/hfile/HFileBlock.BlockWritable.html   |     6 +-
 .../hadoop/hbase/io/hfile/HFileBlock.FSReader.html |    18 +-
 .../hbase/io/hfile/HFileBlock.FSReaderImpl.html    |    62 +-
 .../hadoop/hbase/io/hfile/HFileBlock.Header.html   |    18 +-
 .../io/hfile/HFileBlock.PrefetchedHeader.html      |    12 +-
 .../hbase/io/hfile/HFileBlock.Writer.State.html    |    12 +-
 .../hadoop/hbase/io/hfile/HFileBlock.Writer.html   |    84 +-
 .../apache/hadoop/hbase/io/hfile/HFileBlock.html   |   148 +-
 .../hadoop/hbase/io/hfile/HFileWriterImpl.html     |   134 +-
 .../hfile/LruAdaptiveBlockCache.BlockBucket.html   |    28 +-
 .../LruAdaptiveBlockCache.EvictionThread.html      |    18 +-
 .../LruAdaptiveBlockCache.StatisticsThread.html    |     8 +-
 .../hbase/io/hfile/LruAdaptiveBlockCache.html      |   202 +-
 .../hadoop/hbase/io/hfile/PrefetchExecutor.html    |    26 +-
 .../org/apache/hadoop/hbase/ipc/CallRunner.html    |    28 +-
 .../hadoop/hbase/ipc/NettyServerRpcConnection.html |    20 +-
 .../ipc/RpcServer.BlockingServiceAndInterface.html |    12 +-
 .../hadoop/hbase/ipc/RpcServer.CallCleanup.html    |     4 +-
 .../org/apache/hadoop/hbase/ipc/RpcServer.html     |   192 +-
 .../org/apache/hadoop/hbase/ipc/ServerCall.html    |   140 +-
 .../ipc/SimpleRpcServer.ConnectionManager.html     |    40 +-
 .../hbase/ipc/SimpleRpcServer.Listener.Reader.html |    14 +-
 .../hadoop/hbase/ipc/SimpleRpcServer.Listener.html |    30 +-
 .../apache/hadoop/hbase/ipc/SimpleRpcServer.html   |    40 +-
 .../hadoop/hbase/ipc/SimpleRpcServerResponder.html |    28 +-
 .../hbase/ipc/SimpleServerRpcConnection.html       |    58 +-
 .../hadoop/hbase/mapred/TableRecordReaderImpl.html |    56 +-
 .../mapreduce/HFileOutputFormat2.WriterLength.html |     8 +-
 .../hadoop/hbase/mapreduce/HFileOutputFormat2.html |    42 +-
 .../ImportTsv.TsvParser.BadTsvLineException.html   |     6 +-
 .../mapreduce/ImportTsv.TsvParser.ParsedLine.html  |    42 +-
 .../hbase/mapreduce/ImportTsv.TsvParser.html       |    66 +-
 .../apache/hadoop/hbase/mapreduce/ImportTsv.html   |    60 +-
 .../SyncTable.SyncMapper.CellScanner.html          |    18 +-
 .../mapreduce/SyncTable.SyncMapper.Counter.html    |    34 +-
 .../hbase/mapreduce/SyncTable.SyncMapper.html      |    66 +-
 .../apache/hadoop/hbase/mapreduce/SyncTable.html   |    58 +-
 .../hbase/mapreduce/TableRecordReaderImpl.html     |    64 +-
 .../hadoop/hbase/mapreduce/WALPlayer.Counter.html  |    16 +-
 .../mapreduce/WALPlayer.WALKeyValueMapper.html     |    12 +-
 .../hbase/mapreduce/WALPlayer.WALMapper.html       |    14 +-
 .../apache/hadoop/hbase/mapreduce/WALPlayer.html   |    38 +-
 .../master/HMaster.TableDescriptorGetter.html      |     4 +-
 .../org/apache/hadoop/hbase/master/HMaster.html    |   502 +-
 .../hadoop/hbase/master/MasterRpcServices.html     |    74 +-
 .../hadoop/hbase/master/RegionState.State.html     |    40 +-
 .../apache/hadoop/hbase/master/RegionState.html    |   106 +-
 .../ServerManager.FlushedSequenceIdFlusher.html    |     6 +-
 .../master/ServerManager.ServerLiveState.html      |     8 +-
 .../apache/hadoop/hbase/master/ServerManager.html  |    66 +-
 .../balancer/SimpleLoadBalancer.BalanceInfo.html   |    20 +-
 .../hbase/master/balancer/SimpleLoadBalancer.html  |    36 +-
 .../hadoop/hbase/master/cleaner/DirScanPool.html   |    30 +-
 .../cleaner/HFileCleaner.HFileDeleteTask.html      |    18 +-
 .../hadoop/hbase/master/cleaner/HFileCleaner.html  |   110 +-
 .../master/locking/LockManager.MasterLock.html     |    30 +-
 .../master/locking/LockManager.RemoteLocks.html    |    12 +-
 .../hadoop/hbase/master/locking/LockManager.html   |    20 +-
 .../locking/LockProcedure.LockInterface.html       |     6 +-
 .../LockProcedure.NamespaceExclusiveLock.html      |     8 +-
 .../locking/LockProcedure.RegionExclusiveLock.html |     8 +-
 .../locking/LockProcedure.TableExclusiveLock.html  |     8 +-
 .../locking/LockProcedure.TableSharedLock.html     |     8 +-
 .../hadoop/hbase/master/locking/LockProcedure.html |    96 +-
 .../MonitoredTaskImpl.StatusJournalEntryImpl.html  |    14 +-
 .../hadoop/hbase/monitoring/MonitoredTaskImpl.html |    76 +-
 .../hbase/namequeues/impl/SlowLogQueueService.html |    32 +-
 .../store/wal/WALProcedureStore.PushType.html      |    12 +-
 .../store/wal/WALProcedureStore.SyncMetrics.html   |    24 +-
 .../procedure2/store/wal/WALProcedureStore.html    |   244 +-
 .../hbase/regionserver/NoLimitScannerContext.html  |     2 +-
 .../hbase/regionserver/ScannerContext.Builder.html |    24 +-
 .../regionserver/ScannerContext.LimitFields.html   |    60 +-
 .../regionserver/ScannerContext.LimitScope.html    |    12 +-
 .../regionserver/ScannerContext.NextState.html     |    28 +-
 .../ScannerContext.ProgressFields.html             |    30 +-
 .../hadoop/hbase/regionserver/ScannerContext.html  |    94 +-
 .../regionserver/handler/WALSplitterHandler.html   |    20 +-
 .../hadoop/hbase/regionserver/wal/WALUtil.html     |    26 +-
 .../DumpReplicationQueues.DumpOptions.html         |    18 +-
 .../DumpReplicationQueues.WarnOnlyAbortable.html   |     8 +-
 .../DumpReplicationQueues.WarnOnlyStoppable.html   |     8 +-
 .../regionserver/DumpReplicationQueues.html        |    42 +-
 .../HBaseInterClusterReplicationEndpoint.html      |    88 +-
 .../replication/regionserver/MetricsSink.html      |    26 +-
 .../ReplicationSourceShipper.WorkerState.html      |    12 +-
 .../regionserver/ReplicationSourceShipper.html     |    66 +-
 .../ReplicationSyncUp.DummyServer.html             |    38 +-
 .../regionserver/ReplicationSyncUp.html            |    10 +-
 .../org/apache/hadoop/hbase/rest/RESTServer.html   |    66 +-
 .../hadoop/hbase/rest/ScannerResultGenerator.html  |    34 +-
 ...nt.ClientTrustStoreInitializationException.html |     4 +-
 .../apache/hadoop/hbase/rest/client/Client.html    |   116 +-
 ...nnerHDFSAclHelper.HDFSAclOperation.AclType.html |    12 +-
 ...erHDFSAclHelper.HDFSAclOperation.Operation.html |     4 +-
 ...FSAclHelper.HDFSAclOperation.OperationType.html |    10 +-
 ...pshotScannerHDFSAclHelper.HDFSAclOperation.html |    28 +-
 .../SnapshotScannerHDFSAclHelper.PathHelper.html   |    56 +-
 .../access/SnapshotScannerHDFSAclHelper.html       |   104 +-
 .../hadoop/hbase/slowlog/SlowLogTableAccessor.html |     8 +-
 .../hbase/snapshot/ExportSnapshot.Counter.html     |    20 +-
 .../snapshot/ExportSnapshot.ExportMapper.html      |    64 +-
 ...apshotInputFormat.ExportSnapshotInputSplit.html |    20 +-
 ...shotInputFormat.ExportSnapshotRecordReader.html |    24 +-
 .../ExportSnapshot.ExportSnapshotInputFormat.html  |     8 +-
 .../hbase/snapshot/ExportSnapshot.Options.html     |    28 +-
 .../hbase/snapshot/ExportSnapshot.Testing.html     |    12 +-
 .../hadoop/hbase/snapshot/ExportSnapshot.html      |    94 +-
 .../thrift/TBoundedThreadPoolServer.Args.html      |    10 +-
 ...TBoundedThreadPoolServer.ClientConnnection.html |     8 +-
 .../hbase/thrift/TBoundedThreadPoolServer.html     |    40 +-
 .../apache/hadoop/hbase/thrift/ThriftServer.html   |    98 +-
 .../util/compaction/MajorCompactionTTLRequest.html |    16 +-
 .../util/compaction/MajorCompactor.Compact.html    |    14 +-
 .../hbase/util/compaction/MajorCompactor.html      |    64 +-
 .../wal/AbstractWALRoller.RollController.html      |    20 +-
 .../apache/hadoop/hbase/wal/AbstractWALRoller.html |    42 +-
 .../hbase/wal/WALSplitUtil.MutationReplay.html     |    20 +-
 .../org/apache/hadoop/hbase/wal/WALSplitUtil.html  |    60 +-
 .../hadoop/hbase/zookeeper/MetaTableLocator.html   |    42 +-
 .../hbase/zookeeper/MiniZooKeeperCluster.html      |    72 +-
 .../hadoop/hbase/zookeeper/ZKNodeTracker.html      |    36 +-
 .../org/apache/hadoop/hbase/HealthCheckChore.html  |   150 +-
 .../org/apache/hadoop/hbase/ScheduledChore.html    |   666 +-
 .../ServerMetricsBuilder.ServerMetricsImpl.html    |   799 +-
 .../apache/hadoop/hbase/ServerMetricsBuilder.html  |   799 +-
 .../hadoop/hbase/backup/impl/BackupManager.html    |   979 +-
 .../hadoop/hbase/client/ClientIdGenerator.html     |   127 +-
 .../org/apache/hadoop/hbase/client/Delete.html     |     2 +-
 .../hadoop/hbase/client/RegionInfoBuilder.html     |   187 +-
 .../example/ExampleMasterObserverWithMetrics.html  |   221 +-
 .../example/WriteHeavyIncrementObserver.html       |   427 +-
 .../apache/hadoop/hbase/hbtop/screen/Screen.html   |   207 +-
 .../hbase/hbtop/screen/top/TopScreenModel.html     |   429 +-
 .../hbase/hbtop/screen/top/TopScreenPresenter.html |   637 +-
 .../apache/hadoop/hbase/http/NoCacheFilter.html    |     4 +-
 .../io/hadoopbackport/ThrottledInputStream.html    |     4 +-
 .../io/hfile/HFileBlock.BlockDeserializer.html     |  4063 +++----
 .../hbase/io/hfile/HFileBlock.BlockIterator.html   |  4063 +++----
 .../hbase/io/hfile/HFileBlock.BlockWritable.html   |  4063 +++----
 .../hadoop/hbase/io/hfile/HFileBlock.FSReader.html |  4063 +++----
 .../hbase/io/hfile/HFileBlock.FSReaderImpl.html    |  4063 +++----
 .../hadoop/hbase/io/hfile/HFileBlock.Header.html   |  4063 +++----
 .../io/hfile/HFileBlock.PrefetchedHeader.html      |  4063 +++----
 .../hbase/io/hfile/HFileBlock.Writer.State.html    |  4063 +++----
 .../hadoop/hbase/io/hfile/HFileBlock.Writer.html   |  4063 +++----
 .../apache/hadoop/hbase/io/hfile/HFileBlock.html   |  4063 +++----
 .../hadoop/hbase/io/hfile/HFileWriterImpl.html     |  1603 +--
 .../hfile/LruAdaptiveBlockCache.BlockBucket.html   |  2775 ++---
 .../LruAdaptiveBlockCache.EvictionThread.html      |  2775 ++---
 .../LruAdaptiveBlockCache.StatisticsThread.html    |  2775 ++---
 .../hbase/io/hfile/LruAdaptiveBlockCache.html      |  2775 ++---
 .../hadoop/hbase/io/hfile/PrefetchExecutor.html    |   213 +-
 .../org/apache/hadoop/hbase/ipc/CallRunner.html    |   403 +-
 .../hadoop/hbase/ipc/NettyServerRpcConnection.html |   191 +-
 .../ipc/RpcServer.BlockingServiceAndInterface.html |  1541 +--
 .../hadoop/hbase/ipc/RpcServer.CallCleanup.html    |  1541 +--
 .../org/apache/hadoop/hbase/ipc/RpcServer.html     |  1541 +--
 .../org/apache/hadoop/hbase/ipc/ServerCall.html    |  1079 +-
 .../ipc/SimpleRpcServer.ConnectionManager.html     |  1270 +--
 .../hbase/ipc/SimpleRpcServer.Listener.Reader.html |  1270 +--
 .../hadoop/hbase/ipc/SimpleRpcServer.Listener.html |  1270 +--
 .../apache/hadoop/hbase/ipc/SimpleRpcServer.html   |  1270 +--
 .../hadoop/hbase/ipc/SimpleRpcServerResponder.html |   561 +-
 .../hbase/ipc/SimpleServerRpcConnection.html       |   601 +-
 .../hadoop/hbase/mapred/TableRecordReaderImpl.html |   435 +-
 .../mapreduce/HFileOutputFormat2.TableInfo.html    |  1066 +-
 .../mapreduce/HFileOutputFormat2.WriterLength.html |  1066 +-
 .../hadoop/hbase/mapreduce/HFileOutputFormat2.html |  1066 +-
 .../ImportTsv.TsvParser.BadTsvLineException.html   |  1487 +--
 .../mapreduce/ImportTsv.TsvParser.ParsedLine.html  |  1487 +--
 .../hbase/mapreduce/ImportTsv.TsvParser.html       |  1487 +--
 .../apache/hadoop/hbase/mapreduce/ImportTsv.html   |  1487 +--
 .../SyncTable.SyncMapper.CellScanner.html          |  1649 +--
 .../mapreduce/SyncTable.SyncMapper.Counter.html    |  1649 +--
 .../hbase/mapreduce/SyncTable.SyncMapper.html      |  1649 +--
 .../apache/hadoop/hbase/mapreduce/SyncTable.html   |  1649 +--
 .../hbase/mapreduce/TableRecordReaderImpl.html     |   611 +-
 .../hadoop/hbase/mapreduce/WALPlayer.Counter.html  |   739 +-
 .../mapreduce/WALPlayer.WALKeyValueMapper.html     |   739 +-
 .../hbase/mapreduce/WALPlayer.WALMapper.html       |   739 +-
 .../apache/hadoop/hbase/mapreduce/WALPlayer.html   |   739 +-
 .../master/HMaster.TableDescriptorGetter.html      |  7181 ++++++------
 .../org/apache/hadoop/hbase/master/HMaster.html    |  7181 ++++++------
 .../MasterRpcServices.BalanceSwitchMode.html       |  1761 +--
 .../hadoop/hbase/master/MasterRpcServices.html     |  1761 +--
 .../hadoop/hbase/master/RegionState.State.html     |   851 +-
 .../apache/hadoop/hbase/master/RegionState.html    |   851 +-
 .../ServerManager.FlushedSequenceIdFlusher.html    |  1353 ++-
 .../master/ServerManager.ServerLiveState.html      |  1353 ++-
 .../apache/hadoop/hbase/master/ServerManager.html  |  1353 ++-
 ...ignmentManager.DeadServerMetricRegionChore.html |     4 +-
 .../AssignmentManager.RegionInTransitionChore.html |     4 +-
 .../AssignmentManager.RegionInTransitionStat.html  |     4 +-
 ...AssignmentManager.RegionMetaLoadingVisitor.html |     4 +-
 .../hbase/master/assignment/AssignmentManager.html |     4 +-
 .../RegionStateStore.RegionStateVisitor.html       |     4 +-
 .../hbase/master/assignment/RegionStateStore.html  |     4 +-
 .../balancer/SimpleLoadBalancer.BalanceInfo.html   |  1261 +--
 .../hbase/master/balancer/SimpleLoadBalancer.html  |  1261 +--
 .../hadoop/hbase/master/cleaner/DirScanPool.html   |   189 +-
 .../cleaner/HFileCleaner.HFileDeleteTask.html      |   941 +-
 .../hadoop/hbase/master/cleaner/HFileCleaner.html  |   941 +-
 .../master/locking/LockManager.MasterLock.html     |   475 +-
 .../master/locking/LockManager.RemoteLocks.html    |   475 +-
 .../hadoop/hbase/master/locking/LockManager.html   |   475 +-
 .../locking/LockProcedure.LockInterface.html       |   903 +-
 .../LockProcedure.NamespaceExclusiveLock.html      |   903 +-
 .../locking/LockProcedure.RegionExclusiveLock.html |   903 +-
 .../locking/LockProcedure.TableExclusiveLock.html  |   903 +-
 .../locking/LockProcedure.TableSharedLock.html     |   903 +-
 .../hadoop/hbase/master/locking/LockProcedure.html |   903 +-
 .../MemoryBoundedLogMessageBuffer.LogMessage.html  |     6 +-
 .../monitoring/MemoryBoundedLogMessageBuffer.html  |     6 +-
 .../hbase/monitoring/MonitoredRPCHandlerImpl.html  |     4 +-
 .../MonitoredTaskImpl.StatusJournalEntryImpl.html  |   530 +-
 .../hadoop/hbase/monitoring/MonitoredTaskImpl.html |   530 +-
 .../hbase/namequeues/impl/SlowLogQueueService.html |   457 +-
 .../ProcedureExecutor.KeepAliveWorkerThread.html   |     2 +-
 ...rocedureExecutor.ProcedureExecutorListener.html |     2 +-
 .../procedure2/ProcedureExecutor.Testing.html      |     2 +-
 .../ProcedureExecutor.WorkerMonitor.html           |     2 +-
 .../procedure2/ProcedureExecutor.WorkerThread.html |     2 +-
 .../hadoop/hbase/procedure2/ProcedureExecutor.html |     2 +-
 .../store/wal/WALProcedureStore.PushType.html      |  2729 ++---
 .../store/wal/WALProcedureStore.SyncMetrics.html   |  2729 ++---
 .../procedure2/store/wal/WALProcedureStore.html    |  2729 ++---
 .../HRegion.BatchOperation.Visitor.html            |     8 +-
 .../hbase/regionserver/HRegion.BatchOperation.html |     8 +-
 .../regionserver/HRegion.BulkLoadListener.html     |     8 +-
 .../regionserver/HRegion.FlushResult.Result.html   |     8 +-
 .../hbase/regionserver/HRegion.FlushResult.html    |     8 +-
 .../regionserver/HRegion.FlushResultImpl.html      |     8 +-
 .../HRegion.MutationBatchOperation.html            |     8 +-
 .../HRegion.ObservedExceptionsInBatch.html         |     8 +-
 .../regionserver/HRegion.PrepareFlushResult.html   |     8 +-
 .../regionserver/HRegion.ReplayBatchOperation.html |     8 +-
 .../hbase/regionserver/HRegion.RowLockContext.html |     8 +-
 .../hbase/regionserver/HRegion.RowLockImpl.html    |     8 +-
 .../hbase/regionserver/HRegion.WriteState.html     |     8 +-
 .../apache/hadoop/hbase/regionserver/HRegion.html  |     8 +-
 .../HRegionServer.CompactionChecker.html           |    20 +-
 .../HRegionServer.MovedRegionInfo.html             |    20 +-
 .../HRegionServer.PeriodicMemStoreFlusher.html     |    20 +-
 .../HRegionServer.SystemExitWhenAbortTimeout.html  |    20 +-
 .../hadoop/hbase/regionserver/HRegionServer.html   |    20 +-
 .../RSRpcServices.RegionScannerCloseCallBack.html  |     6 +-
 .../RSRpcServices.RegionScannerHolder.html         |     6 +-
 ...RSRpcServices.RegionScannerShippedCallBack.html |     6 +-
 .../RSRpcServices.RegionScannersCloseCallBack.html |     6 +-
 .../RSRpcServices.ScannerListener.html             |     6 +-
 .../hadoop/hbase/regionserver/RSRpcServices.html   |     6 +-
 .../hbase/regionserver/ScannerContext.Builder.html |  1467 +--
 .../regionserver/ScannerContext.LimitFields.html   |  1467 +--
 .../regionserver/ScannerContext.LimitScope.html    |  1467 +--
 .../regionserver/ScannerContext.NextState.html     |  1467 +--
 .../ScannerContext.ProgressFields.html             |  1467 +--
 .../hadoop/hbase/regionserver/ScannerContext.html  |  1467 +--
 .../compactions/Compactor.CellSinkFactory.html     |     2 +-
 .../compactions/Compactor.FileDetails.html         |     2 +-
 .../Compactor.InternalScannerFactory.html          |     2 +-
 .../hbase/regionserver/compactions/Compactor.html  |     2 +-
 .../regionserver/handler/WALSplitterHandler.html   |   143 +-
 .../regionserver/wal/AbstractFSWAL.WalProps.html   |     2 +-
 .../hbase/regionserver/wal/AbstractFSWAL.html      |     2 +-
 .../hadoop/hbase/regionserver/wal/WALUtil.html     |   375 +-
 .../DumpReplicationQueues.DumpOptions.html         |   746 +-
 .../DumpReplicationQueues.WarnOnlyAbortable.html   |   746 +-
 .../DumpReplicationQueues.WarnOnlyStoppable.html   |   746 +-
 .../regionserver/DumpReplicationQueues.html        |   746 +-
 .../HBaseInterClusterReplicationEndpoint.html      |  1116 +-
 .../replication/regionserver/MetricsSink.html      |   195 +-
 .../ReplicationSourceShipper.WorkerState.html      |   697 +-
 .../regionserver/ReplicationSourceShipper.html     |   697 +-
 .../ReplicationSyncUp.DummyServer.html             |   306 +-
 .../regionserver/ReplicationSyncUp.html            |   306 +-
 .../org/apache/hadoop/hbase/rest/RESTServer.html   |   841 +-
 .../hadoop/hbase/rest/ScannerResultGenerator.html  |   349 +-
 ...nt.ClientTrustStoreInitializationException.html |  1581 +--
 .../apache/hadoop/hbase/rest/client/Client.html    |  1581 +--
 ...nnerHDFSAclHelper.HDFSAclOperation.AclType.html |  1577 +--
 ...erHDFSAclHelper.HDFSAclOperation.Operation.html |  1577 +--
 ...FSAclHelper.HDFSAclOperation.OperationType.html |  1577 +--
 ...pshotScannerHDFSAclHelper.HDFSAclOperation.html |  1577 +--
 .../SnapshotScannerHDFSAclHelper.PathHelper.html   |  1577 +--
 .../access/SnapshotScannerHDFSAclHelper.html       |  1577 +--
 .../hadoop/hbase/slowlog/SlowLogTableAccessor.html |     8 +-
 .../hbase/snapshot/ExportSnapshot.Counter.html     |  2183 ++--
 .../snapshot/ExportSnapshot.ExportMapper.html      |  2183 ++--
 ...apshotInputFormat.ExportSnapshotInputSplit.html |  2183 ++--
 ...shotInputFormat.ExportSnapshotRecordReader.html |  2183 ++--
 .../ExportSnapshot.ExportSnapshotInputFormat.html  |  2183 ++--
 .../hbase/snapshot/ExportSnapshot.Options.html     |  2183 ++--
 .../hbase/snapshot/ExportSnapshot.Testing.html     |  2183 ++--
 .../hadoop/hbase/snapshot/ExportSnapshot.html      |  2183 ++--
 .../thrift/TBoundedThreadPoolServer.Args.html      |   577 +-
 ...TBoundedThreadPoolServer.ClientConnnection.html |   577 +-
 .../hbase/thrift/TBoundedThreadPoolServer.html     |   577 +-
 .../apache/hadoop/hbase/thrift/ThriftServer.html   |  1517 +--
 .../hadoop/hbase/tool/CanaryTool.Monitor.html      |    10 +-
 .../hbase/tool/CanaryTool.RegionMonitor.html       |    10 +-
 .../hbase/tool/CanaryTool.RegionServerMonitor.html |    10 +-
 .../tool/CanaryTool.RegionServerStdOutSink.html    |    10 +-
 .../hbase/tool/CanaryTool.RegionServerTask.html    |    10 +-
 .../hbase/tool/CanaryTool.RegionStdOutSink.html    |    10 +-
 .../hbase/tool/CanaryTool.RegionTask.TaskType.html |    10 +-
 .../hadoop/hbase/tool/CanaryTool.RegionTask.html   |    10 +-
 .../hbase/tool/CanaryTool.RegionTaskResult.html    |    10 +-
 .../apache/hadoop/hbase/tool/CanaryTool.Sink.html  |    10 +-
 .../hadoop/hbase/tool/CanaryTool.StdOutSink.html   |    10 +-
 .../hbase/tool/CanaryTool.ZookeeperMonitor.html    |    10 +-
 .../hbase/tool/CanaryTool.ZookeeperStdOutSink.html |    10 +-
 .../hbase/tool/CanaryTool.ZookeeperTask.html       |    10 +-
 .../org/apache/hadoop/hbase/tool/CanaryTool.html   |    10 +-
 .../hadoop/hbase/util/CoprocessorClassLoader.html  |     4 +-
 .../hbase/util/FSUtils.BlackListDirFilter.html     |     2 +-
 .../hadoop/hbase/util/FSUtils.DirFilter.html       |     2 +-
 .../hadoop/hbase/util/FSUtils.FamilyDirFilter.html |     2 +-
 .../hadoop/hbase/util/FSUtils.FileFilter.html      |     2 +-
 .../hadoop/hbase/util/FSUtils.HFileFilter.html     |     2 +-
 .../hadoop/hbase/util/FSUtils.HFileLinkFilter.html |     2 +-
 .../hbase/util/FSUtils.ProgressReporter.html       |     2 +-
 .../hbase/util/FSUtils.ReferenceFileFilter.html    |     2 +-
 .../hadoop/hbase/util/FSUtils.RegionDirFilter.html |     2 +-
 .../hbase/util/FSUtils.UserTableDirFilter.html     |     2 +-
 .../org/apache/hadoop/hbase/util/FSUtils.html      |     2 +-
 .../org/apache/hadoop/hbase/util/IdLock.Entry.html |     4 +-
 .../org/apache/hadoop/hbase/util/IdLock.html       |     4 +-
 .../hbase/util/JVMClusterUtil.MasterThread.html    |     4 +-
 .../util/JVMClusterUtil.RegionServerThread.html    |     4 +-
 .../apache/hadoop/hbase/util/JVMClusterUtil.html   |     4 +-
 .../util/ModifyRegionUtils.RegionEditTask.html     |     2 +-
 .../util/ModifyRegionUtils.RegionFillTask.html     |     2 +-
 .../hadoop/hbase/util/ModifyRegionUtils.html       |     2 +-
 .../org/apache/hadoop/hbase/util/Random64.html     |     4 +-
 .../apache/hadoop/hbase/util/ReflectionUtils.html  |     2 +-
 .../util/RegionSplitter.DecimalStringSplit.html    |     6 +-
 .../hbase/util/RegionSplitter.HexStringSplit.html  |     6 +-
 .../util/RegionSplitter.NumberStringSplit.html     |     6 +-
 .../hbase/util/RegionSplitter.SplitAlgorithm.html  |     6 +-
 .../hbase/util/RegionSplitter.UniformSplit.html    |     6 +-
 .../apache/hadoop/hbase/util/RegionSplitter.html   |     6 +-
 .../org/apache/hadoop/hbase/util/Sleeper.html      |     6 +-
 .../hbase/util/Threads.PrintThreadInfoHelper.html  |     4 +-
 .../util/Threads.PrintThreadInfoLazyHolder.html    |     4 +-
 .../org/apache/hadoop/hbase/util/Threads.html      |     4 +-
 .../util/compaction/MajorCompactionTTLRequest.html |   151 +-
 .../util/compaction/MajorCompactor.Compact.html    |   964 +-
 .../hbase/util/compaction/MajorCompactor.html      |   964 +-
 .../wal/AbstractWALRoller.RollController.html      |   506 +-
 .../apache/hadoop/hbase/wal/AbstractWALRoller.html |   506 +-
 .../hbase/wal/WALSplitUtil.MutationReplay.html     |  1065 +-
 .../org/apache/hadoop/hbase/wal/WALSplitUtil.html  |  1065 +-
 .../hadoop/hbase/zookeeper/MetaTableLocator.html   |   702 +-
 .../hbase/zookeeper/MiniZooKeeperCluster.html      |   790 +-
 .../hadoop/hbase/zookeeper/ZKNodeTracker.html      |   473 +-
 .../apache/hadoop/hbase/HBaseTestingUtility.html   |   480 +-
 .../org/apache/hadoop/hbase/MiniHBaseCluster.html  |   152 +-
 .../hadoop/hbase/codec/CodecPerformance.html       |     8 +-
 .../apache/hadoop/hbase/HBaseTestingUtility.html   |  8429 +++++++-------
 .../org/apache/hadoop/hbase/MiniHBaseCluster.html  |  1829 +--
 .../hadoop/hbase/codec/CodecPerformance.html       |   199 +-
 testdevapidocs/index-all.html                      |     2 +-
 .../hadoop/hbase/ChaosZKClient.TaskObject.html     |    12 +-
 .../org/apache/hadoop/hbase/ChaosZKClient.html     |    58 +-
 ...luster.ServerNameIgnoreStartCodeComparator.html |     6 +-
 .../hadoop/hbase/DistributedHBaseCluster.html      |    96 +-
 .../org/apache/hadoop/hbase/HBaseCluster.html      |    96 +-
 .../hbase/HBaseTestingUtility.SeenRowTracker.html  |    20 +-
 .../apache/hadoop/hbase/HBaseTestingUtility.html   |   540 +-
 ...anceEvaluation.GaussianRandomReadBenchmark.html |    10 +-
 .../HFilePerformanceEvaluation.ReadBenchmark.html  |    10 +-
 ...PerformanceEvaluation.RowOrientedBenchmark.html |    28 +-
 ...formanceEvaluation.SequentialReadBenchmark.html |    12 +-
 ...ormanceEvaluation.SequentialWriteBenchmark.html |    20 +-
 ...manceEvaluation.UniformRandomReadBenchmark.html |    10 +-
 ...rformanceEvaluation.UniformRandomSmallScan.html |    10 +-
 .../hadoop/hbase/HFilePerformanceEvaluation.html   |    38 +-
 .../hadoop/hbase/IntegrationTestBackupRestore.html |   106 +-
 .../apache/hadoop/hbase/IntegrationTestIngest.html |    66 +-
 .../hadoop/hbase/IntegrationTestManyRegions.html   |    40 +-
 ...caReplication.DelayingMultiThreadedUpdater.html |     8 +-
 ...icaReplication.DelayingMultiThreadedWriter.html |     8 +-
 .../IntegrationTestRegionReplicaReplication.html   |    24 +-
 ...iHBaseCluster.MiniHBaseClusterRegionServer.html |    22 +-
 ...BaseCluster.SingleFileSystemShutdownThread.html |     8 +-
 .../org/apache/hadoop/hbase/MiniHBaseCluster.html  |   162 +-
 .../MultithreadedTestUtil.RepeatingTestThread.html |    10 +-
 .../hbase/MultithreadedTestUtil.TestContext.html   |    34 +-
 .../hbase/MultithreadedTestUtil.TestThread.html    |    14 +-
 .../apache/hadoop/hbase/MultithreadedTestUtil.html |     8 +-
 .../hbase/PerformanceEvaluation.AppendTest.html    |     6 +-
 .../PerformanceEvaluation.AsyncRandomReadTest.html |    20 +-
 ...PerformanceEvaluation.AsyncRandomWriteTest.html |     6 +-
 .../hbase/PerformanceEvaluation.AsyncScanTest.html |    14 +-
 ...formanceEvaluation.AsyncSequentialReadTest.html |     6 +-
 ...ormanceEvaluation.AsyncSequentialWriteTest.html |    10 +-
 .../PerformanceEvaluation.AsyncTableTest.html      |    10 +-
 .../hbase/PerformanceEvaluation.AsyncTest.html     |     6 +-
 .../PerformanceEvaluation.BufferedMutatorTest.html |    12 +-
 .../hbase/PerformanceEvaluation.CASTableTest.html  |    12 +-
 .../PerformanceEvaluation.CheckAndDeleteTest.html  |     6 +-
 .../PerformanceEvaluation.CheckAndMutateTest.html  |     6 +-
 .../PerformanceEvaluation.CheckAndPutTest.html     |     6 +-
 .../hbase/PerformanceEvaluation.CleanMetaTest.html |     6 +-
 .../hbase/PerformanceEvaluation.CmdDescriptor.html |    16 +-
 .../hbase/PerformanceEvaluation.Counter.html       |    10 +-
 .../PerformanceEvaluation.EvaluationMapTask.html   |    16 +-
 .../PerformanceEvaluation.FilteredScanTest.html    |    10 +-
 .../hbase/PerformanceEvaluation.IncrementTest.html |     6 +-
 .../PerformanceEvaluation.MetaRandomReadTest.html  |    14 +-
 .../hbase/PerformanceEvaluation.MetaTest.html      |    10 +-
 .../hbase/PerformanceEvaluation.MetaWriteTest.html |     6 +-
 .../PerformanceEvaluation.RandomReadTest.html      |    18 +-
 ...nceEvaluation.RandomScanWithRange10000Test.html |     6 +-
 ...anceEvaluation.RandomScanWithRange1000Test.html |     6 +-
 ...manceEvaluation.RandomScanWithRange100Test.html |     6 +-
 ...rmanceEvaluation.RandomScanWithRange10Test.html |     6 +-
 ...formanceEvaluation.RandomScanWithRangeTest.html |    12 +-
 .../PerformanceEvaluation.RandomSeekScanTest.html  |     8 +-
 .../PerformanceEvaluation.RandomWriteTest.html     |     6 +-
 .../hbase/PerformanceEvaluation.RunResult.html     |    18 +-
 .../hbase/PerformanceEvaluation.ScanTest.html      |    10 +-
 .../PerformanceEvaluation.SequentialReadTest.html  |     6 +-
 .../PerformanceEvaluation.SequentialWriteTest.html |    10 +-
 .../hadoop/hbase/PerformanceEvaluation.Status.html |     4 +-
 .../hbase/PerformanceEvaluation.TableTest.html     |    10 +-
 .../hadoop/hbase/PerformanceEvaluation.Test.html   |     6 +-
 .../hbase/PerformanceEvaluation.TestBase.html      |    88 +-
 .../hbase/PerformanceEvaluation.TestOptions.html   |   266 +-
 .../apache/hadoop/hbase/PerformanceEvaluation.html |   106 +-
 .../hadoop/hbase/PerformanceEvaluationCommons.html |    18 +-
 ...formanceEvaluation.SeqShardedDataGenerator.html |    26 +-
 .../StripeCompactionsPerformanceEvaluation.html    |    82 +-
 .../apache/hadoop/hbase/TestCellComparator.html    |    40 +-
 .../hadoop/hbase/TestGlobalMemStoreSize.html       |    28 +-
 ...Fencing.BlockCompactionsInCompletionHStore.html |     8 +-
 ...Fencing.BlockCompactionsInCompletionRegion.html |     6 +-
 ...TestIOFencing.BlockCompactionsInPrepRegion.html |     6 +-
 .../TestIOFencing.CompactionBlockerRegion.html     |    22 +-
 .../org/apache/hadoop/hbase/TestIOFencing.html     |    24 +-
 .../hadoop/hbase/TestKeyValue.FailureCase.html     |    18 +-
 .../org/apache/hadoop/hbase/TestKeyValue.html      |    66 +-
 .../TestMetaTableLocator.WaitOnMetaThread.html     |     8 +-
 .../apache/hadoop/hbase/TestMetaTableLocator.html  |    32 +-
 .../hbase/TestMetaUpdatesGoToPriorityQueue.html    |    16 +-
 .../org/apache/hadoop/hbase/TestSerialization.html |    36 +-
 .../hbase/TestZooKeeper.MockLoadBalancer.html      |     8 +-
 .../org/apache/hadoop/hbase/TestZooKeeper.html     |    36 +-
 .../hadoop/hbase/Waiter.ExplainingPredicate.html   |     4 +-
 .../org/apache/hadoop/hbase/Waiter.Predicate.html  |     4 +-
 testdevapidocs/org/apache/hadoop/hbase/Waiter.html |    24 +-
 .../hadoop/hbase/backup/TestBackupManager.html     |    32 +-
 .../hadoop/hbase/backup/TestBackupSystemTable.html |    62 +-
 .../TestHFileArchiving.ArchivingFunction.html      |     4 +-
 .../hadoop/hbase/backup/TestHFileArchiving.html    |    74 +-
 .../apache/hadoop/hbase/backup/package-tree.html   |     2 +-
 .../chaos/actions/MoveRegionsOfTableAction.html    |    20 +-
 .../hbase/chaos/actions/SnapshotTableAction.html   |    16 +-
 .../hadoop/hbase/chaos/actions/package-tree.html   |     2 +-
 .../hbase/chaos/policies/PeriodicPolicy.html       |    12 +-
 ...shotFromClientAfterSplittingRegionTestBase.html |    10 +-
 ...hotFromClientCloneLinksAfterDeleteTestBase.html |     8 +-
 .../CloneSnapshotFromClientErrorTestBase.html      |     8 +-
 .../CloneSnapshotFromClientNormalTestBase.html     |    12 +-
 .../client/CloneSnapshotFromClientTestBase.html    |    36 +-
 .../RestoreSnapshotFromClientCloneTestBase.html    |    10 +-
 .../RestoreSnapshotFromClientSimpleTestBase.html   |     8 +-
 .../client/RestoreSnapshotFromClientTestBase.html  |    36 +-
 .../org/apache/hadoop/hbase/client/TestAdmin2.html |    84 +-
 .../org/apache/hadoop/hbase/client/TestAdmin3.html |    24 +-
 .../hbase/client/TestAsyncConnectionTracing.html   |    26 +-
 .../client/TestAsyncRegionLocatorTracing.html      |    30 +-
 .../apache/hadoop/hbase/client/TestAsyncTable.html |   112 +-
 .../hbase/client/TestAsyncTableAdminApi2.html      |    26 +-
 ...ictionFromClient.CustomInnerRegionObserver.html |    24 +-
 ...romClient.CustomInnerRegionObserverWrapper.html |     6 +-
 .../TestBlockEvictionFromClient.CustomScanner.html |    28 +-
 .../TestBlockEvictionFromClient.GetThread.html     |    14 +-
 ...TestBlockEvictionFromClient.MultiGetThread.html |    10 +-
 .../TestBlockEvictionFromClient.ScanThread.html    |    12 +-
 .../hbase/client/TestBlockEvictionFromClient.html  |    98 +-
 ...nerRPCTimeout.RSRpcServicesWithScanTimeout.html |    16 +-
 ...nnerRPCTimeout.RegionServerWithScanTimeout.html |     6 +-
 .../hbase/client/TestClientScannerRPCTimeout.html  |    30 +-
 .../hadoop/hbase/client/TestFromClientSide.html    |    68 +-
 ...ientSide3.WaitingForMultiMutationsObserver.html |    10 +-
 ...TestFromClientSide3.WaitingForScanObserver.html |    12 +-
 .../hadoop/hbase/client/TestFromClientSide3.html   |   106 +-
 .../hadoop/hbase/client/TestFromClientSide5.html   |    60 +-
 ...loneLinksAfterDelete.DelayFlushCoprocessor.html |     8 +-
 ...oneSnapshotFromClientCloneLinksAfterDelete.html |    20 +-
 .../hbase/client/TestMutationGetCellBuilder.html   |    16 +-
 .../client/TestPutDeleteEtcCellIteration.html      |    24 +-
 .../hadoop/hbase/client/TestRegionInfoBuilder.html |    34 +-
 .../hadoop/hbase/client/TestRegionInfoDisplay.html |    14 +-
 .../client/TestSnapshotCloneIndependence.html      |    82 +-
 .../hadoop/hbase/client/TestSnapshotMetadata.html  |    80 +-
 .../client/TestSnapshotTemporaryDirectory.html     |    52 +-
 .../hbase/client/TestTableSnapshotScanner.html     |    58 +-
 .../hbase/client/locking/TestEntityLocks.html      |    36 +-
 .../hadoop/hbase/codec/CodecPerformance.html       |    20 +-
 ...estCoprocessorMetrics.CustomMasterObserver.html |    16 +-
 ...estCoprocessorMetrics.CustomRegionEndpoint.html |    10 +-
 ...estCoprocessorMetrics.CustomRegionObserver.html |    12 +-
 ...stCoprocessorMetrics.CustomRegionObserver2.html |     4 +-
 ...rocessorMetrics.CustomRegionServerObserver.html |    12 +-
 .../TestCoprocessorMetrics.CustomWALObserver.html  |    12 +-
 .../hbase/coprocessor/TestCoprocessorMetrics.html  |    42 +-
 .../hbase/coprocessor/TestCoprocessorStop.html     |    12 +-
 .../TestRegionObserverStacking.ObserverA.html      |    10 +-
 .../TestRegionObserverStacking.ObserverB.html      |    10 +-
 .../TestRegionObserverStacking.ObserverC.html      |    10 +-
 .../coprocessor/TestRegionObserverStacking.html    |    14 +-
 .../hadoop/hbase/coprocessor/TestWALObserver.html  |    10 +-
 .../example/TestZooKeeperScanPolicyObserver.html   |    30 +-
 .../favored/TestFavoredNodeAssignmentHelper.html   |    68 +-
 .../hbase/filter/TestDependentColumnFilter.html    |    46 +-
 .../hbase/filter/TestFilterSerialization.html      |    60 +-
 .../filter/TestFuzzyRowAndColumnRangeFilter.html   |    26 +-
 .../hbase/filter/TestFuzzyRowFilterEndToEnd.html   |    52 +-
 .../apache/hadoop/hbase/fs/TestBlockReorder.html   |    30 +-
 .../hbase/fs/TestBlockReorderBlockLocation.html    |    30 +-
 .../hbase/fs/TestBlockReorderMultiBlocks.html      |    34 +-
 .../org/apache/hadoop/hbase/io/TestHeapSize.html   |    24 +-
 .../hbase/io/encoding/TestChangingEncoding.html    |    62 +-
 .../io/hfile/TestHFileBlock.BlockReaderThread.html |    16 +-
 .../hadoop/hbase/io/hfile/TestHFileBlock.html      |    96 +-
 .../hfile/TestHFileScannerImplReferenceCount.html  |    68 +-
 .../apache/hadoop/hbase/io/hfile/package-tree.html |     2 +-
 .../hbase/ipc/TestProtobufRpcServiceImpl.html      |    22 +-
 .../hadoop/hbase/ipc/TestSimpleRpcScheduler.html   |     8 +-
 .../IntegrationTestTableSnapshotInputFormat.html   |    50 +-
 .../hadoop/hbase/mapreduce/TestCellCounter.html    |    52 +-
 .../hadoop/hbase/mapreduce/TestCopyTable.html      |    70 +-
 .../TestImportExport.MetadataController.html       |     8 +-
 .../TestImportExport.TableWALActionListener.html   |    12 +-
 .../hadoop/hbase/mapreduce/TestImportExport.html   |    94 +-
 .../hadoop/hbase/mapreduce/TestRowCounter.html     |    92 +-
 .../hadoop/hbase/mapreduce/TestSyncTable.html      |    38 +-
 .../hadoop/hbase/mapreduce/TestWALInputFormat.html |     8 +-
 .../hbase/mapreduce/TestWALRecordReader.html       |    58 +-
 .../hadoop/hbase/master/AbstractTestDLS.html       |    66 +-
 .../TestActiveMasterManager.DummyMaster.html       |    12 +-
 ...stActiveMasterManager.NodeDeletionListener.html |    14 +-
 ...stActiveMasterManager.WaitToBeMasterThread.html |    12 +-
 .../hbase/master/TestActiveMasterManager.html      |    22 +-
 .../hbase/master/TestClockSkewDetection.html       |    10 +-
 .../hbase/master/TestMasterMetrics.MyMaster.html   |     8 +-
 .../master/TestMasterMetrics.MyRegionServer.html   |     6 +-
 .../hadoop/hbase/master/TestMasterMetrics.html     |    26 +-
 .../hbase/master/TestMasterMetricsWrapper.html     |    22 +-
 .../master/TestMetaAssignmentWithStopMaster.html   |    18 +-
 .../hadoop/hbase/master/TestRegionPlacement.html   |    52 +-
 .../TestSplitLogManager.DummyMasterServices.html   |    14 +-
 .../hbase/master/TestSplitLogManager.Expr.html     |     4 +-
 .../hadoop/hbase/master/TestSplitLogManager.html   |    62 +-
 .../hadoop/hbase/master/TestWarmupRegion.html      |    42 +-
 .../MockMasterServices.MockRegionStateStore.html   |     6 +-
 .../master/assignment/MockMasterServices.html      |    72 +-
 .../master/assignment/TestAssignmentManager.html   |    40 +-
 ...tManagerBase.CallQueueTooBigOnceRsExecutor.html |    10 +-
 ...TestAssignmentManagerBase.FaultyRsExecutor.html |     8 +-
 .../TestAssignmentManagerBase.GoodRsExecutor.html  |     8 +-
 ...ManagerBase.HangOnCloseThenRSCrashExecutor.html |    10 +-
 ...ignmentManagerBase.HangThenRSCrashExecutor.html |     8 +-
 ...nmentManagerBase.HangThenRSRestartExecutor.html |     8 +-
 .../TestAssignmentManagerBase.MockRSExecutor.html  |     4 +-
 ...e.MockRSProcedureDispatcher.MockRemoteCall.html |     6 +-
 ...nmentManagerBase.MockRSProcedureDispatcher.html |    10 +-
 .../TestAssignmentManagerBase.NoopRsExecutor.html  |    10 +-
 .../TestAssignmentManagerBase.RandRsExecutor.html  |    12 +-
 ...tManagerBase.ServerNotYetRunningRsExecutor.html |     6 +-
 ...ignmentManagerBase.SocketTimeoutRsExecutor.html |    12 +-
 ...rBase.TimeoutThenCallQueueTooBigRsExecutor.html |    12 +-
 .../assignment/TestAssignmentManagerBase.html      |    98 +-
 .../master/assignment/TestRegionReplicaSplit.html  |    28 +-
 .../hbase/master/assignment/TestRegionStates.html  |    36 +-
 .../master/assignment/TestRogueRSAssignment.html   |    44 +-
 .../cleaner/TestLogsCleaner.DummyServer.html       |     8 +-
 .../TestLogsCleaner.FaultyZooKeeperWatcher.html    |    10 +-
 .../hbase/master/cleaner/TestLogsCleaner.html      |    34 +-
 .../TestReplicationHFileCleaner.DummyServer.html   |     8 +-
 ...icationHFileCleaner.FaultyZooKeeperWatcher.html |    10 +-
 .../cleaner/TestReplicationHFileCleaner.html       |    38 +-
 .../hbase/master/janitor/TestCatalogJanitor.html   |    56 +-
 .../master/janitor/TestCatalogJanitorCluster.html  |    42 +-
 .../janitor/TestCatalogJanitorInMemoryStates.html  |    24 +-
 .../hadoop/hbase/master/janitor/TestMetaFixer.html |    38 +-
 .../hbase/master/locking/TestLockProcedure.html    |    90 +-
 ...reTestingUtility.InjectAbortOnLoadListener.html |    16 +-
 .../MasterProcedureTestingUtility.StepHook.html    |     4 +-
 .../procedure/MasterProcedureTestingUtility.html   |    58 +-
 .../procedure/TestCloneSnapshotProcedure.html      |    28 +-
 .../procedure/TestRestoreSnapshotProcedure.html    |    54 +-
 .../procedure/TestSafemodeBringsDownMaster.html    |    26 +-
 .../hbase/master/region/MasterRegionTestBase.html  |    32 +-
 .../master/region/TestMasterRegionCompaction.html  |    20 +-
 .../region/TestMasterRegionOnTwoFileSystems.html   |    38 +-
 .../org/apache/hadoop/hbase/mob/MobTestUtil.html   |    20 +-
 .../hbase/mob/TestExpiredMobFileCleaner.html       |    42 +-
 .../hadoop/hbase/mob/TestMobDataBlockEncoding.html |    42 +-
 .../hadoop/hbase/mob/TestMobStoreCompaction.html   |    60 +-
 .../hadoop/hbase/mob/TestMobStoreScanner.html      |    80 +-
 .../org/apache/hadoop/hbase/package-tree.html      |    16 +-
 ...chedulerConcurrency.TestProcedureWithEvent.html |     8 +-
 .../TestProcedureSchedulerConcurrency.html         |    20 +-
 .../hadoop/hbase/procedure2/package-tree.html      |     4 +-
 ...ProcedureStorePerformanceEvaluation.Worker.html |     8 +-
 .../store/ProcedureStorePerformanceEvaluation.html |     2 +-
 ...dureStorePerformanceEvaluation.DummyServer.html |    12 +-
 .../RegionProcedureStorePerformanceEvaluation.html |    16 +-
 .../region/RegionProcedureStoreTestHelper.html     |     8 +-
 .../store/region/TestRegionProcedureStore.html     |    18 +-
 ...WALLoaderPerformanceEvaluation.LoadCounter.html |    10 +-
 .../ProcedureWALLoaderPerformanceEvaluation.html   |    58 +-
 .../TestCompactingToCellFlatMapMemStore.html       |    56 +-
 .../TestCompactionState.StateSource.html           |    10 +-
 .../hbase/regionserver/TestCompactionState.html    |    46 +-
 .../regionserver/TestDataBlockEncodingTool.html    |    30 +-
 ...TestEndToEndSplitTransaction.RegionChecker.html |    24 +-
 ...estEndToEndSplitTransaction.RegionSplitter.html |    22 +-
 .../regionserver/TestEndToEndSplitTransaction.html |    36 +-
 .../hadoop/hbase/regionserver/TestHMobStore.html   |    92 +-
 ...estHRegionServerBulkLoad.AtomicHFileLoader.html |    12 +-
 ...TestHRegionServerBulkLoad.AtomicScanReader.html |    16 +-
 ...RegionServerBulkLoad.FindBulkHBaseListener.html |    10 +-
 .../TestHRegionServerBulkLoad.MyObserver.html      |    10 +-
 .../regionserver/TestHRegionServerBulkLoad.html    |    44 +-
 .../hadoop/hbase/regionserver/TestHStoreFile.html  |    90 +-
 .../hbase/regionserver/TestMajorCompaction.html    |    72 +-
 ...tMasterAddressTracker.NodeCreationListener.html |    14 +-
 .../regionserver/TestMasterAddressTracker.html     |    34 +-
 .../regionserver/TestMemStoreSegmentsIterator.html |    42 +-
 ...estRegionIncrement.CrossRowCellIncrementer.html |    12 +-
 .../TestRegionIncrement.SingleCellIncrementer.html |    12 +-
 .../hbase/regionserver/TestRegionIncrement.html    |    32 +-
 .../hadoop/hbase/regionserver/TestRegionInfo.html  |    46 +-
 ...stRegionMergeTransactionOnCluster.MyMaster.html |     6 +-
 ...geTransactionOnCluster.MyMasterRpcServices.html |    10 +-
 .../TestRegionMergeTransactionOnCluster.html       |    62 +-
 .../hadoop/hbase/regionserver/TestRegionOpen.html  |    24 +-
 .../hbase/regionserver/TestRegionReplicas.html     |    48 +-
 ...rverAbortTimeout.SleepWhenCloseCoprocessor.html |     8 +-
 ...ionServerAbortTimeout.TestAbortTimeoutTask.html |     6 +-
 .../regionserver/TestRegionServerAbortTimeout.html |    28 +-
 ...stRegionServerReportForDuty.MyRegionServer.html |    14 +-
 .../TestRegionServerReportForDuty.html             |     8 +-
 .../hbase/regionserver/TestReversibleScanners.html |    82 +-
 .../regionserver/TestRowPrefixBloomFilter.html     |    62 +-
 .../hadoop/hbase/regionserver/TestScanner.html     |    66 +-
 .../regionserver/TestScannerWithBulkload.html      |    30 +-
 .../regionserver/TestSimpleTimeRangeTracker.html   |    26 +-
 .../TestStoreFileScannerWithTagCompression.html    |    22 +-
 .../TestStoreScanner.CellGridStoreScanner.html     |    18 +-
 ...ner.CellWithVersionsNoOptimizeStoreScanner.html |    10 +-
 ...tStoreScanner.CellWithVersionsStoreScanner.html |    10 +-
 .../TestStoreScanner.KeyValueHeapWithCount.html    |     8 +-
 .../hbase/regionserver/TestStoreScanner.html       |   108 +-
 .../regionserver/TestWALLockup.DodgyFSLog.html     |    14 +-
 .../hadoop/hbase/regionserver/TestWALLockup.html   |    34 +-
 .../hadoop/hbase/regionserver/TestWideScanner.html |    30 +-
 .../regionserver/compactions/TestCloseChecker.html |     8 +-
 .../hadoop/hbase/regionserver/package-tree.html    |     2 +-
 .../TestCompactionWithThroughputController.html    |    32 +-
 .../wal/AbstractTestLogRollPeriod.html             |    20 +-
 .../regionserver/wal/AbstractTestProtobufLog.html  |    28 +-
 .../AbstractTestWALReplay.CustomStoreFlusher.html  |     8 +-
 .../wal/AbstractTestWALReplay.MockWAL.html         |     8 +-
 .../wal/AbstractTestWALReplay.TestFlusher.html     |    18 +-
 .../regionserver/wal/AbstractTestWALReplay.html    |    56 +-
 .../hbase/regionserver/wal/TestAsyncFSWAL.html     |    20 +-
 .../regionserver/wal/TestCombinedAsyncWriter.html  |    28 +-
 .../hbase/regionserver/wal/TestDurability.html     |    50 +-
 .../hbase/regionserver/wal/TestLogRollAbort.html   |    36 +-
 .../hbase/regionserver/wal/TestLogRolling.html     |    18 +-
 .../wal/TestLogRollingNoCluster.Appender.html      |    20 +-
 ...tLogRollingNoCluster.HighLatencySyncWriter.html |     6 +-
 .../regionserver/wal/TestLogRollingNoCluster.html  |    16 +-
 .../TestReplicationEmptyWALRecovery.html           |    32 +-
 ...ionEndpoint.EverythingPassesWALEntryFilter.html |    10 +-
 ...int.EverythingPassesWALEntryFilterSubclass.html |     4 +-
 ...int.InterClusterReplicationEndpointForTest.html |    12 +-
 ...icationEndpoint.ReplicationEndpointForTest.html |    30 +-
 ...Endpoint.ReplicationEndpointReturningFalse.html |    12 +-
 ...oint.ReplicationEndpointWithWALEntryFilter.html |    10 +-
 ...ndpoint.SleepingReplicationEndpointForTest.html |    10 +-
 .../hbase/replication/TestReplicationEndpoint.html |    40 +-
 .../hbase/replication/TestReplicationKillRS.html   |    12 +-
 .../replication/TestReplicationSmallTests.html     |     4 +-
 ...ALEntryFilters.FilterAllCellsWALCellFilter.html |     8 +-
 ...LEntryFilters.FilterSomeCellsWALCellFilter.html |     8 +-
 .../TestReplicationWALEntryFilters.html            |    36 +-
 .../hbase/replication/TestVerifyReplication.html   |    40 +-
 .../replication/TestVerifyReplicationAdjunct.html  |    32 +-
 .../TestVerifyReplicationCrossDiffHdfs.html        |    38 +-
 .../master/TestRecoverStandbyProcedure.html        |    52 +-
 .../regionserver/TestDumpReplicationQueues.html    |     8 +-
 ...InterClusterReplicationEndpointFilterEdits.html |    32 +-
 .../regionserver/TestReplicationSink.html          |    60 +-
 ...ationSourceManager.DummyNodeFailoverWorker.html |    16 +-
 .../TestReplicationSourceManager.DummyServer.html  |    14 +-
 ...nager.FailInitializeDummyReplicationSource.html |     6 +-
 .../regionserver/TestReplicationSourceManager.html |    34 +-
 ...TestSerialReplicationEndpoint.TestEndpoint.html |    16 +-
 .../TestSerialReplicationEndpoint.html             |    24 +-
 .../TestWALEntryStream.FailingWALEntryFilter.html  |    12 +-
 .../TestWALEntryStream.PathWatcher.html            |     8 +-
 ...stWALEntryStream.WALEntryStreamWithRetries.html |     8 +-
 .../regionserver/TestWALEntryStream.html           |   114 +-
 .../PerformanceEvaluation.BufferedMutatorTest.html |    12 +-
 .../rest/PerformanceEvaluation.CmdDescriptor.html  |    16 +-
 .../hbase/rest/PerformanceEvaluation.Counter.html  |    10 +-
 .../PerformanceEvaluation.EvaluationMapTask.html   |    18 +-
 .../PerformanceEvaluation.FilteredScanTest.html    |    10 +-
 ...nceEvaluation.PeInputFormat.PeRecordReader.html |    24 +-
 .../rest/PerformanceEvaluation.PeInputFormat.html  |     8 +-
 .../rest/PerformanceEvaluation.PeInputSplit.html   |    46 +-
 .../rest/PerformanceEvaluation.RandomReadTest.html |     8 +-
 ...nceEvaluation.RandomScanWithRange10000Test.html |     6 +-
 ...anceEvaluation.RandomScanWithRange1000Test.html |     6 +-
 ...manceEvaluation.RandomScanWithRange100Test.html |     6 +-
 ...rmanceEvaluation.RandomScanWithRange10Test.html |     6 +-
 ...formanceEvaluation.RandomScanWithRangeTest.html |    12 +-
 .../PerformanceEvaluation.RandomSeekScanTest.html  |     8 +-
 .../PerformanceEvaluation.RandomWriteTest.html     |     6 +-
 .../hbase/rest/PerformanceEvaluation.ScanTest.html |    10 +-
 .../PerformanceEvaluation.SequentialReadTest.html  |     6 +-
 .../PerformanceEvaluation.SequentialWriteTest.html |     6 +-
 .../hbase/rest/PerformanceEvaluation.Status.html   |     4 +-
 .../rest/PerformanceEvaluation.TableTest.html      |    10 +-
 .../hbase/rest/PerformanceEvaluation.Test.html     |    44 +-
 .../rest/PerformanceEvaluation.TestOptions.html    |    40 +-
 .../hadoop/hbase/rest/PerformanceEvaluation.html   |   102 +-
 .../TestRemoteAdminRetries.CallExecutor.html       |     4 +-
 .../hbase/rest/client/TestRemoteAdminRetries.html  |    38 +-
 .../TestRemoteHTableRetries.CallExecutor.html      |     4 +-
 .../hbase/rest/client/TestRemoteHTableRetries.html |    48 +-
 .../hadoop/hbase/rest/client/TestRemoteTable.html  |    78 +-
 .../hbase/rsgroup/EnableRSGroupsTestBase.html      |    16 +-
 .../hadoop/hbase/rsgroup/TestRSGroupsAdmin2.html   |    44 +-
 ...tAccessController.BulkLoadAccessTestAction.html |    10 +-
 .../TestAccessController.BulkLoadHelper.html       |    18 +-
 ...ssController.MyShellBasedUnixGroupsMapping.html |     6 +-
 .../TestAccessController.PingCoprocessor.html      |    20 +-
 ...TestAccessController.TestTableDDLProcedure.html |    22 +-
 .../security/access/TestAccessController.html      |   264 +-
 ...stZKSecretWatcherRefreshKeys.MockAbortable.html |    10 +-
 .../token/TestZKSecretWatcherRefreshKeys.html      |    18 +-
 .../hbase/snapshot/SnapshotTestingUtils.html       |    10 +-
 .../TestExportSnapshot.RegionPredicate.html        |     4 +-
 .../hadoop/hbase/snapshot/TestExportSnapshot.html  |    66 +-
 .../snapshot/TestExportSnapshotV1NoCluster.html    |    24 +-
 .../snapshot/TestFlushSnapshotFromClient.html      |    56 +-
 .../TestRestoreFlushSnapshotFromClient.html        |    56 +-
 .../test/IntegrationTestBigLinkedList.CINode.html  |    12 +-
 .../test/IntegrationTestBigLinkedList.Clean.html   |     6 +-
 .../test/IntegrationTestBigLinkedList.Delete.html  |     6 +-
 ...egrationTestBigLinkedList.Generator.Counts.html |    14 +-
 ...r.GeneratorInputFormat.GeneratorInputSplit.html |    12 +-
 ...GeneratorInputFormat.GeneratorRecordReader.html |    22 +-
 ...gLinkedList.Generator.GeneratorInputFormat.html |     8 +-
 ...Generator.GeneratorMapper.ConcurrentWalker.html |     8 +-
 ...GeneratorMapper.ContinuousConcurrentWalker.html |    18 +-
 ...estBigLinkedList.Generator.GeneratorMapper.html |    60 +-
 ...gLinkedList.Generator.OneFilePerMapperSFIF.html |     6 +-
 .../IntegrationTestBigLinkedList.Generator.html    |    30 +-
 .../test/IntegrationTestBigLinkedList.Loop.html    |    16 +-
 .../test/IntegrationTestBigLinkedList.Print.html   |     6 +-
 ...dList.Search.WALSearcher.WALMapperSearcher.html |    12 +-
 ...rationTestBigLinkedList.Search.WALSearcher.html |     6 +-
 .../test/IntegrationTestBigLinkedList.Search.html  |    22 +-
 ...IntegrationTestBigLinkedList.Verify.Counts.html |    20 +-
 ...ationTestBigLinkedList.Verify.VerifyMapper.html |    14 +-
 ...tionTestBigLinkedList.Verify.VerifyReducer.html |    28 +-
 .../test/IntegrationTestBigLinkedList.Verify.html  |    26 +-
 .../test/IntegrationTestBigLinkedList.Walker.html  |     6 +-
 .../IntegrationTestBigLinkedList.WalkerBase.html   |     8 +-
 .../hbase/test/IntegrationTestBigLinkedList.html   |    82 +-
 .../IntegrationTestLoadCommonCrawl.Counts.html     |    12 +-
 ...rationTestLoadCommonCrawl.HBaseKeyWritable.html |    76 +-
 ...ionTestLoadCommonCrawl.Loader.LoaderMapper.html |    18 +-
 .../IntegrationTestLoadCommonCrawl.Loader.html     |    16 +-
 ...onTestLoadCommonCrawl.OneFilePerMapperSFIF.html |     6 +-
 ...ionTestLoadCommonCrawl.Verify.VerifyMapper.html |    14 +-
 .../IntegrationTestLoadCommonCrawl.Verify.html     |    14 +-
 .../hbase/test/IntegrationTestLoadCommonCrawl.html |    58 +-
 ...eader.TimeBoundedMultiThreadedReaderThread.html |    10 +-
 ...meBoundedMultiThreadedReader.TimeoutThread.html |    10 +-
 ...ionReplicas.TimeBoundedMultiThreadedReader.html |    22 +-
 ...nTestTimeBoundedRequestsWithRegionReplicas.html |    32 +-
 .../org/apache/hadoop/hbase/test/package-tree.html |     6 +-
 .../TestThriftServer.MySlowHBaseHandler.html       |     6 +-
 .../hadoop/hbase/thrift/TestThriftServer.html      |   112 +-
 .../hadoop/hbase/thrift2/TestThriftConnection.html |   110 +-
 ...HBaseServiceHandler.DelayingRegionObserver.html |    14 +-
 .../thrift2/TestThriftHBaseServiceHandler.html     |   122 +-
 .../apache/hadoop/hbase/util/HFileTestUtil.html    |     2 +-
 .../MultiThreadedWriterBase.WroteKeysTracker.html  |     6 +-
 .../hadoop/hbase/util/MultiThreadedWriterBase.html |    12 +-
 .../hbase/util/TestDefaultEnvironmentEdge.html     |     8 +-
 ...Utils.AlwaysFailSetStoragePolicyFileSystem.html |     6 +-
 .../org/apache/hadoop/hbase/util/TestFSUtils.html  |    46 +-
 .../hbase/util/compaction/TestMajorCompactor.html  |    18 +-
 .../apache/hadoop/hbase/wal/TestCompressedWAL.html |    26 +-
 .../hadoop/hbase/wal/TestFSHLogProvider.html       |    42 +-
 .../org/apache/hadoop/hbase/wal/TestSecureWAL.html |    22 +-
 ...estSyncReplicationWALProvider.InfoProvider.html |     8 +-
 .../hbase/wal/TestSyncReplicationWALProvider.html  |    30 +-
 .../wal/TestWALFactory.BrokenWALCellCodec.html     |    10 +-
 .../wal/TestWALFactory.DumbWALActionsListener.html |    10 +-
 .../hbase/wal/TestWALFactory.InputStreamProxy.html |    10 +-
 .../apache/hadoop/hbase/wal/TestWALFactory.html    |    68 +-
 .../apache/hadoop/hbase/wal/TestWALMethods.html    |    26 +-
 .../hadoop/hbase/wal/TestWALReaderOnSecureWAL.html |    26 +-
 .../apache/hadoop/hbase/wal/TestWALRootDir.html    |    42 +-
 .../hadoop/hbase/wal/TestWALSplitToHFile.html      |    32 +-
 .../WALPerformanceEvaluation.WALPutBenchmark.html  |    18 +-
 .../hadoop/hbase/wal/WALPerformanceEvaluation.html |    62 +-
 .../org/apache/hadoop/hbase/wal/package-tree.html  |     2 +-
 .../hadoop/hbase/ChaosZKClient.TaskObject.html     |   619 +-
 .../org/apache/hadoop/hbase/ChaosZKClient.html     |   619 +-
 ...luster.ServerNameIgnoreStartCodeComparator.html |   969 +-
 .../hadoop/hbase/DistributedHBaseCluster.html      |   969 +-
 .../org/apache/hadoop/hbase/HBaseCluster.html      |   745 +-
 .../hbase/HBaseTestingUtility.SeenRowTracker.html  |  8429 +++++++-------
 .../apache/hadoop/hbase/HBaseTestingUtility.html   |  8429 +++++++-------
 ...anceEvaluation.GaussianRandomReadBenchmark.html |  1071 +-
 .../HFilePerformanceEvaluation.ReadBenchmark.html  |  1071 +-
 ...PerformanceEvaluation.RowOrientedBenchmark.html |  1071 +-
 ...formanceEvaluation.SequentialReadBenchmark.html |  1071 +-
 ...ormanceEvaluation.SequentialWriteBenchmark.html |  1071 +-
 ...manceEvaluation.UniformRandomReadBenchmark.html |  1071 +-
 ...rformanceEvaluation.UniformRandomSmallScan.html |  1071 +-
 .../hadoop/hbase/HFilePerformanceEvaluation.html   |  1071 +-
 .../hadoop/hbase/IntegrationTestBackupRestore.html |   821 +-
 .../apache/hadoop/hbase/IntegrationTestIngest.html |   469 +-
 .../hadoop/hbase/IntegrationTestManyRegions.html   |   217 +-
 ...caReplication.DelayingMultiThreadedUpdater.html |   401 +-
 ...icaReplication.DelayingMultiThreadedWriter.html |   401 +-
 .../IntegrationTestRegionReplicaReplication.html   |   401 +-
 ...iHBaseCluster.MiniHBaseClusterRegionServer.html |  1829 +--
 ...BaseCluster.SingleFileSystemShutdownThread.html |  1829 +--
 .../org/apache/hadoop/hbase/MiniHBaseCluster.html  |  1829 +--
 .../MultithreadedTestUtil.RepeatingTestThread.html |   335 +-
 .../hbase/MultithreadedTestUtil.TestContext.html   |   335 +-
 .../hbase/MultithreadedTestUtil.TestThread.html    |   335 +-
 .../apache/hadoop/hbase/MultithreadedTestUtil.html |   335 +-
 .../hbase/PerformanceEvaluation.AppendTest.html    |  6021 +++++-----
 .../PerformanceEvaluation.AsyncRandomReadTest.html |  6021 +++++-----
 ...PerformanceEvaluation.AsyncRandomWriteTest.html |  6021 +++++-----
 .../hbase/PerformanceEvaluation.AsyncScanTest.html |  6021 +++++-----
 ...formanceEvaluation.AsyncSequentialReadTest.html |  6021 +++++-----
 ...ormanceEvaluation.AsyncSequentialWriteTest.html |  6021 +++++-----
 .../PerformanceEvaluation.AsyncTableTest.html      |  6021 +++++-----
 .../hbase/PerformanceEvaluation.AsyncTest.html     |  6021 +++++-----
 .../PerformanceEvaluation.BufferedMutatorTest.html |  6021 +++++-----
 .../hbase/PerformanceEvaluation.CASTableTest.html  |  6021 +++++-----
 .../PerformanceEvaluation.CheckAndDeleteTest.html  |  6021 +++++-----
 .../PerformanceEvaluation.CheckAndMutateTest.html  |  6021 +++++-----
 .../PerformanceEvaluation.CheckAndPutTest.html     |  6021 +++++-----
 .../hbase/PerformanceEvaluation.CleanMetaTest.html |  6021 +++++-----
 .../hbase/PerformanceEvaluation.CmdDescriptor.html |  6021 +++++-----
 .../hbase/PerformanceEvaluation.Counter.html       |  6021 +++++-----
 .../PerformanceEvaluation.EvaluationMapTask.html   |  6021 +++++-----
 .../PerformanceEvaluation.FilteredScanTest.html    |  6021 +++++-----
 .../hbase/PerformanceEvaluation.IncrementTest.html |  6021 +++++-----
 .../PerformanceEvaluation.MetaRandomReadTest.html  |  6021 +++++-----
 .../hbase/PerformanceEvaluation.MetaTest.html      |  6021 +++++-----
 .../hbase/PerformanceEvaluation.MetaWriteTest.html |  6021 +++++-----
 .../PerformanceEvaluation.RandomReadTest.html      |  6021 +++++-----
 ...nceEvaluation.RandomScanWithRange10000Test.html |  6021 +++++-----
 ...anceEvaluation.RandomScanWithRange1000Test.html |  6021 +++++-----
 ...manceEvaluation.RandomScanWithRange100Test.html |  6021 +++++-----
 ...rmanceEvaluation.RandomScanWithRange10Test.html |  6021 +++++-----
 ...formanceEvaluation.RandomScanWithRangeTest.html |  6021 +++++-----
 .../PerformanceEvaluation.RandomSeekScanTest.html  |  6021 +++++-----
 .../PerformanceEvaluation.RandomWriteTest.html     |  6021 +++++-----
 .../hbase/PerformanceEvaluation.RunResult.html     |  6021 +++++-----
 .../hbase/PerformanceEvaluation.ScanTest.html      |  6021 +++++-----
 .../PerformanceEvaluation.SequentialReadTest.html  |  6021 +++++-----
 .../PerformanceEvaluation.SequentialWriteTest.html |  6021 +++++-----
 .../hadoop/hbase/PerformanceEvaluation.Status.html |  6021 +++++-----
 .../hbase/PerformanceEvaluation.TableTest.html     |  6021 +++++-----
 .../hadoop/hbase/PerformanceEvaluation.Test.html   |  6021 +++++-----
 .../hbase/PerformanceEvaluation.TestBase.html      |  6021 +++++-----
 .../hbase/PerformanceEvaluation.TestOptions.html   |  6021 +++++-----
 .../apache/hadoop/hbase/PerformanceEvaluation.html |  6021 +++++-----
 .../hadoop/hbase/PerformanceEvaluationCommons.html |   123 +-
 ...formanceEvaluation.SeqShardedDataGenerator.html |   636 +-
 .../StripeCompactionsPerformanceEvaluation.html    |   636 +-
 .../apache/hadoop/hbase/TestCellComparator.html    |   439 +-
 .../hadoop/hbase/TestGlobalMemStoreSize.html       |   311 +-
 ...Fencing.BlockCompactionsInCompletionHStore.html |   683 +-
 ...Fencing.BlockCompactionsInCompletionRegion.html |   683 +-
 ...TestIOFencing.BlockCompactionsInPrepRegion.html |   683 +-
 .../TestIOFencing.CompactionBlockerRegion.html     |   683 +-
 .../org/apache/hadoop/hbase/TestIOFencing.html     |   683 +-
 .../hadoop/hbase/TestKeyValue.FailureCase.html     |  1419 +--
 .../org/apache/hadoop/hbase/TestKeyValue.html      |  1419 +--
 .../hbase/TestMetaTableAccessor.MetaTask.html      |    12 +-
 .../TestMetaTableAccessor.SpyingRpcScheduler.html  |    12 +-
 ...etaTableAccessor.SpyingRpcSchedulerFactory.html |    12 +-
 .../apache/hadoop/hbase/TestMetaTableAccessor.html |    12 +-
 .../TestMetaTableLocator.WaitOnMetaThread.html     |   359 +-
 .../apache/hadoop/hbase/TestMetaTableLocator.html  |   359 +-
 .../hbase/TestMetaUpdatesGoToPriorityQueue.html    |   193 +-
 .../org/apache/hadoop/hbase/TestSerialization.html |   467 +-
 .../hbase/TestZooKeeper.MockLoadBalancer.html      |   499 +-
 .../org/apache/hadoop/hbase/TestZooKeeper.html     |   499 +-
 .../hadoop/hbase/Waiter.ExplainingPredicate.html   |   409 +-
 .../org/apache/hadoop/hbase/Waiter.Predicate.html  |   409 +-
 .../src-html/org/apache/hadoop/hbase/Waiter.html   |   409 +-
 ...estBackupBase.FullTableBackupClientForTest.html |     2 +-
 ...upBase.IncrementalTableBackupClientForTest.html |     2 +-
 .../apache/hadoop/hbase/backup/TestBackupBase.html |     2 +-
 .../hadoop/hbase/backup/TestBackupManager.html     |   209 +-
 .../hadoop/hbase/backup/TestBackupSystemTable.html |   997 +-
 .../TestHFileArchiving.ArchivingFunction.html      |  1331 +--
 .../hadoop/hbase/backup/TestHFileArchiving.html    |  1331 +--
 .../chaos/actions/MoveRegionsOfTableAction.html    |   151 +-
 .../hbase/chaos/actions/SnapshotTableAction.html   |    85 +-
 .../hbase/chaos/policies/PeriodicPolicy.html       |    77 +-
 ...shotFromClientAfterSplittingRegionTestBase.html |   183 +-
 ...hotFromClientCloneLinksAfterDeleteTestBase.html |   129 +-
 .../CloneSnapshotFromClientErrorTestBase.html      |    37 +-
 .../CloneSnapshotFromClientNormalTestBase.html     |    77 +-
 .../client/CloneSnapshotFromClientTestBase.html    |   124 +-
 .../RestoreSnapshotFromClientCloneTestBase.html    |    87 +-
 .../RestoreSnapshotFromClientSimpleTestBase.html   |   107 +-
 .../client/RestoreSnapshotFromClientTestBase.html  |   116 +-
 .../org/apache/hadoop/hbase/client/TestAdmin2.html |  1631 +--
 .../org/apache/hadoop/hbase/client/TestAdmin3.html |   701 +-
 .../hbase/client/TestAsyncConnectionTracing.html   |   155 +-
 .../hbase/client/TestAsyncRegionAdminApi.html      |    12 +-
 .../client/TestAsyncRegionLocatorTracing.html      |   234 +-
 .../apache/hadoop/hbase/client/TestAsyncTable.html |  3323 +++---
 .../hbase/client/TestAsyncTableAdminApi2.html      |   509 +-
 ...ictionFromClient.CustomInnerRegionObserver.html |  3146 +++---
 ...romClient.CustomInnerRegionObserverWrapper.html |  3146 +++---
 .../TestBlockEvictionFromClient.CustomScanner.html |  3146 +++---
 .../TestBlockEvictionFromClient.GetThread.html     |  3146 +++---
 ...TestBlockEvictionFromClient.MultiGetThread.html |  3146 +++---
 .../TestBlockEvictionFromClient.ScanThread.html    |  3146 +++---
 .../hbase/client/TestBlockEvictionFromClient.html  |  3146 +++---
 ...nerRPCTimeout.RSRpcServicesWithScanTimeout.html |   325 +-
 ...nnerRPCTimeout.RegionServerWithScanTimeout.html |   325 +-
 .../hbase/client/TestClientScannerRPCTimeout.html  |   325 +-
 .../apache/hadoop/hbase/client/TestConnection.html |     2 +-
 .../hadoop/hbase/client/TestFromClientSide.html    |  3813 +++----
 ...ientSide3.WaitingForMultiMutationsObserver.html |  2283 ++--
 ...TestFromClientSide3.WaitingForScanObserver.html |  2283 ++--
 .../hadoop/hbase/client/TestFromClientSide3.html   |  2283 ++--
 .../hadoop/hbase/client/TestFromClientSide5.html   |  2907 ++---
 ...loneLinksAfterDelete.DelayFlushCoprocessor.html |   189 +-
 ...oneSnapshotFromClientCloneLinksAfterDelete.html |   189 +-
 .../hbase/client/TestMutationGetCellBuilder.html   |   157 +-
 .../client/TestPutDeleteEtcCellIteration.html      |   249 +-
 .../hadoop/hbase/client/TestRegionInfoBuilder.html |   505 +-
 .../hadoop/hbase/client/TestRegionInfoDisplay.html |   189 +-
 ...cannersFromClientSide.LimitKVsReturnFilter.html |     4 +-
 .../hbase/client/TestScannersFromClientSide.html   |     4 +-
 .../client/TestSnapshotCloneIndependence.html      |   713 +-
 .../hadoop/hbase/client/TestSnapshotMetadata.html  |   547 +-
 .../client/TestSnapshotTemporaryDirectory.html     |   845 +-
 .../hbase/client/TestTableSnapshotScanner.html     |   881 +-
 .../hbase/client/locking/TestEntityLocks.html      |   341 +-
 .../hadoop/hbase/codec/CodecPerformance.html       |   199 +-
 ...estCoprocessorMetrics.CustomMasterObserver.html |  1013 +-
 ...estCoprocessorMetrics.CustomRegionEndpoint.html |  1013 +-
 ...estCoprocessorMetrics.CustomRegionObserver.html |  1013 +-
 ...stCoprocessorMetrics.CustomRegionObserver2.html |  1013 +-
 ...rocessorMetrics.CustomRegionServerObserver.html |  1013 +-
 .../TestCoprocessorMetrics.CustomWALObserver.html  |  1013 +-
 .../hbase/coprocessor/TestCoprocessorMetrics.html  |  1013 +-
 .../TestCoprocessorStop.FooCoprocessor.html        |    50 +-
 .../hbase/coprocessor/TestCoprocessorStop.html     |    50 +-
 ...tRegionObserverInterface.EvenOnlyCompactor.html |     4 +-
 ...erInterface.PreWALAppendWALActionsListener.html |     4 +-
 .../coprocessor/TestRegionObserverInterface.html   |     4 +-
 .../TestRegionObserverStacking.ObserverA.html      |   265 +-
 .../TestRegionObserverStacking.ObserverB.html      |   265 +-
 .../TestRegionObserverStacking.ObserverC.html      |   265 +-
 .../coprocessor/TestRegionObserverStacking.html    |   265 +-
 .../hadoop/hbase/coprocessor/TestWALObserver.html  |   422 +-
 .../example/TestZooKeeperScanPolicyObserver.html   |   209 +-
 .../favored/TestFavoredNodeAssignmentHelper.html   |  1242 +-
 .../hbase/filter/TestDependentColumnFilter.html    |   493 +-
 .../hbase/filter/TestFilterSerialization.html      |   643 +-
 .../filter/TestFuzzyRowAndColumnRangeFilter.html   |   309 +-
 .../hbase/filter/TestFuzzyRowFilterEndToEnd.html   |   831 +-
 .../apache/hadoop/hbase/fs/TestBlockReorder.html   |   328 +-
 .../hbase/fs/TestBlockReorderBlockLocation.html    |   255 +-
 .../hbase/fs/TestBlockReorderMultiBlocks.html      |   465 +-
 .../org/apache/hadoop/hbase/io/TestHeapSize.html   |  1085 +-
 .../hbase/io/encoding/TestChangingEncoding.html    |   435 +-
 .../io/hfile/TestHFileBlock.BlockReaderThread.html |  1833 +--
 .../hadoop/hbase/io/hfile/TestHFileBlock.html      |  1833 +--
 .../hfile/TestHFileScannerImplReferenceCount.html  |   851 +-
 .../hbase/io/hfile/TestScannerFromBucketCache.html |     6 +-
 .../hbase/ipc/TestProtobufRpcServiceImpl.html      |   184 +-
 ...estSimpleRpcScheduler.CoDelEnvironmentEdge.html |   430 +-
 .../hadoop/hbase/ipc/TestSimpleRpcScheduler.html   |   430 +-
 .../IntegrationTestTableSnapshotInputFormat.html   |   325 +-
 .../hadoop/hbase/mapreduce/TestCellCounter.html    |   655 +-
 .../hadoop/hbase/mapreduce/TestCopyTable.html      |   781 +-
 .../TestImportExport.MetadataController.html       |  1879 ++--
 .../TestImportExport.TableWALActionListener.html   |  1879 ++--
 .../hadoop/hbase/mapreduce/TestImportExport.html   |  1879 ++--
 .../hadoop/hbase/mapreduce/TestRowCounter.html     |  1209 +-
 .../hadoop/hbase/mapreduce/TestSyncTable.html      |  1113 +-
 .../hadoop/hbase/mapreduce/TestWALInputFormat.html |    95 +-
 .../hbase/mapreduce/TestWALRecordReader.html       |   604 +-
 .../hadoop/hbase/master/AbstractTestDLS.html       |  1076 +-
 .../TestActiveMasterManager.DummyMaster.html       |   583 +-
 ...stActiveMasterManager.NodeDeletionListener.html |   583 +-
 ...stActiveMasterManager.WaitToBeMasterThread.html |   583 +-
 .../hbase/master/TestActiveMasterManager.html      |   583 +-
 .../hbase/master/TestClockSkewDetection.html       |   173 +-
 .../hbase/master/TestMasterMetrics.MyMaster.html   |   310 +-
 .../master/TestMasterMetrics.MyRegionServer.html   |   310 +-
 .../hadoop/hbase/master/TestMasterMetrics.html     |   310 +-
 .../hbase/master/TestMasterMetricsWrapper.html     |   283 +-
 .../master/TestMetaAssignmentWithStopMaster.html   |   133 +-
 .../hadoop/hbase/master/TestRegionPlacement.html   |   999 +-
 .../TestSplitLogManager.DummyMasterServices.html   |  1035 +-
 .../hbase/master/TestSplitLogManager.Expr.html     |  1035 +-
 .../hadoop/hbase/master/TestSplitLogManager.html   |  1035 +-
 .../hadoop/hbase/master/TestWarmupRegion.html      |   267 +-
 .../MockMasterServices.MockRegionStateStore.html   |   593 +-
 .../master/assignment/MockMasterServices.html      |   593 +-
 .../master/assignment/TestAssignmentManager.html   |   589 +-
 ...tManagerBase.CallQueueTooBigOnceRsExecutor.html |  1271 +--
 ...TestAssignmentManagerBase.FaultyRsExecutor.html |  1271 +--
 .../TestAssignmentManagerBase.GoodRsExecutor.html  |  1271 +--
 ...ManagerBase.HangOnCloseThenRSCrashExecutor.html |  1271 +--
 ...ignmentManagerBase.HangThenRSCrashExecutor.html |  1271 +--
 ...nmentManagerBase.HangThenRSRestartExecutor.html |  1271 +--
 .../TestAssignmentManagerBase.MockRSExecutor.html  |  1271 +--
 ...e.MockRSProcedureDispatcher.MockRemoteCall.html |  1271 +--
 ...nmentManagerBase.MockRSProcedureDispatcher.html |  1271 +--
 .../TestAssignmentManagerBase.NoopRsExecutor.html  |  1271 +--
 .../TestAssignmentManagerBase.RandRsExecutor.html  |  1271 +--
 ...tManagerBase.ServerNotYetRunningRsExecutor.html |  1271 +--
 ...ignmentManagerBase.SocketTimeoutRsExecutor.html |  1271 +--
 ...rBase.TimeoutThenCallQueueTooBigRsExecutor.html |  1271 +--
 .../assignment/TestAssignmentManagerBase.html      |  1271 +--
 .../master/assignment/TestRegionReplicaSplit.html  |   261 +-
 .../master/assignment/TestRegionStateStore.html    |    10 +-
 .../hbase/master/assignment/TestRegionStates.html  |   377 +-
 .../master/assignment/TestRogueRSAssignment.html   |   326 +-
 .../cleaner/TestHFileCleaner.DummyServer.html      |     4 +-
 .../hbase/master/cleaner/TestHFileCleaner.html     |     4 +-
 .../cleaner/TestLogsCleaner.DummyServer.html       |   679 +-
 .../TestLogsCleaner.FaultyZooKeeperWatcher.html    |   679 +-
 .../hbase/master/cleaner/TestLogsCleaner.html      |   679 +-
 .../TestReplicationHFileCleaner.DummyServer.html   |   422 +-
 ...icationHFileCleaner.FaultyZooKeeperWatcher.html |   422 +-
 .../cleaner/TestReplicationHFileCleaner.html       |   422 +-
 .../hbase/master/janitor/TestCatalogJanitor.html   |  1141 +-
 .../master/janitor/TestCatalogJanitorCluster.html  |   571 +-
 .../janitor/TestCatalogJanitorInMemoryStates.html  |   309 +-
 .../hadoop/hbase/master/janitor/TestMetaFixer.html |   851 +-
 .../hbase/master/locking/TestLockProcedure.html    |   815 +-
 ...edulerPerformanceEvaluation.AddProcsWorker.html |     8 +-
 ...lerPerformanceEvaluation.PollAndLockWorker.html |     8 +-
 ...ulerPerformanceEvaluation.ProcedureFactory.html |     8 +-
 ...dulerPerformanceEvaluation.RegionProcedure.html |     8 +-
 ...rformanceEvaluation.RegionProcedureFactory.html |     8 +-
 ...edulerPerformanceEvaluation.TableProcedure.html |     8 +-
 ...erformanceEvaluation.TableProcedureFactory.html |     8 +-
 ...terProcedureSchedulerPerformanceEvaluation.html |     8 +-
 ...reTestingUtility.InjectAbortOnLoadListener.html |  1118 +-
 .../MasterProcedureTestingUtility.StepHook.html    |  1118 +-
 .../procedure/MasterProcedureTestingUtility.html   |  1118 +-
 .../procedure/TestCloneSnapshotProcedure.html      |   297 +-
 .../procedure/TestRestoreSnapshotProcedure.html    |   391 +-
 .../procedure/TestSafemodeBringsDownMaster.html    |   191 +-
 .../hbase/master/region/MasterRegionTestBase.html  |   143 +-
 .../master/region/TestMasterRegionCompaction.html  |   215 +-
 .../region/TestMasterRegionOnTwoFileSystems.html   |   364 +-
 .../org/apache/hadoop/hbase/mob/MobTestUtil.html   |   173 +-
 .../hbase/mob/TestExpiredMobFileCleaner.html       |   291 +-
 .../hadoop/hbase/mob/TestMobDataBlockEncoding.html |   175 +-
 .../hadoop/hbase/mob/TestMobStoreCompaction.html   |   697 +-
 .../hadoop/hbase/mob/TestMobStoreScanner.html      |   829 +-
 ...chedulerConcurrency.TestProcedureWithEvent.html |   269 +-
 .../TestProcedureSchedulerConcurrency.html         |   269 +-
 ...ProcedureStorePerformanceEvaluation.Worker.html |   169 +-
 .../store/ProcedureStorePerformanceEvaluation.html |   169 +-
 ...dureStorePerformanceEvaluation.DummyServer.html |   151 +-
 .../RegionProcedureStorePerformanceEvaluation.html |   151 +-
 .../region/RegionProcedureStoreTestHelper.html     |    57 +-
 .../store/region/TestRegionProcedureStore.html     |   533 +-
 ...WALLoaderPerformanceEvaluation.LoadCounter.html |   452 +-
 .../ProcedureWALLoaderPerformanceEvaluation.html   |   452 +-
 .../hadoop/hbase/quotas/TestRateLimiter.html       |     2 +-
 ...ingMemStore.EnvironmentEdgeForMemstoreTest.html |    10 +-
 ...estCompactingMemStore.MyCompactingMemStore.html |    10 +-
 .../hbase/regionserver/TestCompactingMemStore.html |    10 +-
 .../TestCompactingToCellFlatMapMemStore.html       |  1825 +--
 .../TestCompactionState.StateSource.html           |   489 +-
 .../hbase/regionserver/TestCompactionState.html    |   489 +-
 .../regionserver/TestDataBlockEncodingTool.html    |   223 +-
 .../regionserver/TestDefaultCompactSelection.html  |     2 +-
 ...ultMemStore.EnvironmentEdgeForMemstoreTest.html |    10 +-
 .../TestDefaultMemStore.ReadOwnWritesTester.html   |    10 +-
 .../hbase/regionserver/TestDefaultMemStore.html    |    10 +-
 ...TestEndToEndSplitTransaction.RegionChecker.html |   943 +-
 ...estEndToEndSplitTransaction.RegionSplitter.html |   943 +-
 .../regionserver/TestEndToEndSplitTransaction.html |   943 +-
 .../hadoop/hbase/regionserver/TestHMobStore.html   |   963 +-
 .../hbase/regionserver/TestHRegion.Appender.html   |    40 +-
 .../regionserver/TestHRegion.FlushThread.html      |    40 +-
 .../TestHRegion.GetTillDoneOrException.html        |    40 +-
 .../TestHRegion.HRegionForTesting.html             |    40 +-
 .../regionserver/TestHRegion.HRegionWithSeqId.html |    40 +-
 .../regionserver/TestHRegion.HStoreForTesting.html |    40 +-
 .../regionserver/TestHRegion.Incrementer.html      |    40 +-
 .../regionserver/TestHRegion.IsFlushWALMarker.html |    40 +-
 .../hbase/regionserver/TestHRegion.PutThread.html  |    40 +-
 .../hadoop/hbase/regionserver/TestHRegion.html     |    40 +-
 .../regionserver/TestHRegionReplayEvents.html      |     2 +-
 ...estHRegionServerBulkLoad.AtomicHFileLoader.html |   703 +-
 ...TestHRegionServerBulkLoad.AtomicScanReader.html |   703 +-
 ...RegionServerBulkLoad.FindBulkHBaseListener.html |   703 +-
 .../TestHRegionServerBulkLoad.MyObserver.html      |   703 +-
 .../regionserver/TestHRegionServerBulkLoad.html    |   703 +-
 .../regionserver/TestHStore.DummyStoreEngine.html  |    10 +-
 .../regionserver/TestHStore.FaultyFileSystem.html  |    10 +-
 .../TestHStore.FaultyOutputStream.html             |    10 +-
 .../TestHStore.MyCompactingMemStore.html           |    10 +-
 ...re.MyCompactingMemStoreWithCustomCompactor.html |    10 +-
 .../hbase/regionserver/TestHStore.MyList.html      |    10 +-
 .../hbase/regionserver/TestHStore.MyListHook.html  |    10 +-
 .../TestHStore.MyMemStoreCompactor.html            |    10 +-
 .../hbase/regionserver/TestHStore.MyStore.html     |    10 +-
 .../hbase/regionserver/TestHStore.MyStoreHook.html |    10 +-
 .../hbase/regionserver/TestHStore.MyThread.html    |    10 +-
 .../hadoop/hbase/regionserver/TestHStore.html      |    10 +-
 .../hadoop/hbase/regionserver/TestHStoreFile.html  |  2081 ++--
 .../hbase/regionserver/TestMajorCompaction.html    |   915 +-
 ...tMasterAddressTracker.NodeCreationListener.html |   402 +-
 .../regionserver/TestMasterAddressTracker.html     |   402 +-
 .../regionserver/TestMemStoreSegmentsIterator.html |   255 +-
 ...estRegionIncrement.CrossRowCellIncrementer.html |   407 +-
 .../TestRegionIncrement.SingleCellIncrementer.html |   407 +-
 .../hbase/regionserver/TestRegionIncrement.html    |   407 +-
 .../hadoop/hbase/regionserver/TestRegionInfo.html  |   861 +-
 ...stRegionMergeTransactionOnCluster.MyMaster.html |   993 +-
 ...geTransactionOnCluster.MyMasterRpcServices.html |   993 +-
 .../TestRegionMergeTransactionOnCluster.html       |   993 +-
 .../hadoop/hbase/regionserver/TestRegionOpen.html  |   187 +-
 .../hbase/regionserver/TestRegionReplicas.html     |   941 +-
 ...rverAbortTimeout.SleepWhenCloseCoprocessor.html |   223 +-
 ...ionServerAbortTimeout.TestAbortTimeoutTask.html |   223 +-
 .../regionserver/TestRegionServerAbortTimeout.html |   223 +-
 .../TestRegionServerReportForDuty.LogCapturer.html |   151 +-
 ...stRegionServerReportForDuty.MyRegionServer.html |   151 +-
 ...ServerReportForDuty.NeverInitializedMaster.html |   151 +-
 .../TestRegionServerReportForDuty.html             |   151 +-
 .../hbase/regionserver/TestReversibleScanners.html |  1365 +--
 .../regionserver/TestRowPrefixBloomFilter.html     |   643 +-
 .../hadoop/hbase/regionserver/TestScanner.html     |  1089 +-
 .../regionserver/TestScannerWithBulkload.html      |   544 +-
 .../regionserver/TestSimpleTimeRangeTracker.html   |   235 +-
 .../TestStoreFileScannerWithTagCompression.html    |   165 +-
 .../TestStoreScanner.CellGridStoreScanner.html     |  2041 ++--
 ...ner.CellWithVersionsNoOptimizeStoreScanner.html |  2041 ++--
 ...tStoreScanner.CellWithVersionsStoreScanner.html |  2041 ++--
 .../TestStoreScanner.KeyValueHeapWithCount.html    |  2041 ++--
 .../hbase/regionserver/TestStoreScanner.html       |  2041 ++--
 .../regionserver/TestWALLockup.DodgyFSLog.html     |   827 +-
 .../hadoop/hbase/regionserver/TestWALLockup.html   |   827 +-
 .../hadoop/hbase/regionserver/TestWideScanner.html |   255 +-
 .../regionserver/compactions/TestCloseChecker.html |   103 +-
 .../compactions/TestFIFOCompactionPolicy.html      |     2 +-
 .../TestCompactionWithThroughputController.html    |   519 +-
 ...bstractTestFSWAL.FlushSpecificStoresPolicy.html |     8 +-
 .../hbase/regionserver/wal/AbstractTestFSWAL.html  |     8 +-
 .../wal/AbstractTestLogRollPeriod.html             |   251 +-
 .../regionserver/wal/AbstractTestProtobufLog.html  |   205 +-
 .../AbstractTestWALReplay.CustomStoreFlusher.html  |  2067 ++--
 .../wal/AbstractTestWALReplay.MockWAL.html         |  2067 ++--
 .../wal/AbstractTestWALReplay.TestFlusher.html     |  2067 ++--
 .../regionserver/wal/AbstractTestWALReplay.html    |  2067 ++--
 .../hbase/regionserver/wal/TestAsyncFSWAL.html     |   353 +-
 .../regionserver/wal/TestCombinedAsyncWriter.html  |   193 +-
 .../hbase/regionserver/wal/TestDurability.html     |   543 +-
 .../hbase/regionserver/wal/TestLogRollAbort.html   |   399 +-
 .../hbase/regionserver/wal/TestLogRolling.html     |  1041 +-
 .../wal/TestLogRollingNoCluster.Appender.html      |   329 +-
 ...tLogRollingNoCluster.HighLatencySyncWriter.html |   329 +-
 .../regionserver/wal/TestLogRollingNoCluster.html  |   329 +-
 .../TestReplicationEmptyWALRecovery.html           |   553 +-
 ...ionEndpoint.EverythingPassesWALEntryFilter.html |  1189 +-
 ...int.EverythingPassesWALEntryFilterSubclass.html |  1189 +-
 ...int.InterClusterReplicationEndpointForTest.html |  1189 +-
 ...icationEndpoint.ReplicationEndpointForTest.html |  1189 +-
 ...Endpoint.ReplicationEndpointReturningFalse.html |  1189 +-
 ...oint.ReplicationEndpointWithWALEntryFilter.html |  1189 +-
 ...ndpoint.SleepingReplicationEndpointForTest.html |  1189 +-
 .../hbase/replication/TestReplicationEndpoint.html |  1189 +-
 .../hbase/replication/TestReplicationKillRS.html   |   207 +-
 .../replication/TestReplicationSmallTests.html     |   211 +-
 ...ALEntryFilters.FilterAllCellsWALCellFilter.html |   939 +-
 ...LEntryFilters.FilterSomeCellsWALCellFilter.html |   939 +-
 .../TestReplicationWALEntryFilters.html            |   939 +-
 .../hbase/replication/TestVerifyReplication.html   |   789 +-
 .../replication/TestVerifyReplicationAdjunct.html  |   601 +-
 .../TestVerifyReplicationCrossDiffHdfs.html        |   317 +-
 .../master/TestRecoverStandbyProcedure.html        |   269 +-
 .../regionserver/TestDumpReplicationQueues.html    |   129 +-
 ...InterClusterReplicationEndpointFilterEdits.html |   198 +-
 .../regionserver/TestReplicationSink.html          |   825 +-
 ...ationSourceManager.DummyNodeFailoverWorker.html |  1081 +-
 .../TestReplicationSourceManager.DummyServer.html  |  1081 +-
 ...nager.FailInitializeDummyReplicationSource.html |  1081 +-
 .../regionserver/TestReplicationSourceManager.html |  1081 +-
 ...TestSerialReplicationEndpoint.TestEndpoint.html |   271 +-
 .../TestSerialReplicationEndpoint.html             |   271 +-
 .../TestWALEntryStream.FailingWALEntryFilter.html  |  1682 +--
 .../TestWALEntryStream.PathWatcher.html            |  1682 +--
 ...stWALEntryStream.WALEntryStreamWithRetries.html |  1682 +--
 .../regionserver/TestWALEntryStream.html           |  1682 +--
 .../PerformanceEvaluation.BufferedMutatorTest.html |  2885 ++---
 .../rest/PerformanceEvaluation.CmdDescriptor.html  |  2885 ++---
 .../hbase/rest/PerformanceEvaluation.Counter.html  |  2885 ++---
 .../PerformanceEvaluation.EvaluationMapTask.html   |  2885 ++---
 .../PerformanceEvaluation.FilteredScanTest.html    |  2885 ++---
 ...nceEvaluation.PeInputFormat.PeRecordReader.html |  2885 ++---
 .../rest/PerformanceEvaluation.PeInputFormat.html  |  2885 ++---
 .../rest/PerformanceEvaluation.PeInputSplit.html   |  2885 ++---
 .../rest/PerformanceEvaluation.RandomReadTest.html |  2885 ++---
 ...nceEvaluation.RandomScanWithRange10000Test.html |  2885 ++---
 ...anceEvaluation.RandomScanWithRange1000Test.html |  2885 ++---
 ...manceEvaluation.RandomScanWithRange100Test.html |  2885 ++---
 ...rmanceEvaluation.RandomScanWithRange10Test.html |  2885 ++---
 ...formanceEvaluation.RandomScanWithRangeTest.html |  2885 ++---
 .../PerformanceEvaluation.RandomSeekScanTest.html  |  2885 ++---
 .../PerformanceEvaluation.RandomWriteTest.html     |  2885 ++---
 .../hbase/rest/PerformanceEvaluation.ScanTest.html |  2885 ++---
 .../PerformanceEvaluation.SequentialReadTest.html  |  2885 ++---
 .../PerformanceEvaluation.SequentialWriteTest.html |  2885 ++---
 .../hbase/rest/PerformanceEvaluation.Status.html   |  2885 ++---
 .../rest/PerformanceEvaluation.TableTest.html      |  2885 ++---
 .../hbase/rest/PerformanceEvaluation.Test.html     |  2885 ++---
 .../rest/PerformanceEvaluation.TestOptions.html    |  2885 ++---
 .../hadoop/hbase/rest/PerformanceEvaluation.html   |  2885 ++---
 .../TestRemoteAdminRetries.CallExecutor.html       |   269 +-
 .../hbase/rest/client/TestRemoteAdminRetries.html  |   269 +-
 .../TestRemoteHTableRetries.CallExecutor.html      |   315 +-
 .../hbase/rest/client/TestRemoteHTableRetries.html |   315 +-
 .../hadoop/hbase/rest/client/TestRemoteTable.html  |  1253 +--
 .../hbase/rsgroup/EnableRSGroupsTestBase.html      |   109 +-
 .../hadoop/hbase/rsgroup/TestRSGroupsAdmin2.html   |  1353 +--
 ...tAccessController.BulkLoadAccessTestAction.html |  7287 ++++++------
 .../TestAccessController.BulkLoadHelper.html       |  7287 ++++++------
 ...ssController.MyShellBasedUnixGroupsMapping.html |  7287 ++++++------
 .../TestAccessController.PingCoprocessor.html      |  7287 ++++++------
 ...TestAccessController.TestTableDDLProcedure.html |  7287 ++++++------
 .../security/access/TestAccessController.html      |  7287 ++++++------
 .../access/TestCellACLWithMultipleVersions.html    |     2 +-
 .../token/TestTokenAuthentication.TokenServer.html |     2 +-
 .../security/token/TestTokenAuthentication.html    |     2 +-
 ...stZKSecretWatcherRefreshKeys.MockAbortable.html |   165 +-
 .../token/TestZKSecretWatcherRefreshKeys.html      |   165 +-
 ...apshotTestingUtils.SnapshotMock.RegionData.html |   137 +-
 ...tTestingUtils.SnapshotMock.SnapshotBuilder.html |   137 +-
 .../SnapshotTestingUtils.SnapshotMock.html         |   137 +-
 .../hbase/snapshot/SnapshotTestingUtils.html       |   137 +-
 .../TestExportSnapshot.RegionPredicate.html        |   612 +-
 .../hadoop/hbase/snapshot/TestExportSnapshot.html  |   612 +-
 .../snapshot/TestExportSnapshotV1NoCluster.html    |   181 +-
 .../snapshot/TestFlushSnapshotFromClient.html      |   826 +-
 .../TestRestoreFlushSnapshotFromClient.html        |   380 +-
 .../test/IntegrationTestBigLinkedList.CINode.html  |  3901 +++----
 .../test/IntegrationTestBigLinkedList.Clean.html   |  3901 +++----
 .../test/IntegrationTestBigLinkedList.Delete.html  |  3901 +++----
 ...egrationTestBigLinkedList.Generator.Counts.html |  3901 +++----
 ...r.GeneratorInputFormat.GeneratorInputSplit.html |  3901 +++----
 ...GeneratorInputFormat.GeneratorRecordReader.html |  3901 +++----
 ...gLinkedList.Generator.GeneratorInputFormat.html |  3901 +++----
 ...Generator.GeneratorMapper.ConcurrentWalker.html |  3901 +++----
 ...GeneratorMapper.ContinuousConcurrentWalker.html |  3901 +++----
 ...estBigLinkedList.Generator.GeneratorMapper.html |  3901 +++----
 ...gLinkedList.Generator.OneFilePerMapperSFIF.html |  3901 +++----
 .../IntegrationTestBigLinkedList.Generator.html    |  3901 +++----
 .../test/IntegrationTestBigLinkedList.Loop.html    |  3901 +++----
 .../test/IntegrationTestBigLinkedList.Print.html   |  3901 +++----
 ...dList.Search.WALSearcher.WALMapperSearcher.html |  3901 +++----
 ...rationTestBigLinkedList.Search.WALSearcher.html |  3901 +++----
 .../test/IntegrationTestBigLinkedList.Search.html  |  3901 +++----
 ...IntegrationTestBigLinkedList.Verify.Counts.html |  3901 +++----
 ...ationTestBigLinkedList.Verify.VerifyMapper.html |  3901 +++----
 ...tionTestBigLinkedList.Verify.VerifyReducer.html |  3901 +++----
 .../test/IntegrationTestBigLinkedList.Verify.html  |  3901 +++----
 .../test/IntegrationTestBigLinkedList.Walker.html  |  3901 +++----
 .../IntegrationTestBigLinkedList.WalkerBase.html   |  3901 +++----
 .../hbase/test/IntegrationTestBigLinkedList.html   |  3901 +++----
 .../IntegrationTestLoadCommonCrawl.Counts.html     |  1545 +--
 ...rationTestLoadCommonCrawl.HBaseKeyWritable.html |  1545 +--
 ...ionTestLoadCommonCrawl.Loader.LoaderMapper.html |  1545 +--
 .../IntegrationTestLoadCommonCrawl.Loader.html     |  1545 +--
 ...onTestLoadCommonCrawl.OneFilePerMapperSFIF.html |  1545 +--
 ...ionTestLoadCommonCrawl.Verify.VerifyMapper.html |  1545 +--
 .../IntegrationTestLoadCommonCrawl.Verify.html     |  1545 +--
 .../hbase/test/IntegrationTestLoadCommonCrawl.html |  1545 +--
 ...eader.TimeBoundedMultiThreadedReaderThread.html |   657 +-
 ...meBoundedMultiThreadedReader.TimeoutThread.html |   657 +-
 ...ionReplicas.TimeBoundedMultiThreadedReader.html |   657 +-
 ...nTestTimeBoundedRequestsWithRegionReplicas.html |   657 +-
 .../TestThriftServer.MySlowHBaseHandler.html       |  1707 +--
 .../hadoop/hbase/thrift/TestThriftServer.html      |  1707 +--
 .../hadoop/hbase/thrift2/TestThriftConnection.html |  1599 +--
 ...HBaseServiceHandler.DelayingRegionObserver.html |  3367 +++---
 .../thrift2/TestThriftHBaseServiceHandler.html     |  3367 +++---
 .../util/ConstantDelayQueue.DelayedElement.html    |     2 +-
 .../hadoop/hbase/util/ConstantDelayQueue.html      |     2 +-
 .../apache/hadoop/hbase/util/HFileTestUtil.html    |    61 +-
 .../MultiThreadedAction.DefaultDataGenerator.html  |     6 +-
 .../util/MultiThreadedAction.ProgressReporter.html |     6 +-
 .../hadoop/hbase/util/MultiThreadedAction.html     |     6 +-
 .../MultiThreadedReader.HBaseReaderThread.html     |     6 +-
 .../hadoop/hbase/util/MultiThreadedReader.html     |     6 +-
 ...adedReaderWithACL.HBaseReaderThreadWithACL.html |     2 +-
 .../hbase/util/MultiThreadedReaderWithACL.html     |     2 +-
 .../MultiThreadedUpdater.HBaseUpdaterThread.html   |    18 +-
 .../hadoop/hbase/util/MultiThreadedUpdater.html    |    18 +-
 ...aseUpdaterThreadWithACL.MutateAccessAction.html |    10 +-
 ...edUpdaterWithACL.HBaseUpdaterThreadWithACL.html |    10 +-
 .../hbase/util/MultiThreadedUpdaterWithACL.html    |    10 +-
 .../MultiThreadedWriter.HBaseWriterThread.html     |    10 +-
 .../hadoop/hbase/util/MultiThreadedWriter.html     |    10 +-
 .../MultiThreadedWriterBase.WroteKeysTracker.html  |   223 +-
 .../hadoop/hbase/util/MultiThreadedWriterBase.html |   223 +-
 ...HBaseWriterThreadWithACL.WriteAccessAction.html |     8 +-
 ...adedWriterWithACL.HBaseWriterThreadWithACL.html |     8 +-
 .../hbase/util/MultiThreadedWriterWithACL.html     |     8 +-
 .../hadoop/hbase/util/TestBloomFilterChunk.html    |    12 +-
 .../hbase/util/TestByteBufferArray.Call.html       |     2 +-
 .../hadoop/hbase/util/TestByteBufferArray.html     |     2 +-
 .../org/apache/hadoop/hbase/util/TestBytes.html    |     2 +-
 .../hbase/util/TestDefaultEnvironmentEdge.html     |    75 +-
 ...tFSTableDescriptors.FSTableDescriptorsTest.html |     4 +-
 .../hadoop/hbase/util/TestFSTableDescriptors.html  |     4 +-
 ...Utils.AlwaysFailSetStoragePolicyFileSystem.html |  1100 +-
 .../org/apache/hadoop/hbase/util/TestFSUtils.html  |  1100 +-
 .../hbase/util/TestIdLock.IdLockTestThread.html    |     4 +-
 .../org/apache/hadoop/hbase/util/TestIdLock.html   |     4 +-
 ...adWriteLockWithObjectPool.IdLockTestThread.html |     4 +-
 .../util/TestIdReadWriteLockWithObjectPool.html    |     4 +-
 .../util/TestIncrementingEnvironmentEdge.html      |     2 +-
 .../org/apache/hadoop/hbase/util/TestThreads.html  |     4 +-
 .../hbase/util/compaction/TestMajorCompactor.html  |   119 +-
 .../apache/hadoop/hbase/wal/TestCompressedWAL.html |   233 +-
 .../hadoop/hbase/wal/TestFSHLogProvider.html       |   651 +-
 .../org/apache/hadoop/hbase/wal/TestSecureWAL.html |   237 +-
 ...estSyncReplicationWALProvider.InfoProvider.html |   259 +-
 .../hbase/wal/TestSyncReplicationWALProvider.html  |   259 +-
 .../wal/TestWALFactory.BrokenWALCellCodec.html     |  1649 +--
 .../wal/TestWALFactory.DumbWALActionsListener.html |  1649 +--
 .../hbase/wal/TestWALFactory.InputStreamProxy.html |  1649 +--
 .../apache/hadoop/hbase/wal/TestWALFactory.html    |  1649 +--
 .../apache/hadoop/hbase/wal/TestWALMethods.html    |   315 +-
 .../hadoop/hbase/wal/TestWALReaderOnSecureWAL.html |   340 +-
 .../apache/hadoop/hbase/wal/TestWALRootDir.html    |   226 +-
 .../hadoop/hbase/wal/TestWALSplit.Corruptions.html |     4 +-
 ...stWALSplit.ZombieLastLogWriterRegionServer.html |     4 +-
 .../org/apache/hadoop/hbase/wal/TestWALSplit.html  |     4 +-
 .../hadoop/hbase/wal/TestWALSplitToHFile.html      |   982 +-
 .../WALPerformanceEvaluation.WALPutBenchmark.html  |   985 +-
 .../hadoop/hbase/wal/WALPerformanceEvaluation.html |   985 +-
 1413 files changed, 502757 insertions(+), 502126 deletions(-)

diff --git a/apache_hbase_reference_guide.pdf b/apache_hbase_reference_guide.pdf
index cdff4c2..640c7ca 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:20210601165216+00'00')
-/CreationDate (D:20210601170208+00'00')
+/ModDate (D:20210601200521+00'00')
+/CreationDate (D:20210601201527+00'00')
 >>
 endobj
 2 0 obj
diff --git a/apidocs/org/apache/hadoop/hbase/ScheduledChore.html b/apidocs/org/apache/hadoop/hbase/ScheduledChore.html
index b68a139..2238f0e 100644
--- a/apidocs/org/apache/hadoop/hbase/ScheduledChore.html
+++ b/apidocs/org/apache/hadoop/hbase/ScheduledChore.html
@@ -114,7 +114,7 @@ var activeTableTab = "activeTableTab";
 <hr>
 <br>
 <pre>@InterfaceAudience.Public
-public abstract class <a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.42">ScheduledChore</a>
+public abstract class <a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.44">ScheduledChore</a>
 extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a>
 implements <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html?is-external=true" title="class or interface in java.lang">Runnable</a></pre>
 <div class="block">ScheduledChore is a task performed on a period in hbase. ScheduledChores become active once
@@ -292,7 +292,7 @@ implements <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Runnable
 <li class="blockList">
 <h4>ScheduledChore</h4>
 <pre>@InterfaceAudience.Private
-protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.85">ScheduledChore</a>()</pre>
+protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.87">ScheduledChore</a>()</pre>
 <div class="block">This constructor is for test only. It allows us to create an object and to call chore() on it.</div>
 </li>
 </ul>
@@ -302,7 +302,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>ScheduledChore</h4>
-<pre>public&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.94">ScheduledChore</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;name,
+<pre>public&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.96">ScheduledChore</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;name,
                       <a href="../../../../org/apache/hadoop/hbase/Stoppable.html" title="interface in org.apache.hadoop.hbase">Stoppable</a>&nbsp;stopper,
                       int&nbsp;period)</pre>
 <dl>
@@ -319,7 +319,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>ScheduledChore</h4>
-<pre>public&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.106">ScheduledChore</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;name,
+<pre>public&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.108">ScheduledChore</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;name,
                       <a href="../../../../org/apache/hadoop/hbase/Stoppable.html" title="interface in org.apache.hadoop.hbase">Stoppable</a>&nbsp;stopper,
                       int&nbsp;period,
                       long&nbsp;initialDelay)</pre>
@@ -340,7 +340,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockListLast">
 <li class="blockList">
 <h4>ScheduledChore</h4>
-<pre>public&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.120">ScheduledChore</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;name,
+<pre>public&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.122">ScheduledChore</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;name,
                       <a href="../../../../org/apache/hadoop/hbase/Stoppable.html" title="interface in org.apache.hadoop.hbase">Stoppable</a>&nbsp;stopper,
                       int&nbsp;period,
                       long&nbsp;initialDelay,
@@ -371,7 +371,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>run</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.133">run</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.135">run</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Specified by:</span></dt>
 <dd><code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html?is-external=true#run--" title="class or interface in java.lang">run</a></code>&nbsp;in interface&nbsp;<code><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Runnable.html?is-external=true" title="class or interface in java.lang">Runnable</a></code></dd>
@@ -386,7 +386,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>triggerNow</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.224">triggerNow</a>()</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.226">triggerNow</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>false when the Chore is not currently scheduled with a ChoreService</dd>
@@ -399,7 +399,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>cancel</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.239">cancel</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.241">cancel</a>()</pre>
 </li>
 </ul>
 <a name="cancel-boolean-">
@@ -408,7 +408,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>cancel</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.243">cancel</a>(boolean&nbsp;mayInterruptIfRunning)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.245">cancel</a>(boolean&nbsp;mayInterruptIfRunning)</pre>
 </li>
 </ul>
 <a name="getName--">
@@ -417,7 +417,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>getName</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/ScheduledChore.html#line.250">getName</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/ScheduledChore.html#line.252">getName</a>()</pre>
 </li>
 </ul>
 <a name="getStopper--">
@@ -426,7 +426,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>getStopper</h4>
-<pre>public&nbsp;<a href="../../../../org/apache/hadoop/hbase/Stoppable.html" title="interface in org.apache.hadoop.hbase">Stoppable</a>&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.254">getStopper</a>()</pre>
+<pre>public&nbsp;<a href="../../../../org/apache/hadoop/hbase/Stoppable.html" title="interface in org.apache.hadoop.hbase">Stoppable</a>&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.256">getStopper</a>()</pre>
 </li>
 </ul>
 <a name="getPeriod--">
@@ -435,7 +435,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>getPeriod</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.261">getPeriod</a>()</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.263">getPeriod</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>period to execute chore in getTimeUnit() units</dd>
@@ -448,7 +448,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>getInitialDelay</h4>
-<pre>public&nbsp;long&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.268">getInitialDelay</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.270">getInitialDelay</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>initial delay before executing chore in getTimeUnit() units</dd>
@@ -461,7 +461,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>getTimeUnit</h4>
-<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/TimeUnit.html?is-external=true" title="class or interface in java.util.concurrent">TimeUnit</a>&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.272">getTimeUnit</a>()</pre>
+<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/TimeUnit.html?is-external=true" title="class or interface in java.util.concurrent">TimeUnit</a>&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.274">getTimeUnit</a>()</pre>
 </li>
 </ul>
 <a name="isInitialChoreComplete--">
@@ -470,7 +470,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>isInitialChoreComplete</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.276">isInitialChoreComplete</a>()</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.278">isInitialChoreComplete</a>()</pre>
 </li>
 </ul>
 <a name="isScheduled--">
@@ -479,7 +479,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>isScheduled</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.295">isScheduled</a>()</pre>
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.297">isScheduled</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>true when this Chore is scheduled with a ChoreService</dd>
@@ -492,7 +492,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>chore</h4>
-<pre>protected abstract&nbsp;void&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.309">chore</a>()</pre>
+<pre>protected abstract&nbsp;void&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.311">chore</a>()</pre>
 <div class="block">The task to execute on each scheduled execution of the Chore</div>
 </li>
 </ul>
@@ -502,7 +502,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>initialChore</h4>
-<pre>protected&nbsp;boolean&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.315">initialChore</a>()</pre>
+<pre>protected&nbsp;boolean&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.317">initialChore</a>()</pre>
 <div class="block">Override to run a task before we start looping.</div>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
@@ -516,7 +516,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>cleanup</h4>
-<pre>protected&nbsp;void&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.323">cleanup</a>()</pre>
+<pre>protected&nbsp;void&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.325">cleanup</a>()</pre>
 <div class="block">Override to run cleanup tasks when the Chore encounters an error and must stop running</div>
 </li>
 </ul>
@@ -526,7 +526,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockList">
 <li class="blockList">
 <h4>shutdown</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.330">shutdown</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.332">shutdown</a>()</pre>
 <div class="block">Call <a href="../../../../org/apache/hadoop/hbase/ScheduledChore.html#shutdown-boolean-"><code>shutdown(boolean)</code></a> with <code>true</code>.</div>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
@@ -540,7 +540,7 @@ protected&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledCh
 <ul class="blockListLast">
 <li class="blockList">
 <h4>shutdown</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.340">shutdown</a>(boolean&nbsp;mayInterruptIfRunning)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../src-html/org/apache/hadoop/hbase/ScheduledChore.html#line.342">shutdown</a>(boolean&nbsp;mayInterruptIfRunning)</pre>
 <div class="block">Completely shutdown the ScheduleChore, which means we will call cleanup and you should not
  schedule it again.
  <p/>
diff --git a/apidocs/org/apache/hadoop/hbase/client/Delete.html b/apidocs/org/apache/hadoop/hbase/client/Delete.html
index d473975..4757c9b 100644
--- a/apidocs/org/apache/hadoop/hbase/client/Delete.html
+++ b/apidocs/org/apache/hadoop/hbase/client/Delete.html
@@ -151,7 +151,7 @@ extends <a href="../../../../../org/apache/hadoop/hbase/client/Mutation.html" ti
  Specifying timestamps, deleteFamily and deleteColumns will delete all
  versions with a timestamp less than or equal to that passed.  If no
  timestamp is specified, an entry is added with a timestamp of 'now'
- where 'now' is the servers's System.currentTimeMillis().
+ where 'now' is the servers's EnvironmentEdgeManager.currentTime().
  Specifying a timestamp to the deleteColumn method will
  delete versions only with a timestamp equal to that specified.
  If no timestamp is passed to deleteColumn, internally, it figures the
diff --git a/apidocs/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html b/apidocs/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html
index 6ecdecb..9d992b3 100644
--- a/apidocs/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html
+++ b/apidocs/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html
@@ -110,7 +110,7 @@ var activeTableTab = "activeTableTab";
 <hr>
 <br>
 <pre>@InterfaceAudience.Public
-public class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.43">TableRecordReaderImpl</a>
+public class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.44">TableRecordReaderImpl</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">Iterate over an HBase table data, return (Text, RowResult) pairs</div>
 </li>
@@ -233,7 +233,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>TableRecordReaderImpl</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.43">TableRecordReaderImpl</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.44">TableRecordReaderImpl</a>()</pre>
 </li>
 </ul>
 </li>
@@ -250,7 +250,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>restart</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.61">restart</a>(byte[]&nbsp;firstRow)
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.62">restart</a>(byte[]&nbsp;firstRow)
              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">Restart from survivable exceptions by creating a new scanner.</div>
 <dl>
@@ -265,7 +265,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>init</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.100">init</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.101">init</a>()
           throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <div class="block">Build the scanner. Not done in constructor to allow for extension.</div>
 <dl>
@@ -280,7 +280,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setHTable</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.111">setHTable</a>(<a href="../../../../../org/apache/hadoop/hbase/client/Table.html" title="interface in org.apache.hadoop.hbase.client">Table</a>&nbsp;htable)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.112">setHTable</a>(<a href="../../../../../org/apache/hadoop/hbase/client/Table.html" title="interface in org.apache.hadoop.hbase.client">Table</a>&nbsp;htable)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>htable</code> - the table to scan.</dd>
@@ -293,7 +293,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setInputColumns</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.121">setInputColumns</a>(byte[][]&nbsp;inputColumns)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.122">setInputColumns</a>(byte[][]&nbsp;inputColumns)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>inputColumns</code> - the columns to be placed in <a href="../../../../../org/apache/hadoop/hbase/client/Result.html" title="class in org.apache.hadoop.hbase.client"><code>Result</code></a>.</dd>
@@ -306,7 +306,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setStartRow</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.128">setStartRow</a>(byte[]&nbsp;startRow)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.129">setStartRow</a>(byte[]&nbsp;startRow)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>startRow</code> - the first row in the split</dd>
@@ -319,7 +319,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setEndRow</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.136">setEndRow</a>(byte[]&nbsp;endRow)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.137">setEndRow</a>(byte[]&nbsp;endRow)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>endRow</code> - the last row in the split</dd>
@@ -332,7 +332,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setRowFilter</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.143">setRowFilter</a>(<a href="../../../../../org/apache/hadoop/hbase/filter/Filter.html" title="class in org.apache.hadoop.hbase.filter">Filter</a>&nbsp;rowFilter)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.144">setRowFilter</a>(<a href="../../../../../org/apache/hadoop/hbase/filter/Filter.html" title="class in org.apache.hadoop.hbase.filter">Filter</a>&nbsp;rowFilter)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>rowFilter</code> - the <a href="../../../../../org/apache/hadoop/hbase/filter/Filter.html" title="class in org.apache.hadoop.hbase.filter"><code>Filter</code></a> to be used.</dd>
@@ -345,7 +345,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>close</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.147">close</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.148">close</a>()</pre>
 </li>
 </ul>
 <a name="createKey--">
@@ -354,7 +354,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>createKey</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/mapred/TableRecordReaderImpl.html#line.163">createKey</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/mapred/TableRecordReaderImpl.html#line.164">createKey</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>ImmutableBytesWritable</dd>
@@ -369,7 +369,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>createValue</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/mapred/TableRecordReaderImpl.html#line.172">createValue</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/mapred/TableRecordReaderImpl.html#line.173">createValue</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>RowResult</dd>
@@ -384,7 +384,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/mapred/TableRecordReaderImpl.html#line.176">getPos</a>()</pre>
+<pre>public&nbsp;long&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.177">getPos</a>()</pre>
 </li>
 </ul>
 <a name="getProgress--">
@@ -393,7 +393,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/mapred/TableRecordReaderImpl.html#line.182">getProgress</a>()</pre>
+<pre>public&nbsp;float&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.183">getProgress</a>()</pre>
 </li>
 </ul>
 <a name="next-org.apache.hadoop.hbase.io.ImmutableBytesWritable-org.apache.hadoop.hbase.client.Result-">
@@ -402,7 +402,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>next</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.192">next</a>(<a href="../../../../../org/apache/hadoop/hbase/io/ImmutableBytesWritable.html" title="class in org.apache.hadoop.hbase.io">ImmutableBytesWritable</a>&nbsp;key,
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html#line.193">next</a>(<a href="../../../../../org/apache/hadoop/hbase/io/ImmutableBytesWritable.html" title="class in org.apache.hadoop.hbase.io">ImmutableBytesWritable</a>&nbsp;key,
                     <a href="../../../../../org/apache/hadoop/hbase/client/Result.html" title="class in org.apache.hadoop.hbase.client">Result</a>&nbsp;value)
              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>
diff --git a/apidocs/org/apache/hadoop/hbase/mapreduce/HFileOutputFormat2.html b/apidocs/org/apache/hadoop/hbase/mapreduce/HFileOutputFormat2.html
index 01b3782..992b49c 100644
--- a/apidocs/org/apache/hadoop/hbase/mapreduce/HFileOutputFormat2.html
+++ b/apidocs/org/apache/hadoop/hbase/mapreduce/HFileOutputFormat2.html
@@ -485,7 +485,7 @@ extends org.apache.hadoop.mapreduce.lib.output.FileOutputFormat&lt;<a href="../.
 <ul class="blockList">
 <li class="blockList">
 <h4>configureIncrementalLoad</h4>
-<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/HFileOutputFormat2.html#line.550">configureIncrementalLoad</a>(org.apache.hadoop.mapreduce.Job&nbsp;job,
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/HFileOutputFormat2.html#line.552">configureIncrementalLoad</a>(org.apache.hadoop.mapreduce.Job&nbsp;job,
                                             <a href="../../../../../org/apache/hadoop/hbase/client/Table.html" title="interface in org.apache.hadoop.hbase.client">Table</a>&nbsp;table,
                                             <a href="../../../../../org/apache/hadoop/hbase/client/RegionLocator.html" title="interface in org.apache.hadoop.hbase.client">RegionLocator</a>&nbsp;regionLocator)
                                      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>
@@ -514,7 +514,7 @@ extends org.apache.hadoop.mapreduce.lib.output.FileOutputFormat&lt;<a href="../.
 <ul class="blockList">
 <li class="blockList">
 <h4>configureIncrementalLoad</h4>
-<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/HFileOutputFormat2.html#line.570">configureIncrementalLoad</a>(org.apache.hadoop.mapreduce.Job&nbsp;job,
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/HFileOutputFormat2.html#line.572">configureIncrementalLoad</a>(org.apache.hadoop.mapreduce.Job&nbsp;job,
                                             <a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client">TableDescriptor</a>&nbsp;tableDescriptor,
                                             <a href="../../../../../org/apache/hadoop/hbase/client/RegionLocator.html" title="interface in org.apache.hadoop.hbase.client">RegionLocator</a>&nbsp;regionLocator)
                                      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>
@@ -542,7 +542,7 @@ extends org.apache.hadoop.mapreduce.lib.output.FileOutputFormat&lt;<a href="../.
 <ul class="blockList">
 <li class="blockList">
 <h4>configureIncrementalLoadMap</h4>
-<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/HFileOutputFormat2.html#line.657">configureIncrementalLoadMap</a>(org.apache.hadoop.mapreduce.Job&nbsp;job,
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/HFileOutputFormat2.html#line.659">configureIncrementalLoadMap</a>(org.apache.hadoop.mapreduce.Job&nbsp;job,
                                                <a href="../../../../../org/apache/hadoop/hbase/client/TableDescriptor.html" title="interface in org.apache.hadoop.hbase.client">TableDescriptor</a>&nbsp;tableDescriptor)
                                         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>
@@ -557,7 +557,7 @@ extends org.apache.hadoop.mapreduce.lib.output.FileOutputFormat&lt;<a href="../.
 <ul class="blockListLast">
 <li class="blockList">
 <h4>configureRemoteCluster</h4>
-<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/HFileOutputFormat2.html#line.709">configureRemoteCluster</a>(org.apache.hadoop.mapreduce.Job&nbsp;job,
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/HFileOutputFormat2.html#line.711">configureRemoteCluster</a>(org.apache.hadoop.mapreduce.Job&nbsp;job,
                                           org.apache.hadoop.conf.Configuration&nbsp;clusterConf)</pre>
 <div class="block">Configure HBase cluster key for remote cluster to load region location for locality-sensitive
  if it's enabled.
diff --git a/apidocs/org/apache/hadoop/hbase/mapreduce/ImportTsv.html b/apidocs/org/apache/hadoop/hbase/mapreduce/ImportTsv.html
index e9fbb66..98d9dfa 100644
--- a/apidocs/org/apache/hadoop/hbase/mapreduce/ImportTsv.html
+++ b/apidocs/org/apache/hadoop/hbase/mapreduce/ImportTsv.html
@@ -119,7 +119,7 @@ var activeTableTab = "activeTableTab";
 <hr>
 <br>
 <pre>@InterfaceAudience.Public
-public class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/ImportTsv.html#line.77">ImportTsv</a>
+public class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/ImportTsv.html#line.78">ImportTsv</a>
 extends org.apache.hadoop.conf.Configured
 implements org.apache.hadoop.util.Tool</pre>
 <div class="block">Tool to import data from a TSV file.
@@ -297,7 +297,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>LOG</h4>
-<pre>protected static final&nbsp;org.slf4j.Logger <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/ImportTsv.html#line.79">LOG</a></pre>
+<pre>protected static final&nbsp;org.slf4j.Logger <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/ImportTsv.html#line.80">LOG</a></pre>
 </li>
 </ul>
 <a name="MAPPER_CONF_KEY">
@@ -306,7 +306,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>MAPPER_CONF_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/ImportTsv.html#line.83">MAPPER_CONF_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/ImportTsv.html#line.84">MAPPER_CONF_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.ImportTsv.MAPPER_CONF_KEY">Constant Field Values</a></dd>
@@ -319,7 +319,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>BULK_OUTPUT_CONF_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/ImportTsv.html#line.84">BULK_OUTPUT_CONF_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/ImportTsv.html#line.85">BULK_OUTPUT_CONF_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.ImportTsv.BULK_OUTPUT_CONF_KEY">Constant Field Values</a></dd>
@@ -332,7 +332,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>TIMESTAMP_CONF_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/ImportTsv.html#line.85">TIMESTAMP_CONF_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/ImportTsv.html#line.86">TIMESTAMP_CONF_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.ImportTsv.TIMESTAMP_CONF_KEY">Constant Field Values</a></dd>
@@ -345,7 +345,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>JOB_NAME_CONF_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/ImportTsv.html#line.86">JOB_NAME_CONF_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/ImportTsv.html#line.87">JOB_NAME_CONF_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.ImportTsv.JOB_NAME_CONF_KEY">Constant Field Values</a></dd>
@@ -358,7 +358,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>DRY_RUN_CONF_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/ImportTsv.html#line.89">DRY_RUN_CONF_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/ImportTsv.html#line.90">DRY_RUN_CONF_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.ImportTsv.DRY_RUN_CONF_KEY">Constant Field Values</a></dd>
@@ -371,7 +371,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>LOG_BAD_LINES_CONF_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/ImportTsv.html#line.91">LOG_BAD_LINES_CONF_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/ImportTsv.html#line.92">LOG_BAD_LINES_CONF_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.ImportTsv.LOG_BAD_LINES_CONF_KEY">Constant Field Values</a></dd>
@@ -384,7 +384,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>SKIP_LINES_CONF_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/ImportTsv.html#line.92">SKIP_LINES_CONF_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/ImportTsv.html#line.93">SKIP_LINES_CONF_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.ImportTsv.SKIP_LINES_CONF_KEY">Constant Field Values</a></dd>
@@ -397,7 +397,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>SKIP_EMPTY_COLUMNS</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/ImportTsv.html#line.93">SKIP_EMPTY_COLUMNS</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/ImportTsv.html#line.94">SKIP_EMPTY_COLUMNS</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.ImportTsv.SKIP_EMPTY_COLUMNS">Constant Field Values</a></dd>
@@ -410,7 +410,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>COLUMNS_CONF_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/ImportTsv.html#line.94">COLUMNS_CONF_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/ImportTsv.html#line.95">COLUMNS_CONF_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.ImportTsv.COLUMNS_CONF_KEY">Constant Field Values</a></dd>
@@ -423,7 +423,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>SEPARATOR_CONF_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/ImportTsv.html#line.95">SEPARATOR_CONF_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/ImportTsv.html#line.96">SEPARATOR_CONF_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.ImportTsv.SEPARATOR_CONF_KEY">Constant Field Values</a></dd>
@@ -436,7 +436,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>ATTRIBUTE_SEPERATOR_CONF_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/ImportTsv.html#line.96">ATTRIBUTE_SEPERATOR_CONF_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/ImportTsv.html#line.97">ATTRIBUTE_SEPERATOR_CONF_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.ImportTsv.ATTRIBUTE_SEPERATOR_CONF_KEY">Constant Field Values</a></dd>
@@ -449,7 +449,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>CREDENTIALS_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/ImportTsv.html#line.99">CREDENTIALS_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/ImportTsv.html#line.100">CREDENTIALS_LOCATION</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.ImportTsv.CREDENTIALS_LOCATION">Constant Field Values</a></dd>
@@ -462,7 +462,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>CREATE_TABLE_CONF_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/ImportTsv.html#line.104">CREATE_TABLE_CONF_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/ImportTsv.html#line.105">CREATE_TABLE_CONF_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.ImportTsv.CREATE_TABLE_CONF_KEY">Constant Field Values</a></dd>
@@ -475,7 +475,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>NO_STRICT_COL_FAMILY</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/ImportTsv.html#line.105">NO_STRICT_COL_FAMILY</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/ImportTsv.html#line.106">NO_STRICT_COL_FAMILY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.ImportTsv.NO_STRICT_COL_FAMILY">Constant Field Values</a></dd>
@@ -496,7 +496,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>ImportTsv</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/ImportTsv.html#line.77">ImportTsv</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/ImportTsv.html#line.78">ImportTsv</a>()</pre>
 </li>
 </ul>
 </li>
@@ -513,7 +513,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>createSubmittableJob</h4>
-<pre>protected static&nbsp;org.apache.hadoop.mapreduce.Job&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/ImportTsv.html#line.462">createSubmittableJob</a>(org.apache.hadoop.conf.Configuration&nbsp;conf,
+<pre>protected static&nbsp;org.apache.hadoop.mapreduce.Job&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/ImportTsv.html#line.463">createSubmittableJob</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;args)
                                                                throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a>,
                                                                       <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/ClassNotFoundException.html?is-external=true" title="class or interface in java.lang">ClassNotFoundException</a></pre>
@@ -536,7 +536,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>run</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/ImportTsv.html#line.706">run</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>[]&nbsp;args)
+<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/ImportTsv.html#line.707">run</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>[]&nbsp;args)
         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="overrideSpecifyLabel">Specified by:</span></dt>
@@ -552,7 +552,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>main</h4>
-<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/ImportTsv.html#line.788">main</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>[]&nbsp;args)
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/ImportTsv.html#line.789">main</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>[]&nbsp;args)
                  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/apidocs/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html b/apidocs/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html
index 4bb665c..f2763db 100644
--- a/apidocs/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html
+++ b/apidocs/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html
@@ -110,7 +110,7 @@ var activeTableTab = "activeTableTab";
 <hr>
 <br>
 <pre>@InterfaceAudience.Public
-public class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.46">TableRecordReaderImpl</a>
+public class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.47">TableRecordReaderImpl</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">Iterate over an HBase table data, return (ImmutableBytesWritable, Result)
  pairs.</div>
@@ -279,7 +279,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>LOG_PER_ROW_COUNT</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/TableRecordReaderImpl.html#line.47">LOG_PER_ROW_COUNT</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/TableRecordReaderImpl.html#line.48">LOG_PER_ROW_COUNT</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.TableRecordReaderImpl.LOG_PER_ROW_COUNT">Constant Field Values</a></dd>
@@ -300,7 +300,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>TableRecordReaderImpl</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.46">TableRecordReaderImpl</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.47">TableRecordReaderImpl</a>()</pre>
 </li>
 </ul>
 </li>
@@ -317,7 +317,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>restart</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.77">restart</a>(byte[]&nbsp;firstRow)
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.78">restart</a>(byte[]&nbsp;firstRow)
              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">Restart from survivable exceptions by creating a new scanner.</div>
 <dl>
@@ -335,7 +335,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <li class="blockList">
 <h4>retrieveGetCounterWithStringsParams</h4>
 <pre><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Deprecated.html?is-external=true" title="class or interface in java.lang">@Deprecated</a>
-protected static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html?is-external=true" title="class or interface in java.lang.reflect">Method</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.106">retrieveGetCounterWithStringsParams</a>(org.apache.hadoop.mapreduce.TaskAttemptContext&nbsp;context)
+protected static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html?is-external=true" title="class or interface in java.lang.reflect">Method</a>&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.107">retrieveGetCounterWithStringsParams</a>(org.apache.hadoop.mapreduce.TaskAttemptContext&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></pre>
 <div class="block"><span class="deprecatedLabel">Deprecated.</span>&nbsp;<span class="deprecationComment">since 2.4.0 and 2.3.2, will be removed in 4.0.0</span></div>
 <div class="block">In new mapreduce APIs, TaskAttemptContext has two getCounter methods
@@ -354,7 +354,7 @@ protected static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/la
 <ul class="blockList">
 <li class="blockList">
 <h4>setHTable</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.124">setHTable</a>(<a href="../../../../../org/apache/hadoop/hbase/client/Table.html" title="interface in org.apache.hadoop.hbase.client">Table</a>&nbsp;htable)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.125">setHTable</a>(<a href="../../../../../org/apache/hadoop/hbase/client/Table.html" title="interface in org.apache.hadoop.hbase.client">Table</a>&nbsp;htable)</pre>
 <div class="block">Sets the HBase table.</div>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
@@ -368,7 +368,7 @@ protected static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/la
 <ul class="blockList">
 <li class="blockList">
 <h4>setScan</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.136">setScan</a>(<a href="../../../../../org/apache/hadoop/hbase/client/Scan.html" title="class in org.apache.hadoop.hbase.client">Scan</a>&nbsp;scan)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.137">setScan</a>(<a href="../../../../../org/apache/hadoop/hbase/client/Scan.html" title="class in org.apache.hadoop.hbase.client">Scan</a>&nbsp;scan)</pre>
 <div class="block">Sets the scan defining the actual details like columns etc.</div>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
@@ -382,7 +382,7 @@ protected static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/la
 <ul class="blockList">
 <li class="blockList">
 <h4>initialize</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.143">initialize</a>(org.apache.hadoop.mapreduce.InputSplit&nbsp;inputsplit,
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.144">initialize</a>(org.apache.hadoop.mapreduce.InputSplit&nbsp;inputsplit,
                        org.apache.hadoop.mapreduce.TaskAttemptContext&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>
@@ -400,7 +400,7 @@ protected static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/la
 <ul class="blockList">
 <li class="blockList">
 <h4>close</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.157">close</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.158">close</a>()</pre>
 <div class="block">Closes the split.</div>
 </li>
 </ul>
@@ -410,7 +410,7 @@ protected static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/la
 <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/TableRecordReaderImpl.html#line.174">getCurrentKey</a>()
+<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/TableRecordReaderImpl.html#line.175">getCurrentKey</a>()
                                      throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a>,
                                             <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InterruptedException.html?is-external=true" title="class or interface in java.lang">InterruptedException</a></pre>
 <div class="block">Returns the current key.</div>
@@ -429,7 +429,7 @@ protected static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/la
 <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/TableRecordReaderImpl.html#line.186">getCurrentValue</a>()
+<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/TableRecordReaderImpl.html#line.187">getCurrentValue</a>()
                        throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a>,
                               <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InterruptedException.html?is-external=true" title="class or interface in java.lang">InterruptedException</a></pre>
 <div class="block">Returns the current value.</div>
@@ -448,7 +448,7 @@ protected static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/la
 <ul class="blockList">
 <li class="blockList">
 <h4>nextKeyValue</h4>
-<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.198">nextKeyValue</a>()
+<pre>public&nbsp;boolean&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.199">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>,
                             <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InterruptedException.html?is-external=true" title="class or interface in java.lang">InterruptedException</a></pre>
 <div class="block">Positions the record reader to the next record.</div>
@@ -468,7 +468,7 @@ protected static&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/la
 <li class="blockList">
 <h4>updateCounters</h4>
 <pre><a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Deprecated.html?is-external=true" title="class or interface in java.lang">@Deprecated</a>
-protected static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.297">updateCounters</a>(org.apache.hadoop.hbase.client.metrics.ScanMetrics&nbsp;scanMetrics,
+protected static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.298">updateCounters</a>(org.apache.hadoop.hbase.client.metrics.ScanMetrics&nbsp;scanMetrics,
                                                  long&nbsp;numScannerRestarts,
                                                  <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Method.html?is-external=true" title="class or interface in java.lang.reflect">Method</a>&nbsp;getCounter,
                                                  org.apache.hadoop.mapreduce.TaskAttemptContext&nbsp;context,
@@ -483,7 +483,7 @@ protected static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hado
 <ul class="blockList">
 <li class="blockList">
 <h4>updateCounters</h4>
-<pre>protected static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.302">updateCounters</a>(org.apache.hadoop.hbase.client.metrics.ScanMetrics&nbsp;scanMetrics,
+<pre>protected static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.303">updateCounters</a>(org.apache.hadoop.hbase.client.metrics.ScanMetrics&nbsp;scanMetrics,
                                      long&nbsp;numScannerRestarts,
                                      org.apache.hadoop.mapreduce.TaskAttemptContext&nbsp;context,
                                      long&nbsp;numStale)</pre>
@@ -495,7 +495,7 @@ protected static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hado
 <ul class="blockListLast">
 <li class="blockList">
 <h4>getProgress</h4>
-<pre>public&nbsp;float&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.334">getProgress</a>()</pre>
+<pre>public&nbsp;float&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html#line.335">getProgress</a>()</pre>
 <div class="block">The current progress of the record reader through its data.</div>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
diff --git a/apidocs/org/apache/hadoop/hbase/mapreduce/WALPlayer.html b/apidocs/org/apache/hadoop/hbase/mapreduce/WALPlayer.html
index 63e47c1..3916237 100644
--- a/apidocs/org/apache/hadoop/hbase/mapreduce/WALPlayer.html
+++ b/apidocs/org/apache/hadoop/hbase/mapreduce/WALPlayer.html
@@ -119,7 +119,7 @@ var activeTableTab = "activeTableTab";
 <hr>
 <br>
 <pre>@InterfaceAudience.Public
-public class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/WALPlayer.html#line.73">WALPlayer</a>
+public class <a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/WALPlayer.html#line.74">WALPlayer</a>
 extends org.apache.hadoop.conf.Configured
 implements org.apache.hadoop.util.Tool</pre>
 <div class="block">A tool to replay WAL files as a M/R job.
@@ -272,7 +272,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>BULK_OUTPUT_CONF_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/WALPlayer.html#line.76">BULK_OUTPUT_CONF_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/WALPlayer.html#line.77">BULK_OUTPUT_CONF_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.WALPlayer.BULK_OUTPUT_CONF_KEY">Constant Field Values</a></dd>
@@ -285,7 +285,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>TABLES_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/WALPlayer.html#line.77">TABLES_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/WALPlayer.html#line.78">TABLES_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.WALPlayer.TABLES_KEY">Constant Field Values</a></dd>
@@ -298,7 +298,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>TABLE_MAP_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/WALPlayer.html#line.78">TABLE_MAP_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/WALPlayer.html#line.79">TABLE_MAP_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.WALPlayer.TABLE_MAP_KEY">Constant Field Values</a></dd>
@@ -311,7 +311,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>INPUT_FILES_SEPARATOR_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/WALPlayer.html#line.79">INPUT_FILES_SEPARATOR_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/WALPlayer.html#line.80">INPUT_FILES_SEPARATOR_KEY</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.WALPlayer.INPUT_FILES_SEPARATOR_KEY">Constant Field Values</a></dd>
@@ -324,7 +324,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>IGNORE_MISSING_FILES</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/WALPlayer.html#line.80">IGNORE_MISSING_FILES</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/WALPlayer.html#line.81">IGNORE_MISSING_FILES</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.WALPlayer.IGNORE_MISSING_FILES">Constant Field Values</a></dd>
@@ -337,7 +337,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>MULTI_TABLES_SUPPORT</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/WALPlayer.html#line.81">MULTI_TABLES_SUPPORT</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/WALPlayer.html#line.82">MULTI_TABLES_SUPPORT</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.WALPlayer.MULTI_TABLES_SUPPORT">Constant Field Values</a></dd>
@@ -350,7 +350,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>tableSeparator</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/WALPlayer.html#line.83">tableSeparator</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/WALPlayer.html#line.84">tableSeparator</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.mapreduce.WALPlayer.tableSeparator">Constant Field Values</a></dd>
@@ -371,7 +371,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>WALPlayer</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/WALPlayer.html#line.87">WALPlayer</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/WALPlayer.html#line.88">WALPlayer</a>()</pre>
 </li>
 </ul>
 <a name="WALPlayer-org.apache.hadoop.conf.Configuration-">
@@ -380,7 +380,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>WALPlayer</h4>
-<pre>protected&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/WALPlayer.html#line.90">WALPlayer</a>(org.apache.hadoop.conf.Configuration&nbsp;c)</pre>
+<pre>protected&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/WALPlayer.html#line.91">WALPlayer</a>(org.apache.hadoop.conf.Configuration&nbsp;c)</pre>
 </li>
 </ul>
 </li>
@@ -397,7 +397,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>createSubmittableJob</h4>
-<pre>public&nbsp;org.apache.hadoop.mapreduce.Job&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/WALPlayer.html#line.284">createSubmittableJob</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>[]&nbsp;args)
+<pre>public&nbsp;org.apache.hadoop.mapreduce.Job&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/WALPlayer.html#line.285">createSubmittableJob</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>[]&nbsp;args)
                                                      throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <div class="block">Sets up the actual job.</div>
 <dl>
@@ -416,7 +416,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>main</h4>
-<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/WALPlayer.html#line.403">main</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>[]&nbsp;args)
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/WALPlayer.html#line.404">main</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>[]&nbsp;args)
                  throws <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Exception.html?is-external=true" title="class or interface in java.lang">Exception</a></pre>
 <div class="block">Main entry point.</div>
 <dl>
@@ -433,7 +433,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>run</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/WALPlayer.html#line.409">run</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>[]&nbsp;args)
+<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/mapreduce/WALPlayer.html#line.410">run</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>[]&nbsp;args)
         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="overrideSpecifyLabel">Specified by:</span></dt>
diff --git a/apidocs/org/apache/hadoop/hbase/rest/client/Client.html b/apidocs/org/apache/hadoop/hbase/rest/client/Client.html
index 7e10edd..446597fc 100644
--- a/apidocs/org/apache/hadoop/hbase/rest/client/Client.html
+++ b/apidocs/org/apache/hadoop/hbase/rest/client/Client.html
@@ -110,7 +110,7 @@ var activeTableTab = "activeTableTab";
 <hr>
 <br>
 <pre>@InterfaceAudience.Public
-public class <a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.76">Client</a>
+public class <a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.77">Client</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">A wrapper around HttpClient which provides some useful function and
  semantics for interacting with the REST gateway.</div>
@@ -499,7 +499,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>EMPTY_HEADER_ARRAY</h4>
-<pre>public static final&nbsp;org.apache.http.Header[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.77">EMPTY_HEADER_ARRAY</a></pre>
+<pre>public static final&nbsp;org.apache.http.Header[] <a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.78">EMPTY_HEADER_ARRAY</a></pre>
 </li>
 </ul>
 </li>
@@ -516,7 +516,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>Client</h4>
-<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.97">Client</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.98">Client</a>()</pre>
 <div class="block">Default Constructor</div>
 </li>
 </ul>
@@ -526,7 +526,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>Client</h4>
-<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.142">Client</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster)</pre>
+<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.143">Client</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster)</pre>
 <div class="block">Constructor</div>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
@@ -540,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>Client</h4>
-<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.151">Client</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.152">Client</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
               boolean&nbsp;sslEnabled)</pre>
 <div class="block">Constructor</div>
 <dl>
@@ -556,7 +556,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>Client</h4>
-<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.161">Client</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.162">Client</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
               org.apache.hadoop.conf.Configuration&nbsp;conf,
               boolean&nbsp;sslEnabled)</pre>
 <div class="block">Constructor</div>
@@ -574,7 +574,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>Client</h4>
-<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.175">Client</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.176">Client</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
               <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;trustStorePath,
               <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html?is-external=true" title="class or interface in java.util">Optional</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;trustStorePassword,
               <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html?is-external=true" title="class or interface in java.util">Optional</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;trustStoreType)</pre>
@@ -596,7 +596,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>Client</h4>
-<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.190">Client</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.191">Client</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
               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;trustStorePath,
               <a href="https://docs.oracle.com/javase/8/docs/api/java/util/Optional.html?is-external=true" title="class or interface in java.util">Optional</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;trustStorePassword,
@@ -628,7 +628,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>shutdown</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.216">shutdown</a>()</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.217">shutdown</a>()</pre>
 <div class="block">Shut down the client. Close any open persistent connections.</div>
 </li>
 </ul>
@@ -638,7 +638,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getHttpClient</h4>
-<pre>public&nbsp;org.apache.http.client.HttpClient&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.222">getHttpClient</a>()</pre>
+<pre>public&nbsp;org.apache.http.client.HttpClient&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.223">getHttpClient</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>the wrapped HttpClient</dd>
@@ -651,7 +651,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>addExtraHeader</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.231">addExtraHeader</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;name,
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.232">addExtraHeader</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;name,
                            <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;value)</pre>
 <div class="block">Add extra headers.  These extra headers will be applied to all http
  methods before they are removed. If any header is not used any more,
@@ -664,7 +664,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getExtraHeader</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/rest/client/Client.html#line.238">getExtraHeader</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;name)</pre>
+<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/rest/client/Client.html#line.239">getExtraHeader</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;name)</pre>
 <div class="block">Get an extra header value.</div>
 </li>
 </ul>
@@ -674,7 +674,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getExtraHeaders</h4>
-<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.html?is-external=true" title="class or interface in java.util">Map</a>&lt;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>,<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&gt;&nbsp;<a href="../../../../../../src-html/org/apa [...]
+<pre>public&nbsp;<a href="https://docs.oracle.com/javase/8/docs/api/java/util/Map.html?is-external=true" title="class or interface in java.util">Map</a>&lt;<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>,<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&gt;&nbsp;<a href="../../../../../../src-html/org/apa [...]
 <div class="block">Get all extra headers (read-only).</div>
 </li>
 </ul>
@@ -684,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>removeExtraHeader</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.252">removeExtraHeader</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;name)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.253">removeExtraHeader</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;name)</pre>
 <div class="block">Remove an extra header.</div>
 </li>
 </ul>
@@ -694,7 +694,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>executePathOnly</h4>
-<pre>public&nbsp;org.apache.http.HttpResponse&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.269">executePathOnly</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;org.apache.http.HttpResponse&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.270">executePathOnly</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
                                                     org.apache.http.client.methods.HttpUriRequest&nbsp;method,
                                                     org.apache.http.Header[]&nbsp;headers,
                                                     <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;path)
@@ -723,7 +723,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>executeURI</h4>
-<pre>public&nbsp;org.apache.http.HttpResponse&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.324">executeURI</a>(org.apache.http.client.methods.HttpUriRequest&nbsp;method,
+<pre>public&nbsp;org.apache.http.HttpResponse&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.325">executeURI</a>(org.apache.http.client.methods.HttpUriRequest&nbsp;method,
                                                org.apache.http.Header[]&nbsp;headers,
                                                <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;uri)
                                         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>
@@ -746,7 +746,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>execute</h4>
-<pre>public&nbsp;org.apache.http.HttpResponse&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.364">execute</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;org.apache.http.HttpResponse&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.365">execute</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
                                             org.apache.http.client.methods.HttpUriRequest&nbsp;method,
                                             org.apache.http.Header[]&nbsp;headers,
                                             <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;path)
@@ -773,7 +773,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getCluster</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.409">getCluster</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.410">getCluster</a>()</pre>
 <dl>
 <dt><span class="returnLabel">Returns:</span></dt>
 <dd>the cluster definition</dd>
@@ -786,7 +786,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setCluster</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.416">setCluster</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.417">setCluster</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster)</pre>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
 <dd><code>cluster</code> - the cluster definition</dd>
@@ -799,7 +799,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>head</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.426">head</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path)
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.427">head</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path)
               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">Send a HEAD request</div>
 <dl>
@@ -818,7 +818,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>head</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.438">head</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.439">head</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
                      <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;path,
                      org.apache.http.Header[]&nbsp;headers)
               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>
@@ -841,7 +841,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>get</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.455">get</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path)
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.456">get</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path)
              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">Send a GET request</div>
 <dl>
@@ -860,7 +860,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>get</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.466">get</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.467">get</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
                     <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;path)
              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">Send a GET request</div>
@@ -881,7 +881,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>get</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.477">get</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.478">get</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
                     <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;accept)
              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">Send a GET request</div>
@@ -902,7 +902,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>get</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.489">get</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.490">get</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
                     <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;path,
                     <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;accept)
              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>
@@ -925,7 +925,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>get</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.504">get</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.505">get</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
                     org.apache.http.Header[]&nbsp;headers)
              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">Send a GET request</div>
@@ -947,7 +947,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getResponseBody</h4>
-<pre>public static&nbsp;byte[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.524">getResponseBody</a>(org.apache.http.HttpResponse&nbsp;resp)
+<pre>public static&nbsp;byte[]&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.525">getResponseBody</a>(org.apache.http.HttpResponse&nbsp;resp)
                               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">Returns the response body of the HTTPResponse, if any, as an array of bytes.
  If response body is not available or cannot be read, returns <tt>null</tt>
@@ -973,7 +973,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>get</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.555">get</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;c,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.556">get</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;c,
                     <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;path,
                     org.apache.http.Header[]&nbsp;headers)
              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>
@@ -996,7 +996,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>put</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.574">put</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.575">put</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
                     <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;contentType,
                     byte[]&nbsp;content)
              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>
@@ -1019,7 +1019,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>put</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.588">put</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.589">put</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
                     <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;contentType,
                     byte[]&nbsp;content,
                     org.apache.http.Header&nbsp;extraHdr)
@@ -1044,7 +1044,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>put</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.602">put</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.603">put</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
                     <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;path,
                     <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;contentType,
                     byte[]&nbsp;content)
@@ -1069,7 +1069,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>put</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.619">put</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.620">put</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
                     <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;path,
                     <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;contentType,
                     byte[]&nbsp;content,
@@ -1096,7 +1096,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>put</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.639">put</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.640">put</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
                     org.apache.http.Header[]&nbsp;headers,
                     byte[]&nbsp;content)
              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>
@@ -1120,7 +1120,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>put</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.654">put</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.655">put</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
                     <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;path,
                     org.apache.http.Header[]&nbsp;headers,
                     byte[]&nbsp;content)
@@ -1146,7 +1146,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>post</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.676">post</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.677">post</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
                      <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;contentType,
                      byte[]&nbsp;content)
               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>
@@ -1169,7 +1169,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>post</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.690">post</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.691">post</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
                      <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;contentType,
                      byte[]&nbsp;content,
                      org.apache.http.Header&nbsp;extraHdr)
@@ -1194,7 +1194,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>post</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.704">post</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.705">post</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
                      <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;path,
                      <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;contentType,
                      byte[]&nbsp;content)
@@ -1219,7 +1219,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>post</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.721">post</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.722">post</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
                      <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;path,
                      <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;contentType,
                      byte[]&nbsp;content,
@@ -1246,7 +1246,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>post</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.741">post</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.742">post</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
                      org.apache.http.Header[]&nbsp;headers,
                      byte[]&nbsp;content)
               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>
@@ -1270,7 +1270,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>post</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.756">post</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.757">post</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
                      <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;path,
                      org.apache.http.Header[]&nbsp;headers,
                      byte[]&nbsp;content)
@@ -1296,7 +1296,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>delete</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.776">delete</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path)
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.777">delete</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path)
                 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">Send a DELETE request</div>
 <dl>
@@ -1315,7 +1315,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>delete</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.787">delete</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.788">delete</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>&nbsp;path,
                        org.apache.http.Header&nbsp;extraHdr)
                 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">Send a DELETE request</div>
@@ -1336,7 +1336,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>delete</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.798">delete</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.799">delete</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
                        <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;path)
                 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">Send a DELETE request</div>
@@ -1357,7 +1357,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>delete</h4>
-<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.817">delete</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
+<pre>public&nbsp;<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Response.html" title="class in org.apache.hadoop.hbase.rest.client">Response</a>&nbsp;<a href="../../../../../../src-html/org/apache/hadoop/hbase/rest/client/Client.html#line.818">delete</a>(<a href="../../../../../../org/apache/hadoop/hbase/rest/client/Cluster.html" title="class in org.apache.hadoop.hbase.rest.client">Cluster</a>&nbsp;cluster,
                        <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;path,
                        org.apache.http.Header&nbsp;extraHdr)
                 throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
diff --git a/apidocs/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html b/apidocs/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html
index c5a4722..bc9d3c7 100644
--- a/apidocs/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html
+++ b/apidocs/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html
@@ -119,7 +119,7 @@ var activeTableTab = "activeTableTab";
 <hr>
 <br>
 <pre>@InterfaceAudience.Public
-public class <a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html#line.94">ExportSnapshot</a>
+public class <a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html#line.95">ExportSnapshot</a>
 extends org.apache.hadoop.hbase.util.AbstractHBaseTool
 implements org.apache.hadoop.util.Tool</pre>
 <div class="block">Export the specified snapshot to a given FileSystem.
@@ -280,7 +280,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>NAME</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/snapshot/ExportSnapshot.html#line.95">NAME</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/snapshot/ExportSnapshot.html#line.96">NAME</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.snapshot.ExportSnapshot.NAME">Constant Field Values</a></dd>
@@ -293,7 +293,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>CONF_SOURCE_PREFIX</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/snapshot/ExportSnapshot.html#line.97">CONF_SOURCE_PREFIX</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/snapshot/ExportSnapshot.html#line.98">CONF_SOURCE_PREFIX</a></pre>
 <div class="block">Configuration prefix for overrides for the source filesystem</div>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
@@ -307,7 +307,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>CONF_DEST_PREFIX</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/snapshot/ExportSnapshot.html#line.99">CONF_DEST_PREFIX</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/snapshot/ExportSnapshot.html#line.100">CONF_DEST_PREFIX</a></pre>
 <div class="block">Configuration prefix for overrides for the destination filesystem</div>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
@@ -321,7 +321,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>CONF_SKIP_TMP</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/snapshot/ExportSnapshot.html#line.117">CONF_SKIP_TMP</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/snapshot/ExportSnapshot.html#line.118">CONF_SKIP_TMP</a></pre>
 <dl>
 <dt><span class="seeLabel">See Also:</span></dt>
 <dd><a href="../../../../../constant-values.html#org.apache.hadoop.hbase.snapshot.ExportSnapshot.CONF_SKIP_TMP">Constant Field Values</a></dd>
@@ -342,7 +342,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>ExportSnapshot</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html#line.94">ExportSnapshot</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html#line.95">ExportSnapshot</a>()</pre>
 </li>
 </ul>
 </li>
@@ -359,7 +359,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>processOptions</h4>
-<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html#line.918">processOptions</a>(org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine&nbsp;cmd)</pre>
+<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html#line.919">processOptions</a>(org.apache.hbase.thirdparty.org.apache.commons.cli.CommandLine&nbsp;cmd)</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from class:&nbsp;<code>org.apache.hadoop.hbase.util.AbstractHBaseTool</code></span></div>
 <div class="block">This method is called to process the options after they have been parsed.</div>
 <dl>
@@ -374,7 +374,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>doWork</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html#line.943">doWork</a>()
+<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html#line.944">doWork</a>()
            throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a></pre>
 <div class="block">Execute the export snapshot by copying the snapshot metadata, hfiles and wals.</div>
 <dl>
@@ -393,7 +393,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>printUsage</h4>
-<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html#line.1116">printUsage</a>()</pre>
+<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html#line.1117">printUsage</a>()</pre>
 <dl>
 <dt><span class="overrideSpecifyLabel">Overrides:</span></dt>
 <dd><code>printUsage</code>&nbsp;in class&nbsp;<code>org.apache.hadoop.hbase.util.AbstractHBaseTool</code></dd>
@@ -406,7 +406,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockList">
 <li class="blockList">
 <h4>addOptions</h4>
-<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html#line.1129">addOptions</a>()</pre>
+<pre>protected&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html#line.1130">addOptions</a>()</pre>
 <div class="block"><span class="descfrmTypeLabel">Description copied from class:&nbsp;<code>org.apache.hadoop.hbase.util.AbstractHBaseTool</code></span></div>
 <div class="block">Override this to add command-line options using <code>AbstractHBaseTool.addOptWithArg(java.lang.String, java.lang.String)</code>
  and similar methods.</div>
@@ -422,7 +422,7 @@ implements org.apache.hadoop.util.Tool</pre>
 <ul class="blockListLast">
 <li class="blockList">
 <h4>main</h4>
-<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html#line.1144">main</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>[]&nbsp;args)</pre>
+<pre>public static&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/snapshot/ExportSnapshot.html#line.1145">main</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/lang/String.html?is-external=true" title="class or interface in java.lang">String</a>[]&nbsp;args)</pre>
 </li>
 </ul>
 </li>
diff --git a/apidocs/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html b/apidocs/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html
index a899bf7..ee01428 100644
--- a/apidocs/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html
+++ b/apidocs/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html
@@ -110,7 +110,7 @@ var activeTableTab = "activeTableTab";
 <hr>
 <br>
 <pre>@InterfaceAudience.Public
-public class <a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.52">MiniZooKeeperCluster</a>
+public class <a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.53">MiniZooKeeperCluster</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">TODO: Most of the code in this class is ripped from ZooKeeper tests. Instead
  of redoing it, we should contribute updates to their code which let us more
@@ -257,7 +257,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>LOOPBACK_HOST</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/zookeeper/MiniZooKeeperCluster.html#line.59">LOOPBACK_HOST</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/zookeeper/MiniZooKeeperCluster.html#line.60">LOOPBACK_HOST</a></pre>
 </li>
 </ul>
 <a name="HOST">
@@ -266,7 +266,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>HOST</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/zookeeper/MiniZooKeeperCluster.html#line.60">HOST</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/zookeeper/MiniZooKeeperCluster.html#line.61">HOST</a></pre>
 </li>
 </ul>
 </li>
@@ -283,7 +283,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>MiniZooKeeperCluster</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.78">MiniZooKeeperCluster</a>()</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.79">MiniZooKeeperCluster</a>()</pre>
 </li>
 </ul>
 <a name="MiniZooKeeperCluster-org.apache.hadoop.conf.Configuration-">
@@ -292,7 +292,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockListLast">
 <li class="blockList">
 <h4>MiniZooKeeperCluster</h4>
-<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.82">MiniZooKeeperCluster</a>(org.apache.hadoop.conf.Configuration&nbsp;configuration)</pre>
+<pre>public&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.83">MiniZooKeeperCluster</a>(org.apache.hadoop.conf.Configuration&nbsp;configuration)</pre>
 </li>
 </ul>
 </li>
@@ -309,7 +309,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>addClientPort</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.98">addClientPort</a>(int&nbsp;clientPort)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.99">addClientPort</a>(int&nbsp;clientPort)</pre>
 <div class="block">Add a client port to the list.</div>
 <dl>
 <dt><span class="paramLabel">Parameters:</span></dt>
@@ -323,7 +323,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setDefaultClientPort</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.121">setDefaultClientPort</a>(int&nbsp;clientPort)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.122">setDefaultClientPort</a>(int&nbsp;clientPort)</pre>
 </li>
 </ul>
 <a name="setTickTime-int-">
@@ -332,7 +332,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>setTickTime</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.162">setTickTime</a>(int&nbsp;tickTime)</pre>
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.163">setTickTime</a>(int&nbsp;tickTime)</pre>
 </li>
 </ul>
 <a name="getBackupZooKeeperServerNum--">
@@ -341,7 +341,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getBackupZooKeeperServerNum</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.166">getBackupZooKeeperServerNum</a>()</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.167">getBackupZooKeeperServerNum</a>()</pre>
 </li>
 </ul>
 <a name="getZooKeeperServerNum--">
@@ -350,7 +350,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>getZooKeeperServerNum</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.170">getZooKeeperServerNum</a>()</pre>
+<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.171">getZooKeeperServerNum</a>()</pre>
 </li>
 </ul>
 <a name="startup-java.io.File-">
@@ -359,7 +359,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>startup</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.186">startup</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/io/File.html?is-external=true" title="class or interface in java.io">File</a>&nbsp;baseDir)
+<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.187">startup</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/io/File.html?is-external=true" title="class or interface in java.io">File</a>&nbsp;baseDir)
             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>
@@ -375,7 +375,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>startup</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.202">startup</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/io/File.html?is-external=true" title="class or interface in java.io">File</a>&nbsp;baseDir,
+<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.203">startup</a>(<a href="https://docs.oracle.com/javase/8/docs/api/java/io/File.html?is-external=true" title="class or interface in java.io">File</a>&nbsp;baseDir,
                    int&nbsp;numZooKeeperServers)
             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>
@@ -398,7 +398,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>shutdown</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.323">shutdown</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.324">shutdown</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>
@@ -412,7 +412,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>killCurrentActiveZooKeeperServer</h4>
-<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.356">killCurrentActiveZooKeeperServer</a>()
+<pre>public&nbsp;int&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.357">killCurrentActiveZooKeeperServer</a>()
                                      throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a>,
                                             <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InterruptedException.html?is-external=true" title="class or interface in java.lang">InterruptedException</a></pre>
 <dl>
@@ -431,7 +431,7 @@ extends <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
 <ul class="blockList">
 <li class="blockList">
 <h4>killOneBackupZooKeeperServer</h4>
-<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.394">killOneBackupZooKeeperServer</a>()
+<pre>public&nbsp;void&nbsp;<a href="../../../../../src-html/org/apache/hadoop/hbase/zookeeper/MiniZooKeeperCluster.html#line.395">killOneBackupZooKeeperServer</a>()
                                   throws <a href="https://docs.oracle.com/javase/8/docs/api/java/io/IOException.html?is-external=true" title="class or interface in java.io">IOException</a>,
                                          <a href="https://docs.oracle.com/javase/8/docs/api/java/lang/InterruptedException.html?is-external=true" title="class or interface in java.lang">InterruptedException</a></pre>
 <div class="block">Kill one back up ZK servers.</div>
diff --git a/apidocs/src-html/org/apache/hadoop/hbase/ScheduledChore.html b/apidocs/src-html/org/apache/hadoop/hbase/ScheduledChore.html
index 4e2b9fa..10020c9 100644
--- a/apidocs/src-html/org/apache/hadoop/hbase/ScheduledChore.html
+++ b/apidocs/src-html/org/apache/hadoop/hbase/ScheduledChore.html
@@ -29,339 +29,341 @@
 <span class="sourceLineNo">021</span>import com.google.errorprone.annotations.RestrictedApi;<a name="line.21"></a>
 <span class="sourceLineNo">022</span>import java.util.concurrent.ScheduledThreadPoolExecutor;<a name="line.22"></a>
 <span class="sourceLineNo">023</span>import java.util.concurrent.TimeUnit;<a name="line.23"></a>
-<span class="sourceLineNo">024</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.24"></a>
-<span class="sourceLineNo">025</span>import org.slf4j.Logger;<a name="line.25"></a>
-<span class="sourceLineNo">026</span>import org.slf4j.LoggerFactory;<a name="line.26"></a>
-<span class="sourceLineNo">027</span><a name="line.27"></a>
-<span class="sourceLineNo">028</span>/**<a name="line.28"></a>
-<span class="sourceLineNo">029</span> * ScheduledChore is a task performed on a period in hbase. ScheduledChores become active once<a name="line.29"></a>
-<span class="sourceLineNo">030</span> * scheduled with a {@link ChoreService} via {@link ChoreService#scheduleChore(ScheduledChore)}. The<a name="line.30"></a>
-<span class="sourceLineNo">031</span> * chore is run in a {@link ScheduledThreadPoolExecutor} and competes with other ScheduledChores for<a name="line.31"></a>
-<span class="sourceLineNo">032</span> * access to the threads in the core thread pool. If an unhandled exception occurs, the chore<a name="line.32"></a>
-<span class="sourceLineNo">033</span> * cancellation is logged. Implementers should consider whether or not the Chore will be able to<a name="line.33"></a>
-<span class="sourceLineNo">034</span> * execute within the defined period. It is bad practice to define a ScheduledChore whose execution<a name="line.34"></a>
-<span class="sourceLineNo">035</span> * time exceeds its period since it will try to hog one of the threads in the {@link ChoreService}'s<a name="line.35"></a>
-<span class="sourceLineNo">036</span> * thread pool.<a name="line.36"></a>
-<span class="sourceLineNo">037</span> * &lt;p/&gt;<a name="line.37"></a>
-<span class="sourceLineNo">038</span> * Don't subclass ScheduledChore if the task relies on being woken up for something to do, such as<a name="line.38"></a>
-<span class="sourceLineNo">039</span> * an entry being added to a queue, etc.<a name="line.39"></a>
-<span class="sourceLineNo">040</span> */<a name="line.40"></a>
-<span class="sourceLineNo">041</span>@InterfaceAudience.Public<a name="line.41"></a>
-<span class="sourceLineNo">042</span>public abstract class ScheduledChore implements Runnable {<a name="line.42"></a>
-<span class="sourceLineNo">043</span>  private static final Logger LOG = LoggerFactory.getLogger(ScheduledChore.class);<a name="line.43"></a>
-<span class="sourceLineNo">044</span><a name="line.44"></a>
-<span class="sourceLineNo">045</span>  private final String name;<a name="line.45"></a>
+<span class="sourceLineNo">024</span><a name="line.24"></a>
+<span class="sourceLineNo">025</span>import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;<a name="line.25"></a>
+<span class="sourceLineNo">026</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.26"></a>
+<span class="sourceLineNo">027</span>import org.slf4j.Logger;<a name="line.27"></a>
+<span class="sourceLineNo">028</span>import org.slf4j.LoggerFactory;<a name="line.28"></a>
+<span class="sourceLineNo">029</span><a name="line.29"></a>
+<span class="sourceLineNo">030</span>/**<a name="line.30"></a>
+<span class="sourceLineNo">031</span> * ScheduledChore is a task performed on a period in hbase. ScheduledChores become active once<a name="line.31"></a>
+<span class="sourceLineNo">032</span> * scheduled with a {@link ChoreService} via {@link ChoreService#scheduleChore(ScheduledChore)}. The<a name="line.32"></a>
+<span class="sourceLineNo">033</span> * chore is run in a {@link ScheduledThreadPoolExecutor} and competes with other ScheduledChores for<a name="line.33"></a>
+<span class="sourceLineNo">034</span> * access to the threads in the core thread pool. If an unhandled exception occurs, the chore<a name="line.34"></a>
+<span class="sourceLineNo">035</span> * cancellation is logged. Implementers should consider whether or not the Chore will be able to<a name="line.35"></a>
+<span class="sourceLineNo">036</span> * execute within the defined period. It is bad practice to define a ScheduledChore whose execution<a name="line.36"></a>
+<span class="sourceLineNo">037</span> * time exceeds its period since it will try to hog one of the threads in the {@link ChoreService}'s<a name="line.37"></a>
+<span class="sourceLineNo">038</span> * thread pool.<a name="line.38"></a>
+<span class="sourceLineNo">039</span> * &lt;p/&gt;<a name="line.39"></a>
+<span class="sourceLineNo">040</span> * Don't subclass ScheduledChore if the task relies on being woken up for something to do, such as<a name="line.40"></a>
+<span class="sourceLineNo">041</span> * an entry being added to a queue, etc.<a name="line.41"></a>
+<span class="sourceLineNo">042</span> */<a name="line.42"></a>
+<span class="sourceLineNo">043</span>@InterfaceAudience.Public<a name="line.43"></a>
+<span class="sourceLineNo">044</span>public abstract class ScheduledChore implements Runnable {<a name="line.44"></a>
+<span class="sourceLineNo">045</span>  private static final Logger LOG = LoggerFactory.getLogger(ScheduledChore.class);<a name="line.45"></a>
 <span class="sourceLineNo">046</span><a name="line.46"></a>
-<span class="sourceLineNo">047</span>  /**<a name="line.47"></a>
-<span class="sourceLineNo">048</span>   * Default values for scheduling parameters should they be excluded during construction<a name="line.48"></a>
-<span class="sourceLineNo">049</span>   */<a name="line.49"></a>
-<span class="sourceLineNo">050</span>  private final static TimeUnit DEFAULT_TIME_UNIT = TimeUnit.MILLISECONDS;<a name="line.50"></a>
-<span class="sourceLineNo">051</span>  private final static long DEFAULT_INITIAL_DELAY = 0;<a name="line.51"></a>
-<span class="sourceLineNo">052</span><a name="line.52"></a>
-<span class="sourceLineNo">053</span>  /**<a name="line.53"></a>
-<span class="sourceLineNo">054</span>   * Scheduling parameters. Used by ChoreService when scheduling the chore to run periodically<a name="line.54"></a>
-<span class="sourceLineNo">055</span>   */<a name="line.55"></a>
-<span class="sourceLineNo">056</span>  private final int period; // in TimeUnit units<a name="line.56"></a>
-<span class="sourceLineNo">057</span>  private final TimeUnit timeUnit;<a name="line.57"></a>
-<span class="sourceLineNo">058</span>  private final long initialDelay; // in TimeUnit units<a name="line.58"></a>
-<span class="sourceLineNo">059</span><a name="line.59"></a>
-<span class="sourceLineNo">060</span>  /**<a name="line.60"></a>
-<span class="sourceLineNo">061</span>   * Interface to the ChoreService that this ScheduledChore is scheduled with. null if the chore is<a name="line.61"></a>
-<span class="sourceLineNo">062</span>   * not scheduled.<a name="line.62"></a>
-<span class="sourceLineNo">063</span>   */<a name="line.63"></a>
-<span class="sourceLineNo">064</span>  private ChoreService choreService;<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>   * Variables that encapsulate the meaningful state information<a name="line.67"></a>
-<span class="sourceLineNo">068</span>   */<a name="line.68"></a>
-<span class="sourceLineNo">069</span>  private long timeOfLastRun = -1; // system time millis<a name="line.69"></a>
-<span class="sourceLineNo">070</span>  private long timeOfThisRun = -1; // system time millis<a name="line.70"></a>
-<span class="sourceLineNo">071</span>  private boolean initialChoreComplete = false;<a name="line.71"></a>
-<span class="sourceLineNo">072</span><a name="line.72"></a>
-<span class="sourceLineNo">073</span>  /**<a name="line.73"></a>
-<span class="sourceLineNo">074</span>   * A means by which a ScheduledChore can be stopped. Once a chore recognizes that it has been<a name="line.74"></a>
-<span class="sourceLineNo">075</span>   * stopped, it will cancel itself. This is particularly useful in the case where a single stopper<a name="line.75"></a>
-<span class="sourceLineNo">076</span>   * instance is given to multiple chores. In such a case, a single {@link Stoppable#stop(String)}<a name="line.76"></a>
-<span class="sourceLineNo">077</span>   * command can cause many chores to stop together.<a name="line.77"></a>
-<span class="sourceLineNo">078</span>   */<a name="line.78"></a>
-<span class="sourceLineNo">079</span>  private final Stoppable stopper;<a name="line.79"></a>
-<span class="sourceLineNo">080</span><a name="line.80"></a>
-<span class="sourceLineNo">081</span>  /**<a name="line.81"></a>
-<span class="sourceLineNo">082</span>   * This constructor is for test only. It allows us to create an object and to call chore() on it.<a name="line.82"></a>
-<span class="sourceLineNo">083</span>   */<a name="line.83"></a>
-<span class="sourceLineNo">084</span>  @InterfaceAudience.Private<a name="line.84"></a>
-<span class="sourceLineNo">085</span>  protected ScheduledChore() {<a name="line.85"></a>
-<span class="sourceLineNo">086</span>    this("TestChore", null, 0, DEFAULT_INITIAL_DELAY, DEFAULT_TIME_UNIT);<a name="line.86"></a>
-<span class="sourceLineNo">087</span>  }<a name="line.87"></a>
-<span class="sourceLineNo">088</span><a name="line.88"></a>
-<span class="sourceLineNo">089</span>  /**<a name="line.89"></a>
-<span class="sourceLineNo">090</span>   * @param name Name assigned to Chore. Useful for identification amongst chores of the same type<a name="line.90"></a>
-<span class="sourceLineNo">091</span>   * @param stopper When {@link Stoppable#isStopped()} is true, this chore will cancel and cleanup<a name="line.91"></a>
-<span class="sourceLineNo">092</span>   * @param period Period in millis with which this Chore repeats execution when scheduled.<a name="line.92"></a>
-<span class="sourceLineNo">093</span>   */<a name="line.93"></a>
-<span class="sourceLineNo">094</span>  public ScheduledChore(final String name, Stoppable stopper, final int period) {<a name="line.94"></a>
-<span class="sourceLineNo">095</span>    this(name, stopper, period, DEFAULT_INITIAL_DELAY);<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>  /**<a name="line.98"></a>
-<span class="sourceLineNo">099</span>   * @param name Name assigned to Chore. Useful for identification amongst chores of the same type<a name="line.99"></a>
-<span class="sourceLineNo">100</span>   * @param stopper When {@link Stoppable#isStopped()} is true, this chore will cancel and cleanup<a name="line.100"></a>
-<span class="sourceLineNo">101</span>   * @param period Period in millis with which this Chore repeats execution when scheduled.<a name="line.101"></a>
-<span class="sourceLineNo">102</span>   * @param initialDelay Delay before this Chore begins to execute once it has been scheduled. A<a name="line.102"></a>
-<span class="sourceLineNo">103</span>   *          value of 0 means the chore will begin to execute immediately. Negative delays are<a name="line.103"></a>
-<span class="sourceLineNo">104</span>   *          invalid and will be corrected to a value of 0.<a name="line.104"></a>
-<span class="sourceLineNo">105</span>   */<a name="line.105"></a>
-<span class="sourceLineNo">106</span>  public ScheduledChore(final String name, Stoppable stopper, final int period,<a name="line.106"></a>
-<span class="sourceLineNo">107</span>      final long initialDelay) {<a name="line.107"></a>
-<span class="sourceLineNo">108</span>    this(name, stopper, period, initialDelay, DEFAULT_TIME_UNIT);<a name="line.108"></a>
-<span class="sourceLineNo">109</span>  }<a name="line.109"></a>
-<span class="sourceLineNo">110</span><a name="line.110"></a>
-<span class="sourceLineNo">111</span>  /**<a name="line.111"></a>
-<span class="sourceLineNo">112</span>   * @param name Name assigned to Chore. Useful for identification amongst chores of the same type<a name="line.112"></a>
-<span class="sourceLineNo">113</span>   * @param stopper When {@link Stoppable#isStopped()} is true, this chore will cancel and cleanup<a name="line.113"></a>
-<span class="sourceLineNo">114</span>   * @param period Period in Timeunit unit with which this Chore repeats execution when scheduled.<a name="line.114"></a>
-<span class="sourceLineNo">115</span>   * @param initialDelay Delay in Timeunit unit before this Chore begins to execute once it has been<a name="line.115"></a>
-<span class="sourceLineNo">116</span>   *          scheduled. A value of 0 means the chore will begin to execute immediately. Negative<a name="line.116"></a>
-<span class="sourceLineNo">117</span>   *          delays are invalid and will be corrected to a value of 0.<a name="line.117"></a>
-<span class="sourceLineNo">118</span>   * @param unit The unit that is used to measure period and initialDelay<a name="line.118"></a>
-<span class="sourceLineNo">119</span>   */<a name="line.119"></a>
-<span class="sourceLineNo">120</span>  public ScheduledChore(final String name, Stoppable stopper, final int period,<a name="line.120"></a>
-<span class="sourceLineNo">121</span>      final long initialDelay, final TimeUnit unit) {<a name="line.121"></a>
-<span class="sourceLineNo">122</span>    this.name = name;<a name="line.122"></a>
-<span class="sourceLineNo">123</span>    this.stopper = stopper;<a name="line.123"></a>
-<span class="sourceLineNo">124</span>    this.period = period;<a name="line.124"></a>
-<span class="sourceLineNo">125</span>    this.initialDelay = initialDelay &lt; 0 ? 0 : initialDelay;<a name="line.125"></a>
-<span class="sourceLineNo">126</span>    this.timeUnit = unit;<a name="line.126"></a>
-<span class="sourceLineNo">127</span>  }<a name="line.127"></a>
-<span class="sourceLineNo">128</span><a name="line.128"></a>
-<span class="sourceLineNo">129</span>  /**<a name="line.129"></a>
-<span class="sourceLineNo">130</span>   * @see java.lang.Runnable#run()<a name="line.130"></a>
-<span class="sourceLineNo">131</span>   */<a name="line.131"></a>
-<span class="sourceLineNo">132</span>  @Override<a name="line.132"></a>
-<span class="sourceLineNo">133</span>  public void run() {<a name="line.133"></a>
-<span class="sourceLineNo">134</span>    updateTimeTrackingBeforeRun();<a name="line.134"></a>
-<span class="sourceLineNo">135</span>    if (missedStartTime() &amp;&amp; isScheduled()) {<a name="line.135"></a>
-<span class="sourceLineNo">136</span>      onChoreMissedStartTime();<a name="line.136"></a>
-<span class="sourceLineNo">137</span>      LOG.info("Chore: {} missed its start time", getName());<a name="line.137"></a>
-<span class="sourceLineNo">138</span>    } else if (stopper.isStopped() || !isScheduled()) {<a name="line.138"></a>
-<span class="sourceLineNo">139</span>      // call shutdown here to cleanup the ScheduledChore.<a name="line.139"></a>
-<span class="sourceLineNo">140</span>      shutdown(false);<a name="line.140"></a>
-<span class="sourceLineNo">141</span>      LOG.info("Chore: {} was stopped", getName());<a name="line.141"></a>
-<span class="sourceLineNo">142</span>    } else {<a name="line.142"></a>
-<span class="sourceLineNo">143</span>      try {<a name="line.143"></a>
-<span class="sourceLineNo">144</span>        // TODO: Histogram metrics per chore name.<a name="line.144"></a>
-<span class="sourceLineNo">145</span>        // For now, just measure and log if DEBUG level logging is enabled.<a name="line.145"></a>
-<span class="sourceLineNo">146</span>        long start = 0;<a name="line.146"></a>
-<span class="sourceLineNo">147</span>        if (LOG.isDebugEnabled()) {<a name="line.147"></a>
-<span class="sourceLineNo">148</span>          start = System.nanoTime();<a name="line.148"></a>
-<span class="sourceLineNo">149</span>        }<a name="line.149"></a>
-<span class="sourceLineNo">150</span>        if (!initialChoreComplete) {<a name="line.150"></a>
-<span class="sourceLineNo">151</span>          initialChoreComplete = initialChore();<a name="line.151"></a>
-<span class="sourceLineNo">152</span>        } else {<a name="line.152"></a>
-<span class="sourceLineNo">153</span>          chore();<a name="line.153"></a>
-<span class="sourceLineNo">154</span>        }<a name="line.154"></a>
-<span class="sourceLineNo">155</span>        if (LOG.isDebugEnabled() &amp;&amp; start &gt; 0) {<a name="line.155"></a>
-<span class="sourceLineNo">156</span>          long end = System.nanoTime();<a name="line.156"></a>
-<span class="sourceLineNo">157</span>          LOG.debug("{} execution time: {} ms.", getName(),<a name="line.157"></a>
-<span class="sourceLineNo">158</span>            TimeUnit.NANOSECONDS.toMillis(end - start));<a name="line.158"></a>
-<span class="sourceLineNo">159</span>        }<a name="line.159"></a>
-<span class="sourceLineNo">160</span>      } catch (Throwable t) {<a name="line.160"></a>
-<span class="sourceLineNo">161</span>        LOG.error("Caught error", t);<a name="line.161"></a>
-<span class="sourceLineNo">162</span>        if (this.stopper.isStopped()) {<a name="line.162"></a>
-<span class="sourceLineNo">163</span>          cancel(false);<a name="line.163"></a>
-<span class="sourceLineNo">164</span>        }<a name="line.164"></a>
-<span class="sourceLineNo">165</span>      }<a name="line.165"></a>
-<span class="sourceLineNo">166</span>    }<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>  /**<a name="line.169"></a>
-<span class="sourceLineNo">170</span>   * Update our time tracking members. Called at the start of an execution of this chore's run()<a name="line.170"></a>
-<span class="sourceLineNo">171</span>   * method so that a correct decision can be made as to whether or not we missed the start time<a name="line.171"></a>
-<span class="sourceLineNo">172</span>   */<a name="line.172"></a>
-<span class="sourceLineNo">173</span>  private synchronized void updateTimeTrackingBeforeRun() {<a name="line.173"></a>
-<span class="sourceLineNo">174</span>    timeOfLastRun = timeOfThisRun;<a name="line.174"></a>
-<span class="sourceLineNo">175</span>    timeOfThisRun = System.currentTimeMillis();<a name="line.175"></a>
-<span class="sourceLineNo">176</span>  }<a name="line.176"></a>
-<span class="sourceLineNo">177</span><a name="line.177"></a>
-<span class="sourceLineNo">178</span>  /**<a name="line.178"></a>
-<span class="sourceLineNo">179</span>   * Notify the ChoreService that this chore has missed its start time. Allows the ChoreService to<a name="line.179"></a>
-<span class="sourceLineNo">180</span>   * make the decision as to whether or not it would be worthwhile to increase the number of core<a name="line.180"></a>
-<span class="sourceLineNo">181</span>   * pool threads<a name="line.181"></a>
-<span class="sourceLineNo">182</span>   */<a name="line.182"></a>
-<span class="sourceLineNo">183</span>  private synchronized void onChoreMissedStartTime() {<a name="line.183"></a>
-<span class="sourceLineNo">184</span>    if (choreService != null) {<a name="line.184"></a>
-<span class="sourceLineNo">185</span>      choreService.onChoreMissedStartTime(this);<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><a name="line.188"></a>
-<span class="sourceLineNo">189</span>  /**<a name="line.189"></a>
-<span class="sourceLineNo">190</span>   * @return How long in millis has it been since this chore last run. Useful for checking if the<a name="line.190"></a>
-<span class="sourceLineNo">191</span>   *         chore has missed its scheduled start time by too large of a margin<a name="line.191"></a>
-<span class="sourceLineNo">192</span>   */<a name="line.192"></a>
-<span class="sourceLineNo">193</span>  synchronized long getTimeBetweenRuns() {<a name="line.193"></a>
-<span class="sourceLineNo">194</span>    return timeOfThisRun - timeOfLastRun;<a name="line.194"></a>
-<span class="sourceLineNo">195</span>  }<a name="line.195"></a>
-<span class="sourceLineNo">196</span><a name="line.196"></a>
-<span class="sourceLineNo">197</span>  /**<a name="line.197"></a>
-<span class="sourceLineNo">198</span>   * @return true when the time between runs exceeds the acceptable threshold<a name="line.198"></a>
-<span class="sourceLineNo">199</span>   */<a name="line.199"></a>
-<span class="sourceLineNo">200</span>  private synchronized boolean missedStartTime() {<a name="line.200"></a>
-<span class="sourceLineNo">201</span>    return isValidTime(timeOfLastRun) &amp;&amp; isValidTime(timeOfThisRun)<a name="line.201"></a>
-<span class="sourceLineNo">202</span>        &amp;&amp; getTimeBetweenRuns() &gt; getMaximumAllowedTimeBetweenRuns();<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>   * @return max allowed time in millis between runs.<a name="line.206"></a>
-<span class="sourceLineNo">207</span>   */<a name="line.207"></a>
-<span class="sourceLineNo">208</span>  private double getMaximumAllowedTimeBetweenRuns() {<a name="line.208"></a>
-<span class="sourceLineNo">209</span>    // Threshold used to determine if the Chore's current run started too late<a name="line.209"></a>
-<span class="sourceLineNo">210</span>    return 1.5 * timeUnit.toMillis(period);<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>  /**<a name="line.213"></a>
-<span class="sourceLineNo">214</span>   * @param time in system millis<a name="line.214"></a>
-<span class="sourceLineNo">215</span>   * @return true if time is earlier or equal to current milli time<a name="line.215"></a>
-<span class="sourceLineNo">216</span>   */<a name="line.216"></a>
-<span class="sourceLineNo">217</span>  private synchronized boolean isValidTime(final long time) {<a name="line.217"></a>
-<span class="sourceLineNo">218</span>    return time &gt; 0 &amp;&amp; time &lt;= System.currentTimeMillis();<a name="line.218"></a>
-<span class="sourceLineNo">219</span>  }<a name="line.219"></a>
-<span class="sourceLineNo">220</span><a name="line.220"></a>
-<span class="sourceLineNo">221</span>  /**<a name="line.221"></a>
-<span class="sourceLineNo">222</span>   * @return false when the Chore is not currently scheduled with a ChoreService<a name="line.222"></a>
-<span class="sourceLineNo">223</span>   */<a name="line.223"></a>
-<span class="sourceLineNo">224</span>  public synchronized boolean triggerNow() {<a name="line.224"></a>
-<span class="sourceLineNo">225</span>    if (choreService == null) {<a name="line.225"></a>
-<span class="sourceLineNo">226</span>      return false;<a name="line.226"></a>
-<span class="sourceLineNo">227</span>    }<a name="line.227"></a>
-<span class="sourceLineNo">228</span>    choreService.triggerNow(this);<a name="line.228"></a>
-<span class="sourceLineNo">229</span>    return true;<a name="line.229"></a>
-<span class="sourceLineNo">230</span>  }<a name="line.230"></a>
-<span class="sourceLineNo">231</span><a name="line.231"></a>
-<span class="sourceLineNo">232</span>  @RestrictedApi(explanation = "Should only be called in ChoreService", link = "",<a name="line.232"></a>
-<span class="sourceLineNo">233</span>    allowedOnPath = ".*/org/apache/hadoop/hbase/ChoreService.java")<a name="line.233"></a>
-<span class="sourceLineNo">234</span>  synchronized void setChoreService(ChoreService service) {<a name="line.234"></a>
-<span class="sourceLineNo">235</span>    choreService = service;<a name="line.235"></a>
-<span class="sourceLineNo">236</span>    timeOfThisRun = -1;<a name="line.236"></a>
-<span class="sourceLineNo">237</span>  }<a name="line.237"></a>
-<span class="sourceLineNo">238</span><a name="line.238"></a>
-<span class="sourceLineNo">239</span>  public synchronized void cancel() {<a name="line.239"></a>
-<span class="sourceLineNo">240</span>    cancel(true);<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>  public synchronized void cancel(boolean mayInterruptIfRunning) {<a name="line.243"></a>
-<span class="sourceLineNo">244</span>    if (isScheduled()) {<a name="line.244"></a>
-<span class="sourceLineNo">245</span>      choreService.cancelChore(this, mayInterruptIfRunning);<a name="line.245"></a>
-<span class="sourceLineNo">246</span>    }<a name="line.246"></a>
-<span class="sourceLineNo">247</span>    choreService = null;<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 String getName() {<a name="line.250"></a>
-<span class="sourceLineNo">251</span>    return name;<a name="line.251"></a>
-<span class="sourceLineNo">252</span>  }<a name="line.252"></a>
-<span class="sourceLineNo">253</span><a name="line.253"></a>
-<span class="sourceLineNo">254</span>  public Stoppable getStopper() {<a name="line.254"></a>
-<span class="sourceLineNo">255</span>    return stopper;<a name="line.255"></a>
-<span class="sourceLineNo">256</span>  }<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>   * @return period to execute chore in getTimeUnit() units<a name="line.259"></a>
-<span class="sourceLineNo">260</span>   */<a name="line.260"></a>
-<span class="sourceLineNo">261</span>  public int getPeriod() {<a name="line.261"></a>
-<span class="sourceLineNo">262</span>    return period;<a name="line.262"></a>
-<span class="sourceLineNo">263</span>  }<a name="line.263"></a>
-<span class="sourceLineNo">264</span><a name="line.264"></a>
-<span class="sourceLineNo">265</span>  /**<a name="line.265"></a>
-<span class="sourceLineNo">266</span>   * @return initial delay before executing chore in getTimeUnit() units<a name="line.266"></a>
-<span class="sourceLineNo">267</span>   */<a name="line.267"></a>
-<span class="sourceLineNo">268</span>  public long getInitialDelay() {<a name="line.268"></a>
-<span class="sourceLineNo">269</span>    return initialDelay;<a name="line.269"></a>
-<span class="sourceLineNo">270</span>  }<a name="line.270"></a>
-<span class="sourceLineNo">271</span><a name="line.271"></a>
-<span class="sourceLineNo">272</span>  public TimeUnit getTimeUnit() {<a name="line.272"></a>
-<span class="sourceLineNo">273</span>    return timeUnit;<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>  public synchronized boolean isInitialChoreComplete() {<a name="line.276"></a>
-<span class="sourceLineNo">277</span>    return initialChoreComplete;<a name="line.277"></a>
-<span class="sourceLineNo">278</span>  }<a name="line.278"></a>
-<span class="sourceLineNo">279</span><a name="line.279"></a>
-<span class="sourceLineNo">280</span>  synchronized ChoreService getChoreService() {<a name="line.280"></a>
-<span class="sourceLineNo">281</span>    return choreService;<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>  synchronized long getTimeOfLastRun() {<a name="line.284"></a>
-<span class="sourceLineNo">285</span>    return timeOfLastRun;<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>  synchronized long getTimeOfThisRun() {<a name="line.288"></a>
-<span class="sourceLineNo">289</span>    return timeOfThisRun;<a name="line.289"></a>
-<span class="sourceLineNo">290</span>  }<a name="line.290"></a>
-<span class="sourceLineNo">291</span><a name="line.291"></a>
-<span class="sourceLineNo">292</span>  /**<a name="line.292"></a>
-<span class="sourceLineNo">293</span>   * @return true when this Chore is scheduled with a ChoreService<a name="line.293"></a>
-<span class="sourceLineNo">294</span>   */<a name="line.294"></a>
-<span class="sourceLineNo">295</span>  public synchronized boolean isScheduled() {<a name="line.295"></a>
-<span class="sourceLineNo">296</span>    return choreService != null &amp;&amp; choreService.isChoreScheduled(this);<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>  @InterfaceAudience.Private<a name="line.299"></a>
-<span class="sourceLineNo">300</span>  @RestrictedApi(explanation = "Should only be called in tests", link = "",<a name="line.300"></a>
-<span class="sourceLineNo">301</span>    allowedOnPath = ".*/src/test/.*")<a name="line.301"></a>
-<span class="sourceLineNo">302</span>  public synchronized void choreForTesting() {<a name="line.302"></a>
-<span class="sourceLineNo">303</span>    chore();<a name="line.303"></a>
-<span class="sourceLineNo">304</span>  }<a name="line.304"></a>
-<span class="sourceLineNo">305</span><a name="line.305"></a>
-<span class="sourceLineNo">306</span>  /**<a name="line.306"></a>
-<span class="sourceLineNo">307</span>   * The task to execute on each scheduled execution of the Chore<a name="line.307"></a>
-<span class="sourceLineNo">308</span>   */<a name="line.308"></a>
-<span class="sourceLineNo">309</span>  protected abstract void chore();<a name="line.309"></a>
-<span class="sourceLineNo">310</span><a name="line.310"></a>
-<span class="sourceLineNo">311</span>  /**<a name="line.311"></a>
-<span class="sourceLineNo">312</span>   * Override to run a task before we start looping.<a name="line.312"></a>
-<span class="sourceLineNo">313</span>   * @return true if initial chore was successful<a name="line.313"></a>
-<span class="sourceLineNo">314</span>   */<a name="line.314"></a>
-<span class="sourceLineNo">315</span>  protected boolean initialChore() {<a name="line.315"></a>
-<span class="sourceLineNo">316</span>    // Default does nothing<a name="line.316"></a>
-<span class="sourceLineNo">317</span>    return true;<a name="line.317"></a>
-<span class="sourceLineNo">318</span>  }<a name="line.318"></a>
-<span class="sourceLineNo">319</span><a name="line.319"></a>
-<span class="sourceLineNo">320</span>  /**<a name="line.320"></a>
-<span class="sourceLineNo">321</span>   * Override to run cleanup tasks when the Chore encounters an error and must stop running<a name="line.321"></a>
-<span class="sourceLineNo">322</span>   */<a name="line.322"></a>
-<span class="sourceLineNo">323</span>  protected void cleanup() {<a name="line.323"></a>
-<span class="sourceLineNo">324</span>  }<a name="line.324"></a>
-<span class="sourceLineNo">325</span><a name="line.325"></a>
-<span class="sourceLineNo">326</span>  /**<a name="line.326"></a>
-<span class="sourceLineNo">327</span>   * Call {@link #shutdown(boolean)} with {@code true}.<a name="line.327"></a>
-<span class="sourceLineNo">328</span>   * @see ScheduledChore#shutdown(boolean)<a name="line.328"></a>
-<span class="sourceLineNo">329</span>   */<a name="line.329"></a>
-<span class="sourceLineNo">330</span>  public synchronized void shutdown() {<a name="line.330"></a>
-<span class="sourceLineNo">331</span>    shutdown(true);<a name="line.331"></a>
-<span class="sourceLineNo">332</span>  }<a name="line.332"></a>
-<span class="sourceLineNo">333</span><a name="line.333"></a>
-<span class="sourceLineNo">334</span>  /**<a name="line.334"></a>
-<span class="sourceLineNo">335</span>   * Completely shutdown the ScheduleChore, which means we will call cleanup and you should not<a name="line.335"></a>
-<span class="sourceLineNo">336</span>   * schedule it again.<a name="line.336"></a>
-<span class="sourceLineNo">337</span>   * &lt;p/&gt;<a name="line.337"></a>
-<span class="sourceLineNo">338</span>   * This is another path to cleanup the chore, comparing to stop the stopper instance passed in.<a name="line.338"></a>
-<span class="sourceLineNo">339</span>   */<a name="line.339"></a>
-<span class="sourceLineNo">340</span>  public synchronized void shutdown(boolean mayInterruptIfRunning) {<a name="line.340"></a>
-<span class="sourceLineNo">341</span>    cancel(mayInterruptIfRunning);<a name="line.341"></a>
-<span class="sourceLineNo">342</span>    cleanup();<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>   * A summation of this chore in human readable format. Downstream users should not presume<a name="line.346"></a>
-<span class="sourceLineNo">347</span>   * parsing of this string can relaibly be done between versions. Instead, they should rely<a name="line.347"></a>
-<span class="sourceLineNo">348</span>   * on the public accessor methods to get the information they desire.<a name="line.348"></a>
-<span class="sourceLineNo">349</span>   */<a name="line.349"></a>
-<span class="sourceLineNo">350</span>  @InterfaceAudience.Private<a name="line.350"></a>
-<span class="sourceLineNo">351</span>  @Override<a name="line.351"></a>
-<span class="sourceLineNo">352</span>  public String toString() {<a name="line.352"></a>
-<span class="sourceLineNo">353</span>    return "ScheduledChore name=" + getName() + ", period=" + getPeriod() +<a name="line.353"></a>
-<span class="sourceLineNo">354</span>      ", unit=" + getTimeUnit();<a name="line.354"></a>
-<span class="sourceLineNo">355</span>  }<a name="line.355"></a>
-<span class="sourceLineNo">356</span>}<a name="line.356"></a>
+<span class="sourceLineNo">047</span>  private final String name;<a name="line.47"></a>
+<span class="sourceLineNo">048</span><a name="line.48"></a>
+<span class="sourceLineNo">049</span>  /**<a name="line.49"></a>
+<span class="sourceLineNo">050</span>   * Default values for scheduling parameters should they be excluded during construction<a name="line.50"></a>
+<span class="sourceLineNo">051</span>   */<a name="line.51"></a>
+<span class="sourceLineNo">052</span>  private final static TimeUnit DEFAULT_TIME_UNIT = TimeUnit.MILLISECONDS;<a name="line.52"></a>
+<span class="sourceLineNo">053</span>  private final static long DEFAULT_INITIAL_DELAY = 0;<a name="line.53"></a>
+<span class="sourceLineNo">054</span><a name="line.54"></a>
+<span class="sourceLineNo">055</span>  /**<a name="line.55"></a>
+<span class="sourceLineNo">056</span>   * Scheduling parameters. Used by ChoreService when scheduling the chore to run periodically<a name="line.56"></a>
+<span class="sourceLineNo">057</span>   */<a name="line.57"></a>
+<span class="sourceLineNo">058</span>  private final int period; // in TimeUnit units<a name="line.58"></a>
+<span class="sourceLineNo">059</span>  private final TimeUnit timeUnit;<a name="line.59"></a>
+<span class="sourceLineNo">060</span>  private final long initialDelay; // in TimeUnit units<a name="line.60"></a>
+<span class="sourceLineNo">061</span><a name="line.61"></a>
+<span class="sourceLineNo">062</span>  /**<a name="line.62"></a>
+<span class="sourceLineNo">063</span>   * Interface to the ChoreService that this ScheduledChore is scheduled with. null if the chore is<a name="line.63"></a>
+<span class="sourceLineNo">064</span>   * not scheduled.<a name="line.64"></a>
+<span class="sourceLineNo">065</span>   */<a name="line.65"></a>
+<span class="sourceLineNo">066</span>  private ChoreService choreService;<a name="line.66"></a>
+<span class="sourceLineNo">067</span><a name="line.67"></a>
+<span class="sourceLineNo">068</span>  /**<a name="line.68"></a>
+<span class="sourceLineNo">069</span>   * Variables that encapsulate the meaningful state information<a name="line.69"></a>
+<span class="sourceLineNo">070</span>   */<a name="line.70"></a>
+<span class="sourceLineNo">071</span>  private long timeOfLastRun = -1; // system time millis<a name="line.71"></a>
+<span class="sourceLineNo">072</span>  private long timeOfThisRun = -1; // system time millis<a name="line.72"></a>
+<span class="sourceLineNo">073</span>  private boolean initialChoreComplete = false;<a name="line.73"></a>
+<span class="sourceLineNo">074</span><a name="line.74"></a>
+<span class="sourceLineNo">075</span>  /**<a name="line.75"></a>
+<span class="sourceLineNo">076</span>   * A means by which a ScheduledChore can be stopped. Once a chore recognizes that it has been<a name="line.76"></a>
+<span class="sourceLineNo">077</span>   * stopped, it will cancel itself. This is particularly useful in the case where a single stopper<a name="line.77"></a>
+<span class="sourceLineNo">078</span>   * instance is given to multiple chores. In such a case, a single {@link Stoppable#stop(String)}<a name="line.78"></a>
+<span class="sourceLineNo">079</span>   * command can cause many chores to stop together.<a name="line.79"></a>
+<span class="sourceLineNo">080</span>   */<a name="line.80"></a>
+<span class="sourceLineNo">081</span>  private final Stoppable stopper;<a name="line.81"></a>
+<span class="sourceLineNo">082</span><a name="line.82"></a>
+<span class="sourceLineNo">083</span>  /**<a name="line.83"></a>
+<span class="sourceLineNo">084</span>   * This constructor is for test only. It allows us to create an object and to call chore() on it.<a name="line.84"></a>
+<span class="sourceLineNo">085</span>   */<a name="line.85"></a>
+<span class="sourceLineNo">086</span>  @InterfaceAudience.Private<a name="line.86"></a>
+<span class="sourceLineNo">087</span>  protected ScheduledChore() {<a name="line.87"></a>
+<span class="sourceLineNo">088</span>    this("TestChore", null, 0, DEFAULT_INITIAL_DELAY, DEFAULT_TIME_UNIT);<a name="line.88"></a>
+<span class="sourceLineNo">089</span>  }<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>   * @param name Name assigned to Chore. Useful for identification amongst chores of the same type<a name="line.92"></a>
+<span class="sourceLineNo">093</span>   * @param stopper When {@link Stoppable#isStopped()} is true, this chore will cancel and cleanup<a name="line.93"></a>
+<span class="sourceLineNo">094</span>   * @param period Period in millis with which this Chore repeats execution when scheduled.<a name="line.94"></a>
+<span class="sourceLineNo">095</span>   */<a name="line.95"></a>
+<span class="sourceLineNo">096</span>  public ScheduledChore(final String name, Stoppable stopper, final int period) {<a name="line.96"></a>
+<span class="sourceLineNo">097</span>    this(name, stopper, period, DEFAULT_INITIAL_DELAY);<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>   * @param name Name assigned to Chore. Useful for identification amongst chores of the same type<a name="line.101"></a>
+<span class="sourceLineNo">102</span>   * @param stopper When {@link Stoppable#isStopped()} is true, this chore will cancel and cleanup<a name="line.102"></a>
+<span class="sourceLineNo">103</span>   * @param period Period in millis with which this Chore repeats execution when scheduled.<a name="line.103"></a>
+<span class="sourceLineNo">104</span>   * @param initialDelay Delay before this Chore begins to execute once it has been scheduled. A<a name="line.104"></a>
+<span class="sourceLineNo">105</span>   *          value of 0 means the chore will begin to execute immediately. Negative delays are<a name="line.105"></a>
+<span class="sourceLineNo">106</span>   *          invalid and will be corrected to a value of 0.<a name="line.106"></a>
+<span class="sourceLineNo">107</span>   */<a name="line.107"></a>
+<span class="sourceLineNo">108</span>  public ScheduledChore(final String name, Stoppable stopper, final int period,<a name="line.108"></a>
+<span class="sourceLineNo">109</span>      final long initialDelay) {<a name="line.109"></a>
+<span class="sourceLineNo">110</span>    this(name, stopper, period, initialDelay, DEFAULT_TIME_UNIT);<a name="line.110"></a>
+<span class="sourceLineNo">111</span>  }<a name="line.111"></a>
+<span class="sourceLineNo">112</span><a name="line.112"></a>
+<span class="sourceLineNo">113</span>  /**<a name="line.113"></a>
+<span class="sourceLineNo">114</span>   * @param name Name assigned to Chore. Useful for identification amongst chores of the same type<a name="line.114"></a>
+<span class="sourceLineNo">115</span>   * @param stopper When {@link Stoppable#isStopped()} is true, this chore will cancel and cleanup<a name="line.115"></a>
+<span class="sourceLineNo">116</span>   * @param period Period in Timeunit unit with which this Chore repeats execution when scheduled.<a name="line.116"></a>
+<span class="sourceLineNo">117</span>   * @param initialDelay Delay in Timeunit unit before this Chore begins to execute once it has been<a name="line.117"></a>
+<span class="sourceLineNo">118</span>   *          scheduled. A value of 0 means the chore will begin to execute immediately. Negative<a name="line.118"></a>
+<span class="sourceLineNo">119</span>   *          delays are invalid and will be corrected to a value of 0.<a name="line.119"></a>
+<span class="sourceLineNo">120</span>   * @param unit The unit that is used to measure period and initialDelay<a name="line.120"></a>
+<span class="sourceLineNo">121</span>   */<a name="line.121"></a>
+<span class="sourceLineNo">122</span>  public ScheduledChore(final String name, Stoppable stopper, final int period,<a name="line.122"></a>
+<span class="sourceLineNo">123</span>      final long initialDelay, final TimeUnit unit) {<a name="line.123"></a>
+<span class="sourceLineNo">124</span>    this.name = name;<a name="line.124"></a>
+<span class="sourceLineNo">125</span>    this.stopper = stopper;<a name="line.125"></a>
+<span class="sourceLineNo">126</span>    this.period = period;<a name="line.126"></a>
+<span class="sourceLineNo">127</span>    this.initialDelay = initialDelay &lt; 0 ? 0 : initialDelay;<a name="line.127"></a>
+<span class="sourceLineNo">128</span>    this.timeUnit = unit;<a name="line.128"></a>
+<span class="sourceLineNo">129</span>  }<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>   * @see java.lang.Runnable#run()<a name="line.132"></a>
+<span class="sourceLineNo">133</span>   */<a name="line.133"></a>
+<span class="sourceLineNo">134</span>  @Override<a name="line.134"></a>
+<span class="sourceLineNo">135</span>  public void run() {<a name="line.135"></a>
+<span class="sourceLineNo">136</span>    updateTimeTrackingBeforeRun();<a name="line.136"></a>
+<span class="sourceLineNo">137</span>    if (missedStartTime() &amp;&amp; isScheduled()) {<a name="line.137"></a>
+<span class="sourceLineNo">138</span>      onChoreMissedStartTime();<a name="line.138"></a>
+<span class="sourceLineNo">139</span>      LOG.info("Chore: {} missed its start time", getName());<a name="line.139"></a>
+<span class="sourceLineNo">140</span>    } else if (stopper.isStopped() || !isScheduled()) {<a name="line.140"></a>
+<span class="sourceLineNo">141</span>      // call shutdown here to cleanup the ScheduledChore.<a name="line.141"></a>
+<span class="sourceLineNo">142</span>      shutdown(false);<a name="line.142"></a>
+<span class="sourceLineNo">143</span>      LOG.info("Chore: {} was stopped", getName());<a name="line.143"></a>
+<span class="sourceLineNo">144</span>    } else {<a name="line.144"></a>
+<span class="sourceLineNo">145</span>      try {<a name="line.145"></a>
+<span class="sourceLineNo">146</span>        // TODO: Histogram metrics per chore name.<a name="line.146"></a>
+<span class="sourceLineNo">147</span>        // For now, just measure and log if DEBUG level logging is enabled.<a name="line.147"></a>
+<span class="sourceLineNo">148</span>        long start = 0;<a name="line.148"></a>
+<span class="sourceLineNo">149</span>        if (LOG.isDebugEnabled()) {<a name="line.149"></a>
+<span class="sourceLineNo">150</span>          start = System.nanoTime();<a name="line.150"></a>
+<span class="sourceLineNo">151</span>        }<a name="line.151"></a>
+<span class="sourceLineNo">152</span>        if (!initialChoreComplete) {<a name="line.152"></a>
+<span class="sourceLineNo">153</span>          initialChoreComplete = initialChore();<a name="line.153"></a>
+<span class="sourceLineNo">154</span>        } else {<a name="line.154"></a>
+<span class="sourceLineNo">155</span>          chore();<a name="line.155"></a>
+<span class="sourceLineNo">156</span>        }<a name="line.156"></a>
+<span class="sourceLineNo">157</span>        if (LOG.isDebugEnabled() &amp;&amp; start &gt; 0) {<a name="line.157"></a>
+<span class="sourceLineNo">158</span>          long end = System.nanoTime();<a name="line.158"></a>
+<span class="sourceLineNo">159</span>          LOG.debug("{} execution time: {} ms.", getName(),<a name="line.159"></a>
+<span class="sourceLineNo">160</span>            TimeUnit.NANOSECONDS.toMillis(end - start));<a name="line.160"></a>
+<span class="sourceLineNo">161</span>        }<a name="line.161"></a>
+<span class="sourceLineNo">162</span>      } catch (Throwable t) {<a name="line.162"></a>
+<span class="sourceLineNo">163</span>        LOG.error("Caught error", t);<a name="line.163"></a>
+<span class="sourceLineNo">164</span>        if (this.stopper.isStopped()) {<a name="line.164"></a>
+<span class="sourceLineNo">165</span>          cancel(false);<a name="line.165"></a>
+<span class="sourceLineNo">166</span>        }<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>  }<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>   * Update our time tracking members. Called at the start of an execution of this chore's run()<a name="line.172"></a>
+<span class="sourceLineNo">173</span>   * method so that a correct decision can be made as to whether or not we missed the start time<a name="line.173"></a>
+<span class="sourceLineNo">174</span>   */<a name="line.174"></a>
+<span class="sourceLineNo">175</span>  private synchronized void updateTimeTrackingBeforeRun() {<a name="line.175"></a>
+<span class="sourceLineNo">176</span>    timeOfLastRun = timeOfThisRun;<a name="line.176"></a>
+<span class="sourceLineNo">177</span>    timeOfThisRun = EnvironmentEdgeManager.currentTime();<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>  /**<a name="line.180"></a>
+<span class="sourceLineNo">181</span>   * Notify the ChoreService that this chore has missed its start time. Allows the ChoreService to<a name="line.181"></a>
+<span class="sourceLineNo">182</span>   * make the decision as to whether or not it would be worthwhile to increase the number of core<a name="line.182"></a>
+<span class="sourceLineNo">183</span>   * pool threads<a name="line.183"></a>
+<span class="sourceLineNo">184</span>   */<a name="line.184"></a>
+<span class="sourceLineNo">185</span>  private synchronized void onChoreMissedStartTime() {<a name="line.185"></a>
+<span class="sourceLineNo">186</span>    if (choreService != null) {<a name="line.186"></a>
+<span class="sourceLineNo">187</span>      choreService.onChoreMissedStartTime(this);<a name="line.187"></a>
+<span class="sourceLineNo">188</span>    }<a name="line.188"></a>
+<span class="sourceLineNo">189</span>  }<a name="line.189"></a>
+<span class="sourceLineNo">190</span><a name="line.190"></a>
+<span class="sourceLineNo">191</span>  /**<a name="line.191"></a>
+<span class="sourceLineNo">192</span>   * @return How long in millis has it been since this chore last run. Useful for checking if the<a name="line.192"></a>
+<span class="sourceLineNo">193</span>   *         chore has missed its scheduled start time by too large of a margin<a name="line.193"></a>
+<span class="sourceLineNo">194</span>   */<a name="line.194"></a>
+<span class="sourceLineNo">195</span>  synchronized long getTimeBetweenRuns() {<a name="line.195"></a>
+<span class="sourceLineNo">196</span>    return timeOfThisRun - timeOfLastRun;<a name="line.196"></a>
+<span class="sourceLineNo">197</span>  }<a name="line.197"></a>
+<span class="sourceLineNo">198</span><a name="line.198"></a>
+<span class="sourceLineNo">199</span>  /**<a name="line.199"></a>
+<span class="sourceLineNo">200</span>   * @return true when the time between runs exceeds the acceptable threshold<a name="line.200"></a>
+<span class="sourceLineNo">201</span>   */<a name="line.201"></a>
+<span class="sourceLineNo">202</span>  private synchronized boolean missedStartTime() {<a name="line.202"></a>
+<span class="sourceLineNo">203</span>    return isValidTime(timeOfLastRun) &amp;&amp; isValidTime(timeOfThisRun)<a name="line.203"></a>
+<span class="sourceLineNo">204</span>        &amp;&amp; getTimeBetweenRuns() &gt; getMaximumAllowedTimeBetweenRuns();<a name="line.204"></a>
+<span class="sourceLineNo">205</span>  }<a name="line.205"></a>
+<span class="sourceLineNo">206</span><a name="line.206"></a>
+<span class="sourceLineNo">207</span>  /**<a name="line.207"></a>
+<span class="sourceLineNo">208</span>   * @return max allowed time in millis between runs.<a name="line.208"></a>
+<span class="sourceLineNo">209</span>   */<a name="line.209"></a>
+<span class="sourceLineNo">210</span>  private double getMaximumAllowedTimeBetweenRuns() {<a name="line.210"></a>
+<span class="sourceLineNo">211</span>    // Threshold used to determine if the Chore's current run started too late<a name="line.211"></a>
+<span class="sourceLineNo">212</span>    return 1.5 * timeUnit.toMillis(period);<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>  /**<a name="line.215"></a>
+<span class="sourceLineNo">216</span>   * @param time in system millis<a name="line.216"></a>
+<span class="sourceLineNo">217</span>   * @return true if time is earlier or equal to current milli time<a name="line.217"></a>
+<span class="sourceLineNo">218</span>   */<a name="line.218"></a>
+<span class="sourceLineNo">219</span>  private synchronized boolean isValidTime(final long time) {<a name="line.219"></a>
+<span class="sourceLineNo">220</span>    return time &gt; 0 &amp;&amp; time &lt;= EnvironmentEdgeManager.currentTime();<a name="line.220"></a>
+<span class="sourceLineNo">221</span>  }<a name="line.221"></a>
+<span class="sourceLineNo">222</span><a name="line.222"></a>
+<span class="sourceLineNo">223</span>  /**<a name="line.223"></a>
+<span class="sourceLineNo">224</span>   * @return false when the Chore is not currently scheduled with a ChoreService<a name="line.224"></a>
+<span class="sourceLineNo">225</span>   */<a name="line.225"></a>
+<span class="sourceLineNo">226</span>  public synchronized boolean triggerNow() {<a name="line.226"></a>
+<span class="sourceLineNo">227</span>    if (choreService == null) {<a name="line.227"></a>
+<span class="sourceLineNo">228</span>      return false;<a name="line.228"></a>
+<span class="sourceLineNo">229</span>    }<a name="line.229"></a>
+<span class="sourceLineNo">230</span>    choreService.triggerNow(this);<a name="line.230"></a>
+<span class="sourceLineNo">231</span>    return true;<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>  @RestrictedApi(explanation = "Should only be called in ChoreService", link = "",<a name="line.234"></a>
+<span class="sourceLineNo">235</span>    allowedOnPath = ".*/org/apache/hadoop/hbase/ChoreService.java")<a name="line.235"></a>
+<span class="sourceLineNo">236</span>  synchronized void setChoreService(ChoreService service) {<a name="line.236"></a>
+<span class="sourceLineNo">237</span>    choreService = service;<a name="line.237"></a>
+<span class="sourceLineNo">238</span>    timeOfThisRun = -1;<a name="line.238"></a>
+<span class="sourceLineNo">239</span>  }<a name="line.239"></a>
+<span class="sourceLineNo">240</span><a name="line.240"></a>
+<span class="sourceLineNo">241</span>  public synchronized void cancel() {<a name="line.241"></a>
+<span class="sourceLineNo">242</span>    cancel(true);<a name="line.242"></a>
+<span class="sourceLineNo">243</span>  }<a name="line.243"></a>
+<span class="sourceLineNo">244</span><a name="line.244"></a>
+<span class="sourceLineNo">245</span>  public synchronized void cancel(boolean mayInterruptIfRunning) {<a name="line.245"></a>
+<span class="sourceLineNo">246</span>    if (isScheduled()) {<a name="line.246"></a>
+<span class="sourceLineNo">247</span>      choreService.cancelChore(this, mayInterruptIfRunning);<a name="line.247"></a>
+<span class="sourceLineNo">248</span>    }<a name="line.248"></a>
+<span class="sourceLineNo">249</span>    choreService = null;<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>  public String getName() {<a name="line.252"></a>
+<span class="sourceLineNo">253</span>    return name;<a name="line.253"></a>
+<span class="sourceLineNo">254</span>  }<a name="line.254"></a>
+<span class="sourceLineNo">255</span><a name="line.255"></a>
+<span class="sourceLineNo">256</span>  public Stoppable getStopper() {<a name="line.256"></a>
+<span class="sourceLineNo">257</span>    return stopper;<a name="line.257"></a>
+<span class="sourceLineNo">258</span>  }<a name="line.258"></a>
+<span class="sourceLineNo">259</span><a name="line.259"></a>
+<span class="sourceLineNo">260</span>  /**<a name="line.260"></a>
+<span class="sourceLineNo">261</span>   * @return period to execute chore in getTimeUnit() units<a name="line.261"></a>
+<span class="sourceLineNo">262</span>   */<a name="line.262"></a>
+<span class="sourceLineNo">263</span>  public int getPeriod() {<a name="line.263"></a>
+<span class="sourceLineNo">264</span>    return period;<a name="line.264"></a>
+<span class="sourceLineNo">265</span>  }<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>   * @return initial delay before executing chore in getTimeUnit() units<a name="line.268"></a>
+<span class="sourceLineNo">269</span>   */<a name="line.269"></a>
+<span class="sourceLineNo">270</span>  public long getInitialDelay() {<a name="line.270"></a>
+<span class="sourceLineNo">271</span>    return initialDelay;<a name="line.271"></a>
+<span class="sourceLineNo">272</span>  }<a name="line.272"></a>
+<span class="sourceLineNo">273</span><a name="line.273"></a>
+<span class="sourceLineNo">274</span>  public TimeUnit getTimeUnit() {<a name="line.274"></a>
+<span class="sourceLineNo">275</span>    return timeUnit;<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 synchronized boolean isInitialChoreComplete() {<a name="line.278"></a>
+<span class="sourceLineNo">279</span>    return initialChoreComplete;<a name="line.279"></a>
+<span class="sourceLineNo">280</span>  }<a name="line.280"></a>
+<span class="sourceLineNo">281</span><a name="line.281"></a>
+<span class="sourceLineNo">282</span>  synchronized ChoreService getChoreService() {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>    return choreService;<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>  synchronized long getTimeOfLastRun() {<a name="line.286"></a>
+<span class="sourceLineNo">287</span>    return timeOfLastRun;<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>  synchronized long getTimeOfThisRun() {<a name="line.290"></a>
+<span class="sourceLineNo">291</span>    return timeOfThisRun;<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>  /**<a name="line.294"></a>
+<span class="sourceLineNo">295</span>   * @return true when this Chore is scheduled with a ChoreService<a name="line.295"></a>
+<span class="sourceLineNo">296</span>   */<a name="line.296"></a>
+<span class="sourceLineNo">297</span>  public synchronized boolean isScheduled() {<a name="line.297"></a>
+<span class="sourceLineNo">298</span>    return choreService != null &amp;&amp; choreService.isChoreScheduled(this);<a name="line.298"></a>
+<span class="sourceLineNo">299</span>  }<a name="line.299"></a>
+<span class="sourceLineNo">300</span><a name="line.300"></a>
+<span class="sourceLineNo">301</span>  @InterfaceAudience.Private<a name="line.301"></a>
+<span class="sourceLineNo">302</span>  @RestrictedApi(explanation = "Should only be called in tests", link = "",<a name="line.302"></a>
+<span class="sourceLineNo">303</span>    allowedOnPath = ".*/src/test/.*")<a name="line.303"></a>
+<span class="sourceLineNo">304</span>  public synchronized void choreForTesting() {<a name="line.304"></a>
+<span class="sourceLineNo">305</span>    chore();<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>   * The task to execute on each scheduled execution of the Chore<a name="line.309"></a>
+<span class="sourceLineNo">310</span>   */<a name="line.310"></a>
+<span class="sourceLineNo">311</span>  protected abstract void chore();<a name="line.311"></a>
+<span class="sourceLineNo">312</span><a name="line.312"></a>
+<span class="sourceLineNo">313</span>  /**<a name="line.313"></a>
+<span class="sourceLineNo">314</span>   * Override to run a task before we start looping.<a name="line.314"></a>
+<span class="sourceLineNo">315</span>   * @return true if initial chore was successful<a name="line.315"></a>
+<span class="sourceLineNo">316</span>   */<a name="line.316"></a>
+<span class="sourceLineNo">317</span>  protected boolean initialChore() {<a name="line.317"></a>
+<span class="sourceLineNo">318</span>    // Default does nothing<a name="line.318"></a>
+<span class="sourceLineNo">319</span>    return true;<a name="line.319"></a>
+<span class="sourceLineNo">320</span>  }<a name="line.320"></a>
+<span class="sourceLineNo">321</span><a name="line.321"></a>
+<span class="sourceLineNo">322</span>  /**<a name="line.322"></a>
+<span class="sourceLineNo">323</span>   * Override to run cleanup tasks when the Chore encounters an error and must stop running<a name="line.323"></a>
+<span class="sourceLineNo">324</span>   */<a name="line.324"></a>
+<span class="sourceLineNo">325</span>  protected void cleanup() {<a name="line.325"></a>
+<span class="sourceLineNo">326</span>  }<a name="line.326"></a>
+<span class="sourceLineNo">327</span><a name="line.327"></a>
+<span class="sourceLineNo">328</span>  /**<a name="line.328"></a>
+<span class="sourceLineNo">329</span>   * Call {@link #shutdown(boolean)} with {@code true}.<a name="line.329"></a>
+<span class="sourceLineNo">330</span>   * @see ScheduledChore#shutdown(boolean)<a name="line.330"></a>
+<span class="sourceLineNo">331</span>   */<a name="line.331"></a>
+<span class="sourceLineNo">332</span>  public synchronized void shutdown() {<a name="line.332"></a>
+<span class="sourceLineNo">333</span>    shutdown(true);<a name="line.333"></a>
+<span class="sourceLineNo">334</span>  }<a name="line.334"></a>
+<span class="sourceLineNo">335</span><a name="line.335"></a>
+<span class="sourceLineNo">336</span>  /**<a name="line.336"></a>
+<span class="sourceLineNo">337</span>   * Completely shutdown the ScheduleChore, which means we will call cleanup and you should not<a name="line.337"></a>
+<span class="sourceLineNo">338</span>   * schedule it again.<a name="line.338"></a>
+<span class="sourceLineNo">339</span>   * &lt;p/&gt;<a name="line.339"></a>
+<span class="sourceLineNo">340</span>   * This is another path to cleanup the chore, comparing to stop the stopper instance passed in.<a name="line.340"></a>
+<span class="sourceLineNo">341</span>   */<a name="line.341"></a>
+<span class="sourceLineNo">342</span>  public synchronized void shutdown(boolean mayInterruptIfRunning) {<a name="line.342"></a>
+<span class="sourceLineNo">343</span>    cancel(mayInterruptIfRunning);<a name="line.343"></a>
+<span class="sourceLineNo">344</span>    cleanup();<a name="line.344"></a>
+<span class="sourceLineNo">345</span>  }<a name="line.345"></a>
+<span class="sourceLineNo">346</span><a name="line.346"></a>
+<span class="sourceLineNo">347</span>  /**<a name="line.347"></a>
+<span class="sourceLineNo">348</span>   * A summation of this chore in human readable format. Downstream users should not presume<a name="line.348"></a>
+<span class="sourceLineNo">349</span>   * parsing of this string can relaibly be done between versions. Instead, they should rely<a name="line.349"></a>
+<span class="sourceLineNo">350</span>   * on the public accessor methods to get the information they desire.<a name="line.350"></a>
+<span class="sourceLineNo">351</span>   */<a name="line.351"></a>
+<span class="sourceLineNo">352</span>  @InterfaceAudience.Private<a name="line.352"></a>
+<span class="sourceLineNo">353</span>  @Override<a name="line.353"></a>
+<span class="sourceLineNo">354</span>  public String toString() {<a name="line.354"></a>
+<span class="sourceLineNo">355</span>    return "ScheduledChore name=" + getName() + ", period=" + getPeriod() +<a name="line.355"></a>
+<span class="sourceLineNo">356</span>      ", unit=" + getTimeUnit();<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>
 
 
 
diff --git a/apidocs/src-html/org/apache/hadoop/hbase/client/Delete.html b/apidocs/src-html/org/apache/hadoop/hbase/client/Delete.html
index 37cdcd4..0aec194 100644
--- a/apidocs/src-html/org/apache/hadoop/hbase/client/Delete.html
+++ b/apidocs/src-html/org/apache/hadoop/hbase/client/Delete.html
@@ -63,7 +63,7 @@
 <span class="sourceLineNo">055</span> * Specifying timestamps, deleteFamily and deleteColumns will delete all<a name="line.55"></a>
 <span class="sourceLineNo">056</span> * versions with a timestamp less than or equal to that passed.  If no<a name="line.56"></a>
 <span class="sourceLineNo">057</span> * timestamp is specified, an entry is added with a timestamp of 'now'<a name="line.57"></a>
-<span class="sourceLineNo">058</span> * where 'now' is the servers's System.currentTimeMillis().<a name="line.58"></a>
+<span class="sourceLineNo">058</span> * where 'now' is the servers's EnvironmentEdgeManager.currentTime().<a name="line.58"></a>
 <span class="sourceLineNo">059</span> * Specifying a timestamp to the deleteColumn method will<a name="line.59"></a>
 <span class="sourceLineNo">060</span> * delete versions only with a timestamp equal to that specified.<a name="line.60"></a>
 <span class="sourceLineNo">061</span> * If no timestamp is passed to deleteColumn, internally, it figures the<a name="line.61"></a>
diff --git a/apidocs/src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html b/apidocs/src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html
index d8b6414..923deca 100644
--- a/apidocs/src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html
+++ b/apidocs/src-html/org/apache/hadoop/hbase/mapred/TableRecordReaderImpl.html
@@ -39,223 +39,224 @@
 <span class="sourceLineNo">031</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<a name="line.31"></a>
 <span class="sourceLineNo">032</span>import org.apache.hadoop.hbase.mapreduce.TableInputFormat;<a name="line.32"></a>
 <span class="sourceLineNo">033</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.33"></a>
-<span class="sourceLineNo">034</span>import org.apache.hadoop.util.StringUtils;<a name="line.34"></a>
-<span class="sourceLineNo">035</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.35"></a>
-<span class="sourceLineNo">036</span>import org.slf4j.Logger;<a name="line.36"></a>
-<span class="sourceLineNo">037</span>import org.slf4j.LoggerFactory;<a name="line.37"></a>
-<span class="sourceLineNo">038</span><a name="line.38"></a>
-<span class="sourceLineNo">039</span>/**<a name="line.39"></a>
-<span class="sourceLineNo">040</span> * Iterate over an HBase table data, return (Text, RowResult) pairs<a name="line.40"></a>
-<span class="sourceLineNo">041</span> */<a name="line.41"></a>
-<span class="sourceLineNo">042</span>@InterfaceAudience.Public<a name="line.42"></a>
-<span class="sourceLineNo">043</span>public class TableRecordReaderImpl {<a name="line.43"></a>
-<span class="sourceLineNo">044</span>  private static final Logger LOG = LoggerFactory.getLogger(TableRecordReaderImpl.class);<a name="line.44"></a>
-<span class="sourceLineNo">045</span><a name="line.45"></a>
-<span class="sourceLineNo">046</span>  private byte [] startRow;<a name="line.46"></a>
-<span class="sourceLineNo">047</span>  private byte [] endRow;<a name="line.47"></a>
-<span class="sourceLineNo">048</span>  private byte [] lastSuccessfulRow;<a name="line.48"></a>
-<span class="sourceLineNo">049</span>  private Filter trrRowFilter;<a name="line.49"></a>
-<span class="sourceLineNo">050</span>  private ResultScanner scanner;<a name="line.50"></a>
-<span class="sourceLineNo">051</span>  private Table htable;<a name="line.51"></a>
-<span class="sourceLineNo">052</span>  private byte [][] trrInputColumns;<a name="line.52"></a>
-<span class="sourceLineNo">053</span>  private long timestamp;<a name="line.53"></a>
-<span class="sourceLineNo">054</span>  private int rowcount;<a name="line.54"></a>
-<span class="sourceLineNo">055</span>  private boolean logScannerActivity = false;<a name="line.55"></a>
-<span class="sourceLineNo">056</span>  private int logPerRowCount = 100;<a name="line.56"></a>
-<span class="sourceLineNo">057</span><a name="line.57"></a>
-<span class="sourceLineNo">058</span>  /**<a name="line.58"></a>
-<span class="sourceLineNo">059</span>   * Restart from survivable exceptions by creating a new scanner.<a name="line.59"></a>
-<span class="sourceLineNo">060</span>   */<a name="line.60"></a>
-<span class="sourceLineNo">061</span>  public void restart(byte[] firstRow) throws IOException {<a name="line.61"></a>
-<span class="sourceLineNo">062</span>    Scan currentScan;<a name="line.62"></a>
-<span class="sourceLineNo">063</span>    if ((endRow != null) &amp;&amp; (endRow.length &gt; 0)) {<a name="line.63"></a>
-<span class="sourceLineNo">064</span>      if (trrRowFilter != null) {<a name="line.64"></a>
-<span class="sourceLineNo">065</span>        Scan scan = new Scan().withStartRow(firstRow).withStopRow(endRow);<a name="line.65"></a>
-<span class="sourceLineNo">066</span>        TableInputFormat.addColumns(scan, trrInputColumns);<a name="line.66"></a>
-<span class="sourceLineNo">067</span>        scan.setFilter(trrRowFilter);<a name="line.67"></a>
-<span class="sourceLineNo">068</span>        scan.setCacheBlocks(false);<a name="line.68"></a>
-<span class="sourceLineNo">069</span>        this.scanner = this.htable.getScanner(scan);<a name="line.69"></a>
-<span class="sourceLineNo">070</span>        currentScan = scan;<a name="line.70"></a>
-<span class="sourceLineNo">071</span>      } else {<a name="line.71"></a>
-<span class="sourceLineNo">072</span>        LOG.debug("TIFB.restart, firstRow: " +<a name="line.72"></a>
-<span class="sourceLineNo">073</span>            Bytes.toStringBinary(firstRow) + ", endRow: " +<a name="line.73"></a>
-<span class="sourceLineNo">074</span>            Bytes.toStringBinary(endRow));<a name="line.74"></a>
-<span class="sourceLineNo">075</span>        Scan scan = new Scan().withStartRow(firstRow).withStopRow(endRow);<a name="line.75"></a>
-<span class="sourceLineNo">076</span>        TableInputFormat.addColumns(scan, trrInputColumns);<a name="line.76"></a>
-<span class="sourceLineNo">077</span>        this.scanner = this.htable.getScanner(scan);<a name="line.77"></a>
-<span class="sourceLineNo">078</span>        currentScan = scan;<a name="line.78"></a>
-<span class="sourceLineNo">079</span>      }<a name="line.79"></a>
-<span class="sourceLineNo">080</span>    } else {<a name="line.80"></a>
-<span class="sourceLineNo">081</span>      LOG.debug("TIFB.restart, firstRow: " +<a name="line.81"></a>
-<span class="sourceLineNo">082</span>          Bytes.toStringBinary(firstRow) + ", no endRow");<a name="line.82"></a>
-<span class="sourceLineNo">083</span><a name="line.83"></a>
-<span class="sourceLineNo">084</span>      Scan scan = new Scan().withStartRow(firstRow);<a name="line.84"></a>
-<span class="sourceLineNo">085</span>      TableInputFormat.addColumns(scan, trrInputColumns);<a name="line.85"></a>
-<span class="sourceLineNo">086</span>      scan.setFilter(trrRowFilter);<a name="line.86"></a>
-<span class="sourceLineNo">087</span>      this.scanner = this.htable.getScanner(scan);<a name="line.87"></a>
-<span class="sourceLineNo">088</span>      currentScan = scan;<a name="line.88"></a>
-<span class="sourceLineNo">089</span>    }<a name="line.89"></a>
-<span class="sourceLineNo">090</span>    if (logScannerActivity) {<a name="line.90"></a>
-<span class="sourceLineNo">091</span>      LOG.info("Current scan=" + currentScan.toString());<a name="line.91"></a>
-<span class="sourceLineNo">092</span>      timestamp = System.currentTimeMillis();<a name="line.92"></a>
-<span class="sourceLineNo">093</span>      rowcount = 0;<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><a name="line.96"></a>
-<span class="sourceLineNo">097</span>  /**<a name="line.97"></a>
-<span class="sourceLineNo">098</span>   * Build the scanner. Not done in constructor to allow for extension.<a name="line.98"></a>
-<span class="sourceLineNo">099</span>   */<a name="line.99"></a>
-<span class="sourceLineNo">100</span>  public void init() throws IOException {<a name="line.100"></a>
-<span class="sourceLineNo">101</span>    restart(startRow);<a name="line.101"></a>
-<span class="sourceLineNo">102</span>  }<a name="line.102"></a>
-<span class="sourceLineNo">103</span><a name="line.103"></a>
-<span class="sourceLineNo">104</span>  byte[] getStartRow() {<a name="line.104"></a>
-<span class="sourceLineNo">105</span>    return this.startRow;<a name="line.105"></a>
-<span class="sourceLineNo">106</span>  }<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>   * @param htable the table to scan.<a name="line.109"></a>
-<span class="sourceLineNo">110</span>   */<a name="line.110"></a>
-<span class="sourceLineNo">111</span>  public void setHTable(Table htable) {<a name="line.111"></a>
-<span class="sourceLineNo">112</span>    Configuration conf = htable.getConfiguration();<a name="line.112"></a>
-<span class="sourceLineNo">113</span>    logScannerActivity = conf.getBoolean(ConnectionConfiguration.LOG_SCANNER_ACTIVITY, false);<a name="line.113"></a>
-<span class="sourceLineNo">114</span>    logPerRowCount = conf.getInt(LOG_PER_ROW_COUNT, 100);<a name="line.114"></a>
-<span class="sourceLineNo">115</span>    this.htable = htable;<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>  /**<a name="line.118"></a>
-<span class="sourceLineNo">119</span>   * @param inputColumns the columns to be placed in {@link Result}.<a name="line.119"></a>
-<span class="sourceLineNo">120</span>   */<a name="line.120"></a>
-<span class="sourceLineNo">121</span>  public void setInputColumns(final byte [][] inputColumns) {<a name="line.121"></a>
-<span class="sourceLineNo">122</span>    this.trrInputColumns = inputColumns;<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>  /**<a name="line.125"></a>
-<span class="sourceLineNo">126</span>   * @param startRow the first row in the split<a name="line.126"></a>
-<span class="sourceLineNo">127</span>   */<a name="line.127"></a>
-<span class="sourceLineNo">128</span>  public void setStartRow(final byte [] startRow) {<a name="line.128"></a>
-<span class="sourceLineNo">129</span>    this.startRow = startRow;<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>  /**<a name="line.132"></a>
-<span class="sourceLineNo">133</span>   *<a name="line.133"></a>
-<span class="sourceLineNo">134</span>   * @param endRow the last row in the split<a name="line.134"></a>
-<span class="sourceLineNo">135</span>   */<a name="line.135"></a>
-<span class="sourceLineNo">136</span>  public void setEndRow(final byte [] endRow) {<a name="line.136"></a>
-<span class="sourceLineNo">137</span>    this.endRow = endRow;<a name="line.137"></a>
-<span class="sourceLineNo">138</span>  }<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>   * @param rowFilter the {@link Filter} to be used.<a name="line.141"></a>
-<span class="sourceLineNo">142</span>   */<a name="line.142"></a>
-<span class="sourceLineNo">143</span>  public void setRowFilter(Filter rowFilter) {<a name="line.143"></a>
-<span class="sourceLineNo">144</span>    this.trrRowFilter = rowFilter;<a name="line.144"></a>
-<span class="sourceLineNo">145</span>  }<a name="line.145"></a>
-<span class="sourceLineNo">146</span><a name="line.146"></a>
-<span class="sourceLineNo">147</span>  public void close() {<a name="line.147"></a>
-<span class="sourceLineNo">148</span>    if (this.scanner != null) {<a name="line.148"></a>
-<span class="sourceLineNo">149</span>      this.scanner.close();<a name="line.149"></a>
-<span class="sourceLineNo">150</span>    }<a name="line.150"></a>
-<span class="sourceLineNo">151</span>    try {<a name="line.151"></a>
-<span class="sourceLineNo">152</span>      this.htable.close();<a name="line.152"></a>
-<span class="sourceLineNo">153</span>    } catch (IOException ioe) {<a name="line.153"></a>
-<span class="sourceLineNo">154</span>      LOG.warn("Error closing table", ioe);<a name="line.154"></a>
-<span class="sourceLineNo">155</span>    }<a name="line.155"></a>
-<span class="sourceLineNo">156</span>  }<a name="line.156"></a>
-<span class="sourceLineNo">157</span><a name="line.157"></a>
-<span class="sourceLineNo">158</span>  /**<a name="line.158"></a>
-<span class="sourceLineNo">159</span>   * @return ImmutableBytesWritable<a name="line.159"></a>
-<span class="sourceLineNo">160</span>   *<a name="line.160"></a>
-<span class="sourceLineNo">161</span>   * @see org.apache.hadoop.mapred.RecordReader#createKey()<a name="line.161"></a>
-<span class="sourceLineNo">162</span>   */<a name="line.162"></a>
-<span class="sourceLineNo">163</span>  public ImmutableBytesWritable createKey() {<a name="line.163"></a>
-<span class="sourceLineNo">164</span>    return new ImmutableBytesWritable();<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>  /**<a name="line.167"></a>
-<span class="sourceLineNo">168</span>   * @return RowResult<a name="line.168"></a>
-<span class="sourceLineNo">169</span>   *<a name="line.169"></a>
-<span class="sourceLineNo">170</span>   * @see org.apache.hadoop.mapred.RecordReader#createValue()<a name="line.170"></a>
-<span class="sourceLineNo">171</span>   */<a name="line.171"></a>
-<span class="sourceLineNo">172</span>  public Result createValue() {<a name="line.172"></a>
-<span class="sourceLineNo">173</span>    return new Result();<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 long getPos() {<a name="line.176"></a>
-<span class="sourceLineNo">177</span>    // This should be the ordinal tuple in the range;<a name="line.177"></a>
-<span class="sourceLineNo">178</span>    // not clear how to calculate...<a name="line.178"></a>
-<span class="sourceLineNo">179</span>    return 0;<a name="line.179"></a>
-<span class="sourceLineNo">180</span>  }<a name="line.180"></a>
-<span class="sourceLineNo">181</span><a name="line.181"></a>
-<span class="sourceLineNo">182</span>  public float getProgress() {<a name="line.182"></a>
-<span class="sourceLineNo">183</span>    // Depends on the total number of tuples and getPos<a name="line.183"></a>
-<span class="sourceLineNo">184</span>    return 0;<a name="line.184"></a>
-<span class="sourceLineNo">185</span>  }<a name="line.185"></a>
-<span class="sourceLineNo">186</span><a name="line.186"></a>
-<span class="sourceLineNo">187</span>  /**<a name="line.187"></a>
-<span class="sourceLineNo">188</span>   * @param key HStoreKey as input key.<a name="line.188"></a>
-<span class="sourceLineNo">189</span>   * @param value MapWritable as input value<a name="line.189"></a>
-<span class="sourceLineNo">190</span>   * @return true if there was more data<a name="line.190"></a>
-<span class="sourceLineNo">191</span>   */<a name="line.191"></a>
-<span class="sourceLineNo">192</span>  public boolean next(ImmutableBytesWritable key, Result value) throws IOException {<a name="line.192"></a>
-<span class="sourceLineNo">193</span>    Result result;<a name="line.193"></a>
-<span class="sourceLineNo">194</span>    try {<a name="line.194"></a>
-<span class="sourceLineNo">195</span>      try {<a name="line.195"></a>
-<span class="sourceLineNo">196</span>        result = this.scanner.next();<a name="line.196"></a>
-<span class="sourceLineNo">197</span>        if (logScannerActivity) {<a name="line.197"></a>
-<span class="sourceLineNo">198</span>          rowcount ++;<a name="line.198"></a>
-<span class="sourceLineNo">199</span>          if (rowcount &gt;= logPerRowCount) {<a name="line.199"></a>
-<span class="sourceLineNo">200</span>            long now = System.currentTimeMillis();<a name="line.200"></a>
-<span class="sourceLineNo">201</span>            LOG.info("Mapper took " + (now-timestamp)<a name="line.201"></a>
-<span class="sourceLineNo">202</span>              + "ms to process " + rowcount + " rows");<a name="line.202"></a>
-<span class="sourceLineNo">203</span>            timestamp = now;<a name="line.203"></a>
-<span class="sourceLineNo">204</span>            rowcount = 0;<a name="line.204"></a>
-<span class="sourceLineNo">205</span>          }<a name="line.205"></a>
-<span class="sourceLineNo">206</span>        }<a name="line.206"></a>
-<span class="sourceLineNo">207</span>      } catch (IOException e) {<a name="line.207"></a>
-<span class="sourceLineNo">208</span>        // do not retry if the exception tells us not to do so<a name="line.208"></a>
-<span class="sourceLineNo">209</span>        if (e instanceof DoNotRetryIOException) {<a name="line.209"></a>
-<span class="sourceLineNo">210</span>          throw e;<a name="line.210"></a>
-<span class="sourceLineNo">211</span>        }<a name="line.211"></a>
-<span class="sourceLineNo">212</span>        // try to handle all other IOExceptions by restarting<a name="line.212"></a>
-<span class="sourceLineNo">213</span>        // the scanner, if the second call fails, it will be rethrown<a name="line.213"></a>
-<span class="sourceLineNo">214</span>        LOG.debug("recovered from " + StringUtils.stringifyException(e));<a name="line.214"></a>
-<span class="sourceLineNo">215</span>        if (lastSuccessfulRow == null) {<a name="line.215"></a>
-<span class="sourceLineNo">216</span>          LOG.warn("We are restarting the first next() invocation," +<a name="line.216"></a>
-<span class="sourceLineNo">217</span>              " if your mapper has restarted a few other times like this" +<a name="line.217"></a>
-<span class="sourceLineNo">218</span>              " then you should consider killing this job and investigate" +<a name="line.218"></a>
-<span class="sourceLineNo">219</span>              " why it's taking so long.");<a name="line.219"></a>
-<span class="sourceLineNo">220</span>        }<a name="line.220"></a>
-<span class="sourceLineNo">221</span>        if (lastSuccessfulRow == null) {<a name="line.221"></a>
-<span class="sourceLineNo">222</span>          restart(startRow);<a name="line.222"></a>
-<span class="sourceLineNo">223</span>        } else {<a name="line.223"></a>
-<span class="sourceLineNo">224</span>          restart(lastSuccessfulRow);<a name="line.224"></a>
-<span class="sourceLineNo">225</span>          this.scanner.next();    // skip presumed already mapped row<a name="line.225"></a>
-<span class="sourceLineNo">226</span>        }<a name="line.226"></a>
-<span class="sourceLineNo">227</span>        result = this.scanner.next();<a name="line.227"></a>
-<span class="sourceLineNo">228</span>      }<a name="line.228"></a>
-<span class="sourceLineNo">229</span><a name="line.229"></a>
-<span class="sourceLineNo">230</span>      if (result != null &amp;&amp; result.size() &gt; 0) {<a name="line.230"></a>
-<span class="sourceLineNo">231</span>        key.set(result.getRow());<a name="line.231"></a>
-<span class="sourceLineNo">232</span>        lastSuccessfulRow = key.get();<a name="line.232"></a>
-<span class="sourceLineNo">233</span>        value.copyFrom(result);<a name="line.233"></a>
-<span class="sourceLineNo">234</span>        return true;<a name="line.234"></a>
-<span class="sourceLineNo">235</span>      }<a name="line.235"></a>
-<span class="sourceLineNo">236</span>      return false;<a name="line.236"></a>
-<span class="sourceLineNo">237</span>    } catch (IOException ioe) {<a name="line.237"></a>
-<span class="sourceLineNo">238</span>      if (logScannerActivity) {<a name="line.238"></a>
-<span class="sourceLineNo">239</span>        long now = System.currentTimeMillis();<a name="line.239"></a>
-<span class="sourceLineNo">240</span>        LOG.info("Mapper took " + (now-timestamp)<a name="line.240"></a>
-<span class="sourceLineNo">241</span>          + "ms to process " + rowcount + " rows");<a name="line.241"></a>
-<span class="sourceLineNo">242</span>        LOG.info(ioe.toString(), ioe);<a name="line.242"></a>
-<span class="sourceLineNo">243</span>        String lastRow = lastSuccessfulRow == null ?<a name="line.243"></a>
-<span class="sourceLineNo">244</span>          "null" : Bytes.toStringBinary(lastSuccessfulRow);<a name="line.244"></a>
-<span class="sourceLineNo">245</span>        LOG.info("lastSuccessfulRow=" + lastRow);<a name="line.245"></a>
-<span class="sourceLineNo">246</span>      }<a name="line.246"></a>
-<span class="sourceLineNo">247</span>      throw ioe;<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>}<a name="line.250"></a>
+<span class="sourceLineNo">034</span>import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.util.StringUtils;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.slf4j.Logger;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.slf4j.LoggerFactory;<a name="line.38"></a>
+<span class="sourceLineNo">039</span><a name="line.39"></a>
+<span class="sourceLineNo">040</span>/**<a name="line.40"></a>
+<span class="sourceLineNo">041</span> * Iterate over an HBase table data, return (Text, RowResult) pairs<a name="line.41"></a>
+<span class="sourceLineNo">042</span> */<a name="line.42"></a>
+<span class="sourceLineNo">043</span>@InterfaceAudience.Public<a name="line.43"></a>
+<span class="sourceLineNo">044</span>public class TableRecordReaderImpl {<a name="line.44"></a>
+<span class="sourceLineNo">045</span>  private static final Logger LOG = LoggerFactory.getLogger(TableRecordReaderImpl.class);<a name="line.45"></a>
+<span class="sourceLineNo">046</span><a name="line.46"></a>
+<span class="sourceLineNo">047</span>  private byte [] startRow;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>  private byte [] endRow;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>  private byte [] lastSuccessfulRow;<a name="line.49"></a>
+<span class="sourceLineNo">050</span>  private Filter trrRowFilter;<a name="line.50"></a>
+<span class="sourceLineNo">051</span>  private ResultScanner scanner;<a name="line.51"></a>
+<span class="sourceLineNo">052</span>  private Table htable;<a name="line.52"></a>
+<span class="sourceLineNo">053</span>  private byte [][] trrInputColumns;<a name="line.53"></a>
+<span class="sourceLineNo">054</span>  private long timestamp;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>  private int rowcount;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>  private boolean logScannerActivity = false;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>  private int logPerRowCount = 100;<a name="line.57"></a>
+<span class="sourceLineNo">058</span><a name="line.58"></a>
+<span class="sourceLineNo">059</span>  /**<a name="line.59"></a>
+<span class="sourceLineNo">060</span>   * Restart from survivable exceptions by creating a new scanner.<a name="line.60"></a>
+<span class="sourceLineNo">061</span>   */<a name="line.61"></a>
+<span class="sourceLineNo">062</span>  public void restart(byte[] firstRow) throws IOException {<a name="line.62"></a>
+<span class="sourceLineNo">063</span>    Scan currentScan;<a name="line.63"></a>
+<span class="sourceLineNo">064</span>    if ((endRow != null) &amp;&amp; (endRow.length &gt; 0)) {<a name="line.64"></a>
+<span class="sourceLineNo">065</span>      if (trrRowFilter != null) {<a name="line.65"></a>
+<span class="sourceLineNo">066</span>        Scan scan = new Scan().withStartRow(firstRow).withStopRow(endRow);<a name="line.66"></a>
+<span class="sourceLineNo">067</span>        TableInputFormat.addColumns(scan, trrInputColumns);<a name="line.67"></a>
+<span class="sourceLineNo">068</span>        scan.setFilter(trrRowFilter);<a name="line.68"></a>
+<span class="sourceLineNo">069</span>        scan.setCacheBlocks(false);<a name="line.69"></a>
+<span class="sourceLineNo">070</span>        this.scanner = this.htable.getScanner(scan);<a name="line.70"></a>
+<span class="sourceLineNo">071</span>        currentScan = scan;<a name="line.71"></a>
+<span class="sourceLineNo">072</span>      } else {<a name="line.72"></a>
+<span class="sourceLineNo">073</span>        LOG.debug("TIFB.restart, firstRow: " +<a name="line.73"></a>
+<span class="sourceLineNo">074</span>            Bytes.toStringBinary(firstRow) + ", endRow: " +<a name="line.74"></a>
+<span class="sourceLineNo">075</span>            Bytes.toStringBinary(endRow));<a name="line.75"></a>
+<span class="sourceLineNo">076</span>        Scan scan = new Scan().withStartRow(firstRow).withStopRow(endRow);<a name="line.76"></a>
+<span class="sourceLineNo">077</span>        TableInputFormat.addColumns(scan, trrInputColumns);<a name="line.77"></a>
+<span class="sourceLineNo">078</span>        this.scanner = this.htable.getScanner(scan);<a name="line.78"></a>
+<span class="sourceLineNo">079</span>        currentScan = scan;<a name="line.79"></a>
+<span class="sourceLineNo">080</span>      }<a name="line.80"></a>
+<span class="sourceLineNo">081</span>    } else {<a name="line.81"></a>
+<span class="sourceLineNo">082</span>      LOG.debug("TIFB.restart, firstRow: " +<a name="line.82"></a>
+<span class="sourceLineNo">083</span>          Bytes.toStringBinary(firstRow) + ", no endRow");<a name="line.83"></a>
+<span class="sourceLineNo">084</span><a name="line.84"></a>
+<span class="sourceLineNo">085</span>      Scan scan = new Scan().withStartRow(firstRow);<a name="line.85"></a>
+<span class="sourceLineNo">086</span>      TableInputFormat.addColumns(scan, trrInputColumns);<a name="line.86"></a>
+<span class="sourceLineNo">087</span>      scan.setFilter(trrRowFilter);<a name="line.87"></a>
+<span class="sourceLineNo">088</span>      this.scanner = this.htable.getScanner(scan);<a name="line.88"></a>
+<span class="sourceLineNo">089</span>      currentScan = scan;<a name="line.89"></a>
+<span class="sourceLineNo">090</span>    }<a name="line.90"></a>
+<span class="sourceLineNo">091</span>    if (logScannerActivity) {<a name="line.91"></a>
+<span class="sourceLineNo">092</span>      LOG.info("Current scan=" + currentScan.toString());<a name="line.92"></a>
+<span class="sourceLineNo">093</span>      timestamp = EnvironmentEdgeManager.currentTime();<a name="line.93"></a>
+<span class="sourceLineNo">094</span>      rowcount = 0;<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>  /**<a name="line.98"></a>
+<span class="sourceLineNo">099</span>   * Build the scanner. Not done in constructor to allow for extension.<a name="line.99"></a>
+<span class="sourceLineNo">100</span>   */<a name="line.100"></a>
+<span class="sourceLineNo">101</span>  public void init() throws IOException {<a name="line.101"></a>
+<span class="sourceLineNo">102</span>    restart(startRow);<a name="line.102"></a>
+<span class="sourceLineNo">103</span>  }<a name="line.103"></a>
+<span class="sourceLineNo">104</span><a name="line.104"></a>
+<span class="sourceLineNo">105</span>  byte[] getStartRow() {<a name="line.105"></a>
+<span class="sourceLineNo">106</span>    return this.startRow;<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>  /**<a name="line.109"></a>
+<span class="sourceLineNo">110</span>   * @param htable the table to scan.<a name="line.110"></a>
+<span class="sourceLineNo">111</span>   */<a name="line.111"></a>
+<span class="sourceLineNo">112</span>  public void setHTable(Table htable) {<a name="line.112"></a>
+<span class="sourceLineNo">113</span>    Configuration conf = htable.getConfiguration();<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    logScannerActivity = conf.getBoolean(ConnectionConfiguration.LOG_SCANNER_ACTIVITY, false);<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    logPerRowCount = conf.getInt(LOG_PER_ROW_COUNT, 100);<a name="line.115"></a>
+<span class="sourceLineNo">116</span>    this.htable = htable;<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>  /**<a name="line.119"></a>
+<span class="sourceLineNo">120</span>   * @param inputColumns the columns to be placed in {@link Result}.<a name="line.120"></a>
+<span class="sourceLineNo">121</span>   */<a name="line.121"></a>
+<span class="sourceLineNo">122</span>  public void setInputColumns(final byte [][] inputColumns) {<a name="line.122"></a>
+<span class="sourceLineNo">123</span>    this.trrInputColumns = inputColumns;<a name="line.123"></a>
+<span class="sourceLineNo">124</span>  }<a name="line.124"></a>
+<span class="sourceLineNo">125</span><a name="line.125"></a>
+<span class="sourceLineNo">126</span>  /**<a name="line.126"></a>
+<span class="sourceLineNo">127</span>   * @param startRow the first row in the split<a name="line.127"></a>
+<span class="sourceLineNo">128</span>   */<a name="line.128"></a>
+<span class="sourceLineNo">129</span>  public void setStartRow(final byte [] startRow) {<a name="line.129"></a>
+<span class="sourceLineNo">130</span>    this.startRow = startRow;<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>  /**<a name="line.133"></a>
+<span class="sourceLineNo">134</span>   *<a name="line.134"></a>
+<span class="sourceLineNo">135</span>   * @param endRow the last row in the split<a name="line.135"></a>
+<span class="sourceLineNo">136</span>   */<a name="line.136"></a>
+<span class="sourceLineNo">137</span>  public void setEndRow(final byte [] endRow) {<a name="line.137"></a>
+<span class="sourceLineNo">138</span>    this.endRow = endRow;<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>  /**<a name="line.141"></a>
+<span class="sourceLineNo">142</span>   * @param rowFilter the {@link Filter} to be used.<a name="line.142"></a>
+<span class="sourceLineNo">143</span>   */<a name="line.143"></a>
+<span class="sourceLineNo">144</span>  public void setRowFilter(Filter rowFilter) {<a name="line.144"></a>
+<span class="sourceLineNo">145</span>    this.trrRowFilter = rowFilter;<a name="line.145"></a>
+<span class="sourceLineNo">146</span>  }<a name="line.146"></a>
+<span class="sourceLineNo">147</span><a name="line.147"></a>
+<span class="sourceLineNo">148</span>  public void close() {<a name="line.148"></a>
+<span class="sourceLineNo">149</span>    if (this.scanner != null) {<a name="line.149"></a>
+<span class="sourceLineNo">150</span>      this.scanner.close();<a name="line.150"></a>
+<span class="sourceLineNo">151</span>    }<a name="line.151"></a>
+<span class="sourceLineNo">152</span>    try {<a name="line.152"></a>
+<span class="sourceLineNo">153</span>      this.htable.close();<a name="line.153"></a>
+<span class="sourceLineNo">154</span>    } catch (IOException ioe) {<a name="line.154"></a>
+<span class="sourceLineNo">155</span>      LOG.warn("Error closing table", ioe);<a name="line.155"></a>
+<span class="sourceLineNo">156</span>    }<a name="line.156"></a>
+<span class="sourceLineNo">157</span>  }<a name="line.157"></a>
+<span class="sourceLineNo">158</span><a name="line.158"></a>
+<span class="sourceLineNo">159</span>  /**<a name="line.159"></a>
+<span class="sourceLineNo">160</span>   * @return ImmutableBytesWritable<a name="line.160"></a>
+<span class="sourceLineNo">161</span>   *<a name="line.161"></a>
+<span class="sourceLineNo">162</span>   * @see org.apache.hadoop.mapred.RecordReader#createKey()<a name="line.162"></a>
+<span class="sourceLineNo">163</span>   */<a name="line.163"></a>
+<span class="sourceLineNo">164</span>  public ImmutableBytesWritable createKey() {<a name="line.164"></a>
+<span class="sourceLineNo">165</span>    return new ImmutableBytesWritable();<a name="line.165"></a>
+<span class="sourceLineNo">166</span>  }<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>   * @return RowResult<a name="line.169"></a>
+<span class="sourceLineNo">170</span>   *<a name="line.170"></a>
+<span class="sourceLineNo">171</span>   * @see org.apache.hadoop.mapred.RecordReader#createValue()<a name="line.171"></a>
+<span class="sourceLineNo">172</span>   */<a name="line.172"></a>
+<span class="sourceLineNo">173</span>  public Result createValue() {<a name="line.173"></a>
+<span class="sourceLineNo">174</span>    return new Result();<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>  public long getPos() {<a name="line.177"></a>
+<span class="sourceLineNo">178</span>    // This should be the ordinal tuple in the range;<a name="line.178"></a>
+<span class="sourceLineNo">179</span>    // not clear how to calculate...<a name="line.179"></a>
+<span class="sourceLineNo">180</span>    return 0;<a name="line.180"></a>
+<span class="sourceLineNo">181</span>  }<a name="line.181"></a>
+<span class="sourceLineNo">182</span><a name="line.182"></a>
+<span class="sourceLineNo">183</span>  public float getProgress() {<a name="line.183"></a>
+<span class="sourceLineNo">184</span>    // Depends on the total number of tuples and getPos<a name="line.184"></a>
+<span class="sourceLineNo">185</span>    return 0;<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>  /**<a name="line.188"></a>
+<span class="sourceLineNo">189</span>   * @param key HStoreKey as input key.<a name="line.189"></a>
+<span class="sourceLineNo">190</span>   * @param value MapWritable as input value<a name="line.190"></a>
+<span class="sourceLineNo">191</span>   * @return true if there was more data<a name="line.191"></a>
+<span class="sourceLineNo">192</span>   */<a name="line.192"></a>
+<span class="sourceLineNo">193</span>  public boolean next(ImmutableBytesWritable key, Result value) throws IOException {<a name="line.193"></a>
+<span class="sourceLineNo">194</span>    Result result;<a name="line.194"></a>
+<span class="sourceLineNo">195</span>    try {<a name="line.195"></a>
+<span class="sourceLineNo">196</span>      try {<a name="line.196"></a>
+<span class="sourceLineNo">197</span>        result = this.scanner.next();<a name="line.197"></a>
+<span class="sourceLineNo">198</span>        if (logScannerActivity) {<a name="line.198"></a>
+<span class="sourceLineNo">199</span>          rowcount ++;<a name="line.199"></a>
+<span class="sourceLineNo">200</span>          if (rowcount &gt;= logPerRowCount) {<a name="line.200"></a>
+<span class="sourceLineNo">201</span>            long now = EnvironmentEdgeManager.currentTime();<a name="line.201"></a>
+<span class="sourceLineNo">202</span>            LOG.info("Mapper took " + (now-timestamp)<a name="line.202"></a>
+<span class="sourceLineNo">203</span>              + "ms to process " + rowcount + " rows");<a name="line.203"></a>
+<span class="sourceLineNo">204</span>            timestamp = now;<a name="line.204"></a>
+<span class="sourceLineNo">205</span>            rowcount = 0;<a name="line.205"></a>
+<span class="sourceLineNo">206</span>          }<a name="line.206"></a>
+<span class="sourceLineNo">207</span>        }<a name="line.207"></a>
+<span class="sourceLineNo">208</span>      } catch (IOException e) {<a name="line.208"></a>
+<span class="sourceLineNo">209</span>        // do not retry if the exception tells us not to do so<a name="line.209"></a>
+<span class="sourceLineNo">210</span>        if (e instanceof DoNotRetryIOException) {<a name="line.210"></a>
+<span class="sourceLineNo">211</span>          throw e;<a name="line.211"></a>
+<span class="sourceLineNo">212</span>        }<a name="line.212"></a>
+<span class="sourceLineNo">213</span>        // try to handle all other IOExceptions by restarting<a name="line.213"></a>
+<span class="sourceLineNo">214</span>        // the scanner, if the second call fails, it will be rethrown<a name="line.214"></a>
+<span class="sourceLineNo">215</span>        LOG.debug("recovered from " + StringUtils.stringifyException(e));<a name="line.215"></a>
+<span class="sourceLineNo">216</span>        if (lastSuccessfulRow == null) {<a name="line.216"></a>
+<span class="sourceLineNo">217</span>          LOG.warn("We are restarting the first next() invocation," +<a name="line.217"></a>
+<span class="sourceLineNo">218</span>              " if your mapper has restarted a few other times like this" +<a name="line.218"></a>
+<span class="sourceLineNo">219</span>              " then you should consider killing this job and investigate" +<a name="line.219"></a>
+<span class="sourceLineNo">220</span>              " why it's taking so long.");<a name="line.220"></a>
+<span class="sourceLineNo">221</span>        }<a name="line.221"></a>
+<span class="sourceLineNo">222</span>        if (lastSuccessfulRow == null) {<a name="line.222"></a>
+<span class="sourceLineNo">223</span>          restart(startRow);<a name="line.223"></a>
+<span class="sourceLineNo">224</span>        } else {<a name="line.224"></a>
+<span class="sourceLineNo">225</span>          restart(lastSuccessfulRow);<a name="line.225"></a>
+<span class="sourceLineNo">226</span>          this.scanner.next();    // skip presumed already mapped row<a name="line.226"></a>
+<span class="sourceLineNo">227</span>        }<a name="line.227"></a>
+<span class="sourceLineNo">228</span>        result = this.scanner.next();<a name="line.228"></a>
+<span class="sourceLineNo">229</span>      }<a name="line.229"></a>
+<span class="sourceLineNo">230</span><a name="line.230"></a>
+<span class="sourceLineNo">231</span>      if (result != null &amp;&amp; result.size() &gt; 0) {<a name="line.231"></a>
+<span class="sourceLineNo">232</span>        key.set(result.getRow());<a name="line.232"></a>
+<span class="sourceLineNo">233</span>        lastSuccessfulRow = key.get();<a name="line.233"></a>
+<span class="sourceLineNo">234</span>        value.copyFrom(result);<a name="line.234"></a>
+<span class="sourceLineNo">235</span>        return true;<a name="line.235"></a>
+<span class="sourceLineNo">236</span>      }<a name="line.236"></a>
+<span class="sourceLineNo">237</span>      return false;<a name="line.237"></a>
+<span class="sourceLineNo">238</span>    } catch (IOException ioe) {<a name="line.238"></a>
+<span class="sourceLineNo">239</span>      if (logScannerActivity) {<a name="line.239"></a>
+<span class="sourceLineNo">240</span>        long now = EnvironmentEdgeManager.currentTime();<a name="line.240"></a>
+<span class="sourceLineNo">241</span>        LOG.info("Mapper took " + (now-timestamp)<a name="line.241"></a>
+<span class="sourceLineNo">242</span>          + "ms to process " + rowcount + " rows");<a name="line.242"></a>
+<span class="sourceLineNo">243</span>        LOG.info(ioe.toString(), ioe);<a name="line.243"></a>
+<span class="sourceLineNo">244</span>        String lastRow = lastSuccessfulRow == null ?<a name="line.244"></a>
+<span class="sourceLineNo">245</span>          "null" : Bytes.toStringBinary(lastSuccessfulRow);<a name="line.245"></a>
+<span class="sourceLineNo">246</span>        LOG.info("lastSuccessfulRow=" + lastRow);<a name="line.246"></a>
+<span class="sourceLineNo">247</span>      }<a name="line.247"></a>
+<span class="sourceLineNo">248</span>      throw ioe;<a name="line.248"></a>
+<span class="sourceLineNo">249</span>    }<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>
 
 
 
diff --git a/apidocs/src-html/org/apache/hadoop/hbase/mapreduce/HFileOutputFormat2.html b/apidocs/src-html/org/apache/hadoop/hbase/mapreduce/HFileOutputFormat2.html
index 87dd1ac..d39352c 100644
--- a/apidocs/src-html/org/apache/hadoop/hbase/mapreduce/HFileOutputFormat2.html
+++ b/apidocs/src-html/org/apache/hadoop/hbase/mapreduce/HFileOutputFormat2.html
@@ -427,540 +427,542 @@
 <span class="sourceLineNo">419</span><a name="line.419"></a>
 <span class="sourceLineNo">420</span>      private void close(final StoreFileWriter w) throws IOException {<a name="line.420"></a>
 <span class="sourceLineNo">421</span>        if (w != null) {<a name="line.421"></a>
-<span class="sourceLineNo">422</span>          w.appendFileInfo(BULKLOAD_TIME_KEY, Bytes.toBytes(System.currentTimeMillis()));<a name="line.422"></a>
-<span class="sourceLineNo">423</span>          w.appendFileInfo(BULKLOAD_TASK_KEY, Bytes.toBytes(context.getTaskAttemptID().toString()));<a name="line.423"></a>
-<span class="sourceLineNo">424</span>          w.appendFileInfo(MAJOR_COMPACTION_KEY, Bytes.toBytes(true));<a name="line.424"></a>
-<span class="sourceLineNo">425</span>          w.appendFileInfo(EXCLUDE_FROM_MINOR_COMPACTION_KEY, Bytes.toBytes(compactionExclude));<a name="line.425"></a>
-<span class="sourceLineNo">426</span>          w.appendTrackedTimestampsToMetadata();<a name="line.426"></a>
-<span class="sourceLineNo">427</span>          w.close();<a name="line.427"></a>
-<span class="sourceLineNo">428</span>        }<a name="line.428"></a>
-<span class="sourceLineNo">429</span>      }<a name="line.429"></a>
-<span class="sourceLineNo">430</span><a name="line.430"></a>
-<span class="sourceLineNo">431</span>      @Override<a name="line.431"></a>
-<span class="sourceLineNo">432</span>      public void close(TaskAttemptContext c) throws IOException, InterruptedException {<a name="line.432"></a>
-<span class="sourceLineNo">433</span>        for (WriterLength wl: this.writers.values()) {<a name="line.433"></a>
-<span class="sourceLineNo">434</span>          close(wl.writer);<a name="line.434"></a>
-<span class="sourceLineNo">435</span>        }<a name="line.435"></a>
-<span class="sourceLineNo">436</span>      }<a name="line.436"></a>
-<span class="sourceLineNo">437</span>    };<a name="line.437"></a>
-<span class="sourceLineNo">438</span>  }<a name="line.438"></a>
-<span class="sourceLineNo">439</span><a name="line.439"></a>
-<span class="sourceLineNo">440</span>  /**<a name="line.440"></a>
-<span class="sourceLineNo">441</span>   * Configure block storage policy for CF after the directory is created.<a name="line.441"></a>
-<span class="sourceLineNo">442</span>   */<a name="line.442"></a>
-<span class="sourceLineNo">443</span>  static void configureStoragePolicy(final Configuration conf, final FileSystem fs,<a name="line.443"></a>
-<span class="sourceLineNo">444</span>      byte[] tableAndFamily, Path cfPath) {<a name="line.444"></a>
-<span class="sourceLineNo">445</span>    if (null == conf || null == fs || null == tableAndFamily || null == cfPath) {<a name="line.445"></a>
-<span class="sourceLineNo">446</span>      return;<a name="line.446"></a>
-<span class="sourceLineNo">447</span>    }<a name="line.447"></a>
-<span class="sourceLineNo">448</span><a name="line.448"></a>
-<span class="sourceLineNo">449</span>    String policy =<a name="line.449"></a>
-<span class="sourceLineNo">450</span>        conf.get(STORAGE_POLICY_PROPERTY_CF_PREFIX + Bytes.toString(tableAndFamily),<a name="line.450"></a>
-<span class="sourceLineNo">451</span>          conf.get(STORAGE_POLICY_PROPERTY));<a name="line.451"></a>
-<span class="sourceLineNo">452</span>    CommonFSUtils.setStoragePolicy(fs, cfPath, policy);<a name="line.452"></a>
-<span class="sourceLineNo">453</span>  }<a name="line.453"></a>
-<span class="sourceLineNo">454</span><a name="line.454"></a>
-<span class="sourceLineNo">455</span>  /*<a name="line.455"></a>
-<span class="sourceLineNo">456</span>   * Data structure to hold a Writer and amount of data written on it.<a name="line.456"></a>
-<span class="sourceLineNo">457</span>   */<a name="line.457"></a>
-<span class="sourceLineNo">458</span>  static class WriterLength {<a name="line.458"></a>
-<span class="sourceLineNo">459</span>    long written = 0;<a name="line.459"></a>
-<span class="sourceLineNo">460</span>    StoreFileWriter writer = null;<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>   * Return the start keys of all of the regions in this table,<a name="line.464"></a>
-<span class="sourceLineNo">465</span>   * as a list of ImmutableBytesWritable.<a name="line.465"></a>
-<span class="sourceLineNo">466</span>   */<a name="line.466"></a>
-<span class="sourceLineNo">467</span>  private static List&lt;ImmutableBytesWritable&gt; getRegionStartKeys(List&lt;RegionLocator&gt; regionLocators,<a name="line.467"></a>
-<span class="sourceLineNo">468</span>                                                                 boolean writeMultipleTables)<a name="line.468"></a>
-<span class="sourceLineNo">469</span>          throws IOException {<a name="line.469"></a>
-<span class="sourceLineNo">470</span><a name="line.470"></a>
-<span class="sourceLineNo">471</span>    ArrayList&lt;ImmutableBytesWritable&gt; ret = new ArrayList&lt;&gt;();<a name="line.471"></a>
-<span class="sourceLineNo">472</span>    for(RegionLocator regionLocator : regionLocators) {<a name="line.472"></a>
-<span class="sourceLineNo">473</span>      TableName tableName = regionLocator.getName();<a name="line.473"></a>
-<span class="sourceLineNo">474</span>      LOG.info("Looking up current regions for table " + tableName);<a name="line.474"></a>
-<span class="sourceLineNo">475</span>      byte[][] byteKeys = regionLocator.getStartKeys();<a name="line.475"></a>
-<span class="sourceLineNo">476</span>      for (byte[] byteKey : byteKeys) {<a name="line.476"></a>
-<span class="sourceLineNo">477</span>        byte[] fullKey = byteKey; //HFileOutputFormat2 use case<a name="line.477"></a>
-<span class="sourceLineNo">478</span>        if (writeMultipleTables) {<a name="line.478"></a>
-<span class="sourceLineNo">479</span>          //MultiTableHFileOutputFormat use case<a name="line.479"></a>
-<span class="sourceLineNo">480</span>          fullKey = combineTableNameSuffix(tableName.getName(), byteKey);<a name="line.480"></a>
-<span class="sourceLineNo">481</span>        }<a name="line.481"></a>
-<span class="sourceLineNo">482</span>        if (LOG.isDebugEnabled()) {<a name="line.482"></a>
-<span class="sourceLineNo">483</span>          LOG.debug("SplitPoint startkey for " + tableName + ": " + Bytes.toStringBinary(fullKey));<a name="line.483"></a>
-<span class="sourceLineNo">484</span>        }<a name="line.484"></a>
-<span class="sourceLineNo">485</span>        ret.add(new ImmutableBytesWritable(fullKey));<a name="line.485"></a>
-<span class="sourceLineNo">486</span>      }<a name="line.486"></a>
-<span class="sourceLineNo">487</span>    }<a name="line.487"></a>
-<span class="sourceLineNo">488</span>    return ret;<a name="line.488"></a>
-<span class="sourceLineNo">489</span>  }<a name="line.489"></a>
-<span class="sourceLineNo">490</span><a name="line.490"></a>
-<span class="sourceLineNo">491</span>  /**<a name="line.491"></a>
-<span class="sourceLineNo">492</span>   * Write out a {@link SequenceFile} that can be read by<a name="line.492"></a>
-<span class="sourceLineNo">493</span>   * {@link TotalOrderPartitioner} that contains the split points in startKeys.<a name="line.493"></a>
-<span class="sourceLineNo">494</span>   */<a name="line.494"></a>
-<span class="sourceLineNo">495</span>  @SuppressWarnings("deprecation")<a name="line.495"></a>
-<span class="sourceLineNo">496</span>  private static void writePartitions(Configuration conf, Path partitionsPath,<a name="line.496"></a>
-<span class="sourceLineNo">497</span>      List&lt;ImmutableBytesWritable&gt; startKeys, boolean writeMultipleTables) throws IOException {<a name="line.497"></a>
-<span class="sourceLineNo">498</span>    LOG.info("Writing partition information to " + partitionsPath);<a name="line.498"></a>
-<span class="sourceLineNo">499</span>    if (startKeys.isEmpty()) {<a name="line.499"></a>
-<span class="sourceLineNo">500</span>      throw new IllegalArgumentException("No regions passed");<a name="line.500"></a>
-<span class="sourceLineNo">501</span>    }<a name="line.501"></a>
-<span class="sourceLineNo">502</span><a name="line.502"></a>
-<span class="sourceLineNo">503</span>    // We're generating a list of split points, and we don't ever<a name="line.503"></a>
-<span class="sourceLineNo">504</span>    // have keys &lt; the first region (which has an empty start key)<a name="line.504"></a>
-<span class="sourceLineNo">505</span>    // so we need to remove it. Otherwise we would end up with an<a name="line.505"></a>
-<span class="sourceLineNo">506</span>    // empty reducer with index 0<a name="line.506"></a>
-<span class="sourceLineNo">507</span>    TreeSet&lt;ImmutableBytesWritable&gt; sorted = new TreeSet&lt;&gt;(startKeys);<a name="line.507"></a>
-<span class="sourceLineNo">508</span>    ImmutableBytesWritable first = sorted.first();<a name="line.508"></a>
-<span class="sourceLineNo">509</span>    if (writeMultipleTables) {<a name="line.509"></a>
-<span class="sourceLineNo">510</span>      first =<a name="line.510"></a>
-<span class="sourceLineNo">511</span>        new ImmutableBytesWritable(MultiTableHFileOutputFormat.getSuffix(sorted.first().get()));<a name="line.511"></a>
-<span class="sourceLineNo">512</span>    }<a name="line.512"></a>
-<span class="sourceLineNo">513</span>    if (!first.equals(HConstants.EMPTY_BYTE_ARRAY)) {<a name="line.513"></a>
-<span class="sourceLineNo">514</span>      throw new IllegalArgumentException(<a name="line.514"></a>
-<span class="sourceLineNo">515</span>          "First region of table should have empty start key. Instead has: "<a name="line.515"></a>
-<span class="sourceLineNo">516</span>          + Bytes.toStringBinary(first.get()));<a name="line.516"></a>
-<span class="sourceLineNo">517</span>    }<a name="line.517"></a>
-<span class="sourceLineNo">518</span>    sorted.remove(sorted.first());<a name="line.518"></a>
-<span class="sourceLineNo">519</span><a name="line.519"></a>
-<span class="sourceLineNo">520</span>    // Write the actual file<a name="line.520"></a>
-<span class="sourceLineNo">521</span>    FileSystem fs = partitionsPath.getFileSystem(conf);<a name="line.521"></a>
-<span class="sourceLineNo">522</span>    SequenceFile.Writer writer = SequenceFile.createWriter(<a name="line.522"></a>
-<span class="sourceLineNo">523</span>      fs, conf, partitionsPath, ImmutableBytesWritable.class,<a name="line.523"></a>
-<span class="sourceLineNo">524</span>      NullWritable.class);<a name="line.524"></a>
-<span class="sourceLineNo">525</span><a name="line.525"></a>
-<span class="sourceLineNo">526</span>    try {<a name="line.526"></a>
-<span class="sourceLineNo">527</span>      for (ImmutableBytesWritable startKey : sorted) {<a name="line.527"></a>
-<span class="sourceLineNo">528</span>        writer.append(startKey, NullWritable.get());<a name="line.528"></a>
-<span class="sourceLineNo">529</span>      }<a name="line.529"></a>
-<span class="sourceLineNo">530</span>    } finally {<a name="line.530"></a>
-<span class="sourceLineNo">531</span>      writer.close();<a name="line.531"></a>
-<span class="sourceLineNo">532</span>    }<a name="line.532"></a>
-<span class="sourceLineNo">533</span>  }<a name="line.533"></a>
-<span class="sourceLineNo">534</span><a name="line.534"></a>
-<span class="sourceLineNo">535</span>  /**<a name="line.535"></a>
-<span class="sourceLineNo">536</span>   * Configure a MapReduce Job to perform an incremental load into the given<a name="line.536"></a>
-<span class="sourceLineNo">537</span>   * table. This<a name="line.537"></a>
-<span class="sourceLineNo">538</span>   * &lt;ul&gt;<a name="line.538"></a>
-<span class="sourceLineNo">539</span>   *   &lt;li&gt;Inspects the table to configure a total order partitioner&lt;/li&gt;<a name="line.539"></a>
-<span class="sourceLineNo">540</span>   *   &lt;li&gt;Uploads the partitions file to the cluster and adds it to the DistributedCache&lt;/li&gt;<a name="line.540"></a>
-<span class="sourceLineNo">541</span>   *   &lt;li&gt;Sets the number of reduce tasks to match the current number of regions&lt;/li&gt;<a name="line.541"></a>
-<span class="sourceLineNo">542</span>   *   &lt;li&gt;Sets the output key/value class to match HFileOutputFormat2's requirements&lt;/li&gt;<a name="line.542"></a>
-<span class="sourceLineNo">543</span>   *   &lt;li&gt;Sets the reducer up to perform the appropriate sorting (either KeyValueSortReducer or<a name="line.543"></a>
-<span class="sourceLineNo">544</span>   *     PutSortReducer)&lt;/li&gt;<a name="line.544"></a>
-<span class="sourceLineNo">545</span>   *   &lt;li&gt;Sets the HBase cluster key to load region locations for locality-sensitive&lt;/li&gt;<a name="line.545"></a>
-<span class="sourceLineNo">546</span>   * &lt;/ul&gt;<a name="line.546"></a>
-<span class="sourceLineNo">547</span>   * The user should be sure to set the map output value class to either KeyValue or Put before<a name="line.547"></a>
-<span class="sourceLineNo">548</span>   * running this function.<a name="line.548"></a>
-<span class="sourceLineNo">549</span>   */<a name="line.549"></a>
-<span class="sourceLineNo">550</span>  public static void configureIncrementalLoad(Job job, Table table, RegionLocator regionLocator)<a name="line.550"></a>
-<span class="sourceLineNo">551</span>      throws IOException {<a name="line.551"></a>
-<span class="sourceLineNo">552</span>    configureIncrementalLoad(job, table.getDescriptor(), regionLocator);<a name="line.552"></a>
-<span class="sourceLineNo">553</span>    configureRemoteCluster(job, table.getConfiguration());<a name="line.553"></a>
-<span class="sourceLineNo">554</span>  }<a name="line.554"></a>
-<span class="sourceLineNo">555</span><a name="line.555"></a>
-<span class="sourceLineNo">556</span>  /**<a name="line.556"></a>
-<span class="sourceLineNo">557</span>   * Configure a MapReduce Job to perform an incremental load into the given<a name="line.557"></a>
-<span class="sourceLineNo">558</span>   * table. This<a name="line.558"></a>
-<span class="sourceLineNo">559</span>   * &lt;ul&gt;<a name="line.559"></a>
-<span class="sourceLineNo">560</span>   *   &lt;li&gt;Inspects the table to configure a total order partitioner&lt;/li&gt;<a name="line.560"></a>
-<span class="sourceLineNo">561</span>   *   &lt;li&gt;Uploads the partitions file to the cluster and adds it to the DistributedCache&lt;/li&gt;<a name="line.561"></a>
-<span class="sourceLineNo">562</span>   *   &lt;li&gt;Sets the number of reduce tasks to match the current number of regions&lt;/li&gt;<a name="line.562"></a>
-<span class="sourceLineNo">563</span>   *   &lt;li&gt;Sets the output key/value class to match HFileOutputFormat2's requirements&lt;/li&gt;<a name="line.563"></a>
-<span class="sourceLineNo">564</span>   *   &lt;li&gt;Sets the reducer up to perform the appropriate sorting (either KeyValueSortReducer or<a name="line.564"></a>
-<span class="sourceLineNo">565</span>   *     PutSortReducer)&lt;/li&gt;<a name="line.565"></a>
-<span class="sourceLineNo">566</span>   * &lt;/ul&gt;<a name="line.566"></a>
-<span class="sourceLineNo">567</span>   * The user should be sure to set the map output value class to either KeyValue or Put before<a name="line.567"></a>
-<span class="sourceLineNo">568</span>   * running this function.<a name="line.568"></a>
-<span class="sourceLineNo">569</span>   */<a name="line.569"></a>
-<span class="sourceLineNo">570</span>  public static void configureIncrementalLoad(Job job, TableDescriptor tableDescriptor,<a name="line.570"></a>
-<span class="sourceLineNo">571</span>      RegionLocator regionLocator) throws IOException {<a name="line.571"></a>
-<span class="sourceLineNo">572</span>    ArrayList&lt;TableInfo&gt; singleTableInfo = new ArrayList&lt;&gt;();<a name="line.572"></a>
-<span class="sourceLineNo">573</span>    singleTableInfo.add(new TableInfo(tableDescriptor, regionLocator));<a name="line.573"></a>
-<span class="sourceLineNo">574</span>    configureIncrementalLoad(job, singleTableInfo, HFileOutputFormat2.class);<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>  static void configureIncrementalLoad(Job job, List&lt;TableInfo&gt; multiTableInfo,<a name="line.577"></a>
-<span class="sourceLineNo">578</span>      Class&lt;? extends OutputFormat&lt;?, ?&gt;&gt; cls) throws IOException {<a name="line.578"></a>
-<span class="sourceLineNo">579</span>    Configuration conf = job.getConfiguration();<a name="line.579"></a>
-<span class="sourceLineNo">580</span>    job.setOutputKeyClass(ImmutableBytesWritable.class);<a name="line.580"></a>
-<span class="sourceLineNo">581</span>    job.setOutputValueClass(MapReduceExtendedCell.class);<a name="line.581"></a>
-<span class="sourceLineNo">582</span>    job.setOutputFormatClass(cls);<a name="line.582"></a>
-<span class="sourceLineNo">583</span><a name="line.583"></a>
-<span class="sourceLineNo">584</span>    if (multiTableInfo.stream().distinct().count() != multiTableInfo.size()) {<a name="line.584"></a>
-<span class="sourceLineNo">585</span>      throw new IllegalArgumentException("Duplicate entries found in TableInfo argument");<a name="line.585"></a>
-<span class="sourceLineNo">586</span>    }<a name="line.586"></a>
-<span class="sourceLineNo">587</span>    boolean writeMultipleTables = false;<a name="line.587"></a>
-<span class="sourceLineNo">588</span>    if (MultiTableHFileOutputFormat.class.equals(cls)) {<a name="line.588"></a>
-<span class="sourceLineNo">589</span>      writeMultipleTables = true;<a name="line.589"></a>
-<span class="sourceLineNo">590</span>      conf.setBoolean(MULTI_TABLE_HFILEOUTPUTFORMAT_CONF_KEY, true);<a name="line.590"></a>
-<span class="sourceLineNo">591</span>    }<a name="line.591"></a>
-<span class="sourceLineNo">592</span>    // Based on the configured map output class, set the correct reducer to properly<a name="line.592"></a>
-<span class="sourceLineNo">593</span>    // sort the incoming values.<a name="line.593"></a>
-<span class="sourceLineNo">594</span>    // TODO it would be nice to pick one or the other of these formats.<a name="line.594"></a>
-<span class="sourceLineNo">595</span>    if (KeyValue.class.equals(job.getMapOutputValueClass())<a name="line.595"></a>
-<span class="sourceLineNo">596</span>        || MapReduceExtendedCell.class.equals(job.getMapOutputValueClass())) {<a name="line.596"></a>
-<span class="sourceLineNo">597</span>      job.setReducerClass(CellSortReducer.class);<a name="line.597"></a>
-<span class="sourceLineNo">598</span>    } else if (Put.class.equals(job.getMapOutputValueClass())) {<a name="line.598"></a>
-<span class="sourceLineNo">599</span>      job.setReducerClass(PutSortReducer.class);<a name="line.599"></a>
-<span class="sourceLineNo">600</span>    } else if (Text.class.equals(job.getMapOutputValueClass())) {<a name="line.600"></a>
-<span class="sourceLineNo">601</span>      job.setReducerClass(TextSortReducer.class);<a name="line.601"></a>
-<span class="sourceLineNo">602</span>    } else {<a name="line.602"></a>
-<span class="sourceLineNo">603</span>      LOG.warn("Unknown map output value type:" + job.getMapOutputValueClass());<a name="line.603"></a>
-<span class="sourceLineNo">604</span>    }<a name="line.604"></a>
-<span class="sourceLineNo">605</span><a name="line.605"></a>
-<span class="sourceLineNo">606</span>    conf.setStrings("io.serializations", conf.get("io.serializations"),<a name="line.606"></a>
-<span class="sourceLineNo">607</span>        MutationSerialization.class.getName(), ResultSerialization.class.getName(),<a name="line.607"></a>
-<span class="sourceLineNo">608</span>        CellSerialization.class.getName());<a name="line.608"></a>
-<span class="sourceLineNo">609</span><a name="line.609"></a>
-<span class="sourceLineNo">610</span>    if (conf.getBoolean(LOCALITY_SENSITIVE_CONF_KEY, DEFAULT_LOCALITY_SENSITIVE)) {<a name="line.610"></a>
-<span class="sourceLineNo">611</span>      LOG.info("bulkload locality sensitive enabled");<a name="line.611"></a>
-<span class="sourceLineNo">612</span>    }<a name="line.612"></a>
-<span class="sourceLineNo">613</span><a name="line.613"></a>
-<span class="sourceLineNo">614</span>    /* Now get the region start keys for every table required */<a name="line.614"></a>
-<span class="sourceLineNo">615</span>    List&lt;String&gt; allTableNames = new ArrayList&lt;&gt;(multiTableInfo.size());<a name="line.615"></a>
-<span class="sourceLineNo">616</span>    List&lt;RegionLocator&gt; regionLocators = new ArrayList&lt;&gt;(multiTableInfo.size());<a name="line.616"></a>
-<span class="sourceLineNo">617</span>    List&lt;TableDescriptor&gt; tableDescriptors = new ArrayList&lt;&gt;(multiTableInfo.size());<a name="line.617"></a>
-<span class="sourceLineNo">618</span><a name="line.618"></a>
-<span class="sourceLineNo">619</span>    for(TableInfo tableInfo : multiTableInfo) {<a name="line.619"></a>
-<span class="sourceLineNo">620</span>      regionLocators.add(tableInfo.getRegionLocator());<a name="line.620"></a>
-<span class="sourceLineNo">621</span>      String tn = writeMultipleTables?<a name="line.621"></a>
-<span class="sourceLineNo">622</span>        tableInfo.getRegionLocator().getName().getNameWithNamespaceInclAsString():<a name="line.622"></a>
-<span class="sourceLineNo">623</span>        tableInfo.getRegionLocator().getName().getNameAsString();<a name="line.623"></a>
-<span class="sourceLineNo">624</span>      allTableNames.add(tn);<a name="line.624"></a>
-<span class="sourceLineNo">625</span>      tableDescriptors.add(tableInfo.getTableDescriptor());<a name="line.625"></a>
-<span class="sourceLineNo">626</span>    }<a name="line.626"></a>
-<span class="sourceLineNo">627</span>    // Record tablenames for creating writer by favored nodes, and decoding compression,<a name="line.627"></a>
-<span class="sourceLineNo">628</span>    // block size and other attributes of columnfamily per table<a name="line.628"></a>
-<span class="sourceLineNo">629</span>    conf.set(OUTPUT_TABLE_NAME_CONF_KEY, StringUtils.join(allTableNames, Bytes<a name="line.629"></a>
-<span class="sourceLineNo">630</span>            .toString(tableSeparator)));<a name="line.630"></a>
-<span class="sourceLineNo">631</span>    List&lt;ImmutableBytesWritable&gt; startKeys =<a name="line.631"></a>
-<span class="sourceLineNo">632</span>      getRegionStartKeys(regionLocators, writeMultipleTables);<a name="line.632"></a>
-<span class="sourceLineNo">633</span>    // Use table's region boundaries for TOP split points.<a name="line.633"></a>
-<span class="sourceLineNo">634</span>    LOG.info("Configuring " + startKeys.size() + " reduce partitions " +<a name="line.634"></a>
-<span class="sourceLineNo">635</span>        "to match current region count for all tables");<a name="line.635"></a>
-<span class="sourceLineNo">636</span>    job.setNumReduceTasks(startKeys.size());<a name="line.636"></a>
-<span class="sourceLineNo">637</span><a name="line.637"></a>
-<span class="sourceLineNo">638</span>    configurePartitioner(job, startKeys, writeMultipleTables);<a name="line.638"></a>
-<span class="sourceLineNo">639</span>    // Set compression algorithms based on column families<a name="line.639"></a>
-<span class="sourceLineNo">640</span><a name="line.640"></a>
-<span class="sourceLineNo">641</span>    conf.set(COMPRESSION_FAMILIES_CONF_KEY, serializeColumnFamilyAttribute(compressionDetails,<a name="line.641"></a>
-<span class="sourceLineNo">642</span>            tableDescriptors));<a name="line.642"></a>
-<span class="sourceLineNo">643</span>    conf.set(BLOCK_SIZE_FAMILIES_CONF_KEY, serializeColumnFamilyAttribute(blockSizeDetails,<a name="line.643"></a>
+<span class="sourceLineNo">422</span>          w.appendFileInfo(BULKLOAD_TIME_KEY,<a name="line.422"></a>
+<span class="sourceLineNo">423</span>            Bytes.toBytes(EnvironmentEdgeManager.currentTime()));<a name="line.423"></a>
+<span class="sourceLineNo">424</span>          w.appendFileInfo(BULKLOAD_TASK_KEY,<a name="line.424"></a>
+<span class="sourceLineNo">425</span>            Bytes.toBytes(context.getTaskAttemptID().toString()));<a name="line.425"></a>
+<span class="sourceLineNo">426</span>          w.appendFileInfo(MAJOR_COMPACTION_KEY, Bytes.toBytes(true));<a name="line.426"></a>
+<span class="sourceLineNo">427</span>          w.appendFileInfo(EXCLUDE_FROM_MINOR_COMPACTION_KEY, Bytes.toBytes(compactionExclude));<a name="line.427"></a>
+<span class="sourceLineNo">428</span>          w.appendTrackedTimestampsToMetadata();<a name="line.428"></a>
+<span class="sourceLineNo">429</span>          w.close();<a name="line.429"></a>
+<span class="sourceLineNo">430</span>        }<a name="line.430"></a>
+<span class="sourceLineNo">431</span>      }<a name="line.431"></a>
+<span class="sourceLineNo">432</span><a name="line.432"></a>
+<span class="sourceLineNo">433</span>      @Override<a name="line.433"></a>
+<span class="sourceLineNo">434</span>      public void close(TaskAttemptContext c) throws IOException, InterruptedException {<a name="line.434"></a>
+<span class="sourceLineNo">435</span>        for (WriterLength wl: this.writers.values()) {<a name="line.435"></a>
+<span class="sourceLineNo">436</span>          close(wl.writer);<a name="line.436"></a>
+<span class="sourceLineNo">437</span>        }<a name="line.437"></a>
+<span class="sourceLineNo">438</span>      }<a name="line.438"></a>
+<span class="sourceLineNo">439</span>    };<a name="line.439"></a>
+<span class="sourceLineNo">440</span>  }<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>   * Configure block storage policy for CF after the directory is created.<a name="line.443"></a>
+<span class="sourceLineNo">444</span>   */<a name="line.444"></a>
+<span class="sourceLineNo">445</span>  static void configureStoragePolicy(final Configuration conf, final FileSystem fs,<a name="line.445"></a>
+<span class="sourceLineNo">446</span>      byte[] tableAndFamily, Path cfPath) {<a name="line.446"></a>
+<span class="sourceLineNo">447</span>    if (null == conf || null == fs || null == tableAndFamily || null == cfPath) {<a name="line.447"></a>
+<span class="sourceLineNo">448</span>      return;<a name="line.448"></a>
+<span class="sourceLineNo">449</span>    }<a name="line.449"></a>
+<span class="sourceLineNo">450</span><a name="line.450"></a>
+<span class="sourceLineNo">451</span>    String policy =<a name="line.451"></a>
+<span class="sourceLineNo">452</span>        conf.get(STORAGE_POLICY_PROPERTY_CF_PREFIX + Bytes.toString(tableAndFamily),<a name="line.452"></a>
+<span class="sourceLineNo">453</span>          conf.get(STORAGE_POLICY_PROPERTY));<a name="line.453"></a>
+<span class="sourceLineNo">454</span>    CommonFSUtils.setStoragePolicy(fs, cfPath, policy);<a name="line.454"></a>
+<span class="sourceLineNo">455</span>  }<a name="line.455"></a>
+<span class="sourceLineNo">456</span><a name="line.456"></a>
+<span class="sourceLineNo">457</span>  /*<a name="line.457"></a>
+<span class="sourceLineNo">458</span>   * Data structure to hold a Writer and amount of data written on it.<a name="line.458"></a>
+<span class="sourceLineNo">459</span>   */<a name="line.459"></a>
+<span class="sourceLineNo">460</span>  static class WriterLength {<a name="line.460"></a>
+<span class="sourceLineNo">461</span>    long written = 0;<a name="line.461"></a>
+<span class="sourceLineNo">462</span>    StoreFileWriter writer = null;<a name="line.462"></a>
+<span class="sourceLineNo">463</span>  }<a name="line.463"></a>
+<span class="sourceLineNo">464</span><a name="line.464"></a>
+<span class="sourceLineNo">465</span>  /**<a name="line.465"></a>
+<span class="sourceLineNo">466</span>   * Return the start keys of all of the regions in this table,<a name="line.466"></a>
+<span class="sourceLineNo">467</span>   * as a list of ImmutableBytesWritable.<a name="line.467"></a>
+<span class="sourceLineNo">468</span>   */<a name="line.468"></a>
+<span class="sourceLineNo">469</span>  private static List&lt;ImmutableBytesWritable&gt; getRegionStartKeys(List&lt;RegionLocator&gt; regionLocators,<a name="line.469"></a>
+<span class="sourceLineNo">470</span>                                                                 boolean writeMultipleTables)<a name="line.470"></a>
+<span class="sourceLineNo">471</span>          throws IOException {<a name="line.471"></a>
+<span class="sourceLineNo">472</span><a name="line.472"></a>
+<span class="sourceLineNo">473</span>    ArrayList&lt;ImmutableBytesWritable&gt; ret = new ArrayList&lt;&gt;();<a name="line.473"></a>
+<span class="sourceLineNo">474</span>    for(RegionLocator regionLocator : regionLocators) {<a name="line.474"></a>
+<span class="sourceLineNo">475</span>      TableName tableName = regionLocator.getName();<a name="line.475"></a>
+<span class="sourceLineNo">476</span>      LOG.info("Looking up current regions for table " + tableName);<a name="line.476"></a>
+<span class="sourceLineNo">477</span>      byte[][] byteKeys = regionLocator.getStartKeys();<a name="line.477"></a>
+<span class="sourceLineNo">478</span>      for (byte[] byteKey : byteKeys) {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>        byte[] fullKey = byteKey; //HFileOutputFormat2 use case<a name="line.479"></a>
+<span class="sourceLineNo">480</span>        if (writeMultipleTables) {<a name="line.480"></a>
+<span class="sourceLineNo">481</span>          //MultiTableHFileOutputFormat use case<a name="line.481"></a>
+<span class="sourceLineNo">482</span>          fullKey = combineTableNameSuffix(tableName.getName(), byteKey);<a name="line.482"></a>
+<span class="sourceLineNo">483</span>        }<a name="line.483"></a>
+<span class="sourceLineNo">484</span>        if (LOG.isDebugEnabled()) {<a name="line.484"></a>
+<span class="sourceLineNo">485</span>          LOG.debug("SplitPoint startkey for " + tableName + ": " + Bytes.toStringBinary(fullKey));<a name="line.485"></a>
+<span class="sourceLineNo">486</span>        }<a name="line.486"></a>
+<span class="sourceLineNo">487</span>        ret.add(new ImmutableBytesWritable(fullKey));<a name="line.487"></a>
+<span class="sourceLineNo">488</span>      }<a name="line.488"></a>
+<span class="sourceLineNo">489</span>    }<a name="line.489"></a>
+<span class="sourceLineNo">490</span>    return ret;<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>  /**<a name="line.493"></a>
+<span class="sourceLineNo">494</span>   * Write out a {@link SequenceFile} that can be read by<a name="line.494"></a>
+<span class="sourceLineNo">495</span>   * {@link TotalOrderPartitioner} that contains the split points in startKeys.<a name="line.495"></a>
+<span class="sourceLineNo">496</span>   */<a name="line.496"></a>
+<span class="sourceLineNo">497</span>  @SuppressWarnings("deprecation")<a name="line.497"></a>
+<span class="sourceLineNo">498</span>  private static void writePartitions(Configuration conf, Path partitionsPath,<a name="line.498"></a>
+<span class="sourceLineNo">499</span>      List&lt;ImmutableBytesWritable&gt; startKeys, boolean writeMultipleTables) throws IOException {<a name="line.499"></a>
+<span class="sourceLineNo">500</span>    LOG.info("Writing partition information to " + partitionsPath);<a name="line.500"></a>
+<span class="sourceLineNo">501</span>    if (startKeys.isEmpty()) {<a name="line.501"></a>
+<span class="sourceLineNo">502</span>      throw new IllegalArgumentException("No regions passed");<a name="line.502"></a>
+<span class="sourceLineNo">503</span>    }<a name="line.503"></a>
+<span class="sourceLineNo">504</span><a name="line.504"></a>
+<span class="sourceLineNo">505</span>    // We're generating a list of split points, and we don't ever<a name="line.505"></a>
+<span class="sourceLineNo">506</span>    // have keys &lt; the first region (which has an empty start key)<a name="line.506"></a>
+<span class="sourceLineNo">507</span>    // so we need to remove it. Otherwise we would end up with an<a name="line.507"></a>
+<span class="sourceLineNo">508</span>    // empty reducer with index 0<a name="line.508"></a>
+<span class="sourceLineNo">509</span>    TreeSet&lt;ImmutableBytesWritable&gt; sorted = new TreeSet&lt;&gt;(startKeys);<a name="line.509"></a>
+<span class="sourceLineNo">510</span>    ImmutableBytesWritable first = sorted.first();<a name="line.510"></a>
+<span class="sourceLineNo">511</span>    if (writeMultipleTables) {<a name="line.511"></a>
+<span class="sourceLineNo">512</span>      first =<a name="line.512"></a>
+<span class="sourceLineNo">513</span>        new ImmutableBytesWritable(MultiTableHFileOutputFormat.getSuffix(sorted.first().get()));<a name="line.513"></a>
+<span class="sourceLineNo">514</span>    }<a name="line.514"></a>
+<span class="sourceLineNo">515</span>    if (!first.equals(HConstants.EMPTY_BYTE_ARRAY)) {<a name="line.515"></a>
+<span class="sourceLineNo">516</span>      throw new IllegalArgumentException(<a name="line.516"></a>
+<span class="sourceLineNo">517</span>          "First region of table should have empty start key. Instead has: "<a name="line.517"></a>
+<span class="sourceLineNo">518</span>          + Bytes.toStringBinary(first.get()));<a name="line.518"></a>
+<span class="sourceLineNo">519</span>    }<a name="line.519"></a>
+<span class="sourceLineNo">520</span>    sorted.remove(sorted.first());<a name="line.520"></a>
+<span class="sourceLineNo">521</span><a name="line.521"></a>
+<span class="sourceLineNo">522</span>    // Write the actual file<a name="line.522"></a>
+<span class="sourceLineNo">523</span>    FileSystem fs = partitionsPath.getFileSystem(conf);<a name="line.523"></a>
+<span class="sourceLineNo">524</span>    SequenceFile.Writer writer = SequenceFile.createWriter(<a name="line.524"></a>
+<span class="sourceLineNo">525</span>      fs, conf, partitionsPath, ImmutableBytesWritable.class,<a name="line.525"></a>
+<span class="sourceLineNo">526</span>      NullWritable.class);<a name="line.526"></a>
+<span class="sourceLineNo">527</span><a name="line.527"></a>
+<span class="sourceLineNo">528</span>    try {<a name="line.528"></a>
+<span class="sourceLineNo">529</span>      for (ImmutableBytesWritable startKey : sorted) {<a name="line.529"></a>
+<span class="sourceLineNo">530</span>        writer.append(startKey, NullWritable.get());<a name="line.530"></a>
+<span class="sourceLineNo">531</span>      }<a name="line.531"></a>
+<span class="sourceLineNo">532</span>    } finally {<a name="line.532"></a>
+<span class="sourceLineNo">533</span>      writer.close();<a name="line.533"></a>
+<span class="sourceLineNo">534</span>    }<a name="line.534"></a>
+<span class="sourceLineNo">535</span>  }<a name="line.535"></a>
+<span class="sourceLineNo">536</span><a name="line.536"></a>
+<span class="sourceLineNo">537</span>  /**<a name="line.537"></a>
+<span class="sourceLineNo">538</span>   * Configure a MapReduce Job to perform an incremental load into the given<a name="line.538"></a>
+<span class="sourceLineNo">539</span>   * table. This<a name="line.539"></a>
+<span class="sourceLineNo">540</span>   * &lt;ul&gt;<a name="line.540"></a>
+<span class="sourceLineNo">541</span>   *   &lt;li&gt;Inspects the table to configure a total order partitioner&lt;/li&gt;<a name="line.541"></a>
+<span class="sourceLineNo">542</span>   *   &lt;li&gt;Uploads the partitions file to the cluster and adds it to the DistributedCache&lt;/li&gt;<a name="line.542"></a>
+<span class="sourceLineNo">543</span>   *   &lt;li&gt;Sets the number of reduce tasks to match the current number of regions&lt;/li&gt;<a name="line.543"></a>
+<span class="sourceLineNo">544</span>   *   &lt;li&gt;Sets the output key/value class to match HFileOutputFormat2's requirements&lt;/li&gt;<a name="line.544"></a>
+<span class="sourceLineNo">545</span>   *   &lt;li&gt;Sets the reducer up to perform the appropriate sorting (either KeyValueSortReducer or<a name="line.545"></a>
+<span class="sourceLineNo">546</span>   *     PutSortReducer)&lt;/li&gt;<a name="line.546"></a>
+<span class="sourceLineNo">547</span>   *   &lt;li&gt;Sets the HBase cluster key to load region locations for locality-sensitive&lt;/li&gt;<a name="line.547"></a>
+<span class="sourceLineNo">548</span>   * &lt;/ul&gt;<a name="line.548"></a>
+<span class="sourceLineNo">549</span>   * The user should be sure to set the map output value class to either KeyValue or Put before<a name="line.549"></a>
+<span class="sourceLineNo">550</span>   * running this function.<a name="line.550"></a>
+<span class="sourceLineNo">551</span>   */<a name="line.551"></a>
+<span class="sourceLineNo">552</span>  public static void configureIncrementalLoad(Job job, Table table, RegionLocator regionLocator)<a name="line.552"></a>
+<span class="sourceLineNo">553</span>      throws IOException {<a name="line.553"></a>
+<span class="sourceLineNo">554</span>    configureIncrementalLoad(job, table.getDescriptor(), regionLocator);<a name="line.554"></a>
+<span class="sourceLineNo">555</span>    configureRemoteCluster(job, table.getConfiguration());<a name="line.555"></a>
+<span class="sourceLineNo">556</span>  }<a name="line.556"></a>
+<span class="sourceLineNo">557</span><a name="line.557"></a>
+<span class="sourceLineNo">558</span>  /**<a name="line.558"></a>
+<span class="sourceLineNo">559</span>   * Configure a MapReduce Job to perform an incremental load into the given<a name="line.559"></a>
+<span class="sourceLineNo">560</span>   * table. This<a name="line.560"></a>
+<span class="sourceLineNo">561</span>   * &lt;ul&gt;<a name="line.561"></a>
+<span class="sourceLineNo">562</span>   *   &lt;li&gt;Inspects the table to configure a total order partitioner&lt;/li&gt;<a name="line.562"></a>
+<span class="sourceLineNo">563</span>   *   &lt;li&gt;Uploads the partitions file to the cluster and adds it to the DistributedCache&lt;/li&gt;<a name="line.563"></a>
+<span class="sourceLineNo">564</span>   *   &lt;li&gt;Sets the number of reduce tasks to match the current number of regions&lt;/li&gt;<a name="line.564"></a>
+<span class="sourceLineNo">565</span>   *   &lt;li&gt;Sets the output key/value class to match HFileOutputFormat2's requirements&lt;/li&gt;<a name="line.565"></a>
+<span class="sourceLineNo">566</span>   *   &lt;li&gt;Sets the reducer up to perform the appropriate sorting (either KeyValueSortReducer or<a name="line.566"></a>
+<span class="sourceLineNo">567</span>   *     PutSortReducer)&lt;/li&gt;<a name="line.567"></a>
+<span class="sourceLineNo">568</span>   * &lt;/ul&gt;<a name="line.568"></a>
+<span class="sourceLineNo">569</span>   * The user should be sure to set the map output value class to either KeyValue or Put before<a name="line.569"></a>
+<span class="sourceLineNo">570</span>   * running this function.<a name="line.570"></a>
+<span class="sourceLineNo">571</span>   */<a name="line.571"></a>
+<span class="sourceLineNo">572</span>  public static void configureIncrementalLoad(Job job, TableDescriptor tableDescriptor,<a name="line.572"></a>
+<span class="sourceLineNo">573</span>      RegionLocator regionLocator) throws IOException {<a name="line.573"></a>
+<span class="sourceLineNo">574</span>    ArrayList&lt;TableInfo&gt; singleTableInfo = new ArrayList&lt;&gt;();<a name="line.574"></a>
+<span class="sourceLineNo">575</span>    singleTableInfo.add(new TableInfo(tableDescriptor, regionLocator));<a name="line.575"></a>
+<span class="sourceLineNo">576</span>    configureIncrementalLoad(job, singleTableInfo, HFileOutputFormat2.class);<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>
+<span class="sourceLineNo">579</span>  static void configureIncrementalLoad(Job job, List&lt;TableInfo&gt; multiTableInfo,<a name="line.579"></a>
+<span class="sourceLineNo">580</span>      Class&lt;? extends OutputFormat&lt;?, ?&gt;&gt; cls) throws IOException {<a name="line.580"></a>
+<span class="sourceLineNo">581</span>    Configuration conf = job.getConfiguration();<a name="line.581"></a>
+<span class="sourceLineNo">582</span>    job.setOutputKeyClass(ImmutableBytesWritable.class);<a name="line.582"></a>
+<span class="sourceLineNo">583</span>    job.setOutputValueClass(MapReduceExtendedCell.class);<a name="line.583"></a>
+<span class="sourceLineNo">584</span>    job.setOutputFormatClass(cls);<a name="line.584"></a>
+<span class="sourceLineNo">585</span><a name="line.585"></a>
+<span class="sourceLineNo">586</span>    if (multiTableInfo.stream().distinct().count() != multiTableInfo.size()) {<a name="line.586"></a>
+<span class="sourceLineNo">587</span>      throw new IllegalArgumentException("Duplicate entries found in TableInfo argument");<a name="line.587"></a>
+<span class="sourceLineNo">588</span>    }<a name="line.588"></a>
+<span class="sourceLineNo">589</span>    boolean writeMultipleTables = false;<a name="line.589"></a>
+<span class="sourceLineNo">590</span>    if (MultiTableHFileOutputFormat.class.equals(cls)) {<a name="line.590"></a>
+<span class="sourceLineNo">591</span>      writeMultipleTables = true;<a name="line.591"></a>
+<span class="sourceLineNo">592</span>      conf.setBoolean(MULTI_TABLE_HFILEOUTPUTFORMAT_CONF_KEY, true);<a name="line.592"></a>
+<span class="sourceLineNo">593</span>    }<a name="line.593"></a>
+<span class="sourceLineNo">594</span>    // Based on the configured map output class, set the correct reducer to properly<a name="line.594"></a>
+<span class="sourceLineNo">595</span>    // sort the incoming values.<a name="line.595"></a>
+<span class="sourceLineNo">596</span>    // TODO it would be nice to pick one or the other of these formats.<a name="line.596"></a>
+<span class="sourceLineNo">597</span>    if (KeyValue.class.equals(job.getMapOutputValueClass())<a name="line.597"></a>
+<span class="sourceLineNo">598</span>        || MapReduceExtendedCell.class.equals(job.getMapOutputValueClass())) {<a name="line.598"></a>
+<span class="sourceLineNo">599</span>      job.setReducerClass(CellSortReducer.class);<a name="line.599"></a>
+<span class="sourceLineNo">600</span>    } else if (Put.class.equals(job.getMapOutputValueClass())) {<a name="line.600"></a>
+<span class="sourceLineNo">601</span>      job.setReducerClass(PutSortReducer.class);<a name="line.601"></a>
+<span class="sourceLineNo">602</span>    } else if (Text.class.equals(job.getMapOutputValueClass())) {<a name="line.602"></a>
+<span class="sourceLineNo">603</span>      job.setReducerClass(TextSortReducer.class);<a name="line.603"></a>
+<span class="sourceLineNo">604</span>    } else {<a name="line.604"></a>
+<span class="sourceLineNo">605</span>      LOG.warn("Unknown map output value type:" + job.getMapOutputValueClass());<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">608</span>    conf.setStrings("io.serializations", conf.get("io.serializations"),<a name="line.608"></a>
+<span class="sourceLineNo">609</span>        MutationSerialization.class.getName(), ResultSerialization.class.getName(),<a name="line.609"></a>
+<span class="sourceLineNo">610</span>        CellSerialization.class.getName());<a name="line.610"></a>
+<span class="sourceLineNo">611</span><a name="line.611"></a>
+<span class="sourceLineNo">612</span>    if (conf.getBoolean(LOCALITY_SENSITIVE_CONF_KEY, DEFAULT_LOCALITY_SENSITIVE)) {<a name="line.612"></a>
+<span class="sourceLineNo">613</span>      LOG.info("bulkload locality sensitive enabled");<a name="line.613"></a>
+<span class="sourceLineNo">614</span>    }<a name="line.614"></a>
+<span class="sourceLineNo">615</span><a name="line.615"></a>
+<span class="sourceLineNo">616</span>    /* Now get the region start keys for every table required */<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    List&lt;String&gt; allTableNames = new ArrayList&lt;&gt;(multiTableInfo.size());<a name="line.617"></a>
+<span class="sourceLineNo">618</span>    List&lt;RegionLocator&gt; regionLocators = new ArrayList&lt;&gt;(multiTableInfo.size());<a name="line.618"></a>
+<span class="sourceLineNo">619</span>    List&lt;TableDescriptor&gt; tableDescriptors = new ArrayList&lt;&gt;(multiTableInfo.size());<a name="line.619"></a>
+<span class="sourceLineNo">620</span><a name="line.620"></a>
+<span class="sourceLineNo">621</span>    for(TableInfo tableInfo : multiTableInfo) {<a name="line.621"></a>
+<span class="sourceLineNo">622</span>      regionLocators.add(tableInfo.getRegionLocator());<a name="line.622"></a>
+<span class="sourceLineNo">623</span>      String tn = writeMultipleTables?<a name="line.623"></a>
+<span class="sourceLineNo">624</span>        tableInfo.getRegionLocator().getName().getNameWithNamespaceInclAsString():<a name="line.624"></a>
+<span class="sourceLineNo">625</span>        tableInfo.getRegionLocator().getName().getNameAsString();<a name="line.625"></a>
+<span class="sourceLineNo">626</span>      allTableNames.add(tn);<a name="line.626"></a>
+<span class="sourceLineNo">627</span>      tableDescriptors.add(tableInfo.getTableDescriptor());<a name="line.627"></a>
+<span class="sourceLineNo">628</span>    }<a name="line.628"></a>
+<span class="sourceLineNo">629</span>    // Record tablenames for creating writer by favored nodes, and decoding compression,<a name="line.629"></a>
+<span class="sourceLineNo">630</span>    // block size and other attributes of columnfamily per table<a name="line.630"></a>
+<span class="sourceLineNo">631</span>    conf.set(OUTPUT_TABLE_NAME_CONF_KEY, StringUtils.join(allTableNames, Bytes<a name="line.631"></a>
+<span class="sourceLineNo">632</span>            .toString(tableSeparator)));<a name="line.632"></a>
+<span class="sourceLineNo">633</span>    List&lt;ImmutableBytesWritable&gt; startKeys =<a name="line.633"></a>
+<span class="sourceLineNo">634</span>      getRegionStartKeys(regionLocators, writeMultipleTables);<a name="line.634"></a>
+<span class="sourceLineNo">635</span>    // Use table's region boundaries for TOP split points.<a name="line.635"></a>
+<span class="sourceLineNo">636</span>    LOG.info("Configuring " + startKeys.size() + " reduce partitions " +<a name="line.636"></a>
+<span class="sourceLineNo">637</span>        "to match current region count for all tables");<a name="line.637"></a>
+<span class="sourceLineNo">638</span>    job.setNumReduceTasks(startKeys.size());<a name="line.638"></a>
+<span class="sourceLineNo">639</span><a name="line.639"></a>
+<span class="sourceLineNo">640</span>    configurePartitioner(job, startKeys, writeMultipleTables);<a name="line.640"></a>
+<span class="sourceLineNo">641</span>    // Set compression algorithms based on column families<a name="line.641"></a>
+<span class="sourceLineNo">642</span><a name="line.642"></a>
+<span class="sourceLineNo">643</span>    conf.set(COMPRESSION_FAMILIES_CONF_KEY, serializeColumnFamilyAttribute(compressionDetails,<a name="line.643"></a>
 <span class="sourceLineNo">644</span>            tableDescriptors));<a name="line.644"></a>
-<span class="sourceLineNo">645</span>    conf.set(BLOOM_TYPE_FAMILIES_CONF_KEY, serializeColumnFamilyAttribute(bloomTypeDetails,<a name="line.645"></a>
+<span class="sourceLineNo">645</span>    conf.set(BLOCK_SIZE_FAMILIES_CONF_KEY, serializeColumnFamilyAttribute(blockSizeDetails,<a name="line.645"></a>
 <span class="sourceLineNo">646</span>            tableDescriptors));<a name="line.646"></a>
-<span class="sourceLineNo">647</span>    conf.set(BLOOM_PARAM_FAMILIES_CONF_KEY, serializeColumnFamilyAttribute(bloomParamDetails,<a name="line.647"></a>
-<span class="sourceLineNo">648</span>        tableDescriptors));<a name="line.648"></a>
-<span class="sourceLineNo">649</span>    conf.set(DATABLOCK_ENCODING_FAMILIES_CONF_KEY,<a name="line.649"></a>
-<span class="sourceLineNo">650</span>            serializeColumnFamilyAttribute(dataBlockEncodingDetails, tableDescriptors));<a name="line.650"></a>
-<span class="sourceLineNo">651</span><a name="line.651"></a>
-<span class="sourceLineNo">652</span>    TableMapReduceUtil.addDependencyJars(job);<a name="line.652"></a>
-<span class="sourceLineNo">653</span>    TableMapReduceUtil.initCredentials(job);<a name="line.653"></a>
-<span class="sourceLineNo">654</span>    LOG.info("Incremental output configured for tables: " + StringUtils.join(allTableNames, ","));<a name="line.654"></a>
-<span class="sourceLineNo">655</span>  }<a name="line.655"></a>
-<span class="sourceLineNo">656</span><a name="line.656"></a>
-<span class="sourceLineNo">657</span>  public static void configureIncrementalLoadMap(Job job, TableDescriptor tableDescriptor) throws<a name="line.657"></a>
-<span class="sourceLineNo">658</span>      IOException {<a name="line.658"></a>
-<span class="sourceLineNo">659</span>    Configuration conf = job.getConfiguration();<a name="line.659"></a>
-<span class="sourceLineNo">660</span><a name="line.660"></a>
-<span class="sourceLineNo">661</span>    job.setOutputKeyClass(ImmutableBytesWritable.class);<a name="line.661"></a>
-<span class="sourceLineNo">662</span>    job.setOutputValueClass(MapReduceExtendedCell.class);<a name="line.662"></a>
-<span class="sourceLineNo">663</span>    job.setOutputFormatClass(HFileOutputFormat2.class);<a name="line.663"></a>
-<span class="sourceLineNo">664</span><a name="line.664"></a>
-<span class="sourceLineNo">665</span>    ArrayList&lt;TableDescriptor&gt; singleTableDescriptor = new ArrayList&lt;&gt;(1);<a name="line.665"></a>
-<span class="sourceLineNo">666</span>    singleTableDescriptor.add(tableDescriptor);<a name="line.666"></a>
-<span class="sourceLineNo">667</span><a name="line.667"></a>
-<span class="sourceLineNo">668</span>    conf.set(OUTPUT_TABLE_NAME_CONF_KEY, tableDescriptor.getTableName().getNameAsString());<a name="line.668"></a>
-<span class="sourceLineNo">669</span>    // Set compression algorithms based on column families<a name="line.669"></a>
-<span class="sourceLineNo">670</span>    conf.set(COMPRESSION_FAMILIES_CONF_KEY,<a name="line.670"></a>
-<span class="sourceLineNo">671</span>        serializeColumnFamilyAttribute(compressionDetails, singleTableDescriptor));<a name="line.671"></a>
-<span class="sourceLineNo">672</span>    conf.set(BLOCK_SIZE_FAMILIES_CONF_KEY,<a name="line.672"></a>
-<span class="sourceLineNo">673</span>        serializeColumnFamilyAttribute(blockSizeDetails, singleTableDescriptor));<a name="line.673"></a>
-<span class="sourceLineNo">674</span>    conf.set(BLOOM_TYPE_FAMILIES_CONF_KEY,<a name="line.674"></a>
-<span class="sourceLineNo">675</span>        serializeColumnFamilyAttribute(bloomTypeDetails, singleTableDescriptor));<a name="line.675"></a>
-<span class="sourceLineNo">676</span>    conf.set(BLOOM_PARAM_FAMILIES_CONF_KEY,<a name="line.676"></a>
-<span class="sourceLineNo">677</span>        serializeColumnFamilyAttribute(bloomParamDetails, singleTableDescriptor));<a name="line.677"></a>
-<span class="sourceLineNo">678</span>    conf.set(DATABLOCK_ENCODING_FAMILIES_CONF_KEY,<a name="line.678"></a>
-<span class="sourceLineNo">679</span>        serializeColumnFamilyAttribute(dataBlockEncodingDetails, singleTableDescriptor));<a name="line.679"></a>
-<span class="sourceLineNo">680</span><a name="line.680"></a>
-<span class="sourceLineNo">681</span>    TableMapReduceUtil.addDependencyJars(job);<a name="line.681"></a>
-<span class="sourceLineNo">682</span>    TableMapReduceUtil.initCredentials(job);<a name="line.682"></a>
-<span class="sourceLineNo">683</span>    LOG.info("Incremental table " + tableDescriptor.getTableName() + " output configured.");<a name="line.683"></a>
-<span class="sourceLineNo">684</span>  }<a name="line.684"></a>
-<span class="sourceLineNo">685</span><a name="line.685"></a>
-<span class="sourceLineNo">686</span>  /**<a name="line.686"></a>
-<span class="sourceLineNo">687</span>   * Configure HBase cluster key for remote cluster to load region location for locality-sensitive<a name="line.687"></a>
-<span class="sourceLineNo">688</span>   * if it's enabled.<a name="line.688"></a>
-<span class="sourceLineNo">689</span>   * It's not necessary to call this method explicitly when the cluster key for HBase cluster to be<a name="line.689"></a>
-<span class="sourceLineNo">690</span>   * used to load region location is configured in the job configuration.<a name="line.690"></a>
-<span class="sourceLineNo">691</span>   * Call this method when another HBase cluster key is configured in the job configuration.<a name="line.691"></a>
-<span class="sourceLineNo">692</span>   * For example, you should call when you load data from HBase cluster A using<a name="line.692"></a>
-<span class="sourceLineNo">693</span>   * {@link TableInputFormat} and generate hfiles for HBase cluster B.<a name="line.693"></a>
-<span class="sourceLineNo">694</span>   * Otherwise, HFileOutputFormat2 fetch location from cluster A and locality-sensitive won't<a name="line.694"></a>
-<span class="sourceLineNo">695</span>   * working correctly.<a name="line.695"></a>
-<span class="sourceLineNo">696</span>   * {@link #configureIncrementalLoad(Job, Table, RegionLocator)} calls this method using<a name="line.696"></a>
-<span class="sourceLineNo">697</span>   * {@link Table#getConfiguration} as clusterConf.<a name="line.697"></a>
-<span class="sourceLineNo">698</span>   * See HBASE-25608.<a name="line.698"></a>
-<span class="sourceLineNo">699</span>   *<a name="line.699"></a>
-<span class="sourceLineNo">700</span>   * @param job which has configuration to be updated<a name="line.700"></a>
-<span class="sourceLineNo">701</span>   * @param clusterConf which contains cluster key of the HBase cluster to be locality-sensitive<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   *<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   * @see #configureIncrementalLoad(Job, Table, RegionLocator)<a name="line.703"></a>
-<span class="sourceLineNo">704</span>   * @see #LOCALITY_SENSITIVE_CONF_KEY<a name="line.704"></a>
-<span class="sourceLineNo">705</span>   * @see #REMOTE_CLUSTER_ZOOKEEPER_QUORUM_CONF_KEY<a name="line.705"></a>
-<span class="sourceLineNo">706</span>   * @see #REMOTE_CLUSTER_ZOOKEEPER_CLIENT_PORT_CONF_KEY<a name="line.706"></a>
-<span class="sourceLineNo">707</span>   * @see #REMOTE_CLUSTER_ZOOKEEPER_ZNODE_PARENT_CONF_KEY<a name="line.707"></a>
-<span class="sourceLineNo">708</span>   */<a name="line.708"></a>
-<span class="sourceLineNo">709</span>  public static void configureRemoteCluster(Job job, Configuration clusterConf) {<a name="line.709"></a>
-<span class="sourceLineNo">710</span>    Configuration conf = job.getConfiguration();<a name="line.710"></a>
-<span class="sourceLineNo">711</span><a name="line.711"></a>
-<span class="sourceLineNo">712</span>    if (!conf.getBoolean(LOCALITY_SENSITIVE_CONF_KEY, DEFAULT_LOCALITY_SENSITIVE)) {<a name="line.712"></a>
-<span class="sourceLineNo">713</span>      return;<a name="line.713"></a>
-<span class="sourceLineNo">714</span>    }<a name="line.714"></a>
-<span class="sourceLineNo">715</span><a name="line.715"></a>
-<span class="sourceLineNo">716</span>    final String quorum = clusterConf.get(HConstants.ZOOKEEPER_QUORUM);<a name="line.716"></a>
-<span class="sourceLineNo">717</span>    final int clientPort = clusterConf.getInt(<a name="line.717"></a>
-<span class="sourceLineNo">718</span>      HConstants.ZOOKEEPER_CLIENT_PORT, HConstants.DEFAULT_ZOOKEEPER_CLIENT_PORT);<a name="line.718"></a>
-<span class="sourceLineNo">719</span>    final String parent = clusterConf.get(<a name="line.719"></a>
-<span class="sourceLineNo">720</span>      HConstants.ZOOKEEPER_ZNODE_PARENT, HConstants.DEFAULT_ZOOKEEPER_ZNODE_PARENT);<a name="line.720"></a>
-<span class="sourceLineNo">721</span><a name="line.721"></a>
-<span class="sourceLineNo">722</span>    conf.set(REMOTE_CLUSTER_ZOOKEEPER_QUORUM_CONF_KEY, quorum);<a name="line.722"></a>
-<span class="sourceLineNo">723</span>    conf.setInt(REMOTE_CLUSTER_ZOOKEEPER_CLIENT_PORT_CONF_KEY, clientPort);<a name="line.723"></a>
-<span class="sourceLineNo">724</span>    conf.set(REMOTE_CLUSTER_ZOOKEEPER_ZNODE_PARENT_CONF_KEY, parent);<a name="line.724"></a>
-<span class="sourceLineNo">725</span><a name="line.725"></a>
-<span class="sourceLineNo">726</span>    LOG.info("ZK configs for remote cluster of bulkload is configured: " +<a name="line.726"></a>
-<span class="sourceLineNo">727</span>      quorum + ":" + clientPort + "/" + parent);<a name="line.727"></a>
-<span class="sourceLineNo">728</span>  }<a name="line.728"></a>
-<span class="sourceLineNo">729</span><a name="line.729"></a>
-<span class="sourceLineNo">730</span>  /**<a name="line.730"></a>
-<span class="sourceLineNo">731</span>   * Runs inside the task to deserialize column family to compression algorithm<a name="line.731"></a>
-<span class="sourceLineNo">732</span>   * map from the configuration.<a name="line.732"></a>
-<span class="sourceLineNo">733</span>   *<a name="line.733"></a>
-<span class="sourceLineNo">734</span>   * @param conf to read the serialized values from<a name="line.734"></a>
-<span class="sourceLineNo">735</span>   * @return a map from column family to the configured compression algorithm<a name="line.735"></a>
-<span class="sourceLineNo">736</span>   */<a name="line.736"></a>
-<span class="sourceLineNo">737</span>  @InterfaceAudience.Private<a name="line.737"></a>
-<span class="sourceLineNo">738</span>  static Map&lt;byte[], Algorithm&gt; createFamilyCompressionMap(Configuration<a name="line.738"></a>
-<span class="sourceLineNo">739</span>      conf) {<a name="line.739"></a>
-<span class="sourceLineNo">740</span>    Map&lt;byte[], String&gt; stringMap = createFamilyConfValueMap(conf,<a name="line.740"></a>
-<span class="sourceLineNo">741</span>        COMPRESSION_FAMILIES_CONF_KEY);<a name="line.741"></a>
-<span class="sourceLineNo">742</span>    Map&lt;byte[], Algorithm&gt; compressionMap = new TreeMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.742"></a>
-<span class="sourceLineNo">743</span>    for (Map.Entry&lt;byte[], String&gt; e : stringMap.entrySet()) {<a name="line.743"></a>
-<span class="sourceLineNo">744</span>      Algorithm algorithm = HFileWriterImpl.compressionByName(e.getValue());<a name="line.744"></a>
-<span class="sourceLineNo">745</span>      compressionMap.put(e.getKey(), algorithm);<a name="line.745"></a>
-<span class="sourceLineNo">746</span>    }<a name="line.746"></a>
-<span class="sourceLineNo">747</span>    return compressionMap;<a name="line.747"></a>
-<span class="sourceLineNo">748</span>  }<a name="line.748"></a>
-<span class="sourceLineNo">749</span><a name="line.749"></a>
-<span class="sourceLineNo">750</span>  /**<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * Runs inside the task to deserialize column family to bloom filter type<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * map from the configuration.<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   *<a name="line.753"></a>
-<span class="sourceLineNo">754</span>   * @param conf to read the serialized values from<a name="line.754"></a>
-<span class="sourceLineNo">755</span>   * @return a map from column family to the the configured bloom filter type<a name="line.755"></a>
-<span class="sourceLineNo">756</span>   */<a name="line.756"></a>
-<span class="sourceLineNo">757</span>  @InterfaceAudience.Private<a name="line.757"></a>
-<span class="sourceLineNo">758</span>  static Map&lt;byte[], BloomType&gt; createFamilyBloomTypeMap(Configuration conf) {<a name="line.758"></a>
-<span class="sourceLineNo">759</span>    Map&lt;byte[], String&gt; stringMap = createFamilyConfValueMap(conf,<a name="line.759"></a>
-<span class="sourceLineNo">760</span>        BLOOM_TYPE_FAMILIES_CONF_KEY);<a name="line.760"></a>
-<span class="sourceLineNo">761</span>    Map&lt;byte[], BloomType&gt; bloomTypeMap = new TreeMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.761"></a>
-<span class="sourceLineNo">762</span>    for (Map.Entry&lt;byte[], String&gt; e : stringMap.entrySet()) {<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      BloomType bloomType = BloomType.valueOf(e.getValue());<a name="line.763"></a>
-<span class="sourceLineNo">764</span>      bloomTypeMap.put(e.getKey(), bloomType);<a name="line.764"></a>
-<span class="sourceLineNo">765</span>    }<a name="line.765"></a>
-<span class="sourceLineNo">766</span>    return bloomTypeMap;<a name="line.766"></a>
-<span class="sourceLineNo">767</span>  }<a name="line.767"></a>
-<span class="sourceLineNo">768</span><a name="line.768"></a>
-<span class="sourceLineNo">769</span>  /**<a name="line.769"></a>
-<span class="sourceLineNo">770</span>   * Runs inside the task to deserialize column family to bloom filter param<a name="line.770"></a>
-<span class="sourceLineNo">771</span>   * map from the configuration.<a name="line.771"></a>
-<span class="sourceLineNo">772</span>   *<a name="line.772"></a>
-<span class="sourceLineNo">773</span>   * @param conf to read the serialized values from<a name="line.773"></a>
-<span class="sourceLineNo">774</span>   * @return a map from column family to the the configured bloom filter param<a name="line.774"></a>
-<span class="sourceLineNo">775</span>   */<a name="line.775"></a>
-<span class="sourceLineNo">776</span>  @InterfaceAudience.Private<a name="line.776"></a>
-<span class="sourceLineNo">777</span>  static Map&lt;byte[], String&gt; createFamilyBloomParamMap(Configuration conf) {<a name="line.777"></a>
-<span class="sourceLineNo">778</span>    return createFamilyConfValueMap(conf, BLOOM_PARAM_FAMILIES_CONF_KEY);<a name="line.778"></a>
-<span class="sourceLineNo">779</span>  }<a name="line.779"></a>
-<span class="sourceLineNo">780</span><a name="line.780"></a>
-<span class="sourceLineNo">781</span>  /**<a name="line.781"></a>
-<span class="sourceLineNo">782</span>   * Runs inside the task to deserialize column family to block size<a name="line.782"></a>
-<span class="sourceLineNo">783</span>   * map from the configuration.<a name="line.783"></a>
-<span class="sourceLineNo">784</span>   *<a name="line.784"></a>
-<span class="sourceLineNo">785</span>   * @param conf to read the serialized values from<a name="line.785"></a>
-<span class="sourceLineNo">786</span>   * @return a map from column family to the configured block size<a name="line.786"></a>
-<span class="sourceLineNo">787</span>   */<a name="line.787"></a>
-<span class="sourceLineNo">788</span>  @InterfaceAudience.Private<a name="line.788"></a>
-<span class="sourceLineNo">789</span>  static Map&lt;byte[], Integer&gt; createFamilyBlockSizeMap(Configuration conf) {<a name="line.789"></a>
-<span class="sourceLineNo">790</span>    Map&lt;byte[], String&gt; stringMap = createFamilyConfValueMap(conf,<a name="line.790"></a>
-<span class="sourceLineNo">791</span>        BLOCK_SIZE_FAMILIES_CONF_KEY);<a name="line.791"></a>
-<span class="sourceLineNo">792</span>    Map&lt;byte[], Integer&gt; blockSizeMap = new TreeMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.792"></a>
-<span class="sourceLineNo">793</span>    for (Map.Entry&lt;byte[], String&gt; e : stringMap.entrySet()) {<a name="line.793"></a>
-<span class="sourceLineNo">794</span>      Integer blockSize = Integer.parseInt(e.getValue());<a name="line.794"></a>
-<span class="sourceLineNo">795</span>      blockSizeMap.put(e.getKey(), blockSize);<a name="line.795"></a>
-<span class="sourceLineNo">796</span>    }<a name="line.796"></a>
-<span class="sourceLineNo">797</span>    return blockSizeMap;<a name="line.797"></a>
-<span class="sourceLineNo">798</span>  }<a name="line.798"></a>
-<span class="sourceLineNo">799</span><a name="line.799"></a>
-<span class="sourceLineNo">800</span>  /**<a name="line.800"></a>
-<span class="sourceLineNo">801</span>   * Runs inside the task to deserialize column family to data block encoding<a name="line.801"></a>
-<span class="sourceLineNo">802</span>   * type map from the configuration.<a name="line.802"></a>
-<span class="sourceLineNo">803</span>   *<a name="line.803"></a>
-<span class="sourceLineNo">804</span>   * @param conf to read the serialized values from<a name="line.804"></a>
-<span class="sourceLineNo">805</span>   * @return a map from column family to HFileDataBlockEncoder for the<a name="line.805"></a>
-<span class="sourceLineNo">806</span>   *         configured data block type for the family<a name="line.806"></a>
-<span class="sourceLineNo">807</span>   */<a name="line.807"></a>
-<span class="sourceLineNo">808</span>  @InterfaceAudience.Private<a name="line.808"></a>
-<span class="sourceLineNo">809</span>  static Map&lt;byte[], DataBlockEncoding&gt; createFamilyDataBlockEncodingMap(<a name="line.809"></a>
-<span class="sourceLineNo">810</span>      Configuration conf) {<a name="line.810"></a>
-<span class="sourceLineNo">811</span>    Map&lt;byte[], String&gt; stringMap = createFamilyConfValueMap(conf,<a name="line.811"></a>
-<span class="sourceLineNo">812</span>        DATABLOCK_ENCODING_FAMILIES_CONF_KEY);<a name="line.812"></a>
-<span class="sourceLineNo">813</span>    Map&lt;byte[], DataBlockEncoding&gt; encoderMap = new TreeMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.813"></a>
-<span class="sourceLineNo">814</span>    for (Map.Entry&lt;byte[], String&gt; e : stringMap.entrySet()) {<a name="line.814"></a>
-<span class="sourceLineNo">815</span>      encoderMap.put(e.getKey(), DataBlockEncoding.valueOf((e.getValue())));<a name="line.815"></a>
-<span class="sourceLineNo">816</span>    }<a name="line.816"></a>
-<span class="sourceLineNo">817</span>    return encoderMap;<a name="line.817"></a>
-<span class="sourceLineNo">818</span>  }<a name="line.818"></a>
-<span class="sourceLineNo">819</span><a name="line.819"></a>
-<span class="sourceLineNo">820</span>  /**<a name="line.820"></a>
-<span class="sourceLineNo">821</span>   * Run inside the task to deserialize column family to given conf value map.<a name="line.821"></a>
-<span class="sourceLineNo">822</span>   *<a name="line.822"></a>
-<span class="sourceLineNo">823</span>   * @param conf to read the serialized values from<a name="line.823"></a>
-<span class="sourceLineNo">824</span>   * @param confName conf key to read from the configuration<a name="line.824"></a>
-<span class="sourceLineNo">825</span>   * @return a map of column family to the given configuration value<a name="line.825"></a>
-<span class="sourceLineNo">826</span>   */<a name="line.826"></a>
-<span class="sourceLineNo">827</span>  private static Map&lt;byte[], String&gt; createFamilyConfValueMap(<a name="line.827"></a>
-<span class="sourceLineNo">828</span>      Configuration conf, String confName) {<a name="line.828"></a>
-<span class="sourceLineNo">829</span>    Map&lt;byte[], String&gt; confValMap = new TreeMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.829"></a>
-<span class="sourceLineNo">830</span>    String confVal = conf.get(confName, "");<a name="line.830"></a>
-<span class="sourceLineNo">831</span>    for (String familyConf : confVal.split("&amp;")) {<a name="line.831"></a>
-<span class="sourceLineNo">832</span>      String[] familySplit = familyConf.split("=");<a name="line.832"></a>
-<span class="sourceLineNo">833</span>      if (familySplit.length != 2) {<a name="line.833"></a>
-<span class="sourceLineNo">834</span>        continue;<a name="line.834"></a>
-<span class="sourceLineNo">835</span>      }<a name="line.835"></a>
-<span class="sourceLineNo">836</span>      try {<a name="line.836"></a>
-<span class="sourceLineNo">837</span>        confValMap.put(Bytes.toBytes(URLDecoder.decode(familySplit[0], "UTF-8")),<a name="line.837"></a>
-<span class="sourceLineNo">838</span>            URLDecoder.decode(familySplit[1], "UTF-8"));<a name="line.838"></a>
-<span class="sourceLineNo">839</span>      } catch (UnsupportedEncodingException e) {<a name="line.839"></a>
-<span class="sourceLineNo">840</span>        // will not happen with UTF-8 encoding<a name="line.840"></a>
-<span class="sourceLineNo">841</span>        throw new AssertionError(e);<a name="line.841"></a>
-<span class="sourceLineNo">842</span>      }<a name="line.842"></a>
-<span class="sourceLineNo">843</span>    }<a name="line.843"></a>
-<span class="sourceLineNo">844</span>    return confValMap;<a name="line.844"></a>
-<span class="sourceLineNo">845</span>  }<a name="line.845"></a>
-<span class="sourceLineNo">846</span><a name="line.846"></a>
-<span class="sourceLineNo">847</span>  /**<a name="line.847"></a>
-<span class="sourceLineNo">848</span>   * Configure &lt;code&gt;job&lt;/code&gt; with a TotalOrderPartitioner, partitioning against<a name="line.848"></a>
-<span class="sourceLineNo">849</span>   * &lt;code&gt;splitPoints&lt;/code&gt;. Cleans up the partitions file after job exists.<a name="line.849"></a>
-<span class="sourceLineNo">850</span>   */<a name="line.850"></a>
-<span class="sourceLineNo">851</span>  static void configurePartitioner(Job job, List&lt;ImmutableBytesWritable&gt; splitPoints, boolean<a name="line.851"></a>
-<span class="sourceLineNo">852</span>          writeMultipleTables)<a name="line.852"></a>
-<span class="sourceLineNo">853</span>      throws IOException {<a name="line.853"></a>
-<span class="sourceLineNo">854</span>    Configuration conf = job.getConfiguration();<a name="line.854"></a>
-<span class="sourceLineNo">855</span>    // create the partitions file<a name="line.855"></a>
-<span class="sourceLineNo">856</span>    FileSystem fs = FileSystem.get(conf);<a name="line.856"></a>
-<span class="sourceLineNo">857</span>    String hbaseTmpFsDir =<a name="line.857"></a>
-<span class="sourceLineNo">858</span>        conf.get(HConstants.TEMPORARY_FS_DIRECTORY_KEY,<a name="line.858"></a>
-<span class="sourceLineNo">859</span>            fs.getHomeDirectory() + "/hbase-staging");<a name="line.859"></a>
-<span class="sourceLineNo">860</span>    Path partitionsPath = new Path(hbaseTmpFsDir, "partitions_" + UUID.randomUUID());<a name="line.860"></a>
-<span class="sourceLineNo">861</span>    fs.makeQualified(partitionsPath);<a name="line.861"></a>
-<span class="sourceLineNo">862</span>    writePartitions(conf, partitionsPath, splitPoints, writeMultipleTables);<a name="line.862"></a>
-<span class="sourceLineNo">863</span>    fs.deleteOnExit(partitionsPath);<a name="line.863"></a>
-<span class="sourceLineNo">864</span><a name="line.864"></a>
-<span class="sourceLineNo">865</span>    // configure job to use it<a name="line.865"></a>
-<span class="sourceLineNo">866</span>    job.setPartitionerClass(TotalOrderPartitioner.class);<a name="line.866"></a>
-<span class="sourceLineNo">867</span>    TotalOrderPartitioner.setPartitionFile(conf, partitionsPath);<a name="line.867"></a>
-<span class="sourceLineNo">868</span>  }<a name="line.868"></a>
-<span class="sourceLineNo">869</span><a name="line.869"></a>
-<span class="sourceLineNo">870</span>  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value =<a name="line.870"></a>
-<span class="sourceLineNo">871</span>    "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE")<a name="line.871"></a>
-<span class="sourceLineNo">872</span>  @InterfaceAudience.Private<a name="line.872"></a>
-<span class="sourceLineNo">873</span>  static String serializeColumnFamilyAttribute(Function&lt;ColumnFamilyDescriptor, String&gt; fn,<a name="line.873"></a>
-<span class="sourceLineNo">874</span>        List&lt;TableDescriptor&gt; allTables)<a name="line.874"></a>
-<span class="sourceLineNo">875</span>      throws UnsupportedEncodingException {<a name="line.875"></a>
-<span class="sourceLineNo">876</span>    StringBuilder attributeValue = new StringBuilder();<a name="line.876"></a>
-<span class="sourceLineNo">877</span>    int i = 0;<a name="line.877"></a>
-<span class="sourceLineNo">878</span>    for (TableDescriptor tableDescriptor : allTables) {<a name="line.878"></a>
-<span class="sourceLineNo">879</span>      if (tableDescriptor == null) {<a name="line.879"></a>
-<span class="sourceLineNo">880</span>        // could happen with mock table instance<a name="line.880"></a>
-<span class="sourceLineNo">881</span>        // CODEREVIEW: Can I set an empty string in conf if mock table instance?<a name="line.881"></a>
-<span class="sourceLineNo">882</span>        return "";<a name="line.882"></a>
-<span class="sourceLineNo">883</span>      }<a name="line.883"></a>
-<span class="sourceLineNo">884</span>      for (ColumnFamilyDescriptor familyDescriptor : tableDescriptor.getColumnFamilies()) {<a name="line.884"></a>
-<span class="sourceLineNo">885</span>        if (i++ &gt; 0) {<a name="line.885"></a>
-<span class="sourceLineNo">886</span>          attributeValue.append('&amp;');<a name="line.886"></a>
-<span class="sourceLineNo">887</span>        }<a name="line.887"></a>
-<span class="sourceLineNo">888</span>        attributeValue.append(URLEncoder.encode(<a name="line.888"></a>
-<span class="sourceLineNo">889</span>          Bytes.toString(combineTableNameSuffix(tableDescriptor.getTableName().getName(),<a name="line.889"></a>
-<span class="sourceLineNo">890</span>            familyDescriptor.getName())), "UTF-8"));<a name="line.890"></a>
-<span class="sourceLineNo">891</span>        attributeValue.append('=');<a name="line.891"></a>
-<span class="sourceLineNo">892</span>        attributeValue.append(URLEncoder.encode(fn.apply(familyDescriptor), "UTF-8"));<a name="line.892"></a>
-<span class="sourceLineNo">893</span>      }<a name="line.893"></a>
-<span class="sourceLineNo">894</span>    }<a name="line.894"></a>
-<span class="sourceLineNo">895</span>    // Get rid of the last ampersand<a name="line.895"></a>
-<span class="sourceLineNo">896</span>    return attributeValue.toString();<a name="line.896"></a>
-<span class="sourceLineNo">897</span>  }<a name="line.897"></a>
-<span class="sourceLineNo">898</span><a name="line.898"></a>
-<span class="sourceLineNo">899</span>  /**<a name="line.899"></a>
-<span class="sourceLineNo">900</span>   * Serialize column family to compression algorithm map to configuration.<a name="line.900"></a>
-<span class="sourceLineNo">901</span>   * Invoked while configuring the MR job for incremental load.<a name="line.901"></a>
-<span class="sourceLineNo">902</span>   */<a name="line.902"></a>
-<span class="sourceLineNo">903</span>  @InterfaceAudience.Private<a name="line.903"></a>
-<span class="sourceLineNo">904</span>  static Function&lt;ColumnFamilyDescriptor, String&gt; compressionDetails = familyDescriptor -&gt;<a name="line.904"></a>
-<span class="sourceLineNo">905</span>          familyDescriptor.getCompressionType().getName();<a name="line.905"></a>
-<span class="sourceLineNo">906</span><a name="line.906"></a>
-<span class="sourceLineNo">907</span>  /**<a name="line.907"></a>
-<span class="sourceLineNo">908</span>   * Serialize column family to block size map to configuration. Invoked while<a name="line.908"></a>
-<span class="sourceLineNo">909</span>   * configuring the MR job for incremental load.<a name="line.909"></a>
-<span class="sourceLineNo">910</span>   */<a name="line.910"></a>
-<span class="sourceLineNo">911</span>  @InterfaceAudience.Private<a name="line.911"></a>
-<span class="sourceLineNo">912</span>  static Function&lt;ColumnFamilyDescriptor, String&gt; blockSizeDetails = familyDescriptor -&gt; String<a name="line.912"></a>
-<span class="sourceLineNo">913</span>          .valueOf(familyDescriptor.getBlocksize());<a name="line.913"></a>
-<span class="sourceLineNo">914</span><a name="line.914"></a>
-<span class="sourceLineNo">915</span>  /**<a name="line.915"></a>
-<span class="sourceLineNo">916</span>   * Serialize column family to bloom type map to configuration. Invoked while<a name="line.916"></a>
-<span class="sourceLineNo">917</span>   * configuring the MR job for incremental load.<a name="line.917"></a>
-<span class="sourceLineNo">918</span>   */<a name="line.918"></a>
-<span class="sourceLineNo">919</span>  @InterfaceAudience.Private<a name="line.919"></a>
-<span class="sourceLineNo">920</span>  static Function&lt;ColumnFamilyDescriptor, String&gt; bloomTypeDetails = familyDescriptor -&gt; {<a name="line.920"></a>
-<span class="sourceLineNo">921</span>    String bloomType = familyDescriptor.getBloomFilterType().toString();<a name="line.921"></a>
-<span class="sourceLineNo">922</span>    if (bloomType == null) {<a name="line.922"></a>
-<span class="sourceLineNo">923</span>      bloomType = ColumnFamilyDescriptorBuilder.DEFAULT_BLOOMFILTER.name();<a name="line.923"></a>
-<span class="sourceLineNo">924</span>    }<a name="line.924"></a>
-<span class="sourceLineNo">925</span>    return bloomType;<a name="line.925"></a>
-<span class="sourceLineNo">926</span>  };<a name="line.926"></a>
-<span class="sourceLineNo">927</span><a name="line.927"></a>
-<span class="sourceLineNo">928</span>  /**<a name="line.928"></a>
-<span class="sourceLineNo">929</span>   * Serialize column family to bloom param map to configuration. Invoked while<a name="line.929"></a>
-<span class="sourceLineNo">930</span>   * configuring the MR job for incremental load.<a name="line.930"></a>
-<span class="sourceLineNo">931</span>   */<a name="line.931"></a>
-<span class="sourceLineNo">932</span>  @InterfaceAudience.Private<a name="line.932"></a>
-<span class="sourceLineNo">933</span>  static Function&lt;ColumnFamilyDescriptor, String&gt; bloomParamDetails = familyDescriptor -&gt; {<a name="line.933"></a>
-<span class="sourceLineNo">934</span>    BloomType bloomType = familyDescriptor.getBloomFilterType();<a name="line.934"></a>
-<span class="sourceLineNo">935</span>    String bloomParam = "";<a name="line.935"></a>
-<span class="sourceLineNo">936</span>    if (bloomType == BloomType.ROWPREFIX_FIXED_LENGTH) {<a name="line.936"></a>
-<span class="sourceLineNo">937</span>      bloomParam = familyDescriptor.getConfigurationValue(BloomFilterUtil.PREFIX_LENGTH_KEY);<a name="line.937"></a>
-<span class="sourceLineNo">938</span>    }<a name="line.938"></a>
-<span class="sourceLineNo">939</span>    return bloomParam;<a name="line.939"></a>
-<span class="sourceLineNo">940</span>  };<a name="line.940"></a>
-<span class="sourceLineNo">941</span><a name="line.941"></a>
-<span class="sourceLineNo">942</span>  /**<a name="line.942"></a>
-<span class="sourceLineNo">943</span>   * Serialize column family to data block encoding map to configuration.<a name="line.943"></a>
-<span class="sourceLineNo">944</span>   * Invoked while configuring the MR job for incremental load.<a name="line.944"></a>
-<span class="sourceLineNo">945</span>   */<a name="line.945"></a>
-<span class="sourceLineNo">946</span>  @InterfaceAudience.Private<a name="line.946"></a>
-<span class="sourceLineNo">947</span>  static Function&lt;ColumnFamilyDescriptor, String&gt; dataBlockEncodingDetails = familyDescriptor -&gt; {<a name="line.947"></a>
-<span class="sourceLineNo">948</span>    DataBlockEncoding encoding = familyDescriptor.getDataBlockEncoding();<a name="line.948"></a>
-<span class="sourceLineNo">949</span>    if (encoding == null) {<a name="line.949"></a>
-<span class="sourceLineNo">950</span>      encoding = DataBlockEncoding.NONE;<a name="line.950"></a>
-<span class="sourceLineNo">951</span>    }<a name="line.951"></a>
-<span class="sourceLineNo">952</span>    return encoding.toString();<a name="line.952"></a>
-<span class="sourceLineNo">953</span>  };<a name="line.953"></a>
-<span class="sourceLineNo">954</span><a name="line.954"></a>
-<span class="sourceLineNo">955</span>}<a name="line.955"></a>
+<span class="sourceLineNo">647</span>    conf.set(BLOOM_TYPE_FAMILIES_CONF_KEY, serializeColumnFamilyAttribute(bloomTypeDetails,<a name="line.647"></a>
+<span class="sourceLineNo">648</span>            tableDescriptors));<a name="line.648"></a>
+<span class="sourceLineNo">649</span>    conf.set(BLOOM_PARAM_FAMILIES_CONF_KEY, serializeColumnFamilyAttribute(bloomParamDetails,<a name="line.649"></a>
+<span class="sourceLineNo">650</span>        tableDescriptors));<a name="line.650"></a>
+<span class="sourceLineNo">651</span>    conf.set(DATABLOCK_ENCODING_FAMILIES_CONF_KEY,<a name="line.651"></a>
+<span class="sourceLineNo">652</span>            serializeColumnFamilyAttribute(dataBlockEncodingDetails, tableDescriptors));<a name="line.652"></a>
+<span class="sourceLineNo">653</span><a name="line.653"></a>
+<span class="sourceLineNo">654</span>    TableMapReduceUtil.addDependencyJars(job);<a name="line.654"></a>
+<span class="sourceLineNo">655</span>    TableMapReduceUtil.initCredentials(job);<a name="line.655"></a>
+<span class="sourceLineNo">656</span>    LOG.info("Incremental output configured for tables: " + StringUtils.join(allTableNames, ","));<a name="line.656"></a>
+<span class="sourceLineNo">657</span>  }<a name="line.657"></a>
+<span class="sourceLineNo">658</span><a name="line.658"></a>
+<span class="sourceLineNo">659</span>  public static void configureIncrementalLoadMap(Job job, TableDescriptor tableDescriptor) throws<a name="line.659"></a>
+<span class="sourceLineNo">660</span>      IOException {<a name="line.660"></a>
+<span class="sourceLineNo">661</span>    Configuration conf = job.getConfiguration();<a name="line.661"></a>
+<span class="sourceLineNo">662</span><a name="line.662"></a>
+<span class="sourceLineNo">663</span>    job.setOutputKeyClass(ImmutableBytesWritable.class);<a name="line.663"></a>
+<span class="sourceLineNo">664</span>    job.setOutputValueClass(MapReduceExtendedCell.class);<a name="line.664"></a>
+<span class="sourceLineNo">665</span>    job.setOutputFormatClass(HFileOutputFormat2.class);<a name="line.665"></a>
+<span class="sourceLineNo">666</span><a name="line.666"></a>
+<span class="sourceLineNo">667</span>    ArrayList&lt;TableDescriptor&gt; singleTableDescriptor = new ArrayList&lt;&gt;(1);<a name="line.667"></a>
+<span class="sourceLineNo">668</span>    singleTableDescriptor.add(tableDescriptor);<a name="line.668"></a>
+<span class="sourceLineNo">669</span><a name="line.669"></a>
+<span class="sourceLineNo">670</span>    conf.set(OUTPUT_TABLE_NAME_CONF_KEY, tableDescriptor.getTableName().getNameAsString());<a name="line.670"></a>
+<span class="sourceLineNo">671</span>    // Set compression algorithms based on column families<a name="line.671"></a>
+<span class="sourceLineNo">672</span>    conf.set(COMPRESSION_FAMILIES_CONF_KEY,<a name="line.672"></a>
+<span class="sourceLineNo">673</span>        serializeColumnFamilyAttribute(compressionDetails, singleTableDescriptor));<a name="line.673"></a>
+<span class="sourceLineNo">674</span>    conf.set(BLOCK_SIZE_FAMILIES_CONF_KEY,<a name="line.674"></a>
+<span class="sourceLineNo">675</span>        serializeColumnFamilyAttribute(blockSizeDetails, singleTableDescriptor));<a name="line.675"></a>
+<span class="sourceLineNo">676</span>    conf.set(BLOOM_TYPE_FAMILIES_CONF_KEY,<a name="line.676"></a>
+<span class="sourceLineNo">677</span>        serializeColumnFamilyAttribute(bloomTypeDetails, singleTableDescriptor));<a name="line.677"></a>
+<span class="sourceLineNo">678</span>    conf.set(BLOOM_PARAM_FAMILIES_CONF_KEY,<a name="line.678"></a>
+<span class="sourceLineNo">679</span>        serializeColumnFamilyAttribute(bloomParamDetails, singleTableDescriptor));<a name="line.679"></a>
+<span class="sourceLineNo">680</span>    conf.set(DATABLOCK_ENCODING_FAMILIES_CONF_KEY,<a name="line.680"></a>
+<span class="sourceLineNo">681</span>        serializeColumnFamilyAttribute(dataBlockEncodingDetails, singleTableDescriptor));<a name="line.681"></a>
+<span class="sourceLineNo">682</span><a name="line.682"></a>
+<span class="sourceLineNo">683</span>    TableMapReduceUtil.addDependencyJars(job);<a name="line.683"></a>
+<span class="sourceLineNo">684</span>    TableMapReduceUtil.initCredentials(job);<a name="line.684"></a>
+<span class="sourceLineNo">685</span>    LOG.info("Incremental table " + tableDescriptor.getTableName() + " output configured.");<a name="line.685"></a>
+<span class="sourceLineNo">686</span>  }<a name="line.686"></a>
+<span class="sourceLineNo">687</span><a name="line.687"></a>
+<span class="sourceLineNo">688</span>  /**<a name="line.688"></a>
+<span class="sourceLineNo">689</span>   * Configure HBase cluster key for remote cluster to load region location for locality-sensitive<a name="line.689"></a>
+<span class="sourceLineNo">690</span>   * if it's enabled.<a name="line.690"></a>
+<span class="sourceLineNo">691</span>   * It's not necessary to call this method explicitly when the cluster key for HBase cluster to be<a name="line.691"></a>
+<span class="sourceLineNo">692</span>   * used to load region location is configured in the job configuration.<a name="line.692"></a>
+<span class="sourceLineNo">693</span>   * Call this method when another HBase cluster key is configured in the job configuration.<a name="line.693"></a>
+<span class="sourceLineNo">694</span>   * For example, you should call when you load data from HBase cluster A using<a name="line.694"></a>
+<span class="sourceLineNo">695</span>   * {@link TableInputFormat} and generate hfiles for HBase cluster B.<a name="line.695"></a>
+<span class="sourceLineNo">696</span>   * Otherwise, HFileOutputFormat2 fetch location from cluster A and locality-sensitive won't<a name="line.696"></a>
+<span class="sourceLineNo">697</span>   * working correctly.<a name="line.697"></a>
+<span class="sourceLineNo">698</span>   * {@link #configureIncrementalLoad(Job, Table, RegionLocator)} calls this method using<a name="line.698"></a>
+<span class="sourceLineNo">699</span>   * {@link Table#getConfiguration} as clusterConf.<a name="line.699"></a>
+<span class="sourceLineNo">700</span>   * See HBASE-25608.<a name="line.700"></a>
+<span class="sourceLineNo">701</span>   *<a name="line.701"></a>
+<span class="sourceLineNo">702</span>   * @param job which has configuration to be updated<a name="line.702"></a>
+<span class="sourceLineNo">703</span>   * @param clusterConf which contains cluster key of the HBase cluster to be locality-sensitive<a name="line.703"></a>
+<span class="sourceLineNo">704</span>   *<a name="line.704"></a>
+<span class="sourceLineNo">705</span>   * @see #configureIncrementalLoad(Job, Table, RegionLocator)<a name="line.705"></a>
+<span class="sourceLineNo">706</span>   * @see #LOCALITY_SENSITIVE_CONF_KEY<a name="line.706"></a>
+<span class="sourceLineNo">707</span>   * @see #REMOTE_CLUSTER_ZOOKEEPER_QUORUM_CONF_KEY<a name="line.707"></a>
+<span class="sourceLineNo">708</span>   * @see #REMOTE_CLUSTER_ZOOKEEPER_CLIENT_PORT_CONF_KEY<a name="line.708"></a>
+<span class="sourceLineNo">709</span>   * @see #REMOTE_CLUSTER_ZOOKEEPER_ZNODE_PARENT_CONF_KEY<a name="line.709"></a>
+<span class="sourceLineNo">710</span>   */<a name="line.710"></a>
+<span class="sourceLineNo">711</span>  public static void configureRemoteCluster(Job job, Configuration clusterConf) {<a name="line.711"></a>
+<span class="sourceLineNo">712</span>    Configuration conf = job.getConfiguration();<a name="line.712"></a>
+<span class="sourceLineNo">713</span><a name="line.713"></a>
+<span class="sourceLineNo">714</span>    if (!conf.getBoolean(LOCALITY_SENSITIVE_CONF_KEY, DEFAULT_LOCALITY_SENSITIVE)) {<a name="line.714"></a>
+<span class="sourceLineNo">715</span>      return;<a name="line.715"></a>
+<span class="sourceLineNo">716</span>    }<a name="line.716"></a>
+<span class="sourceLineNo">717</span><a name="line.717"></a>
+<span class="sourceLineNo">718</span>    final String quorum = clusterConf.get(HConstants.ZOOKEEPER_QUORUM);<a name="line.718"></a>
+<span class="sourceLineNo">719</span>    final int clientPort = clusterConf.getInt(<a name="line.719"></a>
+<span class="sourceLineNo">720</span>      HConstants.ZOOKEEPER_CLIENT_PORT, HConstants.DEFAULT_ZOOKEEPER_CLIENT_PORT);<a name="line.720"></a>
+<span class="sourceLineNo">721</span>    final String parent = clusterConf.get(<a name="line.721"></a>
+<span class="sourceLineNo">722</span>      HConstants.ZOOKEEPER_ZNODE_PARENT, HConstants.DEFAULT_ZOOKEEPER_ZNODE_PARENT);<a name="line.722"></a>
+<span class="sourceLineNo">723</span><a name="line.723"></a>
+<span class="sourceLineNo">724</span>    conf.set(REMOTE_CLUSTER_ZOOKEEPER_QUORUM_CONF_KEY, quorum);<a name="line.724"></a>
+<span class="sourceLineNo">725</span>    conf.setInt(REMOTE_CLUSTER_ZOOKEEPER_CLIENT_PORT_CONF_KEY, clientPort);<a name="line.725"></a>
+<span class="sourceLineNo">726</span>    conf.set(REMOTE_CLUSTER_ZOOKEEPER_ZNODE_PARENT_CONF_KEY, parent);<a name="line.726"></a>
+<span class="sourceLineNo">727</span><a name="line.727"></a>
+<span class="sourceLineNo">728</span>    LOG.info("ZK configs for remote cluster of bulkload is configured: " +<a name="line.728"></a>
+<span class="sourceLineNo">729</span>      quorum + ":" + clientPort + "/" + parent);<a name="line.729"></a>
+<span class="sourceLineNo">730</span>  }<a name="line.730"></a>
+<span class="sourceLineNo">731</span><a name="line.731"></a>
+<span class="sourceLineNo">732</span>  /**<a name="line.732"></a>
+<span class="sourceLineNo">733</span>   * Runs inside the task to deserialize column family to compression algorithm<a name="line.733"></a>
+<span class="sourceLineNo">734</span>   * map from the configuration.<a name="line.734"></a>
+<span class="sourceLineNo">735</span>   *<a name="line.735"></a>
+<span class="sourceLineNo">736</span>   * @param conf to read the serialized values from<a name="line.736"></a>
+<span class="sourceLineNo">737</span>   * @return a map from column family to the configured compression algorithm<a name="line.737"></a>
+<span class="sourceLineNo">738</span>   */<a name="line.738"></a>
+<span class="sourceLineNo">739</span>  @InterfaceAudience.Private<a name="line.739"></a>
+<span class="sourceLineNo">740</span>  static Map&lt;byte[], Algorithm&gt; createFamilyCompressionMap(Configuration<a name="line.740"></a>
+<span class="sourceLineNo">741</span>      conf) {<a name="line.741"></a>
+<span class="sourceLineNo">742</span>    Map&lt;byte[], String&gt; stringMap = createFamilyConfValueMap(conf,<a name="line.742"></a>
+<span class="sourceLineNo">743</span>        COMPRESSION_FAMILIES_CONF_KEY);<a name="line.743"></a>
+<span class="sourceLineNo">744</span>    Map&lt;byte[], Algorithm&gt; compressionMap = new TreeMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.744"></a>
+<span class="sourceLineNo">745</span>    for (Map.Entry&lt;byte[], String&gt; e : stringMap.entrySet()) {<a name="line.745"></a>
+<span class="sourceLineNo">746</span>      Algorithm algorithm = HFileWriterImpl.compressionByName(e.getValue());<a name="line.746"></a>
+<span class="sourceLineNo">747</span>      compressionMap.put(e.getKey(), algorithm);<a name="line.747"></a>
+<span class="sourceLineNo">748</span>    }<a name="line.748"></a>
+<span class="sourceLineNo">749</span>    return compressionMap;<a name="line.749"></a>
+<span class="sourceLineNo">750</span>  }<a name="line.750"></a>
+<span class="sourceLineNo">751</span><a name="line.751"></a>
+<span class="sourceLineNo">752</span>  /**<a name="line.752"></a>
+<span class="sourceLineNo">753</span>   * Runs inside the task to deserialize column family to bloom filter type<a name="line.753"></a>
+<span class="sourceLineNo">754</span>   * map from the configuration.<a name="line.754"></a>
+<span class="sourceLineNo">755</span>   *<a name="line.755"></a>
+<span class="sourceLineNo">756</span>   * @param conf to read the serialized values from<a name="line.756"></a>
+<span class="sourceLineNo">757</span>   * @return a map from column family to the the configured bloom filter type<a name="line.757"></a>
+<span class="sourceLineNo">758</span>   */<a name="line.758"></a>
+<span class="sourceLineNo">759</span>  @InterfaceAudience.Private<a name="line.759"></a>
+<span class="sourceLineNo">760</span>  static Map&lt;byte[], BloomType&gt; createFamilyBloomTypeMap(Configuration conf) {<a name="line.760"></a>
+<span class="sourceLineNo">761</span>    Map&lt;byte[], String&gt; stringMap = createFamilyConfValueMap(conf,<a name="line.761"></a>
+<span class="sourceLineNo">762</span>        BLOOM_TYPE_FAMILIES_CONF_KEY);<a name="line.762"></a>
+<span class="sourceLineNo">763</span>    Map&lt;byte[], BloomType&gt; bloomTypeMap = new TreeMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.763"></a>
+<span class="sourceLineNo">764</span>    for (Map.Entry&lt;byte[], String&gt; e : stringMap.entrySet()) {<a name="line.764"></a>
+<span class="sourceLineNo">765</span>      BloomType bloomType = BloomType.valueOf(e.getValue());<a name="line.765"></a>
+<span class="sourceLineNo">766</span>      bloomTypeMap.put(e.getKey(), bloomType);<a name="line.766"></a>
+<span class="sourceLineNo">767</span>    }<a name="line.767"></a>
+<span class="sourceLineNo">768</span>    return bloomTypeMap;<a name="line.768"></a>
+<span class="sourceLineNo">769</span>  }<a name="line.769"></a>
+<span class="sourceLineNo">770</span><a name="line.770"></a>
+<span class="sourceLineNo">771</span>  /**<a name="line.771"></a>
+<span class="sourceLineNo">772</span>   * Runs inside the task to deserialize column family to bloom filter param<a name="line.772"></a>
+<span class="sourceLineNo">773</span>   * map from the configuration.<a name="line.773"></a>
+<span class="sourceLineNo">774</span>   *<a name="line.774"></a>
+<span class="sourceLineNo">775</span>   * @param conf to read the serialized values from<a name="line.775"></a>
+<span class="sourceLineNo">776</span>   * @return a map from column family to the the configured bloom filter param<a name="line.776"></a>
+<span class="sourceLineNo">777</span>   */<a name="line.777"></a>
+<span class="sourceLineNo">778</span>  @InterfaceAudience.Private<a name="line.778"></a>
+<span class="sourceLineNo">779</span>  static Map&lt;byte[], String&gt; createFamilyBloomParamMap(Configuration conf) {<a name="line.779"></a>
+<span class="sourceLineNo">780</span>    return createFamilyConfValueMap(conf, BLOOM_PARAM_FAMILIES_CONF_KEY);<a name="line.780"></a>
+<span class="sourceLineNo">781</span>  }<a name="line.781"></a>
+<span class="sourceLineNo">782</span><a name="line.782"></a>
+<span class="sourceLineNo">783</span>  /**<a name="line.783"></a>
+<span class="sourceLineNo">784</span>   * Runs inside the task to deserialize column family to block size<a name="line.784"></a>
+<span class="sourceLineNo">785</span>   * map from the configuration.<a name="line.785"></a>
+<span class="sourceLineNo">786</span>   *<a name="line.786"></a>
+<span class="sourceLineNo">787</span>   * @param conf to read the serialized values from<a name="line.787"></a>
+<span class="sourceLineNo">788</span>   * @return a map from column family to the configured block size<a name="line.788"></a>
+<span class="sourceLineNo">789</span>   */<a name="line.789"></a>
+<span class="sourceLineNo">790</span>  @InterfaceAudience.Private<a name="line.790"></a>
+<span class="sourceLineNo">791</span>  static Map&lt;byte[], Integer&gt; createFamilyBlockSizeMap(Configuration conf) {<a name="line.791"></a>
+<span class="sourceLineNo">792</span>    Map&lt;byte[], String&gt; stringMap = createFamilyConfValueMap(conf,<a name="line.792"></a>
+<span class="sourceLineNo">793</span>        BLOCK_SIZE_FAMILIES_CONF_KEY);<a name="line.793"></a>
+<span class="sourceLineNo">794</span>    Map&lt;byte[], Integer&gt; blockSizeMap = new TreeMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.794"></a>
+<span class="sourceLineNo">795</span>    for (Map.Entry&lt;byte[], String&gt; e : stringMap.entrySet()) {<a name="line.795"></a>
+<span class="sourceLineNo">796</span>      Integer blockSize = Integer.parseInt(e.getValue());<a name="line.796"></a>
+<span class="sourceLineNo">797</span>      blockSizeMap.put(e.getKey(), blockSize);<a name="line.797"></a>
+<span class="sourceLineNo">798</span>    }<a name="line.798"></a>
+<span class="sourceLineNo">799</span>    return blockSizeMap;<a name="line.799"></a>
+<span class="sourceLineNo">800</span>  }<a name="line.800"></a>
+<span class="sourceLineNo">801</span><a name="line.801"></a>
+<span class="sourceLineNo">802</span>  /**<a name="line.802"></a>
+<span class="sourceLineNo">803</span>   * Runs inside the task to deserialize column family to data block encoding<a name="line.803"></a>
+<span class="sourceLineNo">804</span>   * type map from the configuration.<a name="line.804"></a>
+<span class="sourceLineNo">805</span>   *<a name="line.805"></a>
+<span class="sourceLineNo">806</span>   * @param conf to read the serialized values from<a name="line.806"></a>
+<span class="sourceLineNo">807</span>   * @return a map from column family to HFileDataBlockEncoder for the<a name="line.807"></a>
+<span class="sourceLineNo">808</span>   *         configured data block type for the family<a name="line.808"></a>
+<span class="sourceLineNo">809</span>   */<a name="line.809"></a>
+<span class="sourceLineNo">810</span>  @InterfaceAudience.Private<a name="line.810"></a>
+<span class="sourceLineNo">811</span>  static Map&lt;byte[], DataBlockEncoding&gt; createFamilyDataBlockEncodingMap(<a name="line.811"></a>
+<span class="sourceLineNo">812</span>      Configuration conf) {<a name="line.812"></a>
+<span class="sourceLineNo">813</span>    Map&lt;byte[], String&gt; stringMap = createFamilyConfValueMap(conf,<a name="line.813"></a>
+<span class="sourceLineNo">814</span>        DATABLOCK_ENCODING_FAMILIES_CONF_KEY);<a name="line.814"></a>
+<span class="sourceLineNo">815</span>    Map&lt;byte[], DataBlockEncoding&gt; encoderMap = new TreeMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.815"></a>
+<span class="sourceLineNo">816</span>    for (Map.Entry&lt;byte[], String&gt; e : stringMap.entrySet()) {<a name="line.816"></a>
+<span class="sourceLineNo">817</span>      encoderMap.put(e.getKey(), DataBlockEncoding.valueOf((e.getValue())));<a name="line.817"></a>
+<span class="sourceLineNo">818</span>    }<a name="line.818"></a>
+<span class="sourceLineNo">819</span>    return encoderMap;<a name="line.819"></a>
+<span class="sourceLineNo">820</span>  }<a name="line.820"></a>
+<span class="sourceLineNo">821</span><a name="line.821"></a>
+<span class="sourceLineNo">822</span>  /**<a name="line.822"></a>
+<span class="sourceLineNo">823</span>   * Run inside the task to deserialize column family to given conf value map.<a name="line.823"></a>
+<span class="sourceLineNo">824</span>   *<a name="line.824"></a>
+<span class="sourceLineNo">825</span>   * @param conf to read the serialized values from<a name="line.825"></a>
+<span class="sourceLineNo">826</span>   * @param confName conf key to read from the configuration<a name="line.826"></a>
+<span class="sourceLineNo">827</span>   * @return a map of column family to the given configuration value<a name="line.827"></a>
+<span class="sourceLineNo">828</span>   */<a name="line.828"></a>
+<span class="sourceLineNo">829</span>  private static Map&lt;byte[], String&gt; createFamilyConfValueMap(<a name="line.829"></a>
+<span class="sourceLineNo">830</span>      Configuration conf, String confName) {<a name="line.830"></a>
+<span class="sourceLineNo">831</span>    Map&lt;byte[], String&gt; confValMap = new TreeMap&lt;&gt;(Bytes.BYTES_COMPARATOR);<a name="line.831"></a>
+<span class="sourceLineNo">832</span>    String confVal = conf.get(confName, "");<a name="line.832"></a>
+<span class="sourceLineNo">833</span>    for (String familyConf : confVal.split("&amp;")) {<a name="line.833"></a>
+<span class="sourceLineNo">834</span>      String[] familySplit = familyConf.split("=");<a name="line.834"></a>
+<span class="sourceLineNo">835</span>      if (familySplit.length != 2) {<a name="line.835"></a>
+<span class="sourceLineNo">836</span>        continue;<a name="line.836"></a>
+<span class="sourceLineNo">837</span>      }<a name="line.837"></a>
+<span class="sourceLineNo">838</span>      try {<a name="line.838"></a>
+<span class="sourceLineNo">839</span>        confValMap.put(Bytes.toBytes(URLDecoder.decode(familySplit[0], "UTF-8")),<a name="line.839"></a>
+<span class="sourceLineNo">840</span>            URLDecoder.decode(familySplit[1], "UTF-8"));<a name="line.840"></a>
+<span class="sourceLineNo">841</span>      } catch (UnsupportedEncodingException e) {<a name="line.841"></a>
+<span class="sourceLineNo">842</span>        // will not happen with UTF-8 encoding<a name="line.842"></a>
+<span class="sourceLineNo">843</span>        throw new AssertionError(e);<a name="line.843"></a>
+<span class="sourceLineNo">844</span>      }<a name="line.844"></a>
+<span class="sourceLineNo">845</span>    }<a name="line.845"></a>
+<span class="sourceLineNo">846</span>    return confValMap;<a name="line.846"></a>
+<span class="sourceLineNo">847</span>  }<a name="line.847"></a>
+<span class="sourceLineNo">848</span><a name="line.848"></a>
+<span class="sourceLineNo">849</span>  /**<a name="line.849"></a>
+<span class="sourceLineNo">850</span>   * Configure &lt;code&gt;job&lt;/code&gt; with a TotalOrderPartitioner, partitioning against<a name="line.850"></a>
+<span class="sourceLineNo">851</span>   * &lt;code&gt;splitPoints&lt;/code&gt;. Cleans up the partitions file after job exists.<a name="line.851"></a>
+<span class="sourceLineNo">852</span>   */<a name="line.852"></a>
+<span class="sourceLineNo">853</span>  static void configurePartitioner(Job job, List&lt;ImmutableBytesWritable&gt; splitPoints, boolean<a name="line.853"></a>
+<span class="sourceLineNo">854</span>          writeMultipleTables)<a name="line.854"></a>
+<span class="sourceLineNo">855</span>      throws IOException {<a name="line.855"></a>
+<span class="sourceLineNo">856</span>    Configuration conf = job.getConfiguration();<a name="line.856"></a>
+<span class="sourceLineNo">857</span>    // create the partitions file<a name="line.857"></a>
+<span class="sourceLineNo">858</span>    FileSystem fs = FileSystem.get(conf);<a name="line.858"></a>
+<span class="sourceLineNo">859</span>    String hbaseTmpFsDir =<a name="line.859"></a>
+<span class="sourceLineNo">860</span>        conf.get(HConstants.TEMPORARY_FS_DIRECTORY_KEY,<a name="line.860"></a>
+<span class="sourceLineNo">861</span>            fs.getHomeDirectory() + "/hbase-staging");<a name="line.861"></a>
+<span class="sourceLineNo">862</span>    Path partitionsPath = new Path(hbaseTmpFsDir, "partitions_" + UUID.randomUUID());<a name="line.862"></a>
+<span class="sourceLineNo">863</span>    fs.makeQualified(partitionsPath);<a name="line.863"></a>
+<span class="sourceLineNo">864</span>    writePartitions(conf, partitionsPath, splitPoints, writeMultipleTables);<a name="line.864"></a>
+<span class="sourceLineNo">865</span>    fs.deleteOnExit(partitionsPath);<a name="line.865"></a>
+<span class="sourceLineNo">866</span><a name="line.866"></a>
+<span class="sourceLineNo">867</span>    // configure job to use it<a name="line.867"></a>
+<span class="sourceLineNo">868</span>    job.setPartitionerClass(TotalOrderPartitioner.class);<a name="line.868"></a>
+<span class="sourceLineNo">869</span>    TotalOrderPartitioner.setPartitionFile(conf, partitionsPath);<a name="line.869"></a>
+<span class="sourceLineNo">870</span>  }<a name="line.870"></a>
+<span class="sourceLineNo">871</span><a name="line.871"></a>
+<span class="sourceLineNo">872</span>  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value =<a name="line.872"></a>
+<span class="sourceLineNo">873</span>    "RCN_REDUNDANT_NULLCHECK_OF_NONNULL_VALUE")<a name="line.873"></a>
+<span class="sourceLineNo">874</span>  @InterfaceAudience.Private<a name="line.874"></a>
+<span class="sourceLineNo">875</span>  static String serializeColumnFamilyAttribute(Function&lt;ColumnFamilyDescriptor, String&gt; fn,<a name="line.875"></a>
+<span class="sourceLineNo">876</span>        List&lt;TableDescriptor&gt; allTables)<a name="line.876"></a>
+<span class="sourceLineNo">877</span>      throws UnsupportedEncodingException {<a name="line.877"></a>
+<span class="sourceLineNo">878</span>    StringBuilder attributeValue = new StringBuilder();<a name="line.878"></a>
+<span class="sourceLineNo">879</span>    int i = 0;<a name="line.879"></a>
+<span class="sourceLineNo">880</span>    for (TableDescriptor tableDescriptor : allTables) {<a name="line.880"></a>
+<span class="sourceLineNo">881</span>      if (tableDescriptor == null) {<a name="line.881"></a>
+<span class="sourceLineNo">882</span>        // could happen with mock table instance<a name="line.882"></a>
+<span class="sourceLineNo">883</span>        // CODEREVIEW: Can I set an empty string in conf if mock table instance?<a name="line.883"></a>
+<span class="sourceLineNo">884</span>        return "";<a name="line.884"></a>
+<span class="sourceLineNo">885</span>      }<a name="line.885"></a>
+<span class="sourceLineNo">886</span>      for (ColumnFamilyDescriptor familyDescriptor : tableDescriptor.getColumnFamilies()) {<a name="line.886"></a>
+<span class="sourceLineNo">887</span>        if (i++ &gt; 0) {<a name="line.887"></a>
+<span class="sourceLineNo">888</span>          attributeValue.append('&amp;');<a name="line.888"></a>
+<span class="sourceLineNo">889</span>        }<a name="line.889"></a>
+<span class="sourceLineNo">890</span>        attributeValue.append(URLEncoder.encode(<a name="line.890"></a>
+<span class="sourceLineNo">891</span>          Bytes.toString(combineTableNameSuffix(tableDescriptor.getTableName().getName(),<a name="line.891"></a>
+<span class="sourceLineNo">892</span>            familyDescriptor.getName())), "UTF-8"));<a name="line.892"></a>
+<span class="sourceLineNo">893</span>        attributeValue.append('=');<a name="line.893"></a>
+<span class="sourceLineNo">894</span>        attributeValue.append(URLEncoder.encode(fn.apply(familyDescriptor), "UTF-8"));<a name="line.894"></a>
+<span class="sourceLineNo">895</span>      }<a name="line.895"></a>
+<span class="sourceLineNo">896</span>    }<a name="line.896"></a>
+<span class="sourceLineNo">897</span>    // Get rid of the last ampersand<a name="line.897"></a>
+<span class="sourceLineNo">898</span>    return attributeValue.toString();<a name="line.898"></a>
+<span class="sourceLineNo">899</span>  }<a name="line.899"></a>
+<span class="sourceLineNo">900</span><a name="line.900"></a>
+<span class="sourceLineNo">901</span>  /**<a name="line.901"></a>
+<span class="sourceLineNo">902</span>   * Serialize column family to compression algorithm map to configuration.<a name="line.902"></a>
+<span class="sourceLineNo">903</span>   * Invoked while configuring the MR job for incremental load.<a name="line.903"></a>
+<span class="sourceLineNo">904</span>   */<a name="line.904"></a>
+<span class="sourceLineNo">905</span>  @InterfaceAudience.Private<a name="line.905"></a>
+<span class="sourceLineNo">906</span>  static Function&lt;ColumnFamilyDescriptor, String&gt; compressionDetails = familyDescriptor -&gt;<a name="line.906"></a>
+<span class="sourceLineNo">907</span>          familyDescriptor.getCompressionType().getName();<a name="line.907"></a>
+<span class="sourceLineNo">908</span><a name="line.908"></a>
+<span class="sourceLineNo">909</span>  /**<a name="line.909"></a>
+<span class="sourceLineNo">910</span>   * Serialize column family to block size map to configuration. Invoked while<a name="line.910"></a>
+<span class="sourceLineNo">911</span>   * configuring the MR job for incremental load.<a name="line.911"></a>
+<span class="sourceLineNo">912</span>   */<a name="line.912"></a>
+<span class="sourceLineNo">913</span>  @InterfaceAudience.Private<a name="line.913"></a>
+<span class="sourceLineNo">914</span>  static Function&lt;ColumnFamilyDescriptor, String&gt; blockSizeDetails = familyDescriptor -&gt; String<a name="line.914"></a>
+<span class="sourceLineNo">915</span>          .valueOf(familyDescriptor.getBlocksize());<a name="line.915"></a>
+<span class="sourceLineNo">916</span><a name="line.916"></a>
+<span class="sourceLineNo">917</span>  /**<a name="line.917"></a>
+<span class="sourceLineNo">918</span>   * Serialize column family to bloom type map to configuration. Invoked while<a name="line.918"></a>
+<span class="sourceLineNo">919</span>   * configuring the MR job for incremental load.<a name="line.919"></a>
+<span class="sourceLineNo">920</span>   */<a name="line.920"></a>
+<span class="sourceLineNo">921</span>  @InterfaceAudience.Private<a name="line.921"></a>
+<span class="sourceLineNo">922</span>  static Function&lt;ColumnFamilyDescriptor, String&gt; bloomTypeDetails = familyDescriptor -&gt; {<a name="line.922"></a>
+<span class="sourceLineNo">923</span>    String bloomType = familyDescriptor.getBloomFilterType().toString();<a name="line.923"></a>
+<span class="sourceLineNo">924</span>    if (bloomType == null) {<a name="line.924"></a>
+<span class="sourceLineNo">925</span>      bloomType = ColumnFamilyDescriptorBuilder.DEFAULT_BLOOMFILTER.name();<a name="line.925"></a>
+<span class="sourceLineNo">926</span>    }<a name="line.926"></a>
+<span class="sourceLineNo">927</span>    return bloomType;<a name="line.927"></a>
+<span class="sourceLineNo">928</span>  };<a name="line.928"></a>
+<span class="sourceLineNo">929</span><a name="line.929"></a>
+<span class="sourceLineNo">930</span>  /**<a name="line.930"></a>
+<span class="sourceLineNo">931</span>   * Serialize column family to bloom param map to configuration. Invoked while<a name="line.931"></a>
+<span class="sourceLineNo">932</span>   * configuring the MR job for incremental load.<a name="line.932"></a>
+<span class="sourceLineNo">933</span>   */<a name="line.933"></a>
+<span class="sourceLineNo">934</span>  @InterfaceAudience.Private<a name="line.934"></a>
+<span class="sourceLineNo">935</span>  static Function&lt;ColumnFamilyDescriptor, String&gt; bloomParamDetails = familyDescriptor -&gt; {<a name="line.935"></a>
+<span class="sourceLineNo">936</span>    BloomType bloomType = familyDescriptor.getBloomFilterType();<a name="line.936"></a>
+<span class="sourceLineNo">937</span>    String bloomParam = "";<a name="line.937"></a>
+<span class="sourceLineNo">938</span>    if (bloomType == BloomType.ROWPREFIX_FIXED_LENGTH) {<a name="line.938"></a>
+<span class="sourceLineNo">939</span>      bloomParam = familyDescriptor.getConfigurationValue(BloomFilterUtil.PREFIX_LENGTH_KEY);<a name="line.939"></a>
+<span class="sourceLineNo">940</span>    }<a name="line.940"></a>
+<span class="sourceLineNo">941</span>    return bloomParam;<a name="line.941"></a>
+<span class="sourceLineNo">942</span>  };<a name="line.942"></a>
+<span class="sourceLineNo">943</span><a name="line.943"></a>
+<span class="sourceLineNo">944</span>  /**<a name="line.944"></a>
+<span class="sourceLineNo">945</span>   * Serialize column family to data block encoding map to configuration.<a name="line.945"></a>
+<span class="sourceLineNo">946</span>   * Invoked while configuring the MR job for incremental load.<a name="line.946"></a>
+<span class="sourceLineNo">947</span>   */<a name="line.947"></a>
+<span class="sourceLineNo">948</span>  @InterfaceAudience.Private<a name="line.948"></a>
+<span class="sourceLineNo">949</span>  static Function&lt;ColumnFamilyDescriptor, String&gt; dataBlockEncodingDetails = familyDescriptor -&gt; {<a name="line.949"></a>
+<span class="sourceLineNo">950</span>    DataBlockEncoding encoding = familyDescriptor.getDataBlockEncoding();<a name="line.950"></a>
+<span class="sourceLineNo">951</span>    if (encoding == null) {<a name="line.951"></a>
+<span class="sourceLineNo">952</span>      encoding = DataBlockEncoding.NONE;<a name="line.952"></a>
+<span class="sourceLineNo">953</span>    }<a name="line.953"></a>
+<span class="sourceLineNo">954</span>    return encoding.toString();<a name="line.954"></a>
+<span class="sourceLineNo">955</span>  };<a name="line.955"></a>
+<span class="sourceLineNo">956</span><a name="line.956"></a>
+<span class="sourceLineNo">957</span>}<a name="line.957"></a>
 
 
 
diff --git a/apidocs/src-html/org/apache/hadoop/hbase/mapreduce/ImportTsv.html b/apidocs/src-html/org/apache/hadoop/hbase/mapreduce/ImportTsv.html
index 5d764e4..f12af3a 100644
--- a/apidocs/src-html/org/apache/hadoop/hbase/mapreduce/ImportTsv.html
+++ b/apidocs/src-html/org/apache/hadoop/hbase/mapreduce/ImportTsv.html
@@ -55,749 +55,750 @@
 <span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.client.TableDescriptorBuilder;<a name="line.47"></a>
 <span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<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.Pair;<a name="line.50"></a>
-<span class="sourceLineNo">051</span>import org.apache.hadoop.io.Text;<a name="line.51"></a>
-<span class="sourceLineNo">052</span>import org.apache.hadoop.mapreduce.Job;<a name="line.52"></a>
-<span class="sourceLineNo">053</span>import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;<a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;<a name="line.54"></a>
-<span class="sourceLineNo">055</span>import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;<a name="line.55"></a>
-<span class="sourceLineNo">056</span>import org.apache.hadoop.mapreduce.lib.output.NullOutputFormat;<a name="line.56"></a>
-<span class="sourceLineNo">057</span>import org.apache.hadoop.security.Credentials;<a name="line.57"></a>
-<span class="sourceLineNo">058</span>import org.apache.hadoop.util.Tool;<a name="line.58"></a>
-<span class="sourceLineNo">059</span>import org.apache.hadoop.util.ToolRunner;<a name="line.59"></a>
-<span class="sourceLineNo">060</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.60"></a>
-<span class="sourceLineNo">061</span>import org.slf4j.Logger;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>import org.slf4j.LoggerFactory;<a name="line.62"></a>
-<span class="sourceLineNo">063</span><a name="line.63"></a>
-<span class="sourceLineNo">064</span>import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;<a name="line.64"></a>
-<span class="sourceLineNo">065</span>import org.apache.hbase.thirdparty.com.google.common.base.Splitter;<a name="line.65"></a>
-<span class="sourceLineNo">066</span>import org.apache.hbase.thirdparty.com.google.common.collect.Lists;<a name="line.66"></a>
-<span class="sourceLineNo">067</span><a name="line.67"></a>
-<span class="sourceLineNo">068</span>/**<a name="line.68"></a>
-<span class="sourceLineNo">069</span> * Tool to import data from a TSV file.<a name="line.69"></a>
-<span class="sourceLineNo">070</span> *<a name="line.70"></a>
-<span class="sourceLineNo">071</span> * This tool is rather simplistic - it doesn't do any quoting or<a name="line.71"></a>
-<span class="sourceLineNo">072</span> * escaping, but is useful for many data loads.<a name="line.72"></a>
-<span class="sourceLineNo">073</span> *<a name="line.73"></a>
-<span class="sourceLineNo">074</span> * @see ImportTsv#usage(String)<a name="line.74"></a>
-<span class="sourceLineNo">075</span> */<a name="line.75"></a>
-<span class="sourceLineNo">076</span>@InterfaceAudience.Public<a name="line.76"></a>
-<span class="sourceLineNo">077</span>public class ImportTsv extends Configured implements Tool {<a name="line.77"></a>
-<span class="sourceLineNo">078</span><a name="line.78"></a>
-<span class="sourceLineNo">079</span>  protected static final Logger LOG = LoggerFactory.getLogger(ImportTsv.class);<a name="line.79"></a>
-<span class="sourceLineNo">080</span><a name="line.80"></a>
-<span class="sourceLineNo">081</span>  final static String NAME = "importtsv";<a name="line.81"></a>
-<span class="sourceLineNo">082</span><a name="line.82"></a>
-<span class="sourceLineNo">083</span>  public final static String MAPPER_CONF_KEY = "importtsv.mapper.class";<a name="line.83"></a>
-<span class="sourceLineNo">084</span>  public final static String BULK_OUTPUT_CONF_KEY = "importtsv.bulk.output";<a name="line.84"></a>
-<span class="sourceLineNo">085</span>  public final static String TIMESTAMP_CONF_KEY = "importtsv.timestamp";<a name="line.85"></a>
-<span class="sourceLineNo">086</span>  public final static String JOB_NAME_CONF_KEY = "mapreduce.job.name";<a name="line.86"></a>
-<span class="sourceLineNo">087</span>  // TODO: the rest of these configs are used exclusively by TsvImporterMapper.<a name="line.87"></a>
-<span class="sourceLineNo">088</span>  // Move them out of the tool and let the mapper handle its own validation.<a name="line.88"></a>
-<span class="sourceLineNo">089</span>  public final static String DRY_RUN_CONF_KEY = "importtsv.dry.run";<a name="line.89"></a>
-<span class="sourceLineNo">090</span>  // If true, bad lines are logged to stderr. Default: false.<a name="line.90"></a>
-<span class="sourceLineNo">091</span>  public final static String LOG_BAD_LINES_CONF_KEY = "importtsv.log.bad.lines";<a name="line.91"></a>
-<span class="sourceLineNo">092</span>  public final static String SKIP_LINES_CONF_KEY = "importtsv.skip.bad.lines";<a name="line.92"></a>
-<span class="sourceLineNo">093</span>  public final static String SKIP_EMPTY_COLUMNS = "importtsv.skip.empty.columns";<a name="line.93"></a>
-<span class="sourceLineNo">094</span>  public final static String COLUMNS_CONF_KEY = "importtsv.columns";<a name="line.94"></a>
-<span class="sourceLineNo">095</span>  public final static String SEPARATOR_CONF_KEY = "importtsv.separator";<a name="line.95"></a>
-<span class="sourceLineNo">096</span>  public final static String ATTRIBUTE_SEPERATOR_CONF_KEY = "attributes.seperator";<a name="line.96"></a>
-<span class="sourceLineNo">097</span>  //This config is used to propagate credentials from parent MR jobs which launch<a name="line.97"></a>
-<span class="sourceLineNo">098</span>  //ImportTSV jobs. SEE IntegrationTestImportTsv.<a name="line.98"></a>
-<span class="sourceLineNo">099</span>  public final static String CREDENTIALS_LOCATION = "credentials_location";<a name="line.99"></a>
-<span class="sourceLineNo">100</span>  final static String DEFAULT_SEPARATOR = "\t";<a name="line.100"></a>
-<span class="sourceLineNo">101</span>  final static String DEFAULT_ATTRIBUTES_SEPERATOR = "=&gt;";<a name="line.101"></a>
-<span class="sourceLineNo">102</span>  final static String DEFAULT_MULTIPLE_ATTRIBUTES_SEPERATOR = ",";<a name="line.102"></a>
-<span class="sourceLineNo">103</span>  final static Class DEFAULT_MAPPER = TsvImporterMapper.class;<a name="line.103"></a>
-<span class="sourceLineNo">104</span>  public final static String CREATE_TABLE_CONF_KEY = "create.table";<a name="line.104"></a>
-<span class="sourceLineNo">105</span>  public final static String NO_STRICT_COL_FAMILY = "no.strict";<a name="line.105"></a>
-<span class="sourceLineNo">106</span>  /**<a name="line.106"></a>
-<span class="sourceLineNo">107</span>   * If table didn't exist and was created in dry-run mode, this flag is<a name="line.107"></a>
-<span class="sourceLineNo">108</span>   * flipped to delete it when MR ends.<a name="line.108"></a>
-<span class="sourceLineNo">109</span>   */<a name="line.109"></a>
-<span class="sourceLineNo">110</span>  private static boolean DRY_RUN_TABLE_CREATED;<a name="line.110"></a>
-<span class="sourceLineNo">111</span><a name="line.111"></a>
-<span class="sourceLineNo">112</span>  public static class TsvParser {<a name="line.112"></a>
-<span class="sourceLineNo">113</span>    /**<a name="line.113"></a>
-<span class="sourceLineNo">114</span>     * Column families and qualifiers mapped to the TSV columns<a name="line.114"></a>
-<span class="sourceLineNo">115</span>     */<a name="line.115"></a>
-<span class="sourceLineNo">116</span>    private final byte[][] families;<a name="line.116"></a>
-<span class="sourceLineNo">117</span>    private final byte[][] qualifiers;<a name="line.117"></a>
-<span class="sourceLineNo">118</span><a name="line.118"></a>
-<span class="sourceLineNo">119</span>    private final byte separatorByte;<a name="line.119"></a>
-<span class="sourceLineNo">120</span><a name="line.120"></a>
-<span class="sourceLineNo">121</span>    private int rowKeyColumnIndex;<a name="line.121"></a>
-<span class="sourceLineNo">122</span><a name="line.122"></a>
-<span class="sourceLineNo">123</span>    private int maxColumnCount;<a name="line.123"></a>
-<span class="sourceLineNo">124</span><a name="line.124"></a>
-<span class="sourceLineNo">125</span>    // Default value must be negative<a name="line.125"></a>
-<span class="sourceLineNo">126</span>    public static final int DEFAULT_TIMESTAMP_COLUMN_INDEX = -1;<a name="line.126"></a>
-<span class="sourceLineNo">127</span><a name="line.127"></a>
-<span class="sourceLineNo">128</span>    private int timestampKeyColumnIndex = DEFAULT_TIMESTAMP_COLUMN_INDEX;<a name="line.128"></a>
-<span class="sourceLineNo">129</span><a name="line.129"></a>
-<span class="sourceLineNo">130</span>    public static final String ROWKEY_COLUMN_SPEC = "HBASE_ROW_KEY";<a name="line.130"></a>
-<span class="sourceLineNo">131</span><a name="line.131"></a>
-<span class="sourceLineNo">132</span>    public static final String TIMESTAMPKEY_COLUMN_SPEC = "HBASE_TS_KEY";<a name="line.132"></a>
-<span class="sourceLineNo">133</span><a name="line.133"></a>
-<span class="sourceLineNo">134</span>    public static final String ATTRIBUTES_COLUMN_SPEC = "HBASE_ATTRIBUTES_KEY";<a name="line.134"></a>
-<span class="sourceLineNo">135</span><a name="line.135"></a>
-<span class="sourceLineNo">136</span>    public static final String CELL_VISIBILITY_COLUMN_SPEC = "HBASE_CELL_VISIBILITY";<a name="line.136"></a>
-<span class="sourceLineNo">137</span><a name="line.137"></a>
-<span class="sourceLineNo">138</span>    public static final String CELL_TTL_COLUMN_SPEC = "HBASE_CELL_TTL";<a name="line.138"></a>
-<span class="sourceLineNo">139</span><a name="line.139"></a>
-<span class="sourceLineNo">140</span>    private int attrKeyColumnIndex = DEFAULT_ATTRIBUTES_COLUMN_INDEX;<a name="line.140"></a>
-<span class="sourceLineNo">141</span><a name="line.141"></a>
-<span class="sourceLineNo">142</span>    public static final int DEFAULT_ATTRIBUTES_COLUMN_INDEX = -1;<a name="line.142"></a>
-<span class="sourceLineNo">143</span><a name="line.143"></a>
-<span class="sourceLineNo">144</span>    public static final int DEFAULT_CELL_VISIBILITY_COLUMN_INDEX = -1;<a name="line.144"></a>
-<span class="sourceLineNo">145</span><a name="line.145"></a>
-<span class="sourceLineNo">146</span>    public static final int DEFAULT_CELL_TTL_COLUMN_INDEX = -1;<a name="line.146"></a>
-<span class="sourceLineNo">147</span><a name="line.147"></a>
-<span class="sourceLineNo">148</span>    private int cellVisibilityColumnIndex = DEFAULT_CELL_VISIBILITY_COLUMN_INDEX;<a name="line.148"></a>
-<span class="sourceLineNo">149</span><a name="line.149"></a>
-<span class="sourceLineNo">150</span>    private int cellTTLColumnIndex = DEFAULT_CELL_TTL_COLUMN_INDEX;<a name="line.150"></a>
-<span class="sourceLineNo">151</span><a name="line.151"></a>
-<span class="sourceLineNo">152</span>    /**<a name="line.152"></a>
-<span class="sourceLineNo">153</span>     * @param columnsSpecification the list of columns to parser out, comma separated.<a name="line.153"></a>
-<span class="sourceLineNo">154</span>     * The row key should be the special token TsvParser.ROWKEY_COLUMN_SPEC<a name="line.154"></a>
-<span class="sourceLineNo">155</span>     * @param separatorStr<a name="line.155"></a>
-<span class="sourceLineNo">156</span>     */<a name="line.156"></a>
-<span class="sourceLineNo">157</span>    public TsvParser(String columnsSpecification, String separatorStr) {<a name="line.157"></a>
-<span class="sourceLineNo">158</span>      // Configure separator<a name="line.158"></a>
-<span class="sourceLineNo">159</span>      byte[] separator = Bytes.toBytes(separatorStr);<a name="line.159"></a>
-<span class="sourceLineNo">160</span>      Preconditions.checkArgument(separator.length == 1,<a name="line.160"></a>
-<span class="sourceLineNo">161</span>        "TsvParser only supports single-byte separators");<a name="line.161"></a>
-<span class="sourceLineNo">162</span>      separatorByte = separator[0];<a name="line.162"></a>
-<span class="sourceLineNo">163</span><a name="line.163"></a>
-<span class="sourceLineNo">164</span>      // Configure columns<a name="line.164"></a>
-<span class="sourceLineNo">165</span>      ArrayList&lt;String&gt; columnStrings = Lists.newArrayList(<a name="line.165"></a>
-<span class="sourceLineNo">166</span>        Splitter.on(',').trimResults().split(columnsSpecification));<a name="line.166"></a>
-<span class="sourceLineNo">167</span><a name="line.167"></a>
-<span class="sourceLineNo">168</span>      maxColumnCount = columnStrings.size();<a name="line.168"></a>
-<span class="sourceLineNo">169</span>      families = new byte[maxColumnCount][];<a name="line.169"></a>
-<span class="sourceLineNo">170</span>      qualifiers = new byte[maxColumnCount][];<a name="line.170"></a>
-<span class="sourceLineNo">171</span><a name="line.171"></a>
-<span class="sourceLineNo">172</span>      for (int i = 0; i &lt; columnStrings.size(); i++) {<a name="line.172"></a>
-<span class="sourceLineNo">173</span>        String str = columnStrings.get(i);<a name="line.173"></a>
-<span class="sourceLineNo">174</span>        if (ROWKEY_COLUMN_SPEC.equals(str)) {<a name="line.174"></a>
-<span class="sourceLineNo">175</span>          rowKeyColumnIndex = i;<a name="line.175"></a>
-<span class="sourceLineNo">176</span>          continue;<a name="line.176"></a>
-<span class="sourceLineNo">177</span>        }<a name="line.177"></a>
-<span class="sourceLineNo">178</span>        if (TIMESTAMPKEY_COLUMN_SPEC.equals(str)) {<a name="line.178"></a>
-<span class="sourceLineNo">179</span>          timestampKeyColumnIndex = i;<a name="line.179"></a>
-<span class="sourceLineNo">180</span>          continue;<a name="line.180"></a>
-<span class="sourceLineNo">181</span>        }<a name="line.181"></a>
-<span class="sourceLineNo">182</span>        if (ATTRIBUTES_COLUMN_SPEC.equals(str)) {<a name="line.182"></a>
-<span class="sourceLineNo">183</span>          attrKeyColumnIndex = i;<a name="line.183"></a>
-<span class="sourceLineNo">184</span>          continue;<a name="line.184"></a>
-<span class="sourceLineNo">185</span>        }<a name="line.185"></a>
-<span class="sourceLineNo">186</span>        if (CELL_VISIBILITY_COLUMN_SPEC.equals(str)) {<a name="line.186"></a>
-<span class="sourceLineNo">187</span>          cellVisibilityColumnIndex = i;<a name="line.187"></a>
-<span class="sourceLineNo">188</span>          continue;<a name="line.188"></a>
-<span class="sourceLineNo">189</span>        }<a name="line.189"></a>
-<span class="sourceLineNo">190</span>        if (CELL_TTL_COLUMN_SPEC.equals(str)) {<a name="line.190"></a>
-<span class="sourceLineNo">191</span>          cellTTLColumnIndex = i;<a name="line.191"></a>
-<span class="sourceLineNo">192</span>          continue;<a name="line.192"></a>
-<span class="sourceLineNo">193</span>        }<a name="line.193"></a>
-<span class="sourceLineNo">194</span>        String[] parts = str.split(":", 2);<a name="line.194"></a>
-<span class="sourceLineNo">195</span>        if (parts.length == 1) {<a name="line.195"></a>
-<span class="sourceLineNo">196</span>          families[i] = Bytes.toBytes(str);<a name="line.196"></a>
-<span class="sourceLineNo">197</span>          qualifiers[i] = HConstants.EMPTY_BYTE_ARRAY;<a name="line.197"></a>
-<span class="sourceLineNo">198</span>        } else {<a name="line.198"></a>
-<span class="sourceLineNo">199</span>          families[i] = Bytes.toBytes(parts[0]);<a name="line.199"></a>
-<span class="sourceLineNo">200</span>          qualifiers[i] = Bytes.toBytes(parts[1]);<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>    }<a name="line.203"></a>
-<span class="sourceLineNo">204</span><a name="line.204"></a>
-<span class="sourceLineNo">205</span>    public boolean hasTimestamp() {<a name="line.205"></a>
-<span class="sourceLineNo">206</span>      return timestampKeyColumnIndex != DEFAULT_TIMESTAMP_COLUMN_INDEX;<a name="line.206"></a>
-<span class="sourceLineNo">207</span>    }<a name="line.207"></a>
-<span class="sourceLineNo">208</span><a name="line.208"></a>
-<span class="sourceLineNo">209</span>    public int getTimestampKeyColumnIndex() {<a name="line.209"></a>
-<span class="sourceLineNo">210</span>      return timestampKeyColumnIndex;<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>    public boolean hasAttributes() {<a name="line.213"></a>
-<span class="sourceLineNo">214</span>      return attrKeyColumnIndex != DEFAULT_ATTRIBUTES_COLUMN_INDEX;<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>    public boolean hasCellVisibility() {<a name="line.217"></a>
-<span class="sourceLineNo">218</span>      return cellVisibilityColumnIndex != DEFAULT_CELL_VISIBILITY_COLUMN_INDEX;<a name="line.218"></a>
-<span class="sourceLineNo">219</span>    }<a name="line.219"></a>
-<span class="sourceLineNo">220</span><a name="line.220"></a>
-<span class="sourceLineNo">221</span>    public boolean hasCellTTL() {<a name="line.221"></a>
-<span class="sourceLineNo">222</span>      return cellTTLColumnIndex != DEFAULT_CELL_VISIBILITY_COLUMN_INDEX;<a name="line.222"></a>
-<span class="sourceLineNo">223</span>    }<a name="line.223"></a>
-<span class="sourceLineNo">224</span><a name="line.224"></a>
-<span class="sourceLineNo">225</span>    public int getAttributesKeyColumnIndex() {<a name="line.225"></a>
-<span class="sourceLineNo">226</span>      return attrKeyColumnIndex;<a name="line.226"></a>
-<span class="sourceLineNo">227</span>    }<a name="line.227"></a>
-<span class="sourceLineNo">228</span><a name="line.228"></a>
-<span class="sourceLineNo">229</span>    public int getCellVisibilityColumnIndex() {<a name="line.229"></a>
-<span class="sourceLineNo">230</span>      return cellVisibilityColumnIndex;<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>    public int getCellTTLColumnIndex() {<a name="line.233"></a>
-<span class="sourceLineNo">234</span>      return cellTTLColumnIndex;<a name="line.234"></a>
-<span class="sourceLineNo">235</span>    }<a name="line.235"></a>
-<span class="sourceLineNo">236</span><a name="line.236"></a>
-<span class="sourceLineNo">237</span>    public int getRowKeyColumnIndex() {<a name="line.237"></a>
-<span class="sourceLineNo">238</span>      return rowKeyColumnIndex;<a name="line.238"></a>
-<span class="sourceLineNo">239</span>    }<a name="line.239"></a>
-<span class="sourceLineNo">240</span><a name="line.240"></a>
-<span class="sourceLineNo">241</span>    public byte[] getFamily(int idx) {<a name="line.241"></a>
-<span class="sourceLineNo">242</span>      return families[idx];<a name="line.242"></a>
-<span class="sourceLineNo">243</span>    }<a name="line.243"></a>
-<span class="sourceLineNo">244</span>    public byte[] getQualifier(int idx) {<a name="line.244"></a>
-<span class="sourceLineNo">245</span>      return qualifiers[idx];<a name="line.245"></a>
-<span class="sourceLineNo">246</span>    }<a name="line.246"></a>
-<span class="sourceLineNo">247</span><a name="line.247"></a>
-<span class="sourceLineNo">248</span>    public ParsedLine parse(byte[] lineBytes, int length)<a name="line.248"></a>
-<span class="sourceLineNo">249</span>    throws BadTsvLineException {<a name="line.249"></a>
-<span class="sourceLineNo">250</span>      // Enumerate separator offsets<a name="line.250"></a>
-<span class="sourceLineNo">251</span>      ArrayList&lt;Integer&gt; tabOffsets = new ArrayList&lt;&gt;(maxColumnCount);<a name="line.251"></a>
-<span class="sourceLineNo">252</span>      for (int i = 0; i &lt; length; i++) {<a name="line.252"></a>
-<span class="sourceLineNo">253</span>        if (lineBytes[i] == separatorByte) {<a name="line.253"></a>
-<span class="sourceLineNo">254</span>          tabOffsets.add(i);<a name="line.254"></a>
-<span class="sourceLineNo">255</span>        }<a name="line.255"></a>
-<span class="sourceLineNo">256</span>      }<a name="line.256"></a>
-<span class="sourceLineNo">257</span>      if (tabOffsets.isEmpty()) {<a name="line.257"></a>
-<span class="sourceLineNo">258</span>        throw new BadTsvLineException("No delimiter");<a name="line.258"></a>
-<span class="sourceLineNo">259</span>      }<a name="line.259"></a>
-<span class="sourceLineNo">260</span><a name="line.260"></a>
-<span class="sourceLineNo">261</span>      tabOffsets.add(length);<a name="line.261"></a>
-<span class="sourceLineNo">262</span><a name="line.262"></a>
-<span class="sourceLineNo">263</span>      if (tabOffsets.size() &gt; maxColumnCount) {<a name="line.263"></a>
-<span class="sourceLineNo">264</span>        throw new BadTsvLineException("Excessive columns");<a name="line.264"></a>
-<span class="sourceLineNo">265</span>      } else if (tabOffsets.size() &lt;= getRowKeyColumnIndex()) {<a name="line.265"></a>
-<span class="sourceLineNo">266</span>        throw new BadTsvLineException("No row key");<a name="line.266"></a>
-<span class="sourceLineNo">267</span>      } else if (hasTimestamp()<a name="line.267"></a>
-<span class="sourceLineNo">268</span>          &amp;&amp; tabOffsets.size() &lt;= getTimestampKeyColumnIndex()) {<a name="line.268"></a>
-<span class="sourceLineNo">269</span>        throw new BadTsvLineException("No timestamp");<a name="line.269"></a>
-<span class="sourceLineNo">270</span>      } else if (hasAttributes() &amp;&amp; tabOffsets.size() &lt;= getAttributesKeyColumnIndex()) {<a name="line.270"></a>
-<span class="sourceLineNo">271</span>        throw new BadTsvLineException("No attributes specified");<a name="line.271"></a>
-<span class="sourceLineNo">272</span>      } else if (hasCellVisibility() &amp;&amp; tabOffsets.size() &lt;= getCellVisibilityColumnIndex()) {<a name="line.272"></a>
-<span class="sourceLineNo">273</span>        throw new BadTsvLineException("No cell visibility specified");<a name="line.273"></a>
-<span class="sourceLineNo">274</span>      } else if (hasCellTTL() &amp;&amp; tabOffsets.size() &lt;= getCellTTLColumnIndex()) {<a name="line.274"></a>
-<span class="sourceLineNo">275</span>        throw new BadTsvLineException("No cell TTL specified");<a name="line.275"></a>
-<span class="sourceLineNo">276</span>      }<a name="line.276"></a>
-<span class="sourceLineNo">277</span>      return new ParsedLine(tabOffsets, lineBytes);<a name="line.277"></a>
-<span class="sourceLineNo">278</span>    }<a name="line.278"></a>
-<span class="sourceLineNo">279</span><a name="line.279"></a>
-<span class="sourceLineNo">280</span>    class ParsedLine {<a name="line.280"></a>
-<span class="sourceLineNo">281</span>      private final ArrayList&lt;Integer&gt; tabOffsets;<a name="line.281"></a>
-<span class="sourceLineNo">282</span>      private byte[] lineBytes;<a name="line.282"></a>
-<span class="sourceLineNo">283</span><a name="line.283"></a>
-<span class="sourceLineNo">284</span>      ParsedLine(ArrayList&lt;Integer&gt; tabOffsets, byte[] lineBytes) {<a name="line.284"></a>
-<span class="sourceLineNo">285</span>        this.tabOffsets = tabOffsets;<a name="line.285"></a>
-<span class="sourceLineNo">286</span>        this.lineBytes = lineBytes;<a name="line.286"></a>
-<span class="sourceLineNo">287</span>      }<a name="line.287"></a>
-<span class="sourceLineNo">288</span><a name="line.288"></a>
-<span class="sourceLineNo">289</span>      public int getRowKeyOffset() {<a name="line.289"></a>
-<span class="sourceLineNo">290</span>        return getColumnOffset(rowKeyColumnIndex);<a name="line.290"></a>
-<span class="sourceLineNo">291</span>      }<a name="line.291"></a>
-<span class="sourceLineNo">292</span>      public int getRowKeyLength() {<a name="line.292"></a>
-<span class="sourceLineNo">293</span>        return getColumnLength(rowKeyColumnIndex);<a name="line.293"></a>
-<span class="sourceLineNo">294</span>      }<a name="line.294"></a>
-<span class="sourceLineNo">295</span><a name="line.295"></a>
-<span class="sourceLineNo">296</span>      public long getTimestamp(long ts) throws BadTsvLineException {<a name="line.296"></a>
-<span class="sourceLineNo">297</span>        // Return ts if HBASE_TS_KEY is not configured in column spec<a name="line.297"></a>
-<span class="sourceLineNo">298</span>        if (!hasTimestamp()) {<a name="line.298"></a>
-<span class="sourceLineNo">299</span>          return ts;<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>        String timeStampStr = Bytes.toString(lineBytes,<a name="line.302"></a>
-<span class="sourceLineNo">303</span>            getColumnOffset(timestampKeyColumnIndex),<a name="line.303"></a>
-<span class="sourceLineNo">304</span>            getColumnLength(timestampKeyColumnIndex));<a name="line.304"></a>
-<span class="sourceLineNo">305</span>        try {<a name="line.305"></a>
-<span class="sourceLineNo">306</span>          return Long.parseLong(timeStampStr);<a name="line.306"></a>
-<span class="sourceLineNo">307</span>        } catch (NumberFormatException nfe) {<a name="line.307"></a>
-<span class="sourceLineNo">308</span>          // treat this record as bad record<a name="line.308"></a>
-<span class="sourceLineNo">309</span>          throw new BadTsvLineException("Invalid timestamp " + timeStampStr);<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><a name="line.312"></a>
-<span class="sourceLineNo">313</span>      private String getAttributes() {<a name="line.313"></a>
-<span class="sourceLineNo">314</span>        if (!hasAttributes()) {<a name="line.314"></a>
-<span class="sourceLineNo">315</span>          return null;<a name="line.315"></a>
-<span class="sourceLineNo">316</span>        } else {<a name="line.316"></a>
-<span class="sourceLineNo">317</span>          return Bytes.toString(lineBytes, getColumnOffset(attrKeyColumnIndex),<a name="line.317"></a>
-<span class="sourceLineNo">318</span>              getColumnLength(attrKeyColumnIndex));<a name="line.318"></a>
-<span class="sourceLineNo">319</span>        }<a name="line.319"></a>
-<span class="sourceLineNo">320</span>      }<a name="line.320"></a>
-<span class="sourceLineNo">321</span><a name="line.321"></a>
-<span class="sourceLineNo">322</span>      public String[] getIndividualAttributes() {<a name="line.322"></a>
-<span class="sourceLineNo">323</span>        String attributes = getAttributes();<a name="line.323"></a>
-<span class="sourceLineNo">324</span>        if (attributes != null) {<a name="line.324"></a>
-<span class="sourceLineNo">325</span>          return attributes.split(DEFAULT_MULTIPLE_ATTRIBUTES_SEPERATOR);<a name="line.325"></a>
-<span class="sourceLineNo">326</span>        } else {<a name="line.326"></a>
-<span class="sourceLineNo">327</span>          return null;<a name="line.327"></a>
-<span class="sourceLineNo">328</span>        }<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 int getAttributeKeyOffset() {<a name="line.331"></a>
-<span class="sourceLineNo">332</span>        if (hasAttributes()) {<a name="line.332"></a>
-<span class="sourceLineNo">333</span>          return getColumnOffset(attrKeyColumnIndex);<a name="line.333"></a>
-<span class="sourceLineNo">334</span>        } else {<a name="line.334"></a>
-<span class="sourceLineNo">335</span>          return DEFAULT_ATTRIBUTES_COLUMN_INDEX;<a name="line.335"></a>
-<span class="sourceLineNo">336</span>        }<a name="line.336"></a>
-<span class="sourceLineNo">337</span>      }<a name="line.337"></a>
-<span class="sourceLineNo">338</span><a name="line.338"></a>
-<span class="sourceLineNo">339</span>      public int getAttributeKeyLength() {<a name="line.339"></a>
-<span class="sourceLineNo">340</span>        if (hasAttributes()) {<a name="line.340"></a>
-<span class="sourceLineNo">341</span>          return getColumnLength(attrKeyColumnIndex);<a name="line.341"></a>
-<span class="sourceLineNo">342</span>        } else {<a name="line.342"></a>
-<span class="sourceLineNo">343</span>          return DEFAULT_ATTRIBUTES_COLUMN_INDEX;<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><a name="line.346"></a>
-<span class="sourceLineNo">347</span>      public int getCellVisibilityColumnOffset() {<a name="line.347"></a>
-<span class="sourceLineNo">348</span>        if (hasCellVisibility()) {<a name="line.348"></a>
-<span class="sourceLineNo">349</span>          return getColumnOffset(cellVisibilityColumnIndex);<a name="line.349"></a>
-<span class="sourceLineNo">350</span>        } else {<a name="line.350"></a>
-<span class="sourceLineNo">351</span>          return DEFAULT_CELL_VISIBILITY_COLUMN_INDEX;<a name="line.351"></a>
-<span class="sourceLineNo">352</span>        }<a name="line.352"></a>
-<span class="sourceLineNo">353</span>      }<a name="line.353"></a>
-<span class="sourceLineNo">354</span><a name="line.354"></a>
-<span class="sourceLineNo">355</span>      public int getCellVisibilityColumnLength() {<a name="line.355"></a>
-<span class="sourceLineNo">356</span>        if (hasCellVisibility()) {<a name="line.356"></a>
-<span class="sourceLineNo">357</span>          return getColumnLength(cellVisibilityColumnIndex);<a name="line.357"></a>
-<span class="sourceLineNo">358</span>        } else {<a name="line.358"></a>
-<span class="sourceLineNo">359</span>          return DEFAULT_CELL_VISIBILITY_COLUMN_INDEX;<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>      public String getCellVisibility() {<a name="line.363"></a>
-<span class="sourceLineNo">364</span>        if (!hasCellVisibility()) {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>          return null;<a name="line.365"></a>
-<span class="sourceLineNo">366</span>        } else {<a name="line.366"></a>
-<span class="sourceLineNo">367</span>          return Bytes.toString(lineBytes, getColumnOffset(cellVisibilityColumnIndex),<a name="line.367"></a>
-<span class="sourceLineNo">368</span>              getColumnLength(cellVisibilityColumnIndex));<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><a name="line.371"></a>
-<span class="sourceLineNo">372</span>      public int getCellTTLColumnOffset() {<a name="line.372"></a>
-<span class="sourceLineNo">373</span>        if (hasCellTTL()) {<a name="line.373"></a>
-<span class="sourceLineNo">374</span>          return getColumnOffset(cellTTLColumnIndex);<a name="line.374"></a>
-<span class="sourceLineNo">375</span>        } else {<a name="line.375"></a>
-<span class="sourceLineNo">376</span>          return DEFAULT_CELL_TTL_COLUMN_INDEX;<a name="line.376"></a>
-<span class="sourceLineNo">377</span>        }<a name="line.377"></a>
-<span class="sourceLineNo">378</span>      }<a name="line.378"></a>
-<span class="sourceLineNo">379</span><a name="line.379"></a>
-<span class="sourceLineNo">380</span>      public int getCellTTLColumnLength() {<a name="line.380"></a>
-<span class="sourceLineNo">381</span>        if (hasCellTTL()) {<a name="line.381"></a>
-<span class="sourceLineNo">382</span>          return getColumnLength(cellTTLColumnIndex);<a name="line.382"></a>
-<span class="sourceLineNo">383</span>        } else {<a name="line.383"></a>
-<span class="sourceLineNo">384</span>          return DEFAULT_CELL_TTL_COLUMN_INDEX;<a name="line.384"></a>
-<span class="sourceLineNo">385</span>        }<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 long getCellTTL() {<a name="line.388"></a>
-<span class="sourceLineNo">389</span>        if (!hasCellTTL()) {<a name="line.389"></a>
-<span class="sourceLineNo">390</span>          return 0;<a name="line.390"></a>
-<span class="sourceLineNo">391</span>        } else {<a name="line.391"></a>
-<span class="sourceLineNo">392</span>          return Bytes.toLong(lineBytes, getColumnOffset(cellTTLColumnIndex),<a name="line.392"></a>
-<span class="sourceLineNo">393</span>              getColumnLength(cellTTLColumnIndex));<a name="line.393"></a>
-<span class="sourceLineNo">394</span>        }<a name="line.394"></a>
-<span class="sourceLineNo">395</span>      }<a name="line.395"></a>
-<span class="sourceLineNo">396</span><a name="line.396"></a>
-<span class="sourceLineNo">397</span>      public int getColumnOffset(int idx) {<a name="line.397"></a>
-<span class="sourceLineNo">398</span>        if (idx &gt; 0)<a name="line.398"></a>
-<span class="sourceLineNo">399</span>          return tabOffsets.get(idx - 1) + 1;<a name="line.399"></a>
-<span class="sourceLineNo">400</span>        else<a name="line.400"></a>
-<span class="sourceLineNo">401</span>          return 0;<a name="line.401"></a>
-<span class="sourceLineNo">402</span>      }<a name="line.402"></a>
-<span class="sourceLineNo">403</span>      public int getColumnLength(int idx) {<a name="line.403"></a>
-<span class="sourceLineNo">404</span>        return tabOffsets.get(idx) - getColumnOffset(idx);<a name="line.404"></a>
-<span class="sourceLineNo">405</span>      }<a name="line.405"></a>
-<span class="sourceLineNo">406</span>      public int getColumnCount() {<a name="line.406"></a>
-<span class="sourceLineNo">407</span>        return tabOffsets.size();<a name="line.407"></a>
-<span class="sourceLineNo">408</span>      }<a name="line.408"></a>
-<span class="sourceLineNo">409</span>      public byte[] getLineBytes() {<a name="line.409"></a>
-<span class="sourceLineNo">410</span>        return lineBytes;<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><a name="line.413"></a>
-<span class="sourceLineNo">414</span>    public static class BadTsvLineException extends Exception {<a name="line.414"></a>
-<span class="sourceLineNo">415</span>      public BadTsvLineException(String err) {<a name="line.415"></a>
-<span class="sourceLineNo">416</span>        super(err);<a name="line.416"></a>
-<span class="sourceLineNo">417</span>      }<a name="line.417"></a>
-<span class="sourceLineNo">418</span>      private static final long serialVersionUID = 1L;<a name="line.418"></a>
-<span class="sourceLineNo">419</span>    }<a name="line.419"></a>
-<span class="sourceLineNo">420</span><a name="line.420"></a>
-<span class="sourceLineNo">421</span>    /**<a name="line.421"></a>
-<span class="sourceLineNo">422</span>     * Return starting position and length of row key from the specified line bytes.<a name="line.422"></a>
-<span class="sourceLineNo">423</span>     * @param lineBytes<a name="line.423"></a>
-<span class="sourceLineNo">424</span>     * @param length<a name="line.424"></a>
-<span class="sourceLineNo">425</span>     * @return Pair of row key offset and length.<a name="line.425"></a>
-<span class="sourceLineNo">426</span>     * @throws BadTsvLineException<a name="line.426"></a>
-<span class="sourceLineNo">427</span>     */<a name="line.427"></a>
-<span class="sourceLineNo">428</span>    public Pair&lt;Integer, Integer&gt; parseRowKey(byte[] lineBytes, int length)<a name="line.428"></a>
-<span class="sourceLineNo">429</span>        throws BadTsvLineException {<a name="line.429"></a>
-<span class="sourceLineNo">430</span>      int rkColumnIndex = 0;<a name="line.430"></a>
-<span class="sourceLineNo">431</span>      int startPos = 0, endPos = 0;<a name="line.431"></a>
-<span class="sourceLineNo">432</span>      for (int i = 0; i &lt;= length; i++) {<a name="line.432"></a>
-<span class="sourceLineNo">433</span>        if (i == length || lineBytes[i] == separatorByte) {<a name="line.433"></a>
-<span class="sourceLineNo">434</span>          endPos = i - 1;<a name="line.434"></a>
-<span class="sourceLineNo">435</span>          if (rkColumnIndex++ == getRowKeyColumnIndex()) {<a name="line.435"></a>
-<span class="sourceLineNo">436</span>            if ((endPos + 1) == startPos) {<a name="line.436"></a>
-<span class="sourceLineNo">437</span>              throw new BadTsvLineException("Empty value for ROW KEY.");<a name="line.437"></a>
-<span class="sourceLineNo">438</span>            }<a name="line.438"></a>
-<span class="sourceLineNo">439</span>            break;<a name="line.439"></a>
-<span class="sourceLineNo">440</span>          } else {<a name="line.440"></a>
-<span class="sourceLineNo">441</span>            startPos = endPos + 2;<a name="line.441"></a>
-<span class="sourceLineNo">442</span>          }<a name="line.442"></a>
-<span class="sourceLineNo">443</span>        }<a name="line.443"></a>
-<span class="sourceLineNo">444</span>        if (i == length) {<a name="line.444"></a>
-<span class="sourceLineNo">445</span>          throw new BadTsvLineException(<a name="line.445"></a>
-<span class="sourceLineNo">446</span>              "Row key does not exist as number of columns in the line"<a name="line.446"></a>
-<span class="sourceLineNo">447</span>                  + " are less than row key position.");<a name="line.447"></a>
-<span class="sourceLineNo">448</span>        }<a name="line.448"></a>
-<span class="sourceLineNo">449</span>      }<a name="line.449"></a>
-<span class="sourceLineNo">450</span>      return new Pair&lt;&gt;(startPos, endPos - startPos + 1);<a name="line.450"></a>
-<span class="sourceLineNo">451</span>    }<a name="line.451"></a>
-<span class="sourceLineNo">452</span>  }<a name="line.452"></a>
-<span class="sourceLineNo">453</span><a name="line.453"></a>
-<span class="sourceLineNo">454</span>  /**<a name="line.454"></a>
-<span class="sourceLineNo">455</span>   * Sets up the actual job.<a name="line.455"></a>
-<span class="sourceLineNo">456</span>   *<a name="line.456"></a>
-<span class="sourceLineNo">457</span>   * @param conf  The current configuration.<a name="line.457"></a>
-<span class="sourceLineNo">458</span>   * @param args  The command line parameters.<a name="line.458"></a>
-<span class="sourceLineNo">459</span>   * @return The newly created job.<a name="line.459"></a>
-<span class="sourceLineNo">460</span>   * @throws IOException When setting up the job fails.<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   */<a name="line.461"></a>
-<span class="sourceLineNo">462</span>  protected static Job createSubmittableJob(Configuration conf, String[] args)<a name="line.462"></a>
-<span class="sourceLineNo">463</span>      throws IOException, ClassNotFoundException {<a name="line.463"></a>
-<span class="sourceLineNo">464</span>    Job job = null;<a name="line.464"></a>
-<span class="sourceLineNo">465</span>    boolean isDryRun = conf.getBoolean(DRY_RUN_CONF_KEY, false);<a name="line.465"></a>
-<span class="sourceLineNo">466</span>    try (Connection connection = ConnectionFactory.createConnection(conf)) {<a name="line.466"></a>
-<span class="sourceLineNo">467</span>      try (Admin admin = connection.getAdmin()) {<a name="line.467"></a>
-<span class="sourceLineNo">468</span>        // Support non-XML supported characters<a name="line.468"></a>
-<span class="sourceLineNo">469</span>        // by re-encoding the passed separator as a Base64 string.<a name="line.469"></a>
-<span class="sourceLineNo">470</span>        String actualSeparator = conf.get(SEPARATOR_CONF_KEY);<a name="line.470"></a>
-<span class="sourceLineNo">471</span>        if (actualSeparator != null) {<a name="line.471"></a>
-<span class="sourceLineNo">472</span>          conf.set(SEPARATOR_CONF_KEY,<a name="line.472"></a>
-<span class="sourceLineNo">473</span>              Bytes.toString(Base64.getEncoder().encode(Bytes.toBytes(actualSeparator))));<a name="line.473"></a>
-<span class="sourceLineNo">474</span>        }<a name="line.474"></a>
-<span class="sourceLineNo">475</span><a name="line.475"></a>
-<span class="sourceLineNo">476</span>        // See if a non-default Mapper was set<a name="line.476"></a>
-<span class="sourceLineNo">477</span>        String mapperClassName = conf.get(MAPPER_CONF_KEY);<a name="line.477"></a>
-<span class="sourceLineNo">478</span>        Class mapperClass = mapperClassName != null? Class.forName(mapperClassName): DEFAULT_MAPPER;<a name="line.478"></a>
-<span class="sourceLineNo">479</span><a name="line.479"></a>
-<span class="sourceLineNo">480</span>        TableName tableName = TableName.valueOf(args[0]);<a name="line.480"></a>
-<span class="sourceLineNo">481</span>        Path inputDir = new Path(args[1]);<a name="line.481"></a>
-<span class="sourceLineNo">482</span>        String jobName = conf.get(JOB_NAME_CONF_KEY,NAME + "_" + tableName.getNameAsString());<a name="line.482"></a>
-<span class="sourceLineNo">483</span>        job = Job.getInstance(conf, jobName);<a name="line.483"></a>
-<span class="sourceLineNo">484</span>        job.setJarByClass(mapperClass);<a name="line.484"></a>
-<span class="sourceLineNo">485</span>        FileInputFormat.setInputPaths(job, inputDir);<a name="line.485"></a>
-<span class="sourceLineNo">486</span>        job.setInputFormatClass(TextInputFormat.class);<a name="line.486"></a>
-<span class="sourceLineNo">487</span>        job.setMapperClass(mapperClass);<a name="line.487"></a>
-<span class="sourceLineNo">488</span>        job.setMapOutputKeyClass(ImmutableBytesWritable.class);<a name="line.488"></a>
-<span class="sourceLineNo">489</span>        String hfileOutPath = conf.get(BULK_OUTPUT_CONF_KEY);<a name="line.489"></a>
-<span class="sourceLineNo">490</span>        String[] columns = conf.getStrings(COLUMNS_CONF_KEY);<a name="line.490"></a>
-<span class="sourceLineNo">491</span>        if(StringUtils.isNotEmpty(conf.get(CREDENTIALS_LOCATION))) {<a name="line.491"></a>
-<span class="sourceLineNo">492</span>          String fileLoc = conf.get(CREDENTIALS_LOCATION);<a name="line.492"></a>
-<span class="sourceLineNo">493</span>          Credentials cred = Credentials.readTokenStorageFile(new File(fileLoc), conf);<a name="line.493"></a>
-<span class="sourceLineNo">494</span>          job.getCredentials().addAll(cred);<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>        if (hfileOutPath != null) {<a name="line.497"></a>
-<span class="sourceLineNo">498</span>          if (!admin.tableExists(tableName)) {<a name="line.498"></a>
-<span class="sourceLineNo">499</span>            LOG.warn(format("Table '%s' does not exist.", tableName));<a name="line.499"></a>
-<span class="sourceLineNo">500</span>            if ("yes".equalsIgnoreCase(conf.get(CREATE_TABLE_CONF_KEY, "yes"))) {<a name="line.500"></a>
-<span class="sourceLineNo">501</span>              // TODO: this is backwards. Instead of depending on the existence of a table,<a name="line.501"></a>
-<span class="sourceLineNo">502</span>              // create a sane splits file for HFileOutputFormat based on data sampling.<a name="line.502"></a>
-<span class="sourceLineNo">503</span>              createTable(admin, tableName, columns);<a name="line.503"></a>
-<span class="sourceLineNo">504</span>              if (isDryRun) {<a name="line.504"></a>
-<span class="sourceLineNo">505</span>                LOG.warn("Dry run: Table will be deleted at end of dry run.");<a name="line.505"></a>
-<span class="sourceLineNo">506</span>                synchronized (ImportTsv.class) {<a name="line.506"></a>
-<span class="sourceLineNo">507</span>                  DRY_RUN_TABLE_CREATED = true;<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>            } else {<a name="line.510"></a>
-<span class="sourceLineNo">511</span>              String errorMsg =<a name="line.511"></a>
-<span class="sourceLineNo">512</span>                  format("Table '%s' does not exist and '%s' is set to no.", tableName,<a name="line.512"></a>
-<span class="sourceLineNo">513</span>                      CREATE_TABLE_CONF_KEY);<a name="line.513"></a>
-<span class="sourceLineNo">514</span>              LOG.error(errorMsg);<a name="line.514"></a>
-<span class="sourceLineNo">515</span>              throw new TableNotFoundException(errorMsg);<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>          try (Table table = connection.getTable(tableName);<a name="line.518"></a>
-<span class="sourceLineNo">519</span>              RegionLocator regionLocator = connection.getRegionLocator(tableName)) {<a name="line.519"></a>
-<span class="sourceLineNo">520</span>            boolean noStrict = conf.getBoolean(NO_STRICT_COL_FAMILY, false);<a name="line.520"></a>
-<span class="sourceLineNo">521</span>            // if no.strict is false then check column family<a name="line.521"></a>
-<span class="sourceLineNo">522</span>            if(!noStrict) {<a name="line.522"></a>
-<span class="sourceLineNo">523</span>              ArrayList&lt;String&gt; unmatchedFamilies = new ArrayList&lt;&gt;();<a name="line.523"></a>
-<span class="sourceLineNo">524</span>              Set&lt;String&gt; cfSet = getColumnFamilies(columns);<a name="line.524"></a>
-<span class="sourceLineNo">525</span>              TableDescriptor tDesc = table.getDescriptor();<a name="line.525"></a>
-<span class="sourceLineNo">526</span>              for (String cf : cfSet) {<a name="line.526"></a>
-<span class="sourceLineNo">527</span>                if(!tDesc.hasColumnFamily(Bytes.toBytes(cf))) {<a name="line.527"></a>
-<span class="sourceLineNo">528</span>                  unmatchedFamilies.add(cf);<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(unmatchedFamilies.size() &gt; 0) {<a name="line.531"></a>
-<span class="sourceLineNo">532</span>                ArrayList&lt;String&gt; familyNames = new ArrayList&lt;&gt;();<a name="line.532"></a>
-<span class="sourceLineNo">533</span>                for (ColumnFamilyDescriptor family : table.getDescriptor().getColumnFamilies()) {<a name="line.533"></a>
-<span class="sourceLineNo">534</span>                  familyNames.add(family.getNameAsString());<a name="line.534"></a>
-<span class="sourceLineNo">535</span>                }<a name="line.535"></a>
-<span class="sourceLineNo">536</span>                String msg =<a name="line.536"></a>
-<span class="sourceLineNo">537</span>                    "Column Families " + unmatchedFamilies + " specified in " + COLUMNS_CONF_KEY<a name="line.537"></a>
-<span class="sourceLineNo">538</span>                    + " does not match with any of the table " + tableName<a name="line.538"></a>
-<span class="sourceLineNo">539</span>                    + " column families " + familyNames + ".\n"<a name="line.539"></a>
-<span class="sourceLineNo">540</span>                    + "To disable column family check, use -D" + NO_STRICT_COL_FAMILY<a name="line.540"></a>
-<span class="sourceLineNo">541</span>                    + "=true.\n";<a name="line.541"></a>
-<span class="sourceLineNo">542</span>                usage(msg);<a name="line.542"></a>
-<span class="sourceLineNo">543</span>                System.exit(-1);<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">546</span>            if (mapperClass.equals(TsvImporterTextMapper.class)) {<a name="line.546"></a>
-<span class="sourceLineNo">547</span>              job.setMapOutputValueClass(Text.class);<a name="line.547"></a>
-<span class="sourceLineNo">548</span>              job.setReducerClass(TextSortReducer.class);<a name="line.548"></a>
-<span class="sourceLineNo">549</span>            } else {<a name="line.549"></a>
-<span class="sourceLineNo">550</span>              job.setMapOutputValueClass(Put.class);<a name="line.550"></a>
-<span class="sourceLineNo">551</span>              job.setCombinerClass(PutCombiner.class);<a name="line.551"></a>
-<span class="sourceLineNo">552</span>              job.setReducerClass(PutSortReducer.class);<a name="line.552"></a>
-<span class="sourceLineNo">553</span>            }<a name="line.553"></a>
-<span class="sourceLineNo">554</span>            if (!isDryRun) {<a name="line.554"></a>
-<span class="sourceLineNo">555</span>              Path outputDir = new Path(hfileOutPath);<a name="line.555"></a>
-<span class="sourceLineNo">556</span>              FileOutputFormat.setOutputPath(job, outputDir);<a name="line.556"></a>
-<span class="sourceLineNo">557</span>              HFileOutputFormat2.configureIncrementalLoad(job, table.getDescriptor(),<a name="line.557"></a>
-<span class="sourceLineNo">558</span>                  regionLocator);<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>        } else {<a name="line.561"></a>
-<span class="sourceLineNo">562</span>          if (!admin.tableExists(tableName)) {<a name="line.562"></a>
-<span class="sourceLineNo">563</span>            String errorMsg = format("Table '%s' does not exist.", tableName);<a name="line.563"></a>
-<span class="sourceLineNo">564</span>            LOG.error(errorMsg);<a name="line.564"></a>
-<span class="sourceLineNo">565</span>            throw new TableNotFoundException(errorMsg);<a name="line.565"></a>
-<span class="sourceLineNo">566</span>          }<a name="line.566"></a>
-<span class="sourceLineNo">567</span>          if (mapperClass.equals(TsvImporterTextMapper.class)) {<a name="line.567"></a>
-<span class="sourceLineNo">568</span>            usage(TsvImporterTextMapper.class.toString()<a name="line.568"></a>
-<span class="sourceLineNo">569</span>                + " should not be used for non bulkloading case. use "<a name="line.569"></a>
-<span class="sourceLineNo">570</span>                + TsvImporterMapper.class.toString()<a name="line.570"></a>
-<span class="sourceLineNo">571</span>                + " or custom mapper whose value type is Put.");<a name="line.571"></a>
-<span class="sourceLineNo">572</span>            System.exit(-1);<a name="line.572"></a>
-<span class="sourceLineNo">573</span>          }<a name="line.573"></a>
-<span class="sourceLineNo">574</span>          if (!isDryRun) {<a name="line.574"></a>
-<span class="sourceLineNo">575</span>            // No reducers. Just write straight to table. Call initTableReducerJob<a name="line.575"></a>
-<span class="sourceLineNo">576</span>            // to set up the TableOutputFormat.<a name="line.576"></a>
-<span class="sourceLineNo">577</span>            TableMapReduceUtil.initTableReducerJob(tableName.getNameAsString(), null, job);<a name="line.577"></a>
-<span class="sourceLineNo">578</span>          }<a name="line.578"></a>
-<span class="sourceLineNo">579</span>          job.setNumReduceTasks(0);<a name="line.579"></a>
-<span class="sourceLineNo">580</span>        }<a name="line.580"></a>
-<span class="sourceLineNo">581</span>        if (isDryRun) {<a name="line.581"></a>
-<span class="sourceLineNo">582</span>          job.setOutputFormatClass(NullOutputFormat.class);<a name="line.582"></a>
-<span class="sourceLineNo">583</span>          job.getConfiguration().setStrings("io.serializations",<a name="line.583"></a>
-<span class="sourceLineNo">584</span>              job.getConfiguration().get("io.serializations"),<a name="line.584"></a>
-<span class="sourceLineNo">585</span>              MutationSerialization.class.getName(), ResultSerialization.class.getName(),<a name="line.585"></a>
-<span class="sourceLineNo">586</span>              CellSerialization.class.getName());<a name="line.586"></a>
-<span class="sourceLineNo">587</span>        }<a name="line.587"></a>
-<span class="sourceLineNo">588</span>        TableMapReduceUtil.addDependencyJars(job);<a name="line.588"></a>
-<span class="sourceLineNo">589</span>        TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.589"></a>
-<span class="sourceLineNo">590</span>            org.apache.hbase.thirdparty.com.google.common.base.Function.class /* Guava used by TsvParser */);<a name="line.590"></a>
-<span class="sourceLineNo">591</span>      }<a name="line.591"></a>
-<span class="sourceLineNo">592</span>    }<a name="line.592"></a>
-<span class="sourceLineNo">593</span>    return job;<a name="line.593"></a>
-<span class="sourceLineNo">594</span>  }<a name="line.594"></a>
-<span class="sourceLineNo">595</span><a name="line.595"></a>
-<span class="sourceLineNo">596</span>  private static void createTable(Admin admin, TableName tableName, String[] columns)<a name="line.596"></a>
-<span class="sourceLineNo">597</span>      throws IOException {<a name="line.597"></a>
-<span class="sourceLineNo">598</span>    TableDescriptorBuilder builder =<a name="line.598"></a>
-<span class="sourceLineNo">599</span>      TableDescriptorBuilder.newBuilder(tableName);<a name="line.599"></a>
-<span class="sourceLineNo">600</span>    Set&lt;String&gt; cfSet = getColumnFamilies(columns);<a name="line.600"></a>
-<span class="sourceLineNo">601</span>    for (String cf : cfSet) {<a name="line.601"></a>
-<span class="sourceLineNo">602</span>      builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of(cf));<a name="line.602"></a>
-<span class="sourceLineNo">603</span>    }<a name="line.603"></a>
-<span class="sourceLineNo">604</span>    LOG.warn(format("Creating table '%s' with '%s' columns and default descriptors.",<a name="line.604"></a>
-<span class="sourceLineNo">605</span>      tableName, cfSet));<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    admin.createTable(builder.build());<a name="line.606"></a>
-<span class="sourceLineNo">607</span>  }<a name="line.607"></a>
-<span class="sourceLineNo">608</span><a name="line.608"></a>
-<span class="sourceLineNo">609</span>  private static void deleteTable(Configuration conf, String[] args) {<a name="line.609"></a>
-<span class="sourceLineNo">610</span>    TableName tableName = TableName.valueOf(args[0]);<a name="line.610"></a>
-<span class="sourceLineNo">611</span>    try (Connection connection = ConnectionFactory.createConnection(conf);<a name="line.611"></a>
-<span class="sourceLineNo">612</span>         Admin admin = connection.getAdmin()) {<a name="line.612"></a>
-<span class="sourceLineNo">613</span>      try {<a name="line.613"></a>
-<span class="sourceLineNo">614</span>        admin.disableTable(tableName);<a name="line.614"></a>
-<span class="sourceLineNo">615</span>      } catch (TableNotEnabledException e) {<a name="line.615"></a>
-<span class="sourceLineNo">616</span>        LOG.debug("Dry mode: Table: " + tableName + " already disabled, so just deleting it.");<a name="line.616"></a>
-<span class="sourceLineNo">617</span>      }<a name="line.617"></a>
-<span class="sourceLineNo">618</span>      admin.deleteTable(tableName);<a name="line.618"></a>
-<span class="sourceLineNo">619</span>    } catch (IOException e) {<a name="line.619"></a>
-<span class="sourceLineNo">620</span>      LOG.error(format("***Dry run: Failed to delete table '%s'.***%n%s", tableName,<a name="line.620"></a>
-<span class="sourceLineNo">621</span>          e.toString()));<a name="line.621"></a>
-<span class="sourceLineNo">622</span>      return;<a name="line.622"></a>
-<span class="sourceLineNo">623</span>    }<a name="line.623"></a>
-<span class="sourceLineNo">624</span>    LOG.info(format("Dry run: Deleted table '%s'.", tableName));<a name="line.624"></a>
-<span class="sourceLineNo">625</span>  }<a name="line.625"></a>
-<span class="sourceLineNo">626</span><a name="line.626"></a>
-<span class="sourceLineNo">627</span>  private static Set&lt;String&gt; getColumnFamilies(String[] columns) {<a name="line.627"></a>
-<span class="sourceLineNo">628</span>    Set&lt;String&gt; cfSet = new HashSet&lt;&gt;();<a name="line.628"></a>
-<span class="sourceLineNo">629</span>    for (String aColumn : columns) {<a name="line.629"></a>
-<span class="sourceLineNo">630</span>      if (TsvParser.ROWKEY_COLUMN_SPEC.equals(aColumn)<a name="line.630"></a>
-<span class="sourceLineNo">631</span>          || TsvParser.TIMESTAMPKEY_COLUMN_SPEC.equals(aColumn)<a name="line.631"></a>
-<span class="sourceLineNo">632</span>          || TsvParser.CELL_VISIBILITY_COLUMN_SPEC.equals(aColumn)<a name="line.632"></a>
-<span class="sourceLineNo">633</span>          || TsvParser.CELL_TTL_COLUMN_SPEC.equals(aColumn)<a name="line.633"></a>
-<span class="sourceLineNo">634</span>          || TsvParser.ATTRIBUTES_COLUMN_SPEC.equals(aColumn))<a name="line.634"></a>
-<span class="sourceLineNo">635</span>        continue;<a name="line.635"></a>
-<span class="sourceLineNo">636</span>      // we are only concerned with the first one (in case this is a cf:cq)<a name="line.636"></a>
-<span class="sourceLineNo">637</span>      cfSet.add(aColumn.split(":", 2)[0]);<a name="line.637"></a>
-<span class="sourceLineNo">638</span>    }<a name="line.638"></a>
-<span class="sourceLineNo">639</span>    return cfSet;<a name="line.639"></a>
-<span class="sourceLineNo">640</span>  }<a name="line.640"></a>
-<span class="sourceLineNo">641</span><a name="line.641"></a>
-<span class="sourceLineNo">642</span>  /*<a name="line.642"></a>
-<span class="sourceLineNo">643</span>   * @param errorMsg Error message.  Can be null.<a name="line.643"></a>
-<span class="sourceLineNo">644</span>   */<a name="line.644"></a>
-<span class="sourceLineNo">645</span>  private static void usage(final String errorMsg) {<a name="line.645"></a>
-<span class="sourceLineNo">646</span>    if (errorMsg != null &amp;&amp; errorMsg.length() &gt; 0) {<a name="line.646"></a>
-<span class="sourceLineNo">647</span>      System.err.println("ERROR: " + errorMsg);<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    }<a name="line.648"></a>
-<span class="sourceLineNo">649</span>    String usage =<a name="line.649"></a>
-<span class="sourceLineNo">650</span>      "Usage: " + NAME + " -D"+ COLUMNS_CONF_KEY + "=a,b,c &lt;tablename&gt; &lt;inputdir&gt;\n" +<a name="line.650"></a>
-<span class="sourceLineNo">651</span>      "\n" +<a name="line.651"></a>
-<span class="sourceLineNo">652</span>      "Imports the given input directory of TSV data into the specified table.\n" +<a name="line.652"></a>
-<span class="sourceLineNo">653</span>      "\n" +<a name="line.653"></a>
-<span class="sourceLineNo">654</span>      "The column names of the TSV data must be specified using the -D" + COLUMNS_CONF_KEY + "\n" +<a name="line.654"></a>
-<span class="sourceLineNo">655</span>      "option. This option takes the form of comma-separated column names, where each\n" +<a name="line.655"></a>
-<span class="sourceLineNo">656</span>      "column name is either a simple column family, or a columnfamily:qualifier. The special\n" +<a name="line.656"></a>
-<span class="sourceLineNo">657</span>      "column name " + TsvParser.ROWKEY_COLUMN_SPEC + " is used to designate that this column should be used\n" +<a name="line.657"></a>
-<span class="sourceLineNo">658</span>      "as the row key for each imported record. You must specify exactly one column\n" +<a name="line.658"></a>
-<span class="sourceLineNo">659</span>      "to be the row key, and you must specify a column name for every column that exists in the\n" +<a name="line.659"></a>
-<span class="sourceLineNo">660</span>      "input data. Another special column" + TsvParser.TIMESTAMPKEY_COLUMN_SPEC +<a name="line.660"></a>
-<span class="sourceLineNo">661</span>      " designates that this column should be\n" +<a name="line.661"></a>
-<span class="sourceLineNo">662</span>      "used as timestamp for each record. Unlike " + TsvParser.ROWKEY_COLUMN_SPEC + ", " +<a name="line.662"></a>
-<span class="sourceLineNo">663</span>      TsvParser.TIMESTAMPKEY_COLUMN_SPEC + " is optional." + "\n" +<a name="line.663"></a>
-<span class="sourceLineNo">664</span>      "You must specify at most one column as timestamp key for each imported record.\n" +<a name="line.664"></a>
-<span class="sourceLineNo">665</span>      "Record with invalid timestamps (blank, non-numeric) will be treated as bad record.\n" +<a name="line.665"></a>
-<span class="sourceLineNo">666</span>      "Note: if you use this option, then '" + TIMESTAMP_CONF_KEY + "' option will be ignored.\n" +<a name="line.666"></a>
-<span class="sourceLineNo">667</span>      "\n" +<a name="line.667"></a>
-<span class="sourceLineNo">668</span>      "Other special columns that can be specified are " + TsvParser.CELL_TTL_COLUMN_SPEC +<a name="line.668"></a>
-<span class="sourceLineNo">669</span>      " and " + TsvParser.CELL_VISIBILITY_COLUMN_SPEC + ".\n" +<a name="line.669"></a>
-<span class="sourceLineNo">670</span>      TsvParser.CELL_TTL_COLUMN_SPEC + " designates that this column will be used " +<a name="line.670"></a>
-<span class="sourceLineNo">671</span>      "as a Cell's Time To Live (TTL) attribute.\n" +<a name="line.671"></a>
-<span class="sourceLineNo">672</span>      TsvParser.CELL_VISIBILITY_COLUMN_SPEC + " designates that this column contains the " +<a name="line.672"></a>
-<span class="sourceLineNo">673</span>      "visibility label expression.\n" +<a name="line.673"></a>
-<span class="sourceLineNo">674</span>      "\n" +<a name="line.674"></a>
-<span class="sourceLineNo">675</span>      TsvParser.ATTRIBUTES_COLUMN_SPEC+" can be used to specify Operation Attributes per record.\n"+<a name="line.675"></a>
-<span class="sourceLineNo">676</span>      " Should be specified as key=&gt;value where "+TsvParser.DEFAULT_ATTRIBUTES_COLUMN_INDEX+ " is used \n"+<a name="line.676"></a>
-<span class="sourceLineNo">677</span>      " as the seperator.  Note that more than one OperationAttributes can be specified.\n"+<a name="line.677"></a>
-<span class="sourceLineNo">678</span>      "By default importtsv will load data directly into HBase. To instead generate\n" +<a name="line.678"></a>
-<span class="sourceLineNo">679</span>      "HFiles of data to prepare for a bulk data load, pass the option:\n" +<a name="line.679"></a>
-<span class="sourceLineNo">680</span>      "  -D" + BULK_OUTPUT_CONF_KEY + "=/path/for/output\n" +<a name="line.680"></a>
-<span class="sourceLineNo">681</span>      "  Note: if you do not use this option, then the target table must already exist in HBase\n" +<a name="line.681"></a>
-<span class="sourceLineNo">682</span>      "\n" +<a name="line.682"></a>
-<span class="sourceLineNo">683</span>      "Other options that may be specified with -D include:\n" +<a name="line.683"></a>
-<span class="sourceLineNo">684</span>      "  -D" + DRY_RUN_CONF_KEY + "=true - Dry run mode. Data is not actually populated into" +<a name="line.684"></a>
-<span class="sourceLineNo">685</span>      " table. If table does not exist, it is created but deleted in the end.\n" +<a name="line.685"></a>
-<span class="sourceLineNo">686</span>      "  -D" + SKIP_LINES_CONF_KEY + "=false - fail if encountering an invalid line\n" +<a name="line.686"></a>
-<span class="sourceLineNo">687</span>      "  -D" + LOG_BAD_LINES_CONF_KEY + "=true - logs invalid lines to stderr\n" +<a name="line.687"></a>
-<span class="sourceLineNo">688</span>      "  -D" + SKIP_EMPTY_COLUMNS + "=false - If true then skip empty columns in bulk import\n" +<a name="line.688"></a>
-<span class="sourceLineNo">689</span>      "  '-D" + SEPARATOR_CONF_KEY + "=|' - eg separate on pipes instead of tabs\n" +<a name="line.689"></a>
-<span class="sourceLineNo">690</span>      "  -D" + TIMESTAMP_CONF_KEY + "=currentTimeAsLong - use the specified timestamp for the import\n" +<a name="line.690"></a>
-<span class="sourceLineNo">691</span>      "  -D" + MAPPER_CONF_KEY + "=my.Mapper - A user-defined Mapper to use instead of " +<a name="line.691"></a>
-<span class="sourceLineNo">692</span>      DEFAULT_MAPPER.getName() + "\n" +<a name="line.692"></a>
-<span class="sourceLineNo">693</span>      "  -D" + JOB_NAME_CONF_KEY + "=jobName - use the specified mapreduce job name for the import\n" +<a name="line.693"></a>
-<span class="sourceLineNo">694</span>      "  -D" + CREATE_TABLE_CONF_KEY + "=no - can be used to avoid creation of table by this tool\n" +<a name="line.694"></a>
-<span class="sourceLineNo">695</span>      "  Note: if you set this to 'no', then the target table must already exist in HBase\n" +<a name="line.695"></a>
-<span class="sourceLineNo">696</span>      "  -D" + NO_STRICT_COL_FAMILY + "=true - ignore column family check in hbase table. " +<a name="line.696"></a>
-<span class="sourceLineNo">697</span>      "Default is false\n\n" +<a name="line.697"></a>
-<span class="sourceLineNo">698</span>      "For performance consider the following options:\n" +<a name="line.698"></a>
-<span class="sourceLineNo">699</span>      "  -Dmapreduce.map.speculative=false\n" +<a name="line.699"></a>
-<span class="sourceLineNo">700</span>      "  -Dmapreduce.reduce.speculative=false";<a name="line.700"></a>
-<span class="sourceLineNo">701</span><a name="line.701"></a>
-<span class="sourceLineNo">702</span>    System.err.println(usage);<a name="line.702"></a>
-<span class="sourceLineNo">703</span>  }<a name="line.703"></a>
-<span class="sourceLineNo">704</span><a name="line.704"></a>
-<span class="sourceLineNo">705</span>  @Override<a name="line.705"></a>
-<span class="sourceLineNo">706</span>  public int run(String[] args) throws Exception {<a name="line.706"></a>
-<span class="sourceLineNo">707</span>    if (args.length &lt; 2) {<a name="line.707"></a>
-<span class="sourceLineNo">708</span>      usage("Wrong number of arguments: " + args.length);<a name="line.708"></a>
-<span class="sourceLineNo">709</span>      return -1;<a name="line.709"></a>
-<span class="sourceLineNo">710</span>    }<a name="line.710"></a>
-<span class="sourceLineNo">711</span><a name="line.711"></a>
-<span class="sourceLineNo">712</span>    // When MAPPER_CONF_KEY is null, the user wants to use the provided TsvImporterMapper, so<a name="line.712"></a>
-<span class="sourceLineNo">713</span>    // perform validation on these additional args. When it's not null, user has provided their<a name="line.713"></a>
-<span class="sourceLineNo">714</span>    // own mapper, thus these validation are not relevant.<a name="line.714"></a>
-<span class="sourceLineNo">715</span>    // TODO: validation for TsvImporterMapper, not this tool. Move elsewhere.<a name="line.715"></a>
-<span class="sourceLineNo">716</span>    if (null == getConf().get(MAPPER_CONF_KEY)) {<a name="line.716"></a>
-<span class="sourceLineNo">717</span>      // Make sure columns are specified<a name="line.717"></a>
-<span class="sourceLineNo">718</span>      String[] columns = getConf().getStrings(COLUMNS_CONF_KEY);<a name="line.718"></a>
-<span class="sourceLineNo">719</span>      if (columns == null) {<a name="line.719"></a>
-<span class="sourceLineNo">720</span>        usage("No columns specified. Please specify with -D" +<a name="line.720"></a>
-<span class="sourceLineNo">721</span>            COLUMNS_CONF_KEY+"=...");<a name="line.721"></a>
-<span class="sourceLineNo">722</span>        return -1;<a name="line.722"></a>
-<span class="sourceLineNo">723</span>      }<a name="line.723"></a>
-<span class="sourceLineNo">724</span><a name="line.724"></a>
-<span class="sourceLineNo">725</span>      // Make sure they specify exactly one column as the row key<a name="line.725"></a>
-<span class="sourceLineNo">726</span>      int rowkeysFound = 0;<a name="line.726"></a>
-<span class="sourceLineNo">727</span>      for (String col : columns) {<a name="line.727"></a>
-<span class="sourceLineNo">728</span>        if (col.equals(TsvParser.ROWKEY_COLUMN_SPEC)) rowkeysFound++;<a name="line.728"></a>
-<span class="sourceLineNo">729</span>      }<a name="line.729"></a>
-<span class="sourceLineNo">730</span>      if (rowkeysFound != 1) {<a name="line.730"></a>
-<span class="sourceLineNo">731</span>        usage("Must specify exactly one column as " + TsvParser.ROWKEY_COLUMN_SPEC);<a name="line.731"></a>
-<span class="sourceLineNo">732</span>        return -1;<a name="line.732"></a>
-<span class="sourceLineNo">733</span>      }<a name="line.733"></a>
-<span class="sourceLineNo">734</span><a name="line.734"></a>
-<span class="sourceLineNo">735</span>      // Make sure we have at most one column as the timestamp key<a name="line.735"></a>
-<span class="sourceLineNo">736</span>      int tskeysFound = 0;<a name="line.736"></a>
-<span class="sourceLineNo">737</span>      for (String col : columns) {<a name="line.737"></a>
-<span class="sourceLineNo">738</span>        if (col.equals(TsvParser.TIMESTAMPKEY_COLUMN_SPEC))<a name="line.738"></a>
-<span class="sourceLineNo">739</span>          tskeysFound++;<a name="line.739"></a>
-<span class="sourceLineNo">740</span>      }<a name="line.740"></a>
-<span class="sourceLineNo">741</span>      if (tskeysFound &gt; 1) {<a name="line.741"></a>
-<span class="sourceLineNo">742</span>        usage("Must specify at most one column as "<a name="line.742"></a>
-<span class="sourceLineNo">743</span>            + TsvParser.TIMESTAMPKEY_COLUMN_SPEC);<a name="line.743"></a>
-<span class="sourceLineNo">744</span>        return -1;<a name="line.744"></a>
-<span class="sourceLineNo">745</span>      }<a name="line.745"></a>
-<span class="sourceLineNo">746</span><a name="line.746"></a>
-<span class="sourceLineNo">747</span>      int attrKeysFound = 0;<a name="line.747"></a>
-<span class="sourceLineNo">748</span>      for (String col : columns) {<a name="line.748"></a>
-<span class="sourceLineNo">749</span>        if (col.equals(TsvParser.ATTRIBUTES_COLUMN_SPEC))<a name="line.749"></a>
-<span class="sourceLineNo">750</span>          attrKeysFound++;<a name="line.750"></a>
-<span class="sourceLineNo">751</span>      }<a name="line.751"></a>
-<span class="sourceLineNo">752</span>      if (attrKeysFound &gt; 1) {<a name="line.752"></a>
-<span class="sourceLineNo">753</span>        usage("Must specify at most one column as "<a name="line.753"></a>
-<span class="sourceLineNo">754</span>            + TsvParser.ATTRIBUTES_COLUMN_SPEC);<a name="line.754"></a>
-<span class="sourceLineNo">755</span>        return -1;<a name="line.755"></a>
-<span class="sourceLineNo">756</span>      }<a name="line.756"></a>
-<span class="sourceLineNo">757</span><a name="line.757"></a>
-<span class="sourceLineNo">758</span>      // Make sure one or more columns are specified excluding rowkey and<a name="line.758"></a>
-<span class="sourceLineNo">759</span>      // timestamp key<a name="line.759"></a>
-<span class="sourceLineNo">760</span>      if (columns.length - (rowkeysFound + tskeysFound + attrKeysFound) &lt; 1) {<a name="line.760"></a>
-<span class="sourceLineNo">761</span>        usage("One or more columns in addition to the row key and timestamp(optional) are required");<a name="line.761"></a>
-<span class="sourceLineNo">762</span>        return -1;<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      }<a name="line.763"></a>
-<span class="sourceLineNo">764</span>    }<a name="line.764"></a>
-<span class="sourceLineNo">765</span><a name="line.765"></a>
-<span class="sourceLineNo">766</span>    // If timestamp option is not specified, use current system time.<a name="line.766"></a>
-<span class="sourceLineNo">767</span>    long timstamp = getConf().getLong(TIMESTAMP_CONF_KEY, System.currentTimeMillis());<a name="line.767"></a>
-<span class="sourceLineNo">768</span><a name="line.768"></a>
-<span class="sourceLineNo">769</span>    // Set it back to replace invalid timestamp (non-numeric) with current<a name="line.769"></a>
-<span class="sourceLineNo">770</span>    // system time<a name="line.770"></a>
-<span class="sourceLineNo">771</span>    getConf().setLong(TIMESTAMP_CONF_KEY, timstamp);<a name="line.771"></a>
-<span class="sourceLineNo">772</span><a name="line.772"></a>
-<span class="sourceLineNo">773</span>    synchronized (ImportTsv.class) {<a name="line.773"></a>
-<span class="sourceLineNo">774</span>      DRY_RUN_TABLE_CREATED = false;<a name="line.774"></a>
-<span class="sourceLineNo">775</span>    }<a name="line.775"></a>
-<span class="sourceLineNo">776</span>    Job job = createSubmittableJob(getConf(), args);<a name="line.776"></a>
-<span class="sourceLineNo">777</span>    boolean success = job.waitForCompletion(true);<a name="line.777"></a>
-<span class="sourceLineNo">778</span>    boolean delete = false;<a name="line.778"></a>
-<span class="sourceLineNo">779</span>    synchronized (ImportTsv.class) {<a name="line.779"></a>
-<span class="sourceLineNo">780</span>      delete = DRY_RUN_TABLE_CREATED;<a name="line.780"></a>
-<span class="sourceLineNo">781</span>    }<a name="line.781"></a>
-<span class="sourceLineNo">782</span>    if (delete) {<a name="line.782"></a>
-<span class="sourceLineNo">783</span>      deleteTable(getConf(), args);<a name="line.783"></a>
-<span class="sourceLineNo">784</span>    }<a name="line.784"></a>
-<span class="sourceLineNo">785</span>    return success ? 0 : 1;<a name="line.785"></a>
-<span class="sourceLineNo">786</span>  }<a name="line.786"></a>
-<span class="sourceLineNo">787</span><a name="line.787"></a>
-<span class="sourceLineNo">788</span>  public static void main(String[] args) throws Exception {<a name="line.788"></a>
-<span class="sourceLineNo">789</span>    int status = ToolRunner.run(HBaseConfiguration.create(), new ImportTsv(), args);<a name="line.789"></a>
-<span class="sourceLineNo">790</span>    System.exit(status);<a name="line.790"></a>
-<span class="sourceLineNo">791</span>  }<a name="line.791"></a>
-<span class="sourceLineNo">792</span>}<a name="line.792"></a>
+<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;<a name="line.50"></a>
+<span class="sourceLineNo">051</span>import org.apache.hadoop.hbase.util.Pair;<a name="line.51"></a>
+<span class="sourceLineNo">052</span>import org.apache.hadoop.io.Text;<a name="line.52"></a>
+<span class="sourceLineNo">053</span>import org.apache.hadoop.mapreduce.Job;<a name="line.53"></a>
+<span class="sourceLineNo">054</span>import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>import org.apache.hadoop.mapreduce.lib.output.NullOutputFormat;<a name="line.57"></a>
+<span class="sourceLineNo">058</span>import org.apache.hadoop.security.Credentials;<a name="line.58"></a>
+<span class="sourceLineNo">059</span>import org.apache.hadoop.util.Tool;<a name="line.59"></a>
+<span class="sourceLineNo">060</span>import org.apache.hadoop.util.ToolRunner;<a name="line.60"></a>
+<span class="sourceLineNo">061</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.61"></a>
+<span class="sourceLineNo">062</span>import org.slf4j.Logger;<a name="line.62"></a>
+<span class="sourceLineNo">063</span>import org.slf4j.LoggerFactory;<a name="line.63"></a>
+<span class="sourceLineNo">064</span><a name="line.64"></a>
+<span class="sourceLineNo">065</span>import org.apache.hbase.thirdparty.com.google.common.base.Preconditions;<a name="line.65"></a>
+<span class="sourceLineNo">066</span>import org.apache.hbase.thirdparty.com.google.common.base.Splitter;<a name="line.66"></a>
+<span class="sourceLineNo">067</span>import org.apache.hbase.thirdparty.com.google.common.collect.Lists;<a name="line.67"></a>
+<span class="sourceLineNo">068</span><a name="line.68"></a>
+<span class="sourceLineNo">069</span>/**<a name="line.69"></a>
+<span class="sourceLineNo">070</span> * Tool to import data from a TSV file.<a name="line.70"></a>
+<span class="sourceLineNo">071</span> *<a name="line.71"></a>
+<span class="sourceLineNo">072</span> * This tool is rather simplistic - it doesn't do any quoting or<a name="line.72"></a>
+<span class="sourceLineNo">073</span> * escaping, but is useful for many data loads.<a name="line.73"></a>
+<span class="sourceLineNo">074</span> *<a name="line.74"></a>
+<span class="sourceLineNo">075</span> * @see ImportTsv#usage(String)<a name="line.75"></a>
+<span class="sourceLineNo">076</span> */<a name="line.76"></a>
+<span class="sourceLineNo">077</span>@InterfaceAudience.Public<a name="line.77"></a>
+<span class="sourceLineNo">078</span>public class ImportTsv extends Configured implements Tool {<a name="line.78"></a>
+<span class="sourceLineNo">079</span><a name="line.79"></a>
+<span class="sourceLineNo">080</span>  protected static final Logger LOG = LoggerFactory.getLogger(ImportTsv.class);<a name="line.80"></a>
+<span class="sourceLineNo">081</span><a name="line.81"></a>
+<span class="sourceLineNo">082</span>  final static String NAME = "importtsv";<a name="line.82"></a>
+<span class="sourceLineNo">083</span><a name="line.83"></a>
+<span class="sourceLineNo">084</span>  public final static String MAPPER_CONF_KEY = "importtsv.mapper.class";<a name="line.84"></a>
+<span class="sourceLineNo">085</span>  public final static String BULK_OUTPUT_CONF_KEY = "importtsv.bulk.output";<a name="line.85"></a>
+<span class="sourceLineNo">086</span>  public final static String TIMESTAMP_CONF_KEY = "importtsv.timestamp";<a name="line.86"></a>
+<span class="sourceLineNo">087</span>  public final static String JOB_NAME_CONF_KEY = "mapreduce.job.name";<a name="line.87"></a>
+<span class="sourceLineNo">088</span>  // TODO: the rest of these configs are used exclusively by TsvImporterMapper.<a name="line.88"></a>
+<span class="sourceLineNo">089</span>  // Move them out of the tool and let the mapper handle its own validation.<a name="line.89"></a>
+<span class="sourceLineNo">090</span>  public final static String DRY_RUN_CONF_KEY = "importtsv.dry.run";<a name="line.90"></a>
+<span class="sourceLineNo">091</span>  // If true, bad lines are logged to stderr. Default: false.<a name="line.91"></a>
+<span class="sourceLineNo">092</span>  public final static String LOG_BAD_LINES_CONF_KEY = "importtsv.log.bad.lines";<a name="line.92"></a>
+<span class="sourceLineNo">093</span>  public final static String SKIP_LINES_CONF_KEY = "importtsv.skip.bad.lines";<a name="line.93"></a>
+<span class="sourceLineNo">094</span>  public final static String SKIP_EMPTY_COLUMNS = "importtsv.skip.empty.columns";<a name="line.94"></a>
+<span class="sourceLineNo">095</span>  public final static String COLUMNS_CONF_KEY = "importtsv.columns";<a name="line.95"></a>
+<span class="sourceLineNo">096</span>  public final static String SEPARATOR_CONF_KEY = "importtsv.separator";<a name="line.96"></a>
+<span class="sourceLineNo">097</span>  public final static String ATTRIBUTE_SEPERATOR_CONF_KEY = "attributes.seperator";<a name="line.97"></a>
+<span class="sourceLineNo">098</span>  //This config is used to propagate credentials from parent MR jobs which launch<a name="line.98"></a>
+<span class="sourceLineNo">099</span>  //ImportTSV jobs. SEE IntegrationTestImportTsv.<a name="line.99"></a>
+<span class="sourceLineNo">100</span>  public final static String CREDENTIALS_LOCATION = "credentials_location";<a name="line.100"></a>
+<span class="sourceLineNo">101</span>  final static String DEFAULT_SEPARATOR = "\t";<a name="line.101"></a>
+<span class="sourceLineNo">102</span>  final static String DEFAULT_ATTRIBUTES_SEPERATOR = "=&gt;";<a name="line.102"></a>
+<span class="sourceLineNo">103</span>  final static String DEFAULT_MULTIPLE_ATTRIBUTES_SEPERATOR = ",";<a name="line.103"></a>
+<span class="sourceLineNo">104</span>  final static Class DEFAULT_MAPPER = TsvImporterMapper.class;<a name="line.104"></a>
+<span class="sourceLineNo">105</span>  public final static String CREATE_TABLE_CONF_KEY = "create.table";<a name="line.105"></a>
+<span class="sourceLineNo">106</span>  public final static String NO_STRICT_COL_FAMILY = "no.strict";<a name="line.106"></a>
+<span class="sourceLineNo">107</span>  /**<a name="line.107"></a>
+<span class="sourceLineNo">108</span>   * If table didn't exist and was created in dry-run mode, this flag is<a name="line.108"></a>
+<span class="sourceLineNo">109</span>   * flipped to delete it when MR ends.<a name="line.109"></a>
+<span class="sourceLineNo">110</span>   */<a name="line.110"></a>
+<span class="sourceLineNo">111</span>  private static boolean DRY_RUN_TABLE_CREATED;<a name="line.111"></a>
+<span class="sourceLineNo">112</span><a name="line.112"></a>
+<span class="sourceLineNo">113</span>  public static class TsvParser {<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    /**<a name="line.114"></a>
+<span class="sourceLineNo">115</span>     * Column families and qualifiers mapped to the TSV columns<a name="line.115"></a>
+<span class="sourceLineNo">116</span>     */<a name="line.116"></a>
+<span class="sourceLineNo">117</span>    private final byte[][] families;<a name="line.117"></a>
+<span class="sourceLineNo">118</span>    private final byte[][] qualifiers;<a name="line.118"></a>
+<span class="sourceLineNo">119</span><a name="line.119"></a>
+<span class="sourceLineNo">120</span>    private final byte separatorByte;<a name="line.120"></a>
+<span class="sourceLineNo">121</span><a name="line.121"></a>
+<span class="sourceLineNo">122</span>    private int rowKeyColumnIndex;<a name="line.122"></a>
+<span class="sourceLineNo">123</span><a name="line.123"></a>
+<span class="sourceLineNo">124</span>    private int maxColumnCount;<a name="line.124"></a>
+<span class="sourceLineNo">125</span><a name="line.125"></a>
+<span class="sourceLineNo">126</span>    // Default value must be negative<a name="line.126"></a>
+<span class="sourceLineNo">127</span>    public static final int DEFAULT_TIMESTAMP_COLUMN_INDEX = -1;<a name="line.127"></a>
+<span class="sourceLineNo">128</span><a name="line.128"></a>
+<span class="sourceLineNo">129</span>    private int timestampKeyColumnIndex = DEFAULT_TIMESTAMP_COLUMN_INDEX;<a name="line.129"></a>
+<span class="sourceLineNo">130</span><a name="line.130"></a>
+<span class="sourceLineNo">131</span>    public static final String ROWKEY_COLUMN_SPEC = "HBASE_ROW_KEY";<a name="line.131"></a>
+<span class="sourceLineNo">132</span><a name="line.132"></a>
+<span class="sourceLineNo">133</span>    public static final String TIMESTAMPKEY_COLUMN_SPEC = "HBASE_TS_KEY";<a name="line.133"></a>
+<span class="sourceLineNo">134</span><a name="line.134"></a>
+<span class="sourceLineNo">135</span>    public static final String ATTRIBUTES_COLUMN_SPEC = "HBASE_ATTRIBUTES_KEY";<a name="line.135"></a>
+<span class="sourceLineNo">136</span><a name="line.136"></a>
+<span class="sourceLineNo">137</span>    public static final String CELL_VISIBILITY_COLUMN_SPEC = "HBASE_CELL_VISIBILITY";<a name="line.137"></a>
+<span class="sourceLineNo">138</span><a name="line.138"></a>
+<span class="sourceLineNo">139</span>    public static final String CELL_TTL_COLUMN_SPEC = "HBASE_CELL_TTL";<a name="line.139"></a>
+<span class="sourceLineNo">140</span><a name="line.140"></a>
+<span class="sourceLineNo">141</span>    private int attrKeyColumnIndex = DEFAULT_ATTRIBUTES_COLUMN_INDEX;<a name="line.141"></a>
+<span class="sourceLineNo">142</span><a name="line.142"></a>
+<span class="sourceLineNo">143</span>    public static final int DEFAULT_ATTRIBUTES_COLUMN_INDEX = -1;<a name="line.143"></a>
+<span class="sourceLineNo">144</span><a name="line.144"></a>
+<span class="sourceLineNo">145</span>    public static final int DEFAULT_CELL_VISIBILITY_COLUMN_INDEX = -1;<a name="line.145"></a>
+<span class="sourceLineNo">146</span><a name="line.146"></a>
+<span class="sourceLineNo">147</span>    public static final int DEFAULT_CELL_TTL_COLUMN_INDEX = -1;<a name="line.147"></a>
+<span class="sourceLineNo">148</span><a name="line.148"></a>
+<span class="sourceLineNo">149</span>    private int cellVisibilityColumnIndex = DEFAULT_CELL_VISIBILITY_COLUMN_INDEX;<a name="line.149"></a>
+<span class="sourceLineNo">150</span><a name="line.150"></a>
+<span class="sourceLineNo">151</span>    private int cellTTLColumnIndex = DEFAULT_CELL_TTL_COLUMN_INDEX;<a name="line.151"></a>
+<span class="sourceLineNo">152</span><a name="line.152"></a>
+<span class="sourceLineNo">153</span>    /**<a name="line.153"></a>
+<span class="sourceLineNo">154</span>     * @param columnsSpecification the list of columns to parser out, comma separated.<a name="line.154"></a>
+<span class="sourceLineNo">155</span>     * The row key should be the special token TsvParser.ROWKEY_COLUMN_SPEC<a name="line.155"></a>
+<span class="sourceLineNo">156</span>     * @param separatorStr<a name="line.156"></a>
+<span class="sourceLineNo">157</span>     */<a name="line.157"></a>
+<span class="sourceLineNo">158</span>    public TsvParser(String columnsSpecification, String separatorStr) {<a name="line.158"></a>
+<span class="sourceLineNo">159</span>      // Configure separator<a name="line.159"></a>
+<span class="sourceLineNo">160</span>      byte[] separator = Bytes.toBytes(separatorStr);<a name="line.160"></a>
+<span class="sourceLineNo">161</span>      Preconditions.checkArgument(separator.length == 1,<a name="line.161"></a>
+<span class="sourceLineNo">162</span>        "TsvParser only supports single-byte separators");<a name="line.162"></a>
+<span class="sourceLineNo">163</span>      separatorByte = separator[0];<a name="line.163"></a>
+<span class="sourceLineNo">164</span><a name="line.164"></a>
+<span class="sourceLineNo">165</span>      // Configure columns<a name="line.165"></a>
+<span class="sourceLineNo">166</span>      ArrayList&lt;String&gt; columnStrings = Lists.newArrayList(<a name="line.166"></a>
+<span class="sourceLineNo">167</span>        Splitter.on(',').trimResults().split(columnsSpecification));<a name="line.167"></a>
+<span class="sourceLineNo">168</span><a name="line.168"></a>
+<span class="sourceLineNo">169</span>      maxColumnCount = columnStrings.size();<a name="line.169"></a>
+<span class="sourceLineNo">170</span>      families = new byte[maxColumnCount][];<a name="line.170"></a>
+<span class="sourceLineNo">171</span>      qualifiers = new byte[maxColumnCount][];<a name="line.171"></a>
+<span class="sourceLineNo">172</span><a name="line.172"></a>
+<span class="sourceLineNo">173</span>      for (int i = 0; i &lt; columnStrings.size(); i++) {<a name="line.173"></a>
+<span class="sourceLineNo">174</span>        String str = columnStrings.get(i);<a name="line.174"></a>
+<span class="sourceLineNo">175</span>        if (ROWKEY_COLUMN_SPEC.equals(str)) {<a name="line.175"></a>
+<span class="sourceLineNo">176</span>          rowKeyColumnIndex = i;<a name="line.176"></a>
+<span class="sourceLineNo">177</span>          continue;<a name="line.177"></a>
+<span class="sourceLineNo">178</span>        }<a name="line.178"></a>
+<span class="sourceLineNo">179</span>        if (TIMESTAMPKEY_COLUMN_SPEC.equals(str)) {<a name="line.179"></a>
+<span class="sourceLineNo">180</span>          timestampKeyColumnIndex = i;<a name="line.180"></a>
+<span class="sourceLineNo">181</span>          continue;<a name="line.181"></a>
+<span class="sourceLineNo">182</span>        }<a name="line.182"></a>
+<span class="sourceLineNo">183</span>        if (ATTRIBUTES_COLUMN_SPEC.equals(str)) {<a name="line.183"></a>
+<span class="sourceLineNo">184</span>          attrKeyColumnIndex = i;<a name="line.184"></a>
+<span class="sourceLineNo">185</span>          continue;<a name="line.185"></a>
+<span class="sourceLineNo">186</span>        }<a name="line.186"></a>
+<span class="sourceLineNo">187</span>        if (CELL_VISIBILITY_COLUMN_SPEC.equals(str)) {<a name="line.187"></a>
+<span class="sourceLineNo">188</span>          cellVisibilityColumnIndex = i;<a name="line.188"></a>
+<span class="sourceLineNo">189</span>          continue;<a name="line.189"></a>
+<span class="sourceLineNo">190</span>        }<a name="line.190"></a>
+<span class="sourceLineNo">191</span>        if (CELL_TTL_COLUMN_SPEC.equals(str)) {<a name="line.191"></a>
+<span class="sourceLineNo">192</span>          cellTTLColumnIndex = i;<a name="line.192"></a>
+<span class="sourceLineNo">193</span>          continue;<a name="line.193"></a>
+<span class="sourceLineNo">194</span>        }<a name="line.194"></a>
+<span class="sourceLineNo">195</span>        String[] parts = str.split(":", 2);<a name="line.195"></a>
+<span class="sourceLineNo">196</span>        if (parts.length == 1) {<a name="line.196"></a>
+<span class="sourceLineNo">197</span>          families[i] = Bytes.toBytes(str);<a name="line.197"></a>
+<span class="sourceLineNo">198</span>          qualifiers[i] = HConstants.EMPTY_BYTE_ARRAY;<a name="line.198"></a>
+<span class="sourceLineNo">199</span>        } else {<a name="line.199"></a>
+<span class="sourceLineNo">200</span>          families[i] = Bytes.toBytes(parts[0]);<a name="line.200"></a>
+<span class="sourceLineNo">201</span>          qualifiers[i] = Bytes.toBytes(parts[1]);<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>    }<a name="line.204"></a>
+<span class="sourceLineNo">205</span><a name="line.205"></a>
+<span class="sourceLineNo">206</span>    public boolean hasTimestamp() {<a name="line.206"></a>
+<span class="sourceLineNo">207</span>      return timestampKeyColumnIndex != DEFAULT_TIMESTAMP_COLUMN_INDEX;<a name="line.207"></a>
+<span class="sourceLineNo">208</span>    }<a name="line.208"></a>
+<span class="sourceLineNo">209</span><a name="line.209"></a>
+<span class="sourceLineNo">210</span>    public int getTimestampKeyColumnIndex() {<a name="line.210"></a>
+<span class="sourceLineNo">211</span>      return timestampKeyColumnIndex;<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>    public boolean hasAttributes() {<a name="line.214"></a>
+<span class="sourceLineNo">215</span>      return attrKeyColumnIndex != DEFAULT_ATTRIBUTES_COLUMN_INDEX;<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>    public boolean hasCellVisibility() {<a name="line.218"></a>
+<span class="sourceLineNo">219</span>      return cellVisibilityColumnIndex != DEFAULT_CELL_VISIBILITY_COLUMN_INDEX;<a name="line.219"></a>
+<span class="sourceLineNo">220</span>    }<a name="line.220"></a>
+<span class="sourceLineNo">221</span><a name="line.221"></a>
+<span class="sourceLineNo">222</span>    public boolean hasCellTTL() {<a name="line.222"></a>
+<span class="sourceLineNo">223</span>      return cellTTLColumnIndex != DEFAULT_CELL_VISIBILITY_COLUMN_INDEX;<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>    public int getAttributesKeyColumnIndex() {<a name="line.226"></a>
+<span class="sourceLineNo">227</span>      return attrKeyColumnIndex;<a name="line.227"></a>
+<span class="sourceLineNo">228</span>    }<a name="line.228"></a>
+<span class="sourceLineNo">229</span><a name="line.229"></a>
+<span class="sourceLineNo">230</span>    public int getCellVisibilityColumnIndex() {<a name="line.230"></a>
+<span class="sourceLineNo">231</span>      return cellVisibilityColumnIndex;<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>    public int getCellTTLColumnIndex() {<a name="line.234"></a>
+<span class="sourceLineNo">235</span>      return cellTTLColumnIndex;<a name="line.235"></a>
+<span class="sourceLineNo">236</span>    }<a name="line.236"></a>
+<span class="sourceLineNo">237</span><a name="line.237"></a>
+<span class="sourceLineNo">238</span>    public int getRowKeyColumnIndex() {<a name="line.238"></a>
+<span class="sourceLineNo">239</span>      return rowKeyColumnIndex;<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>    public byte[] getFamily(int idx) {<a name="line.242"></a>
+<span class="sourceLineNo">243</span>      return families[idx];<a name="line.243"></a>
+<span class="sourceLineNo">244</span>    }<a name="line.244"></a>
+<span class="sourceLineNo">245</span>    public byte[] getQualifier(int idx) {<a name="line.245"></a>
+<span class="sourceLineNo">246</span>      return qualifiers[idx];<a name="line.246"></a>
+<span class="sourceLineNo">247</span>    }<a name="line.247"></a>
+<span class="sourceLineNo">248</span><a name="line.248"></a>
+<span class="sourceLineNo">249</span>    public ParsedLine parse(byte[] lineBytes, int length)<a name="line.249"></a>
+<span class="sourceLineNo">250</span>    throws BadTsvLineException {<a name="line.250"></a>
+<span class="sourceLineNo">251</span>      // Enumerate separator offsets<a name="line.251"></a>
+<span class="sourceLineNo">252</span>      ArrayList&lt;Integer&gt; tabOffsets = new ArrayList&lt;&gt;(maxColumnCount);<a name="line.252"></a>
+<span class="sourceLineNo">253</span>      for (int i = 0; i &lt; length; i++) {<a name="line.253"></a>
+<span class="sourceLineNo">254</span>        if (lineBytes[i] == separatorByte) {<a name="line.254"></a>
+<span class="sourceLineNo">255</span>          tabOffsets.add(i);<a name="line.255"></a>
+<span class="sourceLineNo">256</span>        }<a name="line.256"></a>
+<span class="sourceLineNo">257</span>      }<a name="line.257"></a>
+<span class="sourceLineNo">258</span>      if (tabOffsets.isEmpty()) {<a name="line.258"></a>
+<span class="sourceLineNo">259</span>        throw new BadTsvLineException("No delimiter");<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>      tabOffsets.add(length);<a name="line.262"></a>
+<span class="sourceLineNo">263</span><a name="line.263"></a>
+<span class="sourceLineNo">264</span>      if (tabOffsets.size() &gt; maxColumnCount) {<a name="line.264"></a>
+<span class="sourceLineNo">265</span>        throw new BadTsvLineException("Excessive columns");<a name="line.265"></a>
+<span class="sourceLineNo">266</span>      } else if (tabOffsets.size() &lt;= getRowKeyColumnIndex()) {<a name="line.266"></a>
+<span class="sourceLineNo">267</span>        throw new BadTsvLineException("No row key");<a name="line.267"></a>
+<span class="sourceLineNo">268</span>      } else if (hasTimestamp()<a name="line.268"></a>
+<span class="sourceLineNo">269</span>          &amp;&amp; tabOffsets.size() &lt;= getTimestampKeyColumnIndex()) {<a name="line.269"></a>
+<span class="sourceLineNo">270</span>        throw new BadTsvLineException("No timestamp");<a name="line.270"></a>
+<span class="sourceLineNo">271</span>      } else if (hasAttributes() &amp;&amp; tabOffsets.size() &lt;= getAttributesKeyColumnIndex()) {<a name="line.271"></a>
+<span class="sourceLineNo">272</span>        throw new BadTsvLineException("No attributes specified");<a name="line.272"></a>
+<span class="sourceLineNo">273</span>      } else if (hasCellVisibility() &amp;&amp; tabOffsets.size() &lt;= getCellVisibilityColumnIndex()) {<a name="line.273"></a>
+<span class="sourceLineNo">274</span>        throw new BadTsvLineException("No cell visibility specified");<a name="line.274"></a>
+<span class="sourceLineNo">275</span>      } else if (hasCellTTL() &amp;&amp; tabOffsets.size() &lt;= getCellTTLColumnIndex()) {<a name="line.275"></a>
+<span class="sourceLineNo">276</span>        throw new BadTsvLineException("No cell TTL specified");<a name="line.276"></a>
+<span class="sourceLineNo">277</span>      }<a name="line.277"></a>
+<span class="sourceLineNo">278</span>      return new ParsedLine(tabOffsets, lineBytes);<a name="line.278"></a>
+<span class="sourceLineNo">279</span>    }<a name="line.279"></a>
+<span class="sourceLineNo">280</span><a name="line.280"></a>
+<span class="sourceLineNo">281</span>    class ParsedLine {<a name="line.281"></a>
+<span class="sourceLineNo">282</span>      private final ArrayList&lt;Integer&gt; tabOffsets;<a name="line.282"></a>
+<span class="sourceLineNo">283</span>      private byte[] lineBytes;<a name="line.283"></a>
+<span class="sourceLineNo">284</span><a name="line.284"></a>
+<span class="sourceLineNo">285</span>      ParsedLine(ArrayList&lt;Integer&gt; tabOffsets, byte[] lineBytes) {<a name="line.285"></a>
+<span class="sourceLineNo">286</span>        this.tabOffsets = tabOffsets;<a name="line.286"></a>
+<span class="sourceLineNo">287</span>        this.lineBytes = lineBytes;<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 int getRowKeyOffset() {<a name="line.290"></a>
+<span class="sourceLineNo">291</span>        return getColumnOffset(rowKeyColumnIndex);<a name="line.291"></a>
+<span class="sourceLineNo">292</span>      }<a name="line.292"></a>
+<span class="sourceLineNo">293</span>      public int getRowKeyLength() {<a name="line.293"></a>
+<span class="sourceLineNo">294</span>        return getColumnLength(rowKeyColumnIndex);<a name="line.294"></a>
+<span class="sourceLineNo">295</span>      }<a name="line.295"></a>
+<span class="sourceLineNo">296</span><a name="line.296"></a>
+<span class="sourceLineNo">297</span>      public long getTimestamp(long ts) throws BadTsvLineException {<a name="line.297"></a>
+<span class="sourceLineNo">298</span>        // Return ts if HBASE_TS_KEY is not configured in column spec<a name="line.298"></a>
+<span class="sourceLineNo">299</span>        if (!hasTimestamp()) {<a name="line.299"></a>
+<span class="sourceLineNo">300</span>          return ts;<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>        String timeStampStr = Bytes.toString(lineBytes,<a name="line.303"></a>
+<span class="sourceLineNo">304</span>            getColumnOffset(timestampKeyColumnIndex),<a name="line.304"></a>
+<span class="sourceLineNo">305</span>            getColumnLength(timestampKeyColumnIndex));<a name="line.305"></a>
+<span class="sourceLineNo">306</span>        try {<a name="line.306"></a>
+<span class="sourceLineNo">307</span>          return Long.parseLong(timeStampStr);<a name="line.307"></a>
+<span class="sourceLineNo">308</span>        } catch (NumberFormatException nfe) {<a name="line.308"></a>
+<span class="sourceLineNo">309</span>          // treat this record as bad record<a name="line.309"></a>
+<span class="sourceLineNo">310</span>          throw new BadTsvLineException("Invalid timestamp " + timeStampStr);<a name="line.310"></a>
+<span class="sourceLineNo">311</span>        }<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>      private String getAttributes() {<a name="line.314"></a>
+<span class="sourceLineNo">315</span>        if (!hasAttributes()) {<a name="line.315"></a>
+<span class="sourceLineNo">316</span>          return null;<a name="line.316"></a>
+<span class="sourceLineNo">317</span>        } else {<a name="line.317"></a>
+<span class="sourceLineNo">318</span>          return Bytes.toString(lineBytes, getColumnOffset(attrKeyColumnIndex),<a name="line.318"></a>
+<span class="sourceLineNo">319</span>              getColumnLength(attrKeyColumnIndex));<a name="line.319"></a>
+<span class="sourceLineNo">320</span>        }<a name="line.320"></a>
+<span class="sourceLineNo">321</span>      }<a name="line.321"></a>
+<span class="sourceLineNo">322</span><a name="line.322"></a>
+<span class="sourceLineNo">323</span>      public String[] getIndividualAttributes() {<a name="line.323"></a>
+<span class="sourceLineNo">324</span>        String attributes = getAttributes();<a name="line.324"></a>
+<span class="sourceLineNo">325</span>        if (attributes != null) {<a name="line.325"></a>
+<span class="sourceLineNo">326</span>          return attributes.split(DEFAULT_MULTIPLE_ATTRIBUTES_SEPERATOR);<a name="line.326"></a>
+<span class="sourceLineNo">327</span>        } else {<a name="line.327"></a>
+<span class="sourceLineNo">328</span>          return null;<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><a name="line.331"></a>
+<span class="sourceLineNo">332</span>      public int getAttributeKeyOffset() {<a name="line.332"></a>
+<span class="sourceLineNo">333</span>        if (hasAttributes()) {<a name="line.333"></a>
+<span class="sourceLineNo">334</span>          return getColumnOffset(attrKeyColumnIndex);<a name="line.334"></a>
+<span class="sourceLineNo">335</span>        } else {<a name="line.335"></a>
+<span class="sourceLineNo">336</span>          return DEFAULT_ATTRIBUTES_COLUMN_INDEX;<a name="line.336"></a>
+<span class="sourceLineNo">337</span>        }<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 int getAttributeKeyLength() {<a name="line.340"></a>
+<span class="sourceLineNo">341</span>        if (hasAttributes()) {<a name="line.341"></a>
+<span class="sourceLineNo">342</span>          return getColumnLength(attrKeyColumnIndex);<a name="line.342"></a>
+<span class="sourceLineNo">343</span>        } else {<a name="line.343"></a>
+<span class="sourceLineNo">344</span>          return DEFAULT_ATTRIBUTES_COLUMN_INDEX;<a name="line.344"></a>
+<span class="sourceLineNo">345</span>        }<a name="line.345"></a>
+<span class="sourceLineNo">346</span>      }<a name="line.346"></a>
+<span class="sourceLineNo">347</span><a name="line.347"></a>
+<span class="sourceLineNo">348</span>      public int getCellVisibilityColumnOffset() {<a name="line.348"></a>
+<span class="sourceLineNo">349</span>        if (hasCellVisibility()) {<a name="line.349"></a>
+<span class="sourceLineNo">350</span>          return getColumnOffset(cellVisibilityColumnIndex);<a name="line.350"></a>
+<span class="sourceLineNo">351</span>        } else {<a name="line.351"></a>
+<span class="sourceLineNo">352</span>          return DEFAULT_CELL_VISIBILITY_COLUMN_INDEX;<a name="line.352"></a>
+<span class="sourceLineNo">353</span>        }<a name="line.353"></a>
+<span class="sourceLineNo">354</span>      }<a name="line.354"></a>
+<span class="sourceLineNo">355</span><a name="line.355"></a>
+<span class="sourceLineNo">356</span>      public int getCellVisibilityColumnLength() {<a name="line.356"></a>
+<span class="sourceLineNo">357</span>        if (hasCellVisibility()) {<a name="line.357"></a>
+<span class="sourceLineNo">358</span>          return getColumnLength(cellVisibilityColumnIndex);<a name="line.358"></a>
+<span class="sourceLineNo">359</span>        } else {<a name="line.359"></a>
+<span class="sourceLineNo">360</span>          return DEFAULT_CELL_VISIBILITY_COLUMN_INDEX;<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><a name="line.363"></a>
+<span class="sourceLineNo">364</span>      public String getCellVisibility() {<a name="line.364"></a>
+<span class="sourceLineNo">365</span>        if (!hasCellVisibility()) {<a name="line.365"></a>
+<span class="sourceLineNo">366</span>          return null;<a name="line.366"></a>
+<span class="sourceLineNo">367</span>        } else {<a name="line.367"></a>
+<span class="sourceLineNo">368</span>          return Bytes.toString(lineBytes, getColumnOffset(cellVisibilityColumnIndex),<a name="line.368"></a>
+<span class="sourceLineNo">369</span>              getColumnLength(cellVisibilityColumnIndex));<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><a name="line.372"></a>
+<span class="sourceLineNo">373</span>      public int getCellTTLColumnOffset() {<a name="line.373"></a>
+<span class="sourceLineNo">374</span>        if (hasCellTTL()) {<a name="line.374"></a>
+<span class="sourceLineNo">375</span>          return getColumnOffset(cellTTLColumnIndex);<a name="line.375"></a>
+<span class="sourceLineNo">376</span>        } else {<a name="line.376"></a>
+<span class="sourceLineNo">377</span>          return DEFAULT_CELL_TTL_COLUMN_INDEX;<a name="line.377"></a>
+<span class="sourceLineNo">378</span>        }<a name="line.378"></a>
+<span class="sourceLineNo">379</span>      }<a name="line.379"></a>
+<span class="sourceLineNo">380</span><a name="line.380"></a>
+<span class="sourceLineNo">381</span>      public int getCellTTLColumnLength() {<a name="line.381"></a>
+<span class="sourceLineNo">382</span>        if (hasCellTTL()) {<a name="line.382"></a>
+<span class="sourceLineNo">383</span>          return getColumnLength(cellTTLColumnIndex);<a name="line.383"></a>
+<span class="sourceLineNo">384</span>        } else {<a name="line.384"></a>
+<span class="sourceLineNo">385</span>          return DEFAULT_CELL_TTL_COLUMN_INDEX;<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><a name="line.388"></a>
+<span class="sourceLineNo">389</span>      public long getCellTTL() {<a name="line.389"></a>
+<span class="sourceLineNo">390</span>        if (!hasCellTTL()) {<a name="line.390"></a>
+<span class="sourceLineNo">391</span>          return 0;<a name="line.391"></a>
+<span class="sourceLineNo">392</span>        } else {<a name="line.392"></a>
+<span class="sourceLineNo">393</span>          return Bytes.toLong(lineBytes, getColumnOffset(cellTTLColumnIndex),<a name="line.393"></a>
+<span class="sourceLineNo">394</span>              getColumnLength(cellTTLColumnIndex));<a name="line.394"></a>
+<span class="sourceLineNo">395</span>        }<a name="line.395"></a>
+<span class="sourceLineNo">396</span>      }<a name="line.396"></a>
+<span class="sourceLineNo">397</span><a name="line.397"></a>
+<span class="sourceLineNo">398</span>      public int getColumnOffset(int idx) {<a name="line.398"></a>
+<span class="sourceLineNo">399</span>        if (idx &gt; 0)<a name="line.399"></a>
+<span class="sourceLineNo">400</span>          return tabOffsets.get(idx - 1) + 1;<a name="line.400"></a>
+<span class="sourceLineNo">401</span>        else<a name="line.401"></a>
+<span class="sourceLineNo">402</span>          return 0;<a name="line.402"></a>
+<span class="sourceLineNo">403</span>      }<a name="line.403"></a>
+<span class="sourceLineNo">404</span>      public int getColumnLength(int idx) {<a name="line.404"></a>
+<span class="sourceLineNo">405</span>        return tabOffsets.get(idx) - getColumnOffset(idx);<a name="line.405"></a>
+<span class="sourceLineNo">406</span>      }<a name="line.406"></a>
+<span class="sourceLineNo">407</span>      public int getColumnCount() {<a name="line.407"></a>
+<span class="sourceLineNo">408</span>        return tabOffsets.size();<a name="line.408"></a>
+<span class="sourceLineNo">409</span>      }<a name="line.409"></a>
+<span class="sourceLineNo">410</span>      public byte[] getLineBytes() {<a name="line.410"></a>
+<span class="sourceLineNo">411</span>        return lineBytes;<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      }<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    }<a name="line.413"></a>
+<span class="sourceLineNo">414</span><a name="line.414"></a>
+<span class="sourceLineNo">415</span>    public static class BadTsvLineException extends Exception {<a name="line.415"></a>
+<span class="sourceLineNo">416</span>      public BadTsvLineException(String err) {<a name="line.416"></a>
+<span class="sourceLineNo">417</span>        super(err);<a name="line.417"></a>
+<span class="sourceLineNo">418</span>      }<a name="line.418"></a>
+<span class="sourceLineNo">419</span>      private static final long serialVersionUID = 1L;<a name="line.419"></a>
+<span class="sourceLineNo">420</span>    }<a name="line.420"></a>
+<span class="sourceLineNo">421</span><a name="line.421"></a>
+<span class="sourceLineNo">422</span>    /**<a name="line.422"></a>
+<span class="sourceLineNo">423</span>     * Return starting position and length of row key from the specified line bytes.<a name="line.423"></a>
+<span class="sourceLineNo">424</span>     * @param lineBytes<a name="line.424"></a>
+<span class="sourceLineNo">425</span>     * @param length<a name="line.425"></a>
+<span class="sourceLineNo">426</span>     * @return Pair of row key offset and length.<a name="line.426"></a>
+<span class="sourceLineNo">427</span>     * @throws BadTsvLineException<a name="line.427"></a>
+<span class="sourceLineNo">428</span>     */<a name="line.428"></a>
+<span class="sourceLineNo">429</span>    public Pair&lt;Integer, Integer&gt; parseRowKey(byte[] lineBytes, int length)<a name="line.429"></a>
+<span class="sourceLineNo">430</span>        throws BadTsvLineException {<a name="line.430"></a>
+<span class="sourceLineNo">431</span>      int rkColumnIndex = 0;<a name="line.431"></a>
+<span class="sourceLineNo">432</span>      int startPos = 0, endPos = 0;<a name="line.432"></a>
+<span class="sourceLineNo">433</span>      for (int i = 0; i &lt;= length; i++) {<a name="line.433"></a>
+<span class="sourceLineNo">434</span>        if (i == length || lineBytes[i] == separatorByte) {<a name="line.434"></a>
+<span class="sourceLineNo">435</span>          endPos = i - 1;<a name="line.435"></a>
+<span class="sourceLineNo">436</span>          if (rkColumnIndex++ == getRowKeyColumnIndex()) {<a name="line.436"></a>
+<span class="sourceLineNo">437</span>            if ((endPos + 1) == startPos) {<a name="line.437"></a>
+<span class="sourceLineNo">438</span>              throw new BadTsvLineException("Empty value for ROW KEY.");<a name="line.438"></a>
+<span class="sourceLineNo">439</span>            }<a name="line.439"></a>
+<span class="sourceLineNo">440</span>            break;<a name="line.440"></a>
+<span class="sourceLineNo">441</span>          } else {<a name="line.441"></a>
+<span class="sourceLineNo">442</span>            startPos = endPos + 2;<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>        if (i == length) {<a name="line.445"></a>
+<span class="sourceLineNo">446</span>          throw new BadTsvLineException(<a name="line.446"></a>
+<span class="sourceLineNo">447</span>              "Row key does not exist as number of columns in the line"<a name="line.447"></a>
+<span class="sourceLineNo">448</span>                  + " are less than row key position.");<a name="line.448"></a>
+<span class="sourceLineNo">449</span>        }<a name="line.449"></a>
+<span class="sourceLineNo">450</span>      }<a name="line.450"></a>
+<span class="sourceLineNo">451</span>      return new Pair&lt;&gt;(startPos, endPos - startPos + 1);<a name="line.451"></a>
+<span class="sourceLineNo">452</span>    }<a name="line.452"></a>
+<span class="sourceLineNo">453</span>  }<a name="line.453"></a>
+<span class="sourceLineNo">454</span><a name="line.454"></a>
+<span class="sourceLineNo">455</span>  /**<a name="line.455"></a>
+<span class="sourceLineNo">456</span>   * Sets up the actual job.<a name="line.456"></a>
+<span class="sourceLineNo">457</span>   *<a name="line.457"></a>
+<span class="sourceLineNo">458</span>   * @param conf  The current configuration.<a name="line.458"></a>
+<span class="sourceLineNo">459</span>   * @param args  The command line parameters.<a name="line.459"></a>
+<span class="sourceLineNo">460</span>   * @return The newly created job.<a name="line.460"></a>
+<span class="sourceLineNo">461</span>   * @throws IOException When setting up the job fails.<a name="line.461"></a>
+<span class="sourceLineNo">462</span>   */<a name="line.462"></a>
+<span class="sourceLineNo">463</span>  protected static Job createSubmittableJob(Configuration conf, String[] args)<a name="line.463"></a>
+<span class="sourceLineNo">464</span>      throws IOException, ClassNotFoundException {<a name="line.464"></a>
+<span class="sourceLineNo">465</span>    Job job = null;<a name="line.465"></a>
+<span class="sourceLineNo">466</span>    boolean isDryRun = conf.getBoolean(DRY_RUN_CONF_KEY, false);<a name="line.466"></a>
+<span class="sourceLineNo">467</span>    try (Connection connection = ConnectionFactory.createConnection(conf)) {<a name="line.467"></a>
+<span class="sourceLineNo">468</span>      try (Admin admin = connection.getAdmin()) {<a name="line.468"></a>
+<span class="sourceLineNo">469</span>        // Support non-XML supported characters<a name="line.469"></a>
+<span class="sourceLineNo">470</span>        // by re-encoding the passed separator as a Base64 string.<a name="line.470"></a>
+<span class="sourceLineNo">471</span>        String actualSeparator = conf.get(SEPARATOR_CONF_KEY);<a name="line.471"></a>
+<span class="sourceLineNo">472</span>        if (actualSeparator != null) {<a name="line.472"></a>
+<span class="sourceLineNo">473</span>          conf.set(SEPARATOR_CONF_KEY,<a name="line.473"></a>
+<span class="sourceLineNo">474</span>              Bytes.toString(Base64.getEncoder().encode(Bytes.toBytes(actualSeparator))));<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>        // See if a non-default Mapper was set<a name="line.477"></a>
+<span class="sourceLineNo">478</span>        String mapperClassName = conf.get(MAPPER_CONF_KEY);<a name="line.478"></a>
+<span class="sourceLineNo">479</span>        Class mapperClass = mapperClassName != null? Class.forName(mapperClassName): DEFAULT_MAPPER;<a name="line.479"></a>
+<span class="sourceLineNo">480</span><a name="line.480"></a>
+<span class="sourceLineNo">481</span>        TableName tableName = TableName.valueOf(args[0]);<a name="line.481"></a>
+<span class="sourceLineNo">482</span>        Path inputDir = new Path(args[1]);<a name="line.482"></a>
+<span class="sourceLineNo">483</span>        String jobName = conf.get(JOB_NAME_CONF_KEY,NAME + "_" + tableName.getNameAsString());<a name="line.483"></a>
+<span class="sourceLineNo">484</span>        job = Job.getInstance(conf, jobName);<a name="line.484"></a>
+<span class="sourceLineNo">485</span>        job.setJarByClass(mapperClass);<a name="line.485"></a>
+<span class="sourceLineNo">486</span>        FileInputFormat.setInputPaths(job, inputDir);<a name="line.486"></a>
+<span class="sourceLineNo">487</span>        job.setInputFormatClass(TextInputFormat.class);<a name="line.487"></a>
+<span class="sourceLineNo">488</span>        job.setMapperClass(mapperClass);<a name="line.488"></a>
+<span class="sourceLineNo">489</span>        job.setMapOutputKeyClass(ImmutableBytesWritable.class);<a name="line.489"></a>
+<span class="sourceLineNo">490</span>        String hfileOutPath = conf.get(BULK_OUTPUT_CONF_KEY);<a name="line.490"></a>
+<span class="sourceLineNo">491</span>        String[] columns = conf.getStrings(COLUMNS_CONF_KEY);<a name="line.491"></a>
+<span class="sourceLineNo">492</span>        if(StringUtils.isNotEmpty(conf.get(CREDENTIALS_LOCATION))) {<a name="line.492"></a>
+<span class="sourceLineNo">493</span>          String fileLoc = conf.get(CREDENTIALS_LOCATION);<a name="line.493"></a>
+<span class="sourceLineNo">494</span>          Credentials cred = Credentials.readTokenStorageFile(new File(fileLoc), conf);<a name="line.494"></a>
+<span class="sourceLineNo">495</span>          job.getCredentials().addAll(cred);<a name="line.495"></a>
+<span class="sourceLineNo">496</span>        }<a name="line.496"></a>
+<span class="sourceLineNo">497</span><a name="line.497"></a>
+<span class="sourceLineNo">498</span>        if (hfileOutPath != null) {<a name="line.498"></a>
+<span class="sourceLineNo">499</span>          if (!admin.tableExists(tableName)) {<a name="line.499"></a>
+<span class="sourceLineNo">500</span>            LOG.warn(format("Table '%s' does not exist.", tableName));<a name="line.500"></a>
+<span class="sourceLineNo">501</span>            if ("yes".equalsIgnoreCase(conf.get(CREATE_TABLE_CONF_KEY, "yes"))) {<a name="line.501"></a>
+<span class="sourceLineNo">502</span>              // TODO: this is backwards. Instead of depending on the existence of a table,<a name="line.502"></a>
+<span class="sourceLineNo">503</span>              // create a sane splits file for HFileOutputFormat based on data sampling.<a name="line.503"></a>
+<span class="sourceLineNo">504</span>              createTable(admin, tableName, columns);<a name="line.504"></a>
+<span class="sourceLineNo">505</span>              if (isDryRun) {<a name="line.505"></a>
+<span class="sourceLineNo">506</span>                LOG.warn("Dry run: Table will be deleted at end of dry run.");<a name="line.506"></a>
+<span class="sourceLineNo">507</span>                synchronized (ImportTsv.class) {<a name="line.507"></a>
+<span class="sourceLineNo">508</span>                  DRY_RUN_TABLE_CREATED = true;<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>            } else {<a name="line.511"></a>
+<span class="sourceLineNo">512</span>              String errorMsg =<a name="line.512"></a>
+<span class="sourceLineNo">513</span>                  format("Table '%s' does not exist and '%s' is set to no.", tableName,<a name="line.513"></a>
+<span class="sourceLineNo">514</span>                      CREATE_TABLE_CONF_KEY);<a name="line.514"></a>
+<span class="sourceLineNo">515</span>              LOG.error(errorMsg);<a name="line.515"></a>
+<span class="sourceLineNo">516</span>              throw new TableNotFoundException(errorMsg);<a name="line.516"></a>
+<span class="sourceLineNo">517</span>            }<a name="line.517"></a>
+<span class="sourceLineNo">518</span>          }<a name="line.518"></a>
+<span class="sourceLineNo">519</span>          try (Table table = connection.getTable(tableName);<a name="line.519"></a>
+<span class="sourceLineNo">520</span>              RegionLocator regionLocator = connection.getRegionLocator(tableName)) {<a name="line.520"></a>
+<span class="sourceLineNo">521</span>            boolean noStrict = conf.getBoolean(NO_STRICT_COL_FAMILY, false);<a name="line.521"></a>
+<span class="sourceLineNo">522</span>            // if no.strict is false then check column family<a name="line.522"></a>
+<span class="sourceLineNo">523</span>            if(!noStrict) {<a name="line.523"></a>
+<span class="sourceLineNo">524</span>              ArrayList&lt;String&gt; unmatchedFamilies = new ArrayList&lt;&gt;();<a name="line.524"></a>
+<span class="sourceLineNo">525</span>              Set&lt;String&gt; cfSet = getColumnFamilies(columns);<a name="line.525"></a>
+<span class="sourceLineNo">526</span>              TableDescriptor tDesc = table.getDescriptor();<a name="line.526"></a>
+<span class="sourceLineNo">527</span>              for (String cf : cfSet) {<a name="line.527"></a>
+<span class="sourceLineNo">528</span>                if(!tDesc.hasColumnFamily(Bytes.toBytes(cf))) {<a name="line.528"></a>
+<span class="sourceLineNo">529</span>                  unmatchedFamilies.add(cf);<a name="line.529"></a>
+<span class="sourceLineNo">530</span>                }<a name="line.530"></a>
+<span class="sourceLineNo">531</span>              }<a name="line.531"></a>
+<span class="sourceLineNo">532</span>              if(unmatchedFamilies.size() &gt; 0) {<a name="line.532"></a>
+<span class="sourceLineNo">533</span>                ArrayList&lt;String&gt; familyNames = new ArrayList&lt;&gt;();<a name="line.533"></a>
+<span class="sourceLineNo">534</span>                for (ColumnFamilyDescriptor family : table.getDescriptor().getColumnFamilies()) {<a name="line.534"></a>
+<span class="sourceLineNo">535</span>                  familyNames.add(family.getNameAsString());<a name="line.535"></a>
+<span class="sourceLineNo">536</span>                }<a name="line.536"></a>
+<span class="sourceLineNo">537</span>                String msg =<a name="line.537"></a>
+<span class="sourceLineNo">538</span>                    "Column Families " + unmatchedFamilies + " specified in " + COLUMNS_CONF_KEY<a name="line.538"></a>
+<span class="sourceLineNo">539</span>                    + " does not match with any of the table " + tableName<a name="line.539"></a>
+<span class="sourceLineNo">540</span>                    + " column families " + familyNames + ".\n"<a name="line.540"></a>
+<span class="sourceLineNo">541</span>                    + "To disable column family check, use -D" + NO_STRICT_COL_FAMILY<a name="line.541"></a>
+<span class="sourceLineNo">542</span>                    + "=true.\n";<a name="line.542"></a>
+<span class="sourceLineNo">543</span>                usage(msg);<a name="line.543"></a>
+<span class="sourceLineNo">544</span>                System.exit(-1);<a name="line.544"></a>
+<span class="sourceLineNo">545</span>              }<a name="line.545"></a>
+<span class="sourceLineNo">546</span>            }<a name="line.546"></a>
+<span class="sourceLineNo">547</span>            if (mapperClass.equals(TsvImporterTextMapper.class)) {<a name="line.547"></a>
+<span class="sourceLineNo">548</span>              job.setMapOutputValueClass(Text.class);<a name="line.548"></a>
+<span class="sourceLineNo">549</span>              job.setReducerClass(TextSortReducer.class);<a name="line.549"></a>
+<span class="sourceLineNo">550</span>            } else {<a name="line.550"></a>
+<span class="sourceLineNo">551</span>              job.setMapOutputValueClass(Put.class);<a name="line.551"></a>
+<span class="sourceLineNo">552</span>              job.setCombinerClass(PutCombiner.class);<a name="line.552"></a>
+<span class="sourceLineNo">553</span>              job.setReducerClass(PutSortReducer.class);<a name="line.553"></a>
+<span class="sourceLineNo">554</span>            }<a name="line.554"></a>
+<span class="sourceLineNo">555</span>            if (!isDryRun) {<a name="line.555"></a>
+<span class="sourceLineNo">556</span>              Path outputDir = new Path(hfileOutPath);<a name="line.556"></a>
+<span class="sourceLineNo">557</span>              FileOutputFormat.setOutputPath(job, outputDir);<a name="line.557"></a>
+<span class="sourceLineNo">558</span>              HFileOutputFormat2.configureIncrementalLoad(job, table.getDescriptor(),<a name="line.558"></a>
+<span class="sourceLineNo">559</span>                  regionLocator);<a name="line.559"></a>
+<span class="sourceLineNo">560</span>            }<a name="line.560"></a>
+<span class="sourceLineNo">561</span>          }<a name="line.561"></a>
+<span class="sourceLineNo">562</span>        } else {<a name="line.562"></a>
+<span class="sourceLineNo">563</span>          if (!admin.tableExists(tableName)) {<a name="line.563"></a>
+<span class="sourceLineNo">564</span>            String errorMsg = format("Table '%s' does not exist.", tableName);<a name="line.564"></a>
+<span class="sourceLineNo">565</span>            LOG.error(errorMsg);<a name="line.565"></a>
+<span class="sourceLineNo">566</span>            throw new TableNotFoundException(errorMsg);<a name="line.566"></a>
+<span class="sourceLineNo">567</span>          }<a name="line.567"></a>
+<span class="sourceLineNo">568</span>          if (mapperClass.equals(TsvImporterTextMapper.class)) {<a name="line.568"></a>
+<span class="sourceLineNo">569</span>            usage(TsvImporterTextMapper.class.toString()<a name="line.569"></a>
+<span class="sourceLineNo">570</span>                + " should not be used for non bulkloading case. use "<a name="line.570"></a>
+<span class="sourceLineNo">571</span>                + TsvImporterMapper.class.toString()<a name="line.571"></a>
+<span class="sourceLineNo">572</span>                + " or custom mapper whose value type is Put.");<a name="line.572"></a>
+<span class="sourceLineNo">573</span>            System.exit(-1);<a name="line.573"></a>
+<span class="sourceLineNo">574</span>          }<a name="line.574"></a>
+<span class="sourceLineNo">575</span>          if (!isDryRun) {<a name="line.575"></a>
+<span class="sourceLineNo">576</span>            // No reducers. Just write straight to table. Call initTableReducerJob<a name="line.576"></a>
+<span class="sourceLineNo">577</span>            // to set up the TableOutputFormat.<a name="line.577"></a>
+<span class="sourceLineNo">578</span>            TableMapReduceUtil.initTableReducerJob(tableName.getNameAsString(), null, job);<a name="line.578"></a>
+<span class="sourceLineNo">579</span>          }<a name="line.579"></a>
+<span class="sourceLineNo">580</span>          job.setNumReduceTasks(0);<a name="line.580"></a>
+<span class="sourceLineNo">581</span>        }<a name="line.581"></a>
+<span class="sourceLineNo">582</span>        if (isDryRun) {<a name="line.582"></a>
+<span class="sourceLineNo">583</span>          job.setOutputFormatClass(NullOutputFormat.class);<a name="line.583"></a>
+<span class="sourceLineNo">584</span>          job.getConfiguration().setStrings("io.serializations",<a name="line.584"></a>
+<span class="sourceLineNo">585</span>              job.getConfiguration().get("io.serializations"),<a name="line.585"></a>
+<span class="sourceLineNo">586</span>              MutationSerialization.class.getName(), ResultSerialization.class.getName(),<a name="line.586"></a>
+<span class="sourceLineNo">587</span>              CellSerialization.class.getName());<a name="line.587"></a>
+<span class="sourceLineNo">588</span>        }<a name="line.588"></a>
+<span class="sourceLineNo">589</span>        TableMapReduceUtil.addDependencyJars(job);<a name="line.589"></a>
+<span class="sourceLineNo">590</span>        TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.590"></a>
+<span class="sourceLineNo">591</span>            org.apache.hbase.thirdparty.com.google.common.base.Function.class /* Guava used by TsvParser */);<a name="line.591"></a>
+<span class="sourceLineNo">592</span>      }<a name="line.592"></a>
+<span class="sourceLineNo">593</span>    }<a name="line.593"></a>
+<span class="sourceLineNo">594</span>    return job;<a name="line.594"></a>
+<span class="sourceLineNo">595</span>  }<a name="line.595"></a>
+<span class="sourceLineNo">596</span><a name="line.596"></a>
+<span class="sourceLineNo">597</span>  private static void createTable(Admin admin, TableName tableName, String[] columns)<a name="line.597"></a>
+<span class="sourceLineNo">598</span>      throws IOException {<a name="line.598"></a>
+<span class="sourceLineNo">599</span>    TableDescriptorBuilder builder =<a name="line.599"></a>
+<span class="sourceLineNo">600</span>      TableDescriptorBuilder.newBuilder(tableName);<a name="line.600"></a>
+<span class="sourceLineNo">601</span>    Set&lt;String&gt; cfSet = getColumnFamilies(columns);<a name="line.601"></a>
+<span class="sourceLineNo">602</span>    for (String cf : cfSet) {<a name="line.602"></a>
+<span class="sourceLineNo">603</span>      builder.setColumnFamily(ColumnFamilyDescriptorBuilder.of(cf));<a name="line.603"></a>
+<span class="sourceLineNo">604</span>    }<a name="line.604"></a>
+<span class="sourceLineNo">605</span>    LOG.warn(format("Creating table '%s' with '%s' columns and default descriptors.",<a name="line.605"></a>
+<span class="sourceLineNo">606</span>      tableName, cfSet));<a name="line.606"></a>
+<span class="sourceLineNo">607</span>    admin.createTable(builder.build());<a name="line.607"></a>
+<span class="sourceLineNo">608</span>  }<a name="line.608"></a>
+<span class="sourceLineNo">609</span><a name="line.609"></a>
+<span class="sourceLineNo">610</span>  private static void deleteTable(Configuration conf, String[] args) {<a name="line.610"></a>
+<span class="sourceLineNo">611</span>    TableName tableName = TableName.valueOf(args[0]);<a name="line.611"></a>
+<span class="sourceLineNo">612</span>    try (Connection connection = ConnectionFactory.createConnection(conf);<a name="line.612"></a>
+<span class="sourceLineNo">613</span>         Admin admin = connection.getAdmin()) {<a name="line.613"></a>
+<span class="sourceLineNo">614</span>      try {<a name="line.614"></a>
+<span class="sourceLineNo">615</span>        admin.disableTable(tableName);<a name="line.615"></a>
+<span class="sourceLineNo">616</span>      } catch (TableNotEnabledException e) {<a name="line.616"></a>
+<span class="sourceLineNo">617</span>        LOG.debug("Dry mode: Table: " + tableName + " already disabled, so just deleting it.");<a name="line.617"></a>
+<span class="sourceLineNo">618</span>      }<a name="line.618"></a>
+<span class="sourceLineNo">619</span>      admin.deleteTable(tableName);<a name="line.619"></a>
+<span class="sourceLineNo">620</span>    } catch (IOException e) {<a name="line.620"></a>
+<span class="sourceLineNo">621</span>      LOG.error(format("***Dry run: Failed to delete table '%s'.***%n%s", tableName,<a name="line.621"></a>
+<span class="sourceLineNo">622</span>          e.toString()));<a name="line.622"></a>
+<span class="sourceLineNo">623</span>      return;<a name="line.623"></a>
+<span class="sourceLineNo">624</span>    }<a name="line.624"></a>
+<span class="sourceLineNo">625</span>    LOG.info(format("Dry run: Deleted table '%s'.", tableName));<a name="line.625"></a>
+<span class="sourceLineNo">626</span>  }<a name="line.626"></a>
+<span class="sourceLineNo">627</span><a name="line.627"></a>
+<span class="sourceLineNo">628</span>  private static Set&lt;String&gt; getColumnFamilies(String[] columns) {<a name="line.628"></a>
+<span class="sourceLineNo">629</span>    Set&lt;String&gt; cfSet = new HashSet&lt;&gt;();<a name="line.629"></a>
+<span class="sourceLineNo">630</span>    for (String aColumn : columns) {<a name="line.630"></a>
+<span class="sourceLineNo">631</span>      if (TsvParser.ROWKEY_COLUMN_SPEC.equals(aColumn)<a name="line.631"></a>
+<span class="sourceLineNo">632</span>          || TsvParser.TIMESTAMPKEY_COLUMN_SPEC.equals(aColumn)<a name="line.632"></a>
+<span class="sourceLineNo">633</span>          || TsvParser.CELL_VISIBILITY_COLUMN_SPEC.equals(aColumn)<a name="line.633"></a>
+<span class="sourceLineNo">634</span>          || TsvParser.CELL_TTL_COLUMN_SPEC.equals(aColumn)<a name="line.634"></a>
+<span class="sourceLineNo">635</span>          || TsvParser.ATTRIBUTES_COLUMN_SPEC.equals(aColumn))<a name="line.635"></a>
+<span class="sourceLineNo">636</span>        continue;<a name="line.636"></a>
+<span class="sourceLineNo">637</span>      // we are only concerned with the first one (in case this is a cf:cq)<a name="line.637"></a>
+<span class="sourceLineNo">638</span>      cfSet.add(aColumn.split(":", 2)[0]);<a name="line.638"></a>
+<span class="sourceLineNo">639</span>    }<a name="line.639"></a>
+<span class="sourceLineNo">640</span>    return cfSet;<a name="line.640"></a>
+<span class="sourceLineNo">641</span>  }<a name="line.641"></a>
+<span class="sourceLineNo">642</span><a name="line.642"></a>
+<span class="sourceLineNo">643</span>  /*<a name="line.643"></a>
+<span class="sourceLineNo">644</span>   * @param errorMsg Error message.  Can be null.<a name="line.644"></a>
+<span class="sourceLineNo">645</span>   */<a name="line.645"></a>
+<span class="sourceLineNo">646</span>  private static void usage(final String errorMsg) {<a name="line.646"></a>
+<span class="sourceLineNo">647</span>    if (errorMsg != null &amp;&amp; errorMsg.length() &gt; 0) {<a name="line.647"></a>
+<span class="sourceLineNo">648</span>      System.err.println("ERROR: " + errorMsg);<a name="line.648"></a>
+<span class="sourceLineNo">649</span>    }<a name="line.649"></a>
+<span class="sourceLineNo">650</span>    String usage =<a name="line.650"></a>
+<span class="sourceLineNo">651</span>      "Usage: " + NAME + " -D"+ COLUMNS_CONF_KEY + "=a,b,c &lt;tablename&gt; &lt;inputdir&gt;\n" +<a name="line.651"></a>
+<span class="sourceLineNo">652</span>      "\n" +<a name="line.652"></a>
+<span class="sourceLineNo">653</span>      "Imports the given input directory of TSV data into the specified table.\n" +<a name="line.653"></a>
+<span class="sourceLineNo">654</span>      "\n" +<a name="line.654"></a>
+<span class="sourceLineNo">655</span>      "The column names of the TSV data must be specified using the -D" + COLUMNS_CONF_KEY + "\n" +<a name="line.655"></a>
+<span class="sourceLineNo">656</span>      "option. This option takes the form of comma-separated column names, where each\n" +<a name="line.656"></a>
+<span class="sourceLineNo">657</span>      "column name is either a simple column family, or a columnfamily:qualifier. The special\n" +<a name="line.657"></a>
+<span class="sourceLineNo">658</span>      "column name " + TsvParser.ROWKEY_COLUMN_SPEC + " is used to designate that this column should be used\n" +<a name="line.658"></a>
+<span class="sourceLineNo">659</span>      "as the row key for each imported record. You must specify exactly one column\n" +<a name="line.659"></a>
+<span class="sourceLineNo">660</span>      "to be the row key, and you must specify a column name for every column that exists in the\n" +<a name="line.660"></a>
+<span class="sourceLineNo">661</span>      "input data. Another special column" + TsvParser.TIMESTAMPKEY_COLUMN_SPEC +<a name="line.661"></a>
+<span class="sourceLineNo">662</span>      " designates that this column should be\n" +<a name="line.662"></a>
+<span class="sourceLineNo">663</span>      "used as timestamp for each record. Unlike " + TsvParser.ROWKEY_COLUMN_SPEC + ", " +<a name="line.663"></a>
+<span class="sourceLineNo">664</span>      TsvParser.TIMESTAMPKEY_COLUMN_SPEC + " is optional." + "\n" +<a name="line.664"></a>
+<span class="sourceLineNo">665</span>      "You must specify at most one column as timestamp key for each imported record.\n" +<a name="line.665"></a>
+<span class="sourceLineNo">666</span>      "Record with invalid timestamps (blank, non-numeric) will be treated as bad record.\n" +<a name="line.666"></a>
+<span class="sourceLineNo">667</span>      "Note: if you use this option, then '" + TIMESTAMP_CONF_KEY + "' option will be ignored.\n" +<a name="line.667"></a>
+<span class="sourceLineNo">668</span>      "\n" +<a name="line.668"></a>
+<span class="sourceLineNo">669</span>      "Other special columns that can be specified are " + TsvParser.CELL_TTL_COLUMN_SPEC +<a name="line.669"></a>
+<span class="sourceLineNo">670</span>      " and " + TsvParser.CELL_VISIBILITY_COLUMN_SPEC + ".\n" +<a name="line.670"></a>
+<span class="sourceLineNo">671</span>      TsvParser.CELL_TTL_COLUMN_SPEC + " designates that this column will be used " +<a name="line.671"></a>
+<span class="sourceLineNo">672</span>      "as a Cell's Time To Live (TTL) attribute.\n" +<a name="line.672"></a>
+<span class="sourceLineNo">673</span>      TsvParser.CELL_VISIBILITY_COLUMN_SPEC + " designates that this column contains the " +<a name="line.673"></a>
+<span class="sourceLineNo">674</span>      "visibility label expression.\n" +<a name="line.674"></a>
+<span class="sourceLineNo">675</span>      "\n" +<a name="line.675"></a>
+<span class="sourceLineNo">676</span>      TsvParser.ATTRIBUTES_COLUMN_SPEC+" can be used to specify Operation Attributes per record.\n"+<a name="line.676"></a>
+<span class="sourceLineNo">677</span>      " Should be specified as key=&gt;value where "+TsvParser.DEFAULT_ATTRIBUTES_COLUMN_INDEX+ " is used \n"+<a name="line.677"></a>
+<span class="sourceLineNo">678</span>      " as the seperator.  Note that more than one OperationAttributes can be specified.\n"+<a name="line.678"></a>
+<span class="sourceLineNo">679</span>      "By default importtsv will load data directly into HBase. To instead generate\n" +<a name="line.679"></a>
+<span class="sourceLineNo">680</span>      "HFiles of data to prepare for a bulk data load, pass the option:\n" +<a name="line.680"></a>
+<span class="sourceLineNo">681</span>      "  -D" + BULK_OUTPUT_CONF_KEY + "=/path/for/output\n" +<a name="line.681"></a>
+<span class="sourceLineNo">682</span>      "  Note: if you do not use this option, then the target table must already exist in HBase\n" +<a name="line.682"></a>
+<span class="sourceLineNo">683</span>      "\n" +<a name="line.683"></a>
+<span class="sourceLineNo">684</span>      "Other options that may be specified with -D include:\n" +<a name="line.684"></a>
+<span class="sourceLineNo">685</span>      "  -D" + DRY_RUN_CONF_KEY + "=true - Dry run mode. Data is not actually populated into" +<a name="line.685"></a>
+<span class="sourceLineNo">686</span>      " table. If table does not exist, it is created but deleted in the end.\n" +<a name="line.686"></a>
+<span class="sourceLineNo">687</span>      "  -D" + SKIP_LINES_CONF_KEY + "=false - fail if encountering an invalid line\n" +<a name="line.687"></a>
+<span class="sourceLineNo">688</span>      "  -D" + LOG_BAD_LINES_CONF_KEY + "=true - logs invalid lines to stderr\n" +<a name="line.688"></a>
+<span class="sourceLineNo">689</span>      "  -D" + SKIP_EMPTY_COLUMNS + "=false - If true then skip empty columns in bulk import\n" +<a name="line.689"></a>
+<span class="sourceLineNo">690</span>      "  '-D" + SEPARATOR_CONF_KEY + "=|' - eg separate on pipes instead of tabs\n" +<a name="line.690"></a>
+<span class="sourceLineNo">691</span>      "  -D" + TIMESTAMP_CONF_KEY + "=currentTimeAsLong - use the specified timestamp for the import\n" +<a name="line.691"></a>
+<span class="sourceLineNo">692</span>      "  -D" + MAPPER_CONF_KEY + "=my.Mapper - A user-defined Mapper to use instead of " +<a name="line.692"></a>
+<span class="sourceLineNo">693</span>      DEFAULT_MAPPER.getName() + "\n" +<a name="line.693"></a>
+<span class="sourceLineNo">694</span>      "  -D" + JOB_NAME_CONF_KEY + "=jobName - use the specified mapreduce job name for the import\n" +<a name="line.694"></a>
+<span class="sourceLineNo">695</span>      "  -D" + CREATE_TABLE_CONF_KEY + "=no - can be used to avoid creation of table by this tool\n" +<a name="line.695"></a>
+<span class="sourceLineNo">696</span>      "  Note: if you set this to 'no', then the target table must already exist in HBase\n" +<a name="line.696"></a>
+<span class="sourceLineNo">697</span>      "  -D" + NO_STRICT_COL_FAMILY + "=true - ignore column family check in hbase table. " +<a name="line.697"></a>
+<span class="sourceLineNo">698</span>      "Default is false\n\n" +<a name="line.698"></a>
+<span class="sourceLineNo">699</span>      "For performance consider the following options:\n" +<a name="line.699"></a>
+<span class="sourceLineNo">700</span>      "  -Dmapreduce.map.speculative=false\n" +<a name="line.700"></a>
+<span class="sourceLineNo">701</span>      "  -Dmapreduce.reduce.speculative=false";<a name="line.701"></a>
+<span class="sourceLineNo">702</span><a name="line.702"></a>
+<span class="sourceLineNo">703</span>    System.err.println(usage);<a name="line.703"></a>
+<span class="sourceLineNo">704</span>  }<a name="line.704"></a>
+<span class="sourceLineNo">705</span><a name="line.705"></a>
+<span class="sourceLineNo">706</span>  @Override<a name="line.706"></a>
+<span class="sourceLineNo">707</span>  public int run(String[] args) throws Exception {<a name="line.707"></a>
+<span class="sourceLineNo">708</span>    if (args.length &lt; 2) {<a name="line.708"></a>
+<span class="sourceLineNo">709</span>      usage("Wrong number of arguments: " + args.length);<a name="line.709"></a>
+<span class="sourceLineNo">710</span>      return -1;<a name="line.710"></a>
+<span class="sourceLineNo">711</span>    }<a name="line.711"></a>
+<span class="sourceLineNo">712</span><a name="line.712"></a>
+<span class="sourceLineNo">713</span>    // When MAPPER_CONF_KEY is null, the user wants to use the provided TsvImporterMapper, so<a name="line.713"></a>
+<span class="sourceLineNo">714</span>    // perform validation on these additional args. When it's not null, user has provided their<a name="line.714"></a>
+<span class="sourceLineNo">715</span>    // own mapper, thus these validation are not relevant.<a name="line.715"></a>
+<span class="sourceLineNo">716</span>    // TODO: validation for TsvImporterMapper, not this tool. Move elsewhere.<a name="line.716"></a>
+<span class="sourceLineNo">717</span>    if (null == getConf().get(MAPPER_CONF_KEY)) {<a name="line.717"></a>
+<span class="sourceLineNo">718</span>      // Make sure columns are specified<a name="line.718"></a>
+<span class="sourceLineNo">719</span>      String[] columns = getConf().getStrings(COLUMNS_CONF_KEY);<a name="line.719"></a>
+<span class="sourceLineNo">720</span>      if (columns == null) {<a name="line.720"></a>
+<span class="sourceLineNo">721</span>        usage("No columns specified. Please specify with -D" +<a name="line.721"></a>
+<span class="sourceLineNo">722</span>            COLUMNS_CONF_KEY+"=...");<a name="line.722"></a>
+<span class="sourceLineNo">723</span>        return -1;<a name="line.723"></a>
+<span class="sourceLineNo">724</span>      }<a name="line.724"></a>
+<span class="sourceLineNo">725</span><a name="line.725"></a>
+<span class="sourceLineNo">726</span>      // Make sure they specify exactly one column as the row key<a name="line.726"></a>
+<span class="sourceLineNo">727</span>      int rowkeysFound = 0;<a name="line.727"></a>
+<span class="sourceLineNo">728</span>      for (String col : columns) {<a name="line.728"></a>
+<span class="sourceLineNo">729</span>        if (col.equals(TsvParser.ROWKEY_COLUMN_SPEC)) rowkeysFound++;<a name="line.729"></a>
+<span class="sourceLineNo">730</span>      }<a name="line.730"></a>
+<span class="sourceLineNo">731</span>      if (rowkeysFound != 1) {<a name="line.731"></a>
+<span class="sourceLineNo">732</span>        usage("Must specify exactly one column as " + TsvParser.ROWKEY_COLUMN_SPEC);<a name="line.732"></a>
+<span class="sourceLineNo">733</span>        return -1;<a name="line.733"></a>
+<span class="sourceLineNo">734</span>      }<a name="line.734"></a>
+<span class="sourceLineNo">735</span><a name="line.735"></a>
+<span class="sourceLineNo">736</span>      // Make sure we have at most one column as the timestamp key<a name="line.736"></a>
+<span class="sourceLineNo">737</span>      int tskeysFound = 0;<a name="line.737"></a>
+<span class="sourceLineNo">738</span>      for (String col : columns) {<a name="line.738"></a>
+<span class="sourceLineNo">739</span>        if (col.equals(TsvParser.TIMESTAMPKEY_COLUMN_SPEC))<a name="line.739"></a>
+<span class="sourceLineNo">740</span>          tskeysFound++;<a name="line.740"></a>
+<span class="sourceLineNo">741</span>      }<a name="line.741"></a>
+<span class="sourceLineNo">742</span>      if (tskeysFound &gt; 1) {<a name="line.742"></a>
+<span class="sourceLineNo">743</span>        usage("Must specify at most one column as "<a name="line.743"></a>
+<span class="sourceLineNo">744</span>            + TsvParser.TIMESTAMPKEY_COLUMN_SPEC);<a name="line.744"></a>
+<span class="sourceLineNo">745</span>        return -1;<a name="line.745"></a>
+<span class="sourceLineNo">746</span>      }<a name="line.746"></a>
+<span class="sourceLineNo">747</span><a name="line.747"></a>
+<span class="sourceLineNo">748</span>      int attrKeysFound = 0;<a name="line.748"></a>
+<span class="sourceLineNo">749</span>      for (String col : columns) {<a name="line.749"></a>
+<span class="sourceLineNo">750</span>        if (col.equals(TsvParser.ATTRIBUTES_COLUMN_SPEC))<a name="line.750"></a>
+<span class="sourceLineNo">751</span>          attrKeysFound++;<a name="line.751"></a>
+<span class="sourceLineNo">752</span>      }<a name="line.752"></a>
+<span class="sourceLineNo">753</span>      if (attrKeysFound &gt; 1) {<a name="line.753"></a>
+<span class="sourceLineNo">754</span>        usage("Must specify at most one column as "<a name="line.754"></a>
+<span class="sourceLineNo">755</span>            + TsvParser.ATTRIBUTES_COLUMN_SPEC);<a name="line.755"></a>
+<span class="sourceLineNo">756</span>        return -1;<a name="line.756"></a>
+<span class="sourceLineNo">757</span>      }<a name="line.757"></a>
+<span class="sourceLineNo">758</span><a name="line.758"></a>
+<span class="sourceLineNo">759</span>      // Make sure one or more columns are specified excluding rowkey and<a name="line.759"></a>
+<span class="sourceLineNo">760</span>      // timestamp key<a name="line.760"></a>
+<span class="sourceLineNo">761</span>      if (columns.length - (rowkeysFound + tskeysFound + attrKeysFound) &lt; 1) {<a name="line.761"></a>
+<span class="sourceLineNo">762</span>        usage("One or more columns in addition to the row key and timestamp(optional) are required");<a name="line.762"></a>
+<span class="sourceLineNo">763</span>        return -1;<a name="line.763"></a>
+<span class="sourceLineNo">764</span>      }<a name="line.764"></a>
+<span class="sourceLineNo">765</span>    }<a name="line.765"></a>
+<span class="sourceLineNo">766</span><a name="line.766"></a>
+<span class="sourceLineNo">767</span>    // If timestamp option is not specified, use current system time.<a name="line.767"></a>
+<span class="sourceLineNo">768</span>    long timstamp = getConf().getLong(TIMESTAMP_CONF_KEY, EnvironmentEdgeManager.currentTime());<a name="line.768"></a>
+<span class="sourceLineNo">769</span><a name="line.769"></a>
+<span class="sourceLineNo">770</span>    // Set it back to replace invalid timestamp (non-numeric) with current<a name="line.770"></a>
+<span class="sourceLineNo">771</span>    // system time<a name="line.771"></a>
+<span class="sourceLineNo">772</span>    getConf().setLong(TIMESTAMP_CONF_KEY, timstamp);<a name="line.772"></a>
+<span class="sourceLineNo">773</span><a name="line.773"></a>
+<span class="sourceLineNo">774</span>    synchronized (ImportTsv.class) {<a name="line.774"></a>
+<span class="sourceLineNo">775</span>      DRY_RUN_TABLE_CREATED = false;<a name="line.775"></a>
+<span class="sourceLineNo">776</span>    }<a name="line.776"></a>
+<span class="sourceLineNo">777</span>    Job job = createSubmittableJob(getConf(), args);<a name="line.777"></a>
+<span class="sourceLineNo">778</span>    boolean success = job.waitForCompletion(true);<a name="line.778"></a>
+<span class="sourceLineNo">779</span>    boolean delete = false;<a name="line.779"></a>
+<span class="sourceLineNo">780</span>    synchronized (ImportTsv.class) {<a name="line.780"></a>
+<span class="sourceLineNo">781</span>      delete = DRY_RUN_TABLE_CREATED;<a name="line.781"></a>
+<span class="sourceLineNo">782</span>    }<a name="line.782"></a>
+<span class="sourceLineNo">783</span>    if (delete) {<a name="line.783"></a>
+<span class="sourceLineNo">784</span>      deleteTable(getConf(), args);<a name="line.784"></a>
+<span class="sourceLineNo">785</span>    }<a name="line.785"></a>
+<span class="sourceLineNo">786</span>    return success ? 0 : 1;<a name="line.786"></a>
+<span class="sourceLineNo">787</span>  }<a name="line.787"></a>
+<span class="sourceLineNo">788</span><a name="line.788"></a>
+<span class="sourceLineNo">789</span>  public static void main(String[] args) throws Exception {<a name="line.789"></a>
+<span class="sourceLineNo">790</span>    int status = ToolRunner.run(HBaseConfiguration.create(), new ImportTsv(), args);<a name="line.790"></a>
+<span class="sourceLineNo">791</span>    System.exit(status);<a name="line.791"></a>
+<span class="sourceLineNo">792</span>  }<a name="line.792"></a>
+<span class="sourceLineNo">793</span>}<a name="line.793"></a>
 
 
 
diff --git a/apidocs/src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html b/apidocs/src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html
index 0f8e1cf..0e8e681 100644
--- a/apidocs/src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html
+++ b/apidocs/src-html/org/apache/hadoop/hbase/mapreduce/TableRecordReaderImpl.html
@@ -38,313 +38,314 @@
 <span class="sourceLineNo">030</span>import org.apache.hadoop.hbase.client.metrics.ScanMetrics;<a name="line.30"></a>
 <span class="sourceLineNo">031</span>import org.apache.hadoop.hbase.io.ImmutableBytesWritable;<a name="line.31"></a>
 <span class="sourceLineNo">032</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.32"></a>
-<span class="sourceLineNo">033</span>import org.apache.hadoop.mapreduce.Counter;<a name="line.33"></a>
-<span class="sourceLineNo">034</span>import org.apache.hadoop.mapreduce.InputSplit;<a name="line.34"></a>
-<span class="sourceLineNo">035</span>import org.apache.hadoop.mapreduce.TaskAttemptContext;<a name="line.35"></a>
-<span class="sourceLineNo">036</span>import org.apache.hadoop.util.StringUtils;<a name="line.36"></a>
-<span class="sourceLineNo">037</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.37"></a>
-<span class="sourceLineNo">038</span>import org.slf4j.Logger;<a name="line.38"></a>
-<span class="sourceLineNo">039</span>import org.slf4j.LoggerFactory;<a name="line.39"></a>
-<span class="sourceLineNo">040</span><a name="line.40"></a>
-<span class="sourceLineNo">041</span>/**<a name="line.41"></a>
-<span class="sourceLineNo">042</span> * Iterate over an HBase table data, return (ImmutableBytesWritable, Result)<a name="line.42"></a>
-<span class="sourceLineNo">043</span> * pairs.<a name="line.43"></a>
-<span class="sourceLineNo">044</span> */<a name="line.44"></a>
-<span class="sourceLineNo">045</span>@InterfaceAudience.Public<a name="line.45"></a>
-<span class="sourceLineNo">046</span>public class TableRecordReaderImpl {<a name="line.46"></a>
-<span class="sourceLineNo">047</span>  public static final String LOG_PER_ROW_COUNT<a name="line.47"></a>
-<span class="sourceLineNo">048</span>      = "hbase.mapreduce.log.scanner.rowcount";<a name="line.48"></a>
-<span class="sourceLineNo">049</span><a name="line.49"></a>
-<span class="sourceLineNo">050</span>  private static final Logger LOG = LoggerFactory.getLogger(TableRecordReaderImpl.class);<a name="line.50"></a>
-<span class="sourceLineNo">051</span><a name="line.51"></a>
-<span class="sourceLineNo">052</span>  // HBASE_COUNTER_GROUP_NAME is the name of mapreduce counter group for HBase<a name="line.52"></a>
-<span class="sourceLineNo">053</span>  @InterfaceAudience.Private<a name="line.53"></a>
-<span class="sourceLineNo">054</span>  static final String HBASE_COUNTER_GROUP_NAME = "HBaseCounters";<a name="line.54"></a>
-<span class="sourceLineNo">055</span><a name="line.55"></a>
-<span class="sourceLineNo">056</span>  private ResultScanner scanner = null;<a name="line.56"></a>
-<span class="sourceLineNo">057</span>  private Scan scan = null;<a name="line.57"></a>
-<span class="sourceLineNo">058</span>  private Scan currentScan = null;<a name="line.58"></a>
-<span class="sourceLineNo">059</span>  private Table htable = null;<a name="line.59"></a>
-<span class="sourceLineNo">060</span>  private byte[] lastSuccessfulRow = null;<a name="line.60"></a>
-<span class="sourceLineNo">061</span>  private ImmutableBytesWritable key = null;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>  private Result value = null;<a name="line.62"></a>
-<span class="sourceLineNo">063</span>  private TaskAttemptContext context = null;<a name="line.63"></a>
-<span class="sourceLineNo">064</span>  private long numRestarts = 0;<a name="line.64"></a>
-<span class="sourceLineNo">065</span>  private long numStale = 0;<a name="line.65"></a>
-<span class="sourceLineNo">066</span>  private long timestamp;<a name="line.66"></a>
-<span class="sourceLineNo">067</span>  private int rowcount;<a name="line.67"></a>
-<span class="sourceLineNo">068</span>  private boolean logScannerActivity = false;<a name="line.68"></a>
-<span class="sourceLineNo">069</span>  private int logPerRowCount = 100;<a name="line.69"></a>
-<span class="sourceLineNo">070</span><a name="line.70"></a>
-<span class="sourceLineNo">071</span>  /**<a name="line.71"></a>
-<span class="sourceLineNo">072</span>   * Restart from survivable exceptions by creating a new scanner.<a name="line.72"></a>
-<span class="sourceLineNo">073</span>   *<a name="line.73"></a>
-<span class="sourceLineNo">074</span>   * @param firstRow  The first row to start at.<a name="line.74"></a>
-<span class="sourceLineNo">075</span>   * @throws IOException When restarting fails.<a name="line.75"></a>
-<span class="sourceLineNo">076</span>   */<a name="line.76"></a>
-<span class="sourceLineNo">077</span>  public void restart(byte[] firstRow) throws IOException {<a name="line.77"></a>
-<span class="sourceLineNo">078</span>    // Update counter metrics based on current scan before reinitializing it<a name="line.78"></a>
-<span class="sourceLineNo">079</span>    if (currentScan != null) {<a name="line.79"></a>
-<span class="sourceLineNo">080</span>      updateCounters();<a name="line.80"></a>
-<span class="sourceLineNo">081</span>    }<a name="line.81"></a>
-<span class="sourceLineNo">082</span>    currentScan = new Scan(scan);<a name="line.82"></a>
-<span class="sourceLineNo">083</span>    currentScan.withStartRow(firstRow);<a name="line.83"></a>
-<span class="sourceLineNo">084</span>    currentScan.setScanMetricsEnabled(true);<a name="line.84"></a>
-<span class="sourceLineNo">085</span>    if (this.scanner != null) {<a name="line.85"></a>
-<span class="sourceLineNo">086</span>      if (logScannerActivity) {<a name="line.86"></a>
-<span class="sourceLineNo">087</span>        LOG.info("Closing the previously opened scanner object.");<a name="line.87"></a>
-<span class="sourceLineNo">088</span>      }<a name="line.88"></a>
-<span class="sourceLineNo">089</span>      this.scanner.close();<a name="line.89"></a>
-<span class="sourceLineNo">090</span>    }<a name="line.90"></a>
-<span class="sourceLineNo">091</span>    this.scanner = this.htable.getScanner(currentScan);<a name="line.91"></a>
-<span class="sourceLineNo">092</span>    if (logScannerActivity) {<a name="line.92"></a>
-<span class="sourceLineNo">093</span>      LOG.info("Current scan=" + currentScan.toString());<a name="line.93"></a>
-<span class="sourceLineNo">094</span>      timestamp = System.currentTimeMillis();<a name="line.94"></a>
-<span class="sourceLineNo">095</span>      rowcount = 0;<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><a name="line.98"></a>
-<span class="sourceLineNo">099</span>  /**<a name="line.99"></a>
-<span class="sourceLineNo">100</span>   * In new mapreduce APIs, TaskAttemptContext has two getCounter methods<a name="line.100"></a>
-<span class="sourceLineNo">101</span>   * Check if getCounter(String, String) method is available.<a name="line.101"></a>
-<span class="sourceLineNo">102</span>   * @return The getCounter method or null if not available.<a name="line.102"></a>
-<span class="sourceLineNo">103</span>   * @deprecated since 2.4.0 and 2.3.2, will be removed in 4.0.0<a name="line.103"></a>
-<span class="sourceLineNo">104</span>   */<a name="line.104"></a>
-<span class="sourceLineNo">105</span>  @Deprecated<a name="line.105"></a>
-<span class="sourceLineNo">106</span>  protected static Method retrieveGetCounterWithStringsParams(TaskAttemptContext context)<a name="line.106"></a>
-<span class="sourceLineNo">107</span>    throws IOException {<a name="line.107"></a>
-<span class="sourceLineNo">108</span>    Method m = null;<a name="line.108"></a>
-<span class="sourceLineNo">109</span>    try {<a name="line.109"></a>
-<span class="sourceLineNo">110</span>      m = context.getClass().getMethod("getCounter",<a name="line.110"></a>
-<span class="sourceLineNo">111</span>        new Class [] {String.class, String.class});<a name="line.111"></a>
-<span class="sourceLineNo">112</span>    } catch (SecurityException e) {<a name="line.112"></a>
-<span class="sourceLineNo">113</span>      throw new IOException("Failed test for getCounter", e);<a name="line.113"></a>
-<span class="sourceLineNo">114</span>    } catch (NoSuchMethodException e) {<a name="line.114"></a>
-<span class="sourceLineNo">115</span>      // Ignore<a name="line.115"></a>
-<span class="sourceLineNo">116</span>    }<a name="line.116"></a>
-<span class="sourceLineNo">117</span>    return m;<a name="line.117"></a>
-<span class="sourceLineNo">118</span>  }<a name="line.118"></a>
-<span class="sourceLineNo">119</span><a name="line.119"></a>
-<span class="sourceLineNo">120</span>  /**<a name="line.120"></a>
-<span class="sourceLineNo">121</span>   * Sets the HBase table.<a name="line.121"></a>
-<span class="sourceLineNo">122</span>   * @param htable The table to scan.<a name="line.122"></a>
-<span class="sourceLineNo">123</span>   */<a name="line.123"></a>
-<span class="sourceLineNo">124</span>  public void setHTable(Table htable) {<a name="line.124"></a>
-<span class="sourceLineNo">125</span>    Configuration conf = htable.getConfiguration();<a name="line.125"></a>
-<span class="sourceLineNo">126</span>    logScannerActivity = conf.getBoolean(ConnectionConfiguration.LOG_SCANNER_ACTIVITY, false);<a name="line.126"></a>
-<span class="sourceLineNo">127</span>    logPerRowCount = conf.getInt(LOG_PER_ROW_COUNT, 100);<a name="line.127"></a>
-<span class="sourceLineNo">128</span>    this.htable = htable;<a name="line.128"></a>
-<span class="sourceLineNo">129</span>  }<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>   * Sets the scan defining the actual details like columns etc.<a name="line.132"></a>
-<span class="sourceLineNo">133</span>   *<a name="line.133"></a>
-<span class="sourceLineNo">134</span>   * @param scan  The scan to set.<a name="line.134"></a>
-<span class="sourceLineNo">135</span>   */<a name="line.135"></a>
-<span class="sourceLineNo">136</span>  public void setScan(Scan scan) {<a name="line.136"></a>
-<span class="sourceLineNo">137</span>    this.scan = scan;<a name="line.137"></a>
-<span class="sourceLineNo">138</span>  }<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>   * Build the scanner. Not done in constructor to allow for extension.<a name="line.141"></a>
-<span class="sourceLineNo">142</span>   */<a name="line.142"></a>
-<span class="sourceLineNo">143</span>  public void initialize(InputSplit inputsplit,<a name="line.143"></a>
-<span class="sourceLineNo">144</span>      TaskAttemptContext context) throws IOException,<a name="line.144"></a>
-<span class="sourceLineNo">145</span>      InterruptedException {<a name="line.145"></a>
-<span class="sourceLineNo">146</span>    if (context != null) {<a name="line.146"></a>
-<span class="sourceLineNo">147</span>      this.context = context;<a name="line.147"></a>
-<span class="sourceLineNo">148</span>    }<a name="line.148"></a>
-<span class="sourceLineNo">149</span>    restart(scan.getStartRow());<a name="line.149"></a>
-<span class="sourceLineNo">150</span>  }<a name="line.150"></a>
-<span class="sourceLineNo">151</span><a name="line.151"></a>
-<span class="sourceLineNo">152</span>  /**<a name="line.152"></a>
-<span class="sourceLineNo">153</span>   * Closes the split.<a name="line.153"></a>
-<span class="sourceLineNo">154</span>   *<a name="line.154"></a>
+<span class="sourceLineNo">033</span>import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;<a name="line.33"></a>
+<span class="sourceLineNo">034</span>import org.apache.hadoop.mapreduce.Counter;<a name="line.34"></a>
+<span class="sourceLineNo">035</span>import org.apache.hadoop.mapreduce.InputSplit;<a name="line.35"></a>
+<span class="sourceLineNo">036</span>import org.apache.hadoop.mapreduce.TaskAttemptContext;<a name="line.36"></a>
+<span class="sourceLineNo">037</span>import org.apache.hadoop.util.StringUtils;<a name="line.37"></a>
+<span class="sourceLineNo">038</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.38"></a>
+<span class="sourceLineNo">039</span>import org.slf4j.Logger;<a name="line.39"></a>
+<span class="sourceLineNo">040</span>import org.slf4j.LoggerFactory;<a name="line.40"></a>
+<span class="sourceLineNo">041</span><a name="line.41"></a>
+<span class="sourceLineNo">042</span>/**<a name="line.42"></a>
+<span class="sourceLineNo">043</span> * Iterate over an HBase table data, return (ImmutableBytesWritable, Result)<a name="line.43"></a>
+<span class="sourceLineNo">044</span> * pairs.<a name="line.44"></a>
+<span class="sourceLineNo">045</span> */<a name="line.45"></a>
+<span class="sourceLineNo">046</span>@InterfaceAudience.Public<a name="line.46"></a>
+<span class="sourceLineNo">047</span>public class TableRecordReaderImpl {<a name="line.47"></a>
+<span class="sourceLineNo">048</span>  public static final String LOG_PER_ROW_COUNT<a name="line.48"></a>
+<span class="sourceLineNo">049</span>      = "hbase.mapreduce.log.scanner.rowcount";<a name="line.49"></a>
+<span class="sourceLineNo">050</span><a name="line.50"></a>
+<span class="sourceLineNo">051</span>  private static final Logger LOG = LoggerFactory.getLogger(TableRecordReaderImpl.class);<a name="line.51"></a>
+<span class="sourceLineNo">052</span><a name="line.52"></a>
+<span class="sourceLineNo">053</span>  // HBASE_COUNTER_GROUP_NAME is the name of mapreduce counter group for HBase<a name="line.53"></a>
+<span class="sourceLineNo">054</span>  @InterfaceAudience.Private<a name="line.54"></a>
+<span class="sourceLineNo">055</span>  static final String HBASE_COUNTER_GROUP_NAME = "HBaseCounters";<a name="line.55"></a>
+<span class="sourceLineNo">056</span><a name="line.56"></a>
+<span class="sourceLineNo">057</span>  private ResultScanner scanner = null;<a name="line.57"></a>
+<span class="sourceLineNo">058</span>  private Scan scan = null;<a name="line.58"></a>
+<span class="sourceLineNo">059</span>  private Scan currentScan = null;<a name="line.59"></a>
+<span class="sourceLineNo">060</span>  private Table htable = null;<a name="line.60"></a>
+<span class="sourceLineNo">061</span>  private byte[] lastSuccessfulRow = null;<a name="line.61"></a>
+<span class="sourceLineNo">062</span>  private ImmutableBytesWritable key = null;<a name="line.62"></a>
+<span class="sourceLineNo">063</span>  private Result value = null;<a name="line.63"></a>
+<span class="sourceLineNo">064</span>  private TaskAttemptContext context = null;<a name="line.64"></a>
+<span class="sourceLineNo">065</span>  private long numRestarts = 0;<a name="line.65"></a>
+<span class="sourceLineNo">066</span>  private long numStale = 0;<a name="line.66"></a>
+<span class="sourceLineNo">067</span>  private long timestamp;<a name="line.67"></a>
+<span class="sourceLineNo">068</span>  private int rowcount;<a name="line.68"></a>
+<span class="sourceLineNo">069</span>  private boolean logScannerActivity = false;<a name="line.69"></a>
+<span class="sourceLineNo">070</span>  private int logPerRowCount = 100;<a name="line.70"></a>
+<span class="sourceLineNo">071</span><a name="line.71"></a>
+<span class="sourceLineNo">072</span>  /**<a name="line.72"></a>
+<span class="sourceLineNo">073</span>   * Restart from survivable exceptions by creating a new scanner.<a name="line.73"></a>
+<span class="sourceLineNo">074</span>   *<a name="line.74"></a>
+<span class="sourceLineNo">075</span>   * @param firstRow  The first row to start at.<a name="line.75"></a>
+<span class="sourceLineNo">076</span>   * @throws IOException When restarting fails.<a name="line.76"></a>
+<span class="sourceLineNo">077</span>   */<a name="line.77"></a>
+<span class="sourceLineNo">078</span>  public void restart(byte[] firstRow) throws IOException {<a name="line.78"></a>
+<span class="sourceLineNo">079</span>    // Update counter metrics based on current scan before reinitializing it<a name="line.79"></a>
+<span class="sourceLineNo">080</span>    if (currentScan != null) {<a name="line.80"></a>
+<span class="sourceLineNo">081</span>      updateCounters();<a name="line.81"></a>
+<span class="sourceLineNo">082</span>    }<a name="line.82"></a>
+<span class="sourceLineNo">083</span>    currentScan = new Scan(scan);<a name="line.83"></a>
+<span class="sourceLineNo">084</span>    currentScan.withStartRow(firstRow);<a name="line.84"></a>
+<span class="sourceLineNo">085</span>    currentScan.setScanMetricsEnabled(true);<a name="line.85"></a>
+<span class="sourceLineNo">086</span>    if (this.scanner != null) {<a name="line.86"></a>
+<span class="sourceLineNo">087</span>      if (logScannerActivity) {<a name="line.87"></a>
+<span class="sourceLineNo">088</span>        LOG.info("Closing the previously opened scanner object.");<a name="line.88"></a>
+<span class="sourceLineNo">089</span>      }<a name="line.89"></a>
+<span class="sourceLineNo">090</span>      this.scanner.close();<a name="line.90"></a>
+<span class="sourceLineNo">091</span>    }<a name="line.91"></a>
+<span class="sourceLineNo">092</span>    this.scanner = this.htable.getScanner(currentScan);<a name="line.92"></a>
+<span class="sourceLineNo">093</span>    if (logScannerActivity) {<a name="line.93"></a>
+<span class="sourceLineNo">094</span>      LOG.info("Current scan=" + currentScan.toString());<a name="line.94"></a>
+<span class="sourceLineNo">095</span>      timestamp = EnvironmentEdgeManager.currentTime();<a name="line.95"></a>
+<span class="sourceLineNo">096</span>      rowcount = 0;<a name="line.96"></a>
+<span class="sourceLineNo">097</span>    }<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>   * In new mapreduce APIs, TaskAttemptContext has two getCounter methods<a name="line.101"></a>
+<span class="sourceLineNo">102</span>   * Check if getCounter(String, String) method is available.<a name="line.102"></a>
+<span class="sourceLineNo">103</span>   * @return The getCounter method or null if not available.<a name="line.103"></a>
+<span class="sourceLineNo">104</span>   * @deprecated since 2.4.0 and 2.3.2, will be removed in 4.0.0<a name="line.104"></a>
+<span class="sourceLineNo">105</span>   */<a name="line.105"></a>
+<span class="sourceLineNo">106</span>  @Deprecated<a name="line.106"></a>
+<span class="sourceLineNo">107</span>  protected static Method retrieveGetCounterWithStringsParams(TaskAttemptContext context)<a name="line.107"></a>
+<span class="sourceLineNo">108</span>    throws IOException {<a name="line.108"></a>
+<span class="sourceLineNo">109</span>    Method m = null;<a name="line.109"></a>
+<span class="sourceLineNo">110</span>    try {<a name="line.110"></a>
+<span class="sourceLineNo">111</span>      m = context.getClass().getMethod("getCounter",<a name="line.111"></a>
+<span class="sourceLineNo">112</span>        new Class [] {String.class, String.class});<a name="line.112"></a>
+<span class="sourceLineNo">113</span>    } catch (SecurityException e) {<a name="line.113"></a>
+<span class="sourceLineNo">114</span>      throw new IOException("Failed test for getCounter", e);<a name="line.114"></a>
+<span class="sourceLineNo">115</span>    } catch (NoSuchMethodException e) {<a name="line.115"></a>
+<span class="sourceLineNo">116</span>      // Ignore<a name="line.116"></a>
+<span class="sourceLineNo">117</span>    }<a name="line.117"></a>
+<span class="sourceLineNo">118</span>    return m;<a name="line.118"></a>
+<span class="sourceLineNo">119</span>  }<a name="line.119"></a>
+<span class="sourceLineNo">120</span><a name="line.120"></a>
+<span class="sourceLineNo">121</span>  /**<a name="line.121"></a>
+<span class="sourceLineNo">122</span>   * Sets the HBase table.<a name="line.122"></a>
+<span class="sourceLineNo">123</span>   * @param htable The table to scan.<a name="line.123"></a>
+<span class="sourceLineNo">124</span>   */<a name="line.124"></a>
+<span class="sourceLineNo">125</span>  public void setHTable(Table htable) {<a name="line.125"></a>
+<span class="sourceLineNo">126</span>    Configuration conf = htable.getConfiguration();<a name="line.126"></a>
+<span class="sourceLineNo">127</span>    logScannerActivity = conf.getBoolean(ConnectionConfiguration.LOG_SCANNER_ACTIVITY, false);<a name="line.127"></a>
+<span class="sourceLineNo">128</span>    logPerRowCount = conf.getInt(LOG_PER_ROW_COUNT, 100);<a name="line.128"></a>
+<span class="sourceLineNo">129</span>    this.htable = htable;<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>  /**<a name="line.132"></a>
+<span class="sourceLineNo">133</span>   * Sets the scan defining the actual details like columns etc.<a name="line.133"></a>
+<span class="sourceLineNo">134</span>   *<a name="line.134"></a>
+<span class="sourceLineNo">135</span>   * @param scan  The scan to set.<a name="line.135"></a>
+<span class="sourceLineNo">136</span>   */<a name="line.136"></a>
+<span class="sourceLineNo">137</span>  public void setScan(Scan scan) {<a name="line.137"></a>
+<span class="sourceLineNo">138</span>    this.scan = scan;<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>  /**<a name="line.141"></a>
+<span class="sourceLineNo">142</span>   * Build the scanner. Not done in constructor to allow for extension.<a name="line.142"></a>
+<span class="sourceLineNo">143</span>   */<a name="line.143"></a>
+<span class="sourceLineNo">144</span>  public void initialize(InputSplit inputsplit,<a name="line.144"></a>
+<span class="sourceLineNo">145</span>      TaskAttemptContext context) throws IOException,<a name="line.145"></a>
+<span class="sourceLineNo">146</span>      InterruptedException {<a name="line.146"></a>
+<span class="sourceLineNo">147</span>    if (context != null) {<a name="line.147"></a>
+<span class="sourceLineNo">148</span>      this.context = context;<a name="line.148"></a>
+<span class="sourceLineNo">149</span>    }<a name="line.149"></a>
+<span class="sourceLineNo">150</span>    restart(scan.getStartRow());<a name="line.150"></a>
+<span class="sourceLineNo">151</span>  }<a name="line.151"></a>
+<span class="sourceLineNo">152</span><a name="line.152"></a>
+<span class="sourceLineNo">153</span>  /**<a name="line.153"></a>
+<span class="sourceLineNo">154</span>   * Closes the split.<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 void close() {<a name="line.157"></a>
-<span class="sourceLineNo">158</span>    if (this.scanner != null) {<a name="line.158"></a>
-<span class="sourceLineNo">159</span>      this.scanner.close();<a name="line.159"></a>
-<span class="sourceLineNo">160</span>    }<a name="line.160"></a>
-<span class="sourceLineNo">161</span>    try {<a name="line.161"></a>
-<span class="sourceLineNo">162</span>      this.htable.close();<a name="line.162"></a>
-<span class="sourceLineNo">163</span>    } catch (IOException ioe) {<a name="line.163"></a>
-<span class="sourceLineNo">164</span>      LOG.warn("Error closing table", ioe);<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><a name="line.167"></a>
-<span class="sourceLineNo">168</span>  /**<a name="line.168"></a>
-<span class="sourceLineNo">169</span>   * Returns the current key.<a name="line.169"></a>
-<span class="sourceLineNo">170</span>   *<a name="line.170"></a>
-<span class="sourceLineNo">171</span>   * @return The current key.<a name="line.171"></a>
-<span class="sourceLineNo">172</span>   * @throws InterruptedException When the job is aborted.<a name="line.172"></a>
-<span class="sourceLineNo">173</span>   */<a name="line.173"></a>
-<span class="sourceLineNo">174</span>  public ImmutableBytesWritable getCurrentKey() throws IOException,<a name="line.174"></a>
-<span class="sourceLineNo">175</span>      InterruptedException {<a name="line.175"></a>
-<span class="sourceLineNo">176</span>    return key;<a name="line.176"></a>
-<span class="sourceLineNo">177</span>  }<a name="line.177"></a>
-<span class="sourceLineNo">178</span><a name="line.178"></a>
-<span class="sourceLineNo">179</span>  /**<a name="line.179"></a>
-<span class="sourceLineNo">180</span>   * Returns the current value.<a name="line.180"></a>
-<span class="sourceLineNo">181</span>   *<a name="line.181"></a>
-<span class="sourceLineNo">182</span>   * @return The current value.<a name="line.182"></a>
-<span class="sourceLineNo">183</span>   * @throws IOException When the value is faulty.<a name="line.183"></a>
-<span class="sourceLineNo">184</span>   * @throws InterruptedException When the job is aborted.<a name="line.184"></a>
-<span class="sourceLineNo">185</span>   */<a name="line.185"></a>
-<span class="sourceLineNo">186</span>  public Result getCurrentValue() throws IOException, InterruptedException {<a name="line.186"></a>
-<span class="sourceLineNo">187</span>    return value;<a name="line.187"></a>
-<span class="sourceLineNo">188</span>  }<a name="line.188"></a>
-<span class="sourceLineNo">189</span><a name="line.189"></a>
+<span class="sourceLineNo">156</span>   *<a name="line.156"></a>
+<span class="sourceLineNo">157</span>   */<a name="line.157"></a>
+<span class="sourceLineNo">158</span>  public void close() {<a name="line.158"></a>
+<span class="sourceLineNo">159</span>    if (this.scanner != null) {<a name="line.159"></a>
+<span class="sourceLineNo">160</span>      this.scanner.close();<a name="line.160"></a>
+<span class="sourceLineNo">161</span>    }<a name="line.161"></a>
+<span class="sourceLineNo">162</span>    try {<a name="line.162"></a>
+<span class="sourceLineNo">163</span>      this.htable.close();<a name="line.163"></a>
+<span class="sourceLineNo">164</span>    } catch (IOException ioe) {<a name="line.164"></a>
+<span class="sourceLineNo">165</span>      LOG.warn("Error closing table", ioe);<a name="line.165"></a>
+<span class="sourceLineNo">166</span>    }<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>  /**<a name="line.169"></a>
+<span class="sourceLineNo">170</span>   * Returns the current key.<a name="line.170"></a>
+<span class="sourceLineNo">171</span>   *<a name="line.171"></a>
+<span class="sourceLineNo">172</span>   * @return The current key.<a name="line.172"></a>
+<span class="sourceLineNo">173</span>   * @throws InterruptedException When the job is aborted.<a name="line.173"></a>
+<span class="sourceLineNo">174</span>   */<a name="line.174"></a>
+<span class="sourceLineNo">175</span>  public ImmutableBytesWritable getCurrentKey() throws IOException,<a name="line.175"></a>
+<span class="sourceLineNo">176</span>      InterruptedException {<a name="line.176"></a>
+<span class="sourceLineNo">177</span>    return key;<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>  /**<a name="line.180"></a>
+<span class="sourceLineNo">181</span>   * Returns the current value.<a name="line.181"></a>
+<span class="sourceLineNo">182</span>   *<a name="line.182"></a>
+<span class="sourceLineNo">183</span>   * @return The current value.<a name="line.183"></a>
+<span class="sourceLineNo">184</span>   * @throws IOException When the value is faulty.<a name="line.184"></a>
+<span class="sourceLineNo">185</span>   * @throws InterruptedException When the job is aborted.<a name="line.185"></a>
+<span class="sourceLineNo">186</span>   */<a name="line.186"></a>
+<span class="sourceLineNo">187</span>  public Result getCurrentValue() throws IOException, InterruptedException {<a name="line.187"></a>
+<span class="sourceLineNo">188</span>    return value;<a name="line.188"></a>
+<span class="sourceLineNo">189</span>  }<a name="line.189"></a>
 <span class="sourceLineNo">190</span><a name="line.190"></a>
-<span class="sourceLineNo">191</span>  /**<a name="line.191"></a>
-<span class="sourceLineNo">192</span>   * Positions the record reader to the next record.<a name="line.192"></a>
-<span class="sourceLineNo">193</span>   *<a name="line.193"></a>
-<span class="sourceLineNo">194</span>   * @return &lt;code&gt;true&lt;/code&gt; if there was another record.<a name="line.194"></a>
-<span class="sourceLineNo">195</span>   * @throws IOException When reading the record failed.<a name="line.195"></a>
-<span class="sourceLineNo">196</span>   * @throws InterruptedException When the job was aborted.<a name="line.196"></a>
-<span class="sourceLineNo">197</span>   */<a name="line.197"></a>
-<span class="sourceLineNo">198</span>  public boolean nextKeyValue() throws IOException, InterruptedException {<a name="line.198"></a>
-<span class="sourceLineNo">199</span>    if (key == null) {<a name="line.199"></a>
-<span class="sourceLineNo">200</span>      key = new ImmutableBytesWritable();<a name="line.200"></a>
-<span class="sourceLineNo">201</span>    }<a name="line.201"></a>
-<span class="sourceLineNo">202</span>    if (value == null) {<a name="line.202"></a>
-<span class="sourceLineNo">203</span>      value = new Result();<a name="line.203"></a>
-<span class="sourceLineNo">204</span>    }<a name="line.204"></a>
-<span class="sourceLineNo">205</span>    try {<a name="line.205"></a>
-<span class="sourceLineNo">206</span>      try {<a name="line.206"></a>
-<span class="sourceLineNo">207</span>        value = this.scanner.next();<a name="line.207"></a>
-<span class="sourceLineNo">208</span>        if (value != null &amp;&amp; value.isStale()) {<a name="line.208"></a>
-<span class="sourceLineNo">209</span>          numStale++;<a name="line.209"></a>
-<span class="sourceLineNo">210</span>        }<a name="line.210"></a>
-<span class="sourceLineNo">211</span>        if (logScannerActivity) {<a name="line.211"></a>
-<span class="sourceLineNo">212</span>          rowcount ++;<a name="line.212"></a>
-<span class="sourceLineNo">213</span>          if (rowcount &gt;= logPerRowCount) {<a name="line.213"></a>
-<span class="sourceLineNo">214</span>            long now = System.currentTimeMillis();<a name="line.214"></a>
-<span class="sourceLineNo">215</span>            LOG.info("Mapper took {}ms to process {} rows", (now - timestamp), rowcount);<a name="line.215"></a>
-<span class="sourceLineNo">216</span>            timestamp = now;<a name="line.216"></a>
-<span class="sourceLineNo">217</span>            rowcount = 0;<a name="line.217"></a>
-<span class="sourceLineNo">218</span>          }<a name="line.218"></a>
-<span class="sourceLineNo">219</span>        }<a name="line.219"></a>
-<span class="sourceLineNo">220</span>      } catch (IOException e) {<a name="line.220"></a>
-<span class="sourceLineNo">221</span>        // do not retry if the exception tells us not to do so<a name="line.221"></a>
-<span class="sourceLineNo">222</span>        if (e instanceof DoNotRetryIOException) {<a name="line.222"></a>
-<span class="sourceLineNo">223</span>          updateCounters();<a name="line.223"></a>
-<span class="sourceLineNo">224</span>          throw e;<a name="line.224"></a>
-<span class="sourceLineNo">225</span>        }<a name="line.225"></a>
-<span class="sourceLineNo">226</span>        // try to handle all other IOExceptions by restarting<a name="line.226"></a>
-<span class="sourceLineNo">227</span>        // the scanner, if the second call fails, it will be rethrown<a name="line.227"></a>
-<span class="sourceLineNo">228</span>        LOG.info("recovered from " + StringUtils.stringifyException(e));<a name="line.228"></a>
-<span class="sourceLineNo">229</span>        if (lastSuccessfulRow == null) {<a name="line.229"></a>
-<span class="sourceLineNo">230</span>          LOG.warn("We are restarting the first next() invocation," +<a name="line.230"></a>
-<span class="sourceLineNo">231</span>              " if your mapper has restarted a few other times like this" +<a name="line.231"></a>
-<span class="sourceLineNo">232</span>              " then you should consider killing this job and investigate" +<a name="line.232"></a>
-<span class="sourceLineNo">233</span>              " why it's taking so long.");<a name="line.233"></a>
-<span class="sourceLineNo">234</span>        }<a name="line.234"></a>
-<span class="sourceLineNo">235</span>        if (lastSuccessfulRow == null) {<a name="line.235"></a>
-<span class="sourceLineNo">236</span>          restart(scan.getStartRow());<a name="line.236"></a>
-<span class="sourceLineNo">237</span>        } else {<a name="line.237"></a>
-<span class="sourceLineNo">238</span>          restart(lastSuccessfulRow);<a name="line.238"></a>
-<span class="sourceLineNo">239</span>          scanner.next();    // skip presumed already mapped row<a name="line.239"></a>
-<span class="sourceLineNo">240</span>        }<a name="line.240"></a>
-<span class="sourceLineNo">241</span>        value = scanner.next();<a name="line.241"></a>
-<span class="sourceLineNo">242</span>        if (value != null &amp;&amp; value.isStale()) {<a name="line.242"></a>
-<span class="sourceLineNo">243</span>          numStale++;<a name="line.243"></a>
-<span class="sourceLineNo">244</span>        }<a name="line.244"></a>
-<span class="sourceLineNo">245</span>        numRestarts++;<a name="line.245"></a>
-<span class="sourceLineNo">246</span>      }<a name="line.246"></a>
-<span class="sourceLineNo">247</span><a name="line.247"></a>
-<span class="sourceLineNo">248</span>      if (value != null &amp;&amp; value.size() &gt; 0) {<a name="line.248"></a>
-<span class="sourceLineNo">249</span>        key.set(value.getRow());<a name="line.249"></a>
-<span class="sourceLineNo">250</span>        lastSuccessfulRow = key.get();<a name="line.250"></a>
-<span class="sourceLineNo">251</span>        return true;<a name="line.251"></a>
-<span class="sourceLineNo">252</span>      }<a name="line.252"></a>
-<span class="sourceLineNo">253</span><a name="line.253"></a>
-<span class="sourceLineNo">254</span>      // Need handle cursor result<a name="line.254"></a>
-<span class="sourceLineNo">255</span>      if (value != null &amp;&amp; value.isCursor()) {<a name="line.255"></a>
-<span class="sourceLineNo">256</span>        key.set(value.getCursor().getRow());<a name="line.256"></a>
-<span class="sourceLineNo">257</span>        lastSuccessfulRow = key.get();<a name="line.257"></a>
-<span class="sourceLineNo">258</span>        return true;<a name="line.258"></a>
-<span class="sourceLineNo">259</span>      }<a name="line.259"></a>
-<span class="sourceLineNo">260</span><a name="line.260"></a>
-<span class="sourceLineNo">261</span>      updateCounters();<a name="line.261"></a>
-<span class="sourceLineNo">262</span>      return false;<a name="line.262"></a>
-<span class="sourceLineNo">263</span>    } catch (IOException ioe) {<a name="line.263"></a>
-<span class="sourceLineNo">264</span>      updateCounters();<a name="line.264"></a>
-<span class="sourceLineNo">265</span>      if (logScannerActivity) {<a name="line.265"></a>
-<span class="sourceLineNo">266</span>        long now = System.currentTimeMillis();<a name="line.266"></a>
-<span class="sourceLineNo">267</span>        LOG.info("Mapper took {}ms to process {} rows", (now - timestamp), rowcount);<a name="line.267"></a>
-<span class="sourceLineNo">268</span>        LOG.info(ioe.toString(), ioe);<a name="line.268"></a>
-<span class="sourceLineNo">269</span>        String lastRow = lastSuccessfulRow == null ?<a name="line.269"></a>
-<span class="sourceLineNo">270</span>          "null" : Bytes.toStringBinary(lastSuccessfulRow);<a name="line.270"></a>
-<span class="sourceLineNo">271</span>        LOG.info("lastSuccessfulRow=" + lastRow);<a name="line.271"></a>
-<span class="sourceLineNo">272</span>      }<a name="line.272"></a>
-<span class="sourceLineNo">273</span>      throw ioe;<a name="line.273"></a>
-<span class="sourceLineNo">274</span>    }<a name="line.274"></a>
-<span class="sourceLineNo">275</span>  }<a name="line.275"></a>
-<span class="sourceLineNo">276</span><a name="line.276"></a>
-<span class="sourceLineNo">277</span>  /**<a name="line.277"></a>
-<span class="sourceLineNo">278</span>   * If hbase runs on new version of mapreduce, RecordReader has access to<a name="line.278"></a>
-<span class="sourceLineNo">279</span>   * counters thus can update counters based on scanMetrics.<a name="line.279"></a>
-<span class="sourceLineNo">280</span>   * If hbase runs on old version of mapreduce, it won't be able to get<a name="line.280"></a>
-<span class="sourceLineNo">281</span>   * access to counters and TableRecorderReader can't update counter values.<a name="line.281"></a>
-<span class="sourceLineNo">282</span>   */<a name="line.282"></a>
-<span class="sourceLineNo">283</span>  private void updateCounters() {<a name="line.283"></a>
-<span class="sourceLineNo">284</span>    ScanMetrics scanMetrics = scanner.getScanMetrics();<a name="line.284"></a>
-<span class="sourceLineNo">285</span>    if (scanMetrics == null) {<a name="line.285"></a>
-<span class="sourceLineNo">286</span>      return;<a name="line.286"></a>
-<span class="sourceLineNo">287</span>    }<a name="line.287"></a>
-<span class="sourceLineNo">288</span><a name="line.288"></a>
-<span class="sourceLineNo">289</span>    updateCounters(scanMetrics, numRestarts, context, numStale);<a name="line.289"></a>
-<span class="sourceLineNo">290</span>  }<a name="line.290"></a>
-<span class="sourceLineNo">291</span><a name="line.291"></a>
-<span class="sourceLineNo">292</span>  /**<a name="line.292"></a>
-<span class="sourceLineNo">293</span>   * @deprecated since 2.4.0 and 2.3.2, will be removed in 4.0.0<a name="line.293"></a>
-<span class="sourceLineNo">294</span>   *   Use {@link #updateCounters(ScanMetrics, long, TaskAttemptContext, long)} instead.<a name="line.294"></a>
-<span class="sourceLineNo">295</span>   */<a name="line.295"></a>
-<span class="sourceLineNo">296</span>  @Deprecated<a name="line.296"></a>
-<span class="sourceLineNo">297</span>  protected static void updateCounters(ScanMetrics scanMetrics, long numScannerRestarts,<a name="line.297"></a>
-<span class="sourceLineNo">298</span>      Method getCounter, TaskAttemptContext context, long numStale) {<a name="line.298"></a>
-<span class="sourceLineNo">299</span>    updateCounters(scanMetrics, numScannerRestarts, context, numStale);<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>  protected static void updateCounters(ScanMetrics scanMetrics, long numScannerRestarts,<a name="line.302"></a>
-<span class="sourceLineNo">303</span>      TaskAttemptContext context, long numStale) {<a name="line.303"></a>
-<span class="sourceLineNo">304</span>    // we can get access to counters only if hbase uses new mapreduce APIs<a name="line.304"></a>
-<span class="sourceLineNo">305</span>    if (context == null) {<a name="line.305"></a>
-<span class="sourceLineNo">306</span>      return;<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>      for (Map.Entry&lt;String, Long&gt; entry : scanMetrics.getMetricsMap().entrySet()) {<a name="line.309"></a>
-<span class="sourceLineNo">310</span>        Counter counter = context.getCounter(HBASE_COUNTER_GROUP_NAME, entry.getKey());<a name="line.310"></a>
-<span class="sourceLineNo">311</span>        if (counter != null) {<a name="line.311"></a>
-<span class="sourceLineNo">312</span>          counter.increment(entry.getValue());<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>      if (numScannerRestarts != 0L) {<a name="line.315"></a>
-<span class="sourceLineNo">316</span>        Counter counter = context.getCounter(HBASE_COUNTER_GROUP_NAME, "NUM_SCANNER_RESTARTS");<a name="line.316"></a>
-<span class="sourceLineNo">317</span>        if (counter != null) {<a name="line.317"></a>
-<span class="sourceLineNo">318</span>          counter.increment(numScannerRestarts);<a name="line.318"></a>
-<span class="sourceLineNo">319</span>        }<a name="line.319"></a>
-<span class="sourceLineNo">320</span>      }<a name="line.320"></a>
-<span class="sourceLineNo">321</span>      if (numStale != 0L) {<a name="line.321"></a>
-<span class="sourceLineNo">322</span>        Counter counter = context.getCounter(HBASE_COUNTER_GROUP_NAME, "NUM_SCAN_RESULTS_STALE");<a name="line.322"></a>
-<span class="sourceLineNo">323</span>        if (counter != null) {<a name="line.323"></a>
-<span class="sourceLineNo">324</span>          counter.increment(numStale);<a name="line.324"></a>
-<span class="sourceLineNo">325</span>        }<a name="line.325"></a>
-<span class="sourceLineNo">326</span>      }<a name="line.326"></a>
-<span class="sourceLineNo">327</span>  }<a name="line.327"></a>
-<span class="sourceLineNo">328</span><a name="line.328"></a>
-<span class="sourceLineNo">329</span>  /**<a name="line.329"></a>
-<span class="sourceLineNo">330</span>   * The current progress of the record reader through its data.<a name="line.330"></a>
-<span class="sourceLineNo">331</span>   *<a name="line.331"></a>
-<span class="sourceLineNo">332</span>   * @return A number between 0.0 and 1.0, the fraction of the data read.<a name="line.332"></a>
-<span class="sourceLineNo">333</span>   */<a name="line.333"></a>
-<span class="sourceLineNo">334</span>  public float getProgress() {<a name="line.334"></a>
-<span class="sourceLineNo">335</span>    // Depends on the total number of tuples<a name="line.335"></a>
-<span class="sourceLineNo">336</span>    return 0;<a name="line.336"></a>
-<span class="sourceLineNo">337</span>  }<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">191</span><a name="line.191"></a>
+<span class="sourceLineNo">192</span>  /**<a name="line.192"></a>
+<span class="sourceLineNo">193</span>   * Positions the record reader to the next record.<a name="line.193"></a>
+<span class="sourceLineNo">194</span>   *<a name="line.194"></a>
+<span class="sourceLineNo">195</span>   * @return &lt;code&gt;true&lt;/code&gt; if there was another record.<a name="line.195"></a>
+<span class="sourceLineNo">196</span>   * @throws IOException When reading the record failed.<a name="line.196"></a>
+<span class="sourceLineNo">197</span>   * @throws InterruptedException When the job was aborted.<a name="line.197"></a>
+<span class="sourceLineNo">198</span>   */<a name="line.198"></a>
+<span class="sourceLineNo">199</span>  public boolean nextKeyValue() throws IOException, InterruptedException {<a name="line.199"></a>
+<span class="sourceLineNo">200</span>    if (key == null) {<a name="line.200"></a>
+<span class="sourceLineNo">201</span>      key = new ImmutableBytesWritable();<a name="line.201"></a>
+<span class="sourceLineNo">202</span>    }<a name="line.202"></a>
+<span class="sourceLineNo">203</span>    if (value == null) {<a name="line.203"></a>
+<span class="sourceLineNo">204</span>      value = new Result();<a name="line.204"></a>
+<span class="sourceLineNo">205</span>    }<a name="line.205"></a>
+<span class="sourceLineNo">206</span>    try {<a name="line.206"></a>
+<span class="sourceLineNo">207</span>      try {<a name="line.207"></a>
+<span class="sourceLineNo">208</span>        value = this.scanner.next();<a name="line.208"></a>
+<span class="sourceLineNo">209</span>        if (value != null &amp;&amp; value.isStale()) {<a name="line.209"></a>
+<span class="sourceLineNo">210</span>          numStale++;<a name="line.210"></a>
+<span class="sourceLineNo">211</span>        }<a name="line.211"></a>
+<span class="sourceLineNo">212</span>        if (logScannerActivity) {<a name="line.212"></a>
+<span class="sourceLineNo">213</span>          rowcount ++;<a name="line.213"></a>
+<span class="sourceLineNo">214</span>          if (rowcount &gt;= logPerRowCount) {<a name="line.214"></a>
+<span class="sourceLineNo">215</span>            long now = EnvironmentEdgeManager.currentTime();<a name="line.215"></a>
+<span class="sourceLineNo">216</span>            LOG.info("Mapper took {}ms to process {} rows", (now - timestamp), rowcount);<a name="line.216"></a>
+<span class="sourceLineNo">217</span>            timestamp = now;<a name="line.217"></a>
+<span class="sourceLineNo">218</span>            rowcount = 0;<a name="line.218"></a>
+<span class="sourceLineNo">219</span>          }<a name="line.219"></a>
+<span class="sourceLineNo">220</span>        }<a name="line.220"></a>
+<span class="sourceLineNo">221</span>      } catch (IOException e) {<a name="line.221"></a>
+<span class="sourceLineNo">222</span>        // do not retry if the exception tells us not to do so<a name="line.222"></a>
+<span class="sourceLineNo">223</span>        if (e instanceof DoNotRetryIOException) {<a name="line.223"></a>
+<span class="sourceLineNo">224</span>          updateCounters();<a name="line.224"></a>
+<span class="sourceLineNo">225</span>          throw e;<a name="line.225"></a>
+<span class="sourceLineNo">226</span>        }<a name="line.226"></a>
+<span class="sourceLineNo">227</span>        // try to handle all other IOExceptions by restarting<a name="line.227"></a>
+<span class="sourceLineNo">228</span>        // the scanner, if the second call fails, it will be rethrown<a name="line.228"></a>
+<span class="sourceLineNo">229</span>        LOG.info("recovered from " + StringUtils.stringifyException(e));<a name="line.229"></a>
+<span class="sourceLineNo">230</span>        if (lastSuccessfulRow == null) {<a name="line.230"></a>
+<span class="sourceLineNo">231</span>          LOG.warn("We are restarting the first next() invocation," +<a name="line.231"></a>
+<span class="sourceLineNo">232</span>              " if your mapper has restarted a few other times like this" +<a name="line.232"></a>
+<span class="sourceLineNo">233</span>              " then you should consider killing this job and investigate" +<a name="line.233"></a>
+<span class="sourceLineNo">234</span>              " why it's taking so long.");<a name="line.234"></a>
+<span class="sourceLineNo">235</span>        }<a name="line.235"></a>
+<span class="sourceLineNo">236</span>        if (lastSuccessfulRow == null) {<a name="line.236"></a>
+<span class="sourceLineNo">237</span>          restart(scan.getStartRow());<a name="line.237"></a>
+<span class="sourceLineNo">238</span>        } else {<a name="line.238"></a>
+<span class="sourceLineNo">239</span>          restart(lastSuccessfulRow);<a name="line.239"></a>
+<span class="sourceLineNo">240</span>          scanner.next();    // skip presumed already mapped row<a name="line.240"></a>
+<span class="sourceLineNo">241</span>        }<a name="line.241"></a>
+<span class="sourceLineNo">242</span>        value = scanner.next();<a name="line.242"></a>
+<span class="sourceLineNo">243</span>        if (value != null &amp;&amp; value.isStale()) {<a name="line.243"></a>
+<span class="sourceLineNo">244</span>          numStale++;<a name="line.244"></a>
+<span class="sourceLineNo">245</span>        }<a name="line.245"></a>
+<span class="sourceLineNo">246</span>        numRestarts++;<a name="line.246"></a>
+<span class="sourceLineNo">247</span>      }<a name="line.247"></a>
+<span class="sourceLineNo">248</span><a name="line.248"></a>
+<span class="sourceLineNo">249</span>      if (value != null &amp;&amp; value.size() &gt; 0) {<a name="line.249"></a>
+<span class="sourceLineNo">250</span>        key.set(value.getRow());<a name="line.250"></a>
+<span class="sourceLineNo">251</span>        lastSuccessfulRow = key.get();<a name="line.251"></a>
+<span class="sourceLineNo">252</span>        return true;<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>      // Need handle cursor result<a name="line.255"></a>
+<span class="sourceLineNo">256</span>      if (value != null &amp;&amp; value.isCursor()) {<a name="line.256"></a>
+<span class="sourceLineNo">257</span>        key.set(value.getCursor().getRow());<a name="line.257"></a>
+<span class="sourceLineNo">258</span>        lastSuccessfulRow = key.get();<a name="line.258"></a>
+<span class="sourceLineNo">259</span>        return true;<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>      updateCounters();<a name="line.262"></a>
+<span class="sourceLineNo">263</span>      return false;<a name="line.263"></a>
+<span class="sourceLineNo">264</span>    } catch (IOException ioe) {<a name="line.264"></a>
+<span class="sourceLineNo">265</span>      updateCounters();<a name="line.265"></a>
+<span class="sourceLineNo">266</span>      if (logScannerActivity) {<a name="line.266"></a>
+<span class="sourceLineNo">267</span>        long now = EnvironmentEdgeManager.currentTime();<a name="line.267"></a>
+<span class="sourceLineNo">268</span>        LOG.info("Mapper took {}ms to process {} rows", (now - timestamp), rowcount);<a name="line.268"></a>
+<span class="sourceLineNo">269</span>        LOG.info(ioe.toString(), ioe);<a name="line.269"></a>
+<span class="sourceLineNo">270</span>        String lastRow = lastSuccessfulRow == null ?<a name="line.270"></a>
+<span class="sourceLineNo">271</span>          "null" : Bytes.toStringBinary(lastSuccessfulRow);<a name="line.271"></a>
+<span class="sourceLineNo">272</span>        LOG.info("lastSuccessfulRow=" + lastRow);<a name="line.272"></a>
+<span class="sourceLineNo">273</span>      }<a name="line.273"></a>
+<span class="sourceLineNo">274</span>      throw ioe;<a name="line.274"></a>
+<span class="sourceLineNo">275</span>    }<a name="line.275"></a>
+<span class="sourceLineNo">276</span>  }<a name="line.276"></a>
+<span class="sourceLineNo">277</span><a name="line.277"></a>
+<span class="sourceLineNo">278</span>  /**<a name="line.278"></a>
+<span class="sourceLineNo">279</span>   * If hbase runs on new version of mapreduce, RecordReader has access to<a name="line.279"></a>
+<span class="sourceLineNo">280</span>   * counters thus can update counters based on scanMetrics.<a name="line.280"></a>
+<span class="sourceLineNo">281</span>   * If hbase runs on old version of mapreduce, it won't be able to get<a name="line.281"></a>
+<span class="sourceLineNo">282</span>   * access to counters and TableRecorderReader can't update counter values.<a name="line.282"></a>
+<span class="sourceLineNo">283</span>   */<a name="line.283"></a>
+<span class="sourceLineNo">284</span>  private void updateCounters() {<a name="line.284"></a>
+<span class="sourceLineNo">285</span>    ScanMetrics scanMetrics = scanner.getScanMetrics();<a name="line.285"></a>
+<span class="sourceLineNo">286</span>    if (scanMetrics == null) {<a name="line.286"></a>
+<span class="sourceLineNo">287</span>      return;<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>    updateCounters(scanMetrics, numRestarts, context, numStale);<a name="line.290"></a>
+<span class="sourceLineNo">291</span>  }<a name="line.291"></a>
+<span class="sourceLineNo">292</span><a name="line.292"></a>
+<span class="sourceLineNo">293</span>  /**<a name="line.293"></a>
+<span class="sourceLineNo">294</span>   * @deprecated since 2.4.0 and 2.3.2, will be removed in 4.0.0<a name="line.294"></a>
+<span class="sourceLineNo">295</span>   *   Use {@link #updateCounters(ScanMetrics, long, TaskAttemptContext, long)} instead.<a name="line.295"></a>
+<span class="sourceLineNo">296</span>   */<a name="line.296"></a>
+<span class="sourceLineNo">297</span>  @Deprecated<a name="line.297"></a>
+<span class="sourceLineNo">298</span>  protected static void updateCounters(ScanMetrics scanMetrics, long numScannerRestarts,<a name="line.298"></a>
+<span class="sourceLineNo">299</span>      Method getCounter, TaskAttemptContext context, long numStale) {<a name="line.299"></a>
+<span class="sourceLineNo">300</span>    updateCounters(scanMetrics, numScannerRestarts, context, numStale);<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>  protected static void updateCounters(ScanMetrics scanMetrics, long numScannerRestarts,<a name="line.303"></a>
+<span class="sourceLineNo">304</span>      TaskAttemptContext context, long numStale) {<a name="line.304"></a>
+<span class="sourceLineNo">305</span>    // we can get access to counters only if hbase uses new mapreduce APIs<a name="line.305"></a>
+<span class="sourceLineNo">306</span>    if (context == null) {<a name="line.306"></a>
+<span class="sourceLineNo">307</span>      return;<a name="line.307"></a>
+<span class="sourceLineNo">308</span>    }<a name="line.308"></a>
+<span class="sourceLineNo">309</span><a name="line.309"></a>
+<span class="sourceLineNo">310</span>      for (Map.Entry&lt;String, Long&gt; entry : scanMetrics.getMetricsMap().entrySet()) {<a name="line.310"></a>
+<span class="sourceLineNo">311</span>        Counter counter = context.getCounter(HBASE_COUNTER_GROUP_NAME, entry.getKey());<a name="line.311"></a>
+<span class="sourceLineNo">312</span>        if (counter != null) {<a name="line.312"></a>
+<span class="sourceLineNo">313</span>          counter.increment(entry.getValue());<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>      if (numScannerRestarts != 0L) {<a name="line.316"></a>
+<span class="sourceLineNo">317</span>        Counter counter = context.getCounter(HBASE_COUNTER_GROUP_NAME, "NUM_SCANNER_RESTARTS");<a name="line.317"></a>
+<span class="sourceLineNo">318</span>        if (counter != null) {<a name="line.318"></a>
+<span class="sourceLineNo">319</span>          counter.increment(numScannerRestarts);<a name="line.319"></a>
+<span class="sourceLineNo">320</span>        }<a name="line.320"></a>
+<span class="sourceLineNo">321</span>      }<a name="line.321"></a>
+<span class="sourceLineNo">322</span>      if (numStale != 0L) {<a name="line.322"></a>
+<span class="sourceLineNo">323</span>        Counter counter = context.getCounter(HBASE_COUNTER_GROUP_NAME, "NUM_SCAN_RESULTS_STALE");<a name="line.323"></a>
+<span class="sourceLineNo">324</span>        if (counter != null) {<a name="line.324"></a>
+<span class="sourceLineNo">325</span>          counter.increment(numStale);<a name="line.325"></a>
+<span class="sourceLineNo">326</span>        }<a name="line.326"></a>
+<span class="sourceLineNo">327</span>      }<a name="line.327"></a>
+<span class="sourceLineNo">328</span>  }<a name="line.328"></a>
+<span class="sourceLineNo">329</span><a name="line.329"></a>
+<span class="sourceLineNo">330</span>  /**<a name="line.330"></a>
+<span class="sourceLineNo">331</span>   * The current progress of the record reader through its data.<a name="line.331"></a>
+<span class="sourceLineNo">332</span>   *<a name="line.332"></a>
+<span class="sourceLineNo">333</span>   * @return A number between 0.0 and 1.0, the fraction of the data read.<a name="line.333"></a>
+<span class="sourceLineNo">334</span>   */<a name="line.334"></a>
+<span class="sourceLineNo">335</span>  public float getProgress() {<a name="line.335"></a>
+<span class="sourceLineNo">336</span>    // Depends on the total number of tuples<a name="line.336"></a>
+<span class="sourceLineNo">337</span>    return 0;<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>}<a name="line.340"></a>
 
 
 
diff --git a/apidocs/src-html/org/apache/hadoop/hbase/mapreduce/WALPlayer.html b/apidocs/src-html/org/apache/hadoop/hbase/mapreduce/WALPlayer.html
index 50fd16e..311078a 100644
--- a/apidocs/src-html/org/apache/hadoop/hbase/mapreduce/WALPlayer.html
+++ b/apidocs/src-html/org/apache/hadoop/hbase/mapreduce/WALPlayer.html
@@ -52,377 +52,378 @@
 <span class="sourceLineNo">044</span>import org.apache.hadoop.hbase.mapreduce.HFileOutputFormat2.TableInfo;<a name="line.44"></a>
 <span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.regionserver.wal.WALCellCodec;<a name="line.45"></a>
 <span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.util.Bytes;<a name="line.46"></a>
-<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.util.MapReduceExtendedCell;<a name="line.47"></a>
-<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.wal.WALEdit;<a name="line.48"></a>
-<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.wal.WALKey;<a name="line.49"></a>
-<span class="sourceLineNo">050</span>import org.apache.hadoop.mapreduce.Job;<a name="line.50"></a>
-<span class="sourceLineNo">051</span>import org.apache.hadoop.mapreduce.Mapper;<a name="line.51"></a>
-<span class="sourceLineNo">052</span>import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;<a name="line.52"></a>
-<span class="sourceLineNo">053</span>import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;<a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.apache.hadoop.util.Tool;<a name="line.54"></a>
-<span class="sourceLineNo">055</span>import org.apache.hadoop.util.ToolRunner;<a name="line.55"></a>
-<span class="sourceLineNo">056</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.56"></a>
-<span class="sourceLineNo">057</span>import org.slf4j.Logger;<a name="line.57"></a>
-<span class="sourceLineNo">058</span>import org.slf4j.LoggerFactory;<a name="line.58"></a>
-<span class="sourceLineNo">059</span><a name="line.59"></a>
+<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.apache.hadoop.hbase.util.MapReduceExtendedCell;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.apache.hadoop.hbase.wal.WALEdit;<a name="line.49"></a>
+<span class="sourceLineNo">050</span>import org.apache.hadoop.hbase.wal.WALKey;<a name="line.50"></a>
+<span class="sourceLineNo">051</span>import org.apache.hadoop.mapreduce.Job;<a name="line.51"></a>
+<span class="sourceLineNo">052</span>import org.apache.hadoop.mapreduce.Mapper;<a name="line.52"></a>
+<span class="sourceLineNo">053</span>import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;<a name="line.53"></a>
+<span class="sourceLineNo">054</span>import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>import org.apache.hadoop.util.Tool;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>import org.apache.hadoop.util.ToolRunner;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.57"></a>
+<span class="sourceLineNo">058</span>import org.slf4j.Logger;<a name="line.58"></a>
+<span class="sourceLineNo">059</span>import org.slf4j.LoggerFactory;<a name="line.59"></a>
 <span class="sourceLineNo">060</span><a name="line.60"></a>
 <span class="sourceLineNo">061</span><a name="line.61"></a>
-<span class="sourceLineNo">062</span>/**<a name="line.62"></a>
-<span class="sourceLineNo">063</span> * A tool to replay WAL files as a M/R job.<a name="line.63"></a>
-<span class="sourceLineNo">064</span> * The WAL can be replayed for a set of tables or all tables,<a name="line.64"></a>
-<span class="sourceLineNo">065</span> * and a time range can be provided (in milliseconds).<a name="line.65"></a>
-<span class="sourceLineNo">066</span> * The WAL is filtered to the passed set of tables and  the output<a name="line.66"></a>
-<span class="sourceLineNo">067</span> * can optionally be mapped to another set of tables.<a name="line.67"></a>
-<span class="sourceLineNo">068</span> *<a name="line.68"></a>
-<span class="sourceLineNo">069</span> * WAL replay can also generate HFiles for later bulk importing,<a name="line.69"></a>
-<span class="sourceLineNo">070</span> * in that case the WAL is replayed for a single table only.<a name="line.70"></a>
-<span class="sourceLineNo">071</span> */<a name="line.71"></a>
-<span class="sourceLineNo">072</span>@InterfaceAudience.Public<a name="line.72"></a>
-<span class="sourceLineNo">073</span>public class WALPlayer extends Configured implements Tool {<a name="line.73"></a>
-<span class="sourceLineNo">074</span>  private static final Logger LOG = LoggerFactory.getLogger(WALPlayer.class);<a name="line.74"></a>
-<span class="sourceLineNo">075</span>  final static String NAME = "WALPlayer";<a name="line.75"></a>
-<span class="sourceLineNo">076</span>  public final static String BULK_OUTPUT_CONF_KEY = "wal.bulk.output";<a name="line.76"></a>
-<span class="sourceLineNo">077</span>  public final static String TABLES_KEY = "wal.input.tables";<a name="line.77"></a>
-<span class="sourceLineNo">078</span>  public final static String TABLE_MAP_KEY = "wal.input.tablesmap";<a name="line.78"></a>
-<span class="sourceLineNo">079</span>  public final static String INPUT_FILES_SEPARATOR_KEY = "wal.input.separator";<a name="line.79"></a>
-<span class="sourceLineNo">080</span>  public final static String IGNORE_MISSING_FILES = "wal.input.ignore.missing.files";<a name="line.80"></a>
-<span class="sourceLineNo">081</span>  public final static String MULTI_TABLES_SUPPORT = "wal.multi.tables.support";<a name="line.81"></a>
-<span class="sourceLineNo">082</span><a name="line.82"></a>
-<span class="sourceLineNo">083</span>  protected static final String tableSeparator = ";";<a name="line.83"></a>
-<span class="sourceLineNo">084</span><a name="line.84"></a>
-<span class="sourceLineNo">085</span>  private final static String JOB_NAME_CONF_KEY = "mapreduce.job.name";<a name="line.85"></a>
-<span class="sourceLineNo">086</span><a name="line.86"></a>
-<span class="sourceLineNo">087</span>  public WALPlayer() {<a name="line.87"></a>
-<span class="sourceLineNo">088</span>  }<a name="line.88"></a>
-<span class="sourceLineNo">089</span><a name="line.89"></a>
-<span class="sourceLineNo">090</span>  protected WALPlayer(final Configuration c) {<a name="line.90"></a>
-<span class="sourceLineNo">091</span>    super(c);<a name="line.91"></a>
-<span class="sourceLineNo">092</span>  }<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>   * A mapper that just writes out KeyValues. This one can be used together with<a name="line.95"></a>
-<span class="sourceLineNo">096</span>   * {@link CellSortReducer}<a name="line.96"></a>
-<span class="sourceLineNo">097</span>   */<a name="line.97"></a>
-<span class="sourceLineNo">098</span>  static class WALKeyValueMapper extends Mapper&lt;WALKey, WALEdit, ImmutableBytesWritable, Cell&gt; {<a name="line.98"></a>
-<span class="sourceLineNo">099</span>    private Set&lt;String&gt; tableSet = new HashSet&lt;String&gt;();<a name="line.99"></a>
-<span class="sourceLineNo">100</span>    private boolean multiTableSupport = false;<a name="line.100"></a>
-<span class="sourceLineNo">101</span><a name="line.101"></a>
-<span class="sourceLineNo">102</span>    @Override<a name="line.102"></a>
-<span class="sourceLineNo">103</span>    public void map(WALKey key, WALEdit value, Context context) throws IOException {<a name="line.103"></a>
-<span class="sourceLineNo">104</span>      try {<a name="line.104"></a>
-<span class="sourceLineNo">105</span>        // skip all other tables<a name="line.105"></a>
-<span class="sourceLineNo">106</span>        TableName table = key.getTableName();<a name="line.106"></a>
-<span class="sourceLineNo">107</span>        if (tableSet.contains(table.getNameAsString())) {<a name="line.107"></a>
-<span class="sourceLineNo">108</span>          for (Cell cell : value.getCells()) {<a name="line.108"></a>
-<span class="sourceLineNo">109</span>            if (WALEdit.isMetaEditFamily(cell)) {<a name="line.109"></a>
-<span class="sourceLineNo">110</span>              continue;<a name="line.110"></a>
-<span class="sourceLineNo">111</span>            }<a name="line.111"></a>
-<span class="sourceLineNo">112</span>            byte[] outKey = multiTableSupport<a name="line.112"></a>
-<span class="sourceLineNo">113</span>                ? Bytes.add(table.getName(), Bytes.toBytes(tableSeparator), CellUtil.cloneRow(cell))<a name="line.113"></a>
-<span class="sourceLineNo">114</span>                : CellUtil.cloneRow(cell);<a name="line.114"></a>
-<span class="sourceLineNo">115</span>            context.write(new ImmutableBytesWritable(outKey), new MapReduceExtendedCell(cell));<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>      } catch (InterruptedException e) {<a name="line.118"></a>
-<span class="sourceLineNo">119</span>        LOG.error("Interrupted while emitting Cell", e);<a name="line.119"></a>
-<span class="sourceLineNo">120</span>        Thread.currentThread().interrupt();<a name="line.120"></a>
-<span class="sourceLineNo">121</span>      }<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>    @Override<a name="line.124"></a>
-<span class="sourceLineNo">125</span>    public void setup(Context context) throws IOException {<a name="line.125"></a>
-<span class="sourceLineNo">126</span>      Configuration conf = context.getConfiguration();<a name="line.126"></a>
-<span class="sourceLineNo">127</span>      String[] tables = conf.getStrings(TABLES_KEY);<a name="line.127"></a>
-<span class="sourceLineNo">128</span>      this.multiTableSupport = conf.getBoolean(MULTI_TABLES_SUPPORT, false);<a name="line.128"></a>
-<span class="sourceLineNo">129</span>      for (String table : tables) {<a name="line.129"></a>
-<span class="sourceLineNo">130</span>        tableSet.add(table);<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>  }<a name="line.133"></a>
-<span class="sourceLineNo">134</span><a name="line.134"></a>
-<span class="sourceLineNo">135</span>  /**<a name="line.135"></a>
-<span class="sourceLineNo">136</span>   * Enum for map metrics.  Keep it out here rather than inside in the Map<a name="line.136"></a>
-<span class="sourceLineNo">137</span>   * inner-class so we can find associated properties.<a name="line.137"></a>
-<span class="sourceLineNo">138</span>   */<a name="line.138"></a>
-<span class="sourceLineNo">139</span>  protected static enum Counter {<a name="line.139"></a>
-<span class="sourceLineNo">140</span>    /** Number of aggregated writes */<a name="line.140"></a>
-<span class="sourceLineNo">141</span>    PUTS,<a name="line.141"></a>
-<span class="sourceLineNo">142</span>    /** Number of aggregated deletes */<a name="line.142"></a>
-<span class="sourceLineNo">143</span>    DELETES,<a name="line.143"></a>
-<span class="sourceLineNo">144</span>    CELLS_READ,<a name="line.144"></a>
-<span class="sourceLineNo">145</span>    CELLS_WRITTEN,<a name="line.145"></a>
-<span class="sourceLineNo">146</span>    WALEDITS<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>  /**<a name="line.149"></a>
-<span class="sourceLineNo">150</span>   * A mapper that writes out {@link Mutation} to be directly applied to<a name="line.150"></a>
-<span class="sourceLineNo">151</span>   * a running HBase instance.<a name="line.151"></a>
-<span class="sourceLineNo">152</span>   */<a name="line.152"></a>
-<span class="sourceLineNo">153</span>  protected static class WALMapper<a name="line.153"></a>
-<span class="sourceLineNo">154</span>      extends Mapper&lt;WALKey, WALEdit, ImmutableBytesWritable, Mutation&gt; {<a name="line.154"></a>
-<span class="sourceLineNo">155</span>    private Map&lt;TableName, TableName&gt; tables = new TreeMap&lt;&gt;();<a name="line.155"></a>
-<span class="sourceLineNo">156</span><a name="line.156"></a>
-<span class="sourceLineNo">157</span>    @Override<a name="line.157"></a>
-<span class="sourceLineNo">158</span>    public void map(WALKey key, WALEdit value, Context context) throws IOException {<a name="line.158"></a>
-<span class="sourceLineNo">159</span>      context.getCounter(Counter.WALEDITS).increment(1);<a name="line.159"></a>
-<span class="sourceLineNo">160</span>      try {<a name="line.160"></a>
-<span class="sourceLineNo">161</span>        if (tables.isEmpty() || tables.containsKey(key.getTableName())) {<a name="line.161"></a>
-<span class="sourceLineNo">162</span>          TableName targetTable =<a name="line.162"></a>
-<span class="sourceLineNo">163</span>              tables.isEmpty() ? key.getTableName() : tables.get(key.getTableName());<a name="line.163"></a>
-<span class="sourceLineNo">164</span>          ImmutableBytesWritable tableOut = new ImmutableBytesWritable(targetTable.getName());<a name="line.164"></a>
-<span class="sourceLineNo">165</span>          Put put = null;<a name="line.165"></a>
-<span class="sourceLineNo">166</span>          Delete del = null;<a name="line.166"></a>
-<span class="sourceLineNo">167</span>          Cell lastCell = null;<a name="line.167"></a>
-<span class="sourceLineNo">168</span>          for (Cell cell : value.getCells()) {<a name="line.168"></a>
-<span class="sourceLineNo">169</span>            context.getCounter(Counter.CELLS_READ).increment(1);<a name="line.169"></a>
-<span class="sourceLineNo">170</span>            // Filtering WAL meta marker entries.<a name="line.170"></a>
-<span class="sourceLineNo">171</span>            if (WALEdit.isMetaEditFamily(cell)) {<a name="line.171"></a>
-<span class="sourceLineNo">172</span>              continue;<a name="line.172"></a>
-<span class="sourceLineNo">173</span>            }<a name="line.173"></a>
-<span class="sourceLineNo">174</span>            // Allow a subclass filter out this cell.<a name="line.174"></a>
-<span class="sourceLineNo">175</span>            if (filter(context, cell)) {<a name="line.175"></a>
-<span class="sourceLineNo">176</span>              // A WALEdit may contain multiple operations (HBASE-3584) and/or<a name="line.176"></a>
-<span class="sourceLineNo">177</span>              // multiple rows (HBASE-5229).<a name="line.177"></a>
-<span class="sourceLineNo">178</span>              // Aggregate as much as possible into a single Put/Delete<a name="line.178"></a>
-<span class="sourceLineNo">179</span>              // operation before writing to the context.<a name="line.179"></a>
-<span class="sourceLineNo">180</span>              if (lastCell == null || lastCell.getTypeByte() != cell.getTypeByte()<a name="line.180"></a>
-<span class="sourceLineNo">181</span>                  || !CellUtil.matchingRows(lastCell, cell)) {<a name="line.181"></a>
-<span class="sourceLineNo">182</span>                // row or type changed, write out aggregate KVs.<a name="line.182"></a>
-<span class="sourceLineNo">183</span>                if (put != null) {<a name="line.183"></a>
-<span class="sourceLineNo">184</span>                  context.write(tableOut, put);<a name="line.184"></a>
-<span class="sourceLineNo">185</span>                  context.getCounter(Counter.PUTS).increment(1);<a name="line.185"></a>
-<span class="sourceLineNo">186</span>                }<a name="line.186"></a>
-<span class="sourceLineNo">187</span>                if (del != null) {<a name="line.187"></a>
-<span class="sourceLineNo">188</span>                  context.write(tableOut, del);<a name="line.188"></a>
-<span class="sourceLineNo">189</span>                  context.getCounter(Counter.DELETES).increment(1);<a name="line.189"></a>
-<span class="sourceLineNo">190</span>                }<a name="line.190"></a>
-<span class="sourceLineNo">191</span>                if (CellUtil.isDelete(cell)) {<a name="line.191"></a>
-<span class="sourceLineNo">192</span>                  del = new Delete(CellUtil.cloneRow(cell));<a name="line.192"></a>
-<span class="sourceLineNo">193</span>                } else {<a name="line.193"></a>
-<span class="sourceLineNo">194</span>                  put = new Put(CellUtil.cloneRow(cell));<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>              if (CellUtil.isDelete(cell)) {<a name="line.197"></a>
-<span class="sourceLineNo">198</span>                del.add(cell);<a name="line.198"></a>
-<span class="sourceLineNo">199</span>              } else {<a name="line.199"></a>
-<span class="sourceLineNo">200</span>                put.add(cell);<a name="line.200"></a>
-<span class="sourceLineNo">201</span>              }<a name="line.201"></a>
-<span class="sourceLineNo">202</span>              context.getCounter(Counter.CELLS_WRITTEN).increment(1);<a name="line.202"></a>
-<span class="sourceLineNo">203</span>            }<a name="line.203"></a>
-<span class="sourceLineNo">204</span>            lastCell = cell;<a name="line.204"></a>
-<span class="sourceLineNo">205</span>          }<a name="line.205"></a>
-<span class="sourceLineNo">206</span>          // write residual KVs<a name="line.206"></a>
-<span class="sourceLineNo">207</span>          if (put != null) {<a name="line.207"></a>
-<span class="sourceLineNo">208</span>            context.write(tableOut, put);<a name="line.208"></a>
-<span class="sourceLineNo">209</span>            context.getCounter(Counter.PUTS).increment(1);<a name="line.209"></a>
-<span class="sourceLineNo">210</span>          }<a name="line.210"></a>
-<span class="sourceLineNo">211</span>          if (del != null) {<a name="line.211"></a>
-<span class="sourceLineNo">212</span>            context.getCounter(Counter.DELETES).increment(1);<a name="line.212"></a>
-<span class="sourceLineNo">213</span>            context.write(tableOut, del);<a name="line.213"></a>
-<span class="sourceLineNo">214</span>          }<a name="line.214"></a>
-<span class="sourceLineNo">215</span>        }<a name="line.215"></a>
-<span class="sourceLineNo">216</span>      } catch (InterruptedException e) {<a name="line.216"></a>
-<span class="sourceLineNo">217</span>        LOG.error("Interrupted while writing results", e);<a name="line.217"></a>
-<span class="sourceLineNo">218</span>        Thread.currentThread().interrupt();<a name="line.218"></a>
-<span class="sourceLineNo">219</span>      }<a name="line.219"></a>
-<span class="sourceLineNo">220</span>    }<a name="line.220"></a>
-<span class="sourceLineNo">221</span><a name="line.221"></a>
-<span class="sourceLineNo">222</span>    protected boolean filter(Context context, final Cell cell) {<a name="line.222"></a>
-<span class="sourceLineNo">223</span>      return true;<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>    @Override<a name="line.226"></a>
-<span class="sourceLineNo">227</span>    protected void<a name="line.227"></a>
-<span class="sourceLineNo">228</span>        cleanup(Mapper&lt;WALKey, WALEdit, ImmutableBytesWritable, Mutation&gt;.Context context)<a name="line.228"></a>
-<span class="sourceLineNo">229</span>            throws IOException, InterruptedException {<a name="line.229"></a>
-<span class="sourceLineNo">230</span>      super.cleanup(context);<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>    @SuppressWarnings("checkstyle:EmptyBlock")<a name="line.233"></a>
-<span class="sourceLineNo">234</span>    @Override<a name="line.234"></a>
-<span class="sourceLineNo">235</span>    public void setup(Context context) throws IOException {<a name="line.235"></a>
-<span class="sourceLineNo">236</span>      String[] tableMap = context.getConfiguration().getStrings(TABLE_MAP_KEY);<a name="line.236"></a>
-<span class="sourceLineNo">237</span>      String[] tablesToUse = context.getConfiguration().getStrings(TABLES_KEY);<a name="line.237"></a>
-<span class="sourceLineNo">238</span>      if (tableMap == null) {<a name="line.238"></a>
-<span class="sourceLineNo">239</span>        tableMap = tablesToUse;<a name="line.239"></a>
-<span class="sourceLineNo">240</span>      }<a name="line.240"></a>
-<span class="sourceLineNo">241</span>      if (tablesToUse == null) {<a name="line.241"></a>
-<span class="sourceLineNo">242</span>        // Then user wants all tables.<a name="line.242"></a>
-<span class="sourceLineNo">243</span>      } else if (tablesToUse.length != tableMap.length) {<a name="line.243"></a>
-<span class="sourceLineNo">244</span>        // this can only happen when WALMapper is used directly by a class other than WALPlayer<a name="line.244"></a>
-<span class="sourceLineNo">245</span>        throw new IOException("Incorrect table mapping specified .");<a name="line.245"></a>
-<span class="sourceLineNo">246</span>      }<a name="line.246"></a>
-<span class="sourceLineNo">247</span>      int i = 0;<a name="line.247"></a>
-<span class="sourceLineNo">248</span>      if (tablesToUse != null) {<a name="line.248"></a>
-<span class="sourceLineNo">249</span>        for (String table : tablesToUse) {<a name="line.249"></a>
-<span class="sourceLineNo">250</span>          tables.put(TableName.valueOf(table), TableName.valueOf(tableMap[i++]));<a name="line.250"></a>
-<span class="sourceLineNo">251</span>        }<a name="line.251"></a>
-<span class="sourceLineNo">252</span>      }<a name="line.252"></a>
-<span class="sourceLineNo">253</span>    }<a name="line.253"></a>
-<span class="sourceLineNo">254</span>  }<a name="line.254"></a>
-<span class="sourceLineNo">255</span><a name="line.255"></a>
-<span class="sourceLineNo">256</span>  void setupTime(Configuration conf, String option) throws IOException {<a name="line.256"></a>
-<span class="sourceLineNo">257</span>    String val = conf.get(option);<a name="line.257"></a>
-<span class="sourceLineNo">258</span>    if (null == val) {<a name="line.258"></a>
-<span class="sourceLineNo">259</span>      return;<a name="line.259"></a>
-<span class="sourceLineNo">260</span>    }<a name="line.260"></a>
-<span class="sourceLineNo">261</span>    long ms;<a name="line.261"></a>
-<span class="sourceLineNo">262</span>    try {<a name="line.262"></a>
-<span class="sourceLineNo">263</span>      // first try to parse in user friendly form<a name="line.263"></a>
-<span class="sourceLineNo">264</span>      ms = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SS").parse(val).getTime();<a name="line.264"></a>
-<span class="sourceLineNo">265</span>    } catch (ParseException pe) {<a name="line.265"></a>
-<span class="sourceLineNo">266</span>      try {<a name="line.266"></a>
-<span class="sourceLineNo">267</span>        // then see if just a number of ms's was specified<a name="line.267"></a>
-<span class="sourceLineNo">268</span>        ms = Long.parseLong(val);<a name="line.268"></a>
-<span class="sourceLineNo">269</span>      } catch (NumberFormatException nfe) {<a name="line.269"></a>
-<span class="sourceLineNo">270</span>        throw new IOException(<a name="line.270"></a>
-<span class="sourceLineNo">271</span>            option + " must be specified either in the form 2001-02-20T16:35:06.99 "<a name="line.271"></a>
-<span class="sourceLineNo">272</span>                + "or as number of milliseconds");<a name="line.272"></a>
-<span class="sourceLineNo">273</span>      }<a name="line.273"></a>
-<span class="sourceLineNo">274</span>    }<a name="line.274"></a>
-<span class="sourceLineNo">275</span>    conf.setLong(option, ms);<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>  /**<a name="line.278"></a>
-<span class="sourceLineNo">279</span>   * Sets up the actual job.<a name="line.279"></a>
-<span class="sourceLineNo">280</span>   * @param args The command line parameters.<a name="line.280"></a>
-<span class="sourceLineNo">281</span>   * @return The newly created job.<a name="line.281"></a>
-<span class="sourceLineNo">282</span>   * @throws IOException When setting up the job fails.<a name="line.282"></a>
-<span class="sourceLineNo">283</span>   */<a name="line.283"></a>
-<span class="sourceLineNo">284</span>  public Job createSubmittableJob(String[] args) throws IOException {<a name="line.284"></a>
-<span class="sourceLineNo">285</span>    Configuration conf = getConf();<a name="line.285"></a>
-<span class="sourceLineNo">286</span>    setupTime(conf, WALInputFormat.START_TIME_KEY);<a name="line.286"></a>
-<span class="sourceLineNo">287</span>    setupTime(conf, WALInputFormat.END_TIME_KEY);<a name="line.287"></a>
-<span class="sourceLineNo">288</span>    String inputDirs = args[0];<a name="line.288"></a>
-<span class="sourceLineNo">289</span>    String[] tables = args.length == 1? new String [] {}: args[1].split(",");<a name="line.289"></a>
-<span class="sourceLineNo">290</span>    String[] tableMap;<a name="line.290"></a>
-<span class="sourceLineNo">291</span>    if (args.length &gt; 2) {<a name="line.291"></a>
-<span class="sourceLineNo">292</span>      tableMap = args[2].split(",");<a name="line.292"></a>
-<span class="sourceLineNo">293</span>      if (tableMap.length != tables.length) {<a name="line.293"></a>
-<span class="sourceLineNo">294</span>        throw new IOException("The same number of tables and mapping must be provided.");<a name="line.294"></a>
-<span class="sourceLineNo">295</span>      }<a name="line.295"></a>
-<span class="sourceLineNo">296</span>    } else {<a name="line.296"></a>
-<span class="sourceLineNo">297</span>      // if no mapping is specified, map each table to itself<a name="line.297"></a>
-<span class="sourceLineNo">298</span>      tableMap = tables;<a name="line.298"></a>
-<span class="sourceLineNo">299</span>    }<a name="line.299"></a>
-<span class="sourceLineNo">300</span>    conf.setStrings(TABLES_KEY, tables);<a name="line.300"></a>
-<span class="sourceLineNo">301</span>    conf.setStrings(TABLE_MAP_KEY, tableMap);<a name="line.301"></a>
-<span class="sourceLineNo">302</span>    conf.set(FileInputFormat.INPUT_DIR, inputDirs);<a name="line.302"></a>
-<span class="sourceLineNo">303</span>    Job job =<a name="line.303"></a>
-<span class="sourceLineNo">304</span>        Job.getInstance(conf, conf.get(JOB_NAME_CONF_KEY, NAME + "_" + System.currentTimeMillis()));<a name="line.304"></a>
-<span class="sourceLineNo">305</span>    job.setJarByClass(WALPlayer.class);<a name="line.305"></a>
-<span class="sourceLineNo">306</span><a name="line.306"></a>
-<span class="sourceLineNo">307</span>    job.setInputFormatClass(WALInputFormat.class);<a name="line.307"></a>
-<span class="sourceLineNo">308</span>    job.setMapOutputKeyClass(ImmutableBytesWritable.class);<a name="line.308"></a>
-<span class="sourceLineNo">309</span><a name="line.309"></a>
-<span class="sourceLineNo">310</span>    String hfileOutPath = conf.get(BULK_OUTPUT_CONF_KEY);<a name="line.310"></a>
-<span class="sourceLineNo">311</span>    if (hfileOutPath != null) {<a name="line.311"></a>
-<span class="sourceLineNo">312</span>      LOG.debug("add incremental job :" + hfileOutPath + " from " + inputDirs);<a name="line.312"></a>
-<span class="sourceLineNo">313</span><a name="line.313"></a>
-<span class="sourceLineNo">314</span>      // the bulk HFile case<a name="line.314"></a>
-<span class="sourceLineNo">315</span>      List&lt;TableName&gt; tableNames = getTableNameList(tables);<a name="line.315"></a>
-<span class="sourceLineNo">316</span><a name="line.316"></a>
-<span class="sourceLineNo">317</span>      job.setMapperClass(WALKeyValueMapper.class);<a name="line.317"></a>
-<span class="sourceLineNo">318</span>      job.setReducerClass(CellSortReducer.class);<a name="line.318"></a>
-<span class="sourceLineNo">319</span>      Path outputDir = new Path(hfileOutPath);<a name="line.319"></a>
-<span class="sourceLineNo">320</span>      FileOutputFormat.setOutputPath(job, outputDir);<a name="line.320"></a>
-<span class="sourceLineNo">321</span>      job.setMapOutputValueClass(MapReduceExtendedCell.class);<a name="line.321"></a>
-<span class="sourceLineNo">322</span>      try (Connection conn = ConnectionFactory.createConnection(conf);) {<a name="line.322"></a>
-<span class="sourceLineNo">323</span>        List&lt;TableInfo&gt; tableInfoList = new ArrayList&lt;TableInfo&gt;();<a name="line.323"></a>
-<span class="sourceLineNo">324</span>        for (TableName tableName : tableNames) {<a name="line.324"></a>
-<span class="sourceLineNo">325</span>          Table table = conn.getTable(tableName);<a name="line.325"></a>
-<span class="sourceLineNo">326</span>          RegionLocator regionLocator = conn.getRegionLocator(tableName);<a name="line.326"></a>
-<span class="sourceLineNo">327</span>          tableInfoList.add(new TableInfo(table.getDescriptor(), regionLocator));<a name="line.327"></a>
-<span class="sourceLineNo">328</span>        }<a name="line.328"></a>
-<span class="sourceLineNo">329</span>        MultiTableHFileOutputFormat.configureIncrementalLoad(job, tableInfoList);<a name="line.329"></a>
-<span class="sourceLineNo">330</span>      }<a name="line.330"></a>
-<span class="sourceLineNo">331</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.331"></a>
-<span class="sourceLineNo">332</span>        org.apache.hbase.thirdparty.com.google.common.base.Preconditions.class);<a name="line.332"></a>
-<span class="sourceLineNo">333</span>    } else {<a name="line.333"></a>
-<span class="sourceLineNo">334</span>      // output to live cluster<a name="line.334"></a>
-<span class="sourceLineNo">335</span>      job.setMapperClass(WALMapper.class);<a name="line.335"></a>
-<span class="sourceLineNo">336</span>      job.setOutputFormatClass(MultiTableOutputFormat.class);<a name="line.336"></a>
-<span class="sourceLineNo">337</span>      TableMapReduceUtil.addDependencyJars(job);<a name="line.337"></a>
-<span class="sourceLineNo">338</span>      TableMapReduceUtil.initCredentials(job);<a name="line.338"></a>
-<span class="sourceLineNo">339</span>      // No reducers.<a name="line.339"></a>
-<span class="sourceLineNo">340</span>      job.setNumReduceTasks(0);<a name="line.340"></a>
-<span class="sourceLineNo">341</span>    }<a name="line.341"></a>
-<span class="sourceLineNo">342</span>    String codecCls = WALCellCodec.getWALCellCodecClass(conf).getName();<a name="line.342"></a>
-<span class="sourceLineNo">343</span>    try {<a name="line.343"></a>
-<span class="sourceLineNo">344</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.344"></a>
-<span class="sourceLineNo">345</span>        Class.forName(codecCls));<a name="line.345"></a>
-<span class="sourceLineNo">346</span>    } catch (Exception e) {<a name="line.346"></a>
-<span class="sourceLineNo">347</span>      throw new IOException("Cannot determine wal codec class " + codecCls, e);<a name="line.347"></a>
-<span class="sourceLineNo">348</span>    }<a name="line.348"></a>
-<span class="sourceLineNo">349</span>    return job;<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>  private List&lt;TableName&gt; getTableNameList(String[] tables) {<a name="line.352"></a>
-<span class="sourceLineNo">353</span>    List&lt;TableName&gt; list = new ArrayList&lt;TableName&gt;();<a name="line.353"></a>
-<span class="sourceLineNo">354</span>    for (String name : tables) {<a name="line.354"></a>
-<span class="sourceLineNo">355</span>      list.add(TableName.valueOf(name));<a name="line.355"></a>
-<span class="sourceLineNo">356</span>    }<a name="line.356"></a>
-<span class="sourceLineNo">357</span>    return list;<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>  /**<a name="line.360"></a>
-<span class="sourceLineNo">361</span>   * Print usage<a name="line.361"></a>
-<span class="sourceLineNo">362</span>   * @param errorMsg Error message. Can be null.<a name="line.362"></a>
-<span class="sourceLineNo">363</span>   */<a name="line.363"></a>
-<span class="sourceLineNo">364</span>  private void usage(final String errorMsg) {<a name="line.364"></a>
-<span class="sourceLineNo">365</span>    if (errorMsg != null &amp;&amp; errorMsg.length() &gt; 0) {<a name="line.365"></a>
-<span class="sourceLineNo">366</span>      System.err.println("ERROR: " + errorMsg);<a name="line.366"></a>
-<span class="sourceLineNo">367</span>    }<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    System.err.println("Usage: " + NAME + " [options] &lt;WAL inputdir&gt; [&lt;tables&gt; &lt;tableMappings&gt;]");<a name="line.368"></a>
-<span class="sourceLineNo">369</span>    System.err.println(" &lt;WAL inputdir&gt;   directory of WALs to replay.");<a name="line.369"></a>
-<span class="sourceLineNo">370</span>    System.err.println(" &lt;tables&gt;         comma separated list of tables. If no tables specified,");<a name="line.370"></a>
-<span class="sourceLineNo">371</span>    System.err.println("                  all are imported (even hbase:meta if present).");<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    System.err.println(" &lt;tableMappings&gt;  WAL entries can be mapped to a new set of tables by " +<a name="line.372"></a>
-<span class="sourceLineNo">373</span>      "passing");<a name="line.373"></a>
-<span class="sourceLineNo">374</span>    System.err.println("                  &lt;tableMappings&gt;, a comma separated list of target " +<a name="line.374"></a>
-<span class="sourceLineNo">375</span>      "tables.");<a name="line.375"></a>
-<span class="sourceLineNo">376</span>    System.err.println("                  If specified, each table in &lt;tables&gt; must have a " +<a name="line.376"></a>
-<span class="sourceLineNo">377</span>      "mapping.");<a name="line.377"></a>
-<span class="sourceLineNo">378</span>    System.err.println("To generate HFiles to bulk load instead of loading HBase directly, pass:");<a name="line.378"></a>
-<span class="sourceLineNo">379</span>    System.err.println(" -D" + BULK_OUTPUT_CONF_KEY + "=/path/for/output");<a name="line.379"></a>
-<span class="sourceLineNo">380</span>    System.err.println(" Only one table can be specified, and no mapping allowed!");<a name="line.380"></a>
-<span class="sourceLineNo">381</span>    System.err.println("To specify a time range, pass:");<a name="line.381"></a>
-<span class="sourceLineNo">382</span>    System.err.println(" -D" + WALInputFormat.START_TIME_KEY + "=[date|ms]");<a name="line.382"></a>
-<span class="sourceLineNo">383</span>    System.err.println(" -D" + WALInputFormat.END_TIME_KEY + "=[date|ms]");<a name="line.383"></a>
-<span class="sourceLineNo">384</span>    System.err.println(" The start and the end date of timerange (inclusive). The dates can be");<a name="line.384"></a>
-<span class="sourceLineNo">385</span>    System.err.println(" expressed in milliseconds-since-epoch or yyyy-MM-dd'T'HH:mm:ss.SS " +<a name="line.385"></a>
-<span class="sourceLineNo">386</span>      "format.");<a name="line.386"></a>
-<span class="sourceLineNo">387</span>    System.err.println(" E.g. 1234567890120 or 2009-02-13T23:32:30.12");<a name="line.387"></a>
-<span class="sourceLineNo">388</span>    System.err.println("Other options:");<a name="line.388"></a>
-<span class="sourceLineNo">389</span>    System.err.println(" -D" + JOB_NAME_CONF_KEY + "=jobName");<a name="line.389"></a>
-<span class="sourceLineNo">390</span>    System.err.println(" Use the specified mapreduce job name for the wal player");<a name="line.390"></a>
-<span class="sourceLineNo">391</span>    System.err.println(" -Dwal.input.separator=' '");<a name="line.391"></a>
-<span class="sourceLineNo">392</span>    System.err.println(" Change WAL filename separator (WAL dir names use default ','.)");<a name="line.392"></a>
-<span class="sourceLineNo">393</span>    System.err.println("For performance also consider the following options:\n"<a name="line.393"></a>
-<span class="sourceLineNo">394</span>        + "  -Dmapreduce.map.speculative=false\n"<a name="line.394"></a>
-<span class="sourceLineNo">395</span>        + "  -Dmapreduce.reduce.speculative=false");<a name="line.395"></a>
-<span class="sourceLineNo">396</span>  }<a name="line.396"></a>
-<span class="sourceLineNo">397</span><a name="line.397"></a>
-<span class="sourceLineNo">398</span>  /**<a name="line.398"></a>
-<span class="sourceLineNo">399</span>   * Main entry point.<a name="line.399"></a>
-<span class="sourceLineNo">400</span>   * @param args The command line parameters.<a name="line.400"></a>
-<span class="sourceLineNo">401</span>   * @throws Exception When running the job fails.<a name="line.401"></a>
-<span class="sourceLineNo">402</span>   */<a name="line.402"></a>
-<span class="sourceLineNo">403</span>  public static void main(String[] args) throws Exception {<a name="line.403"></a>
-<span class="sourceLineNo">404</span>    int ret = ToolRunner.run(new WALPlayer(HBaseConfiguration.create()), args);<a name="line.404"></a>
-<span class="sourceLineNo">405</span>    System.exit(ret);<a name="line.405"></a>
-<span class="sourceLineNo">406</span>  }<a name="line.406"></a>
-<span class="sourceLineNo">407</span><a name="line.407"></a>
-<span class="sourceLineNo">408</span>  @Override<a name="line.408"></a>
-<span class="sourceLineNo">409</span>  public int run(String[] args) throws Exception {<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    if (args.length &lt; 1) {<a name="line.410"></a>
-<span class="sourceLineNo">411</span>      usage("Wrong number of arguments: " + args.length);<a name="line.411"></a>
-<span class="sourceLineNo">412</span>      System.exit(-1);<a name="line.412"></a>
-<span class="sourceLineNo">413</span>    }<a name="line.413"></a>
-<span class="sourceLineNo">414</span>    Job job = createSubmittableJob(args);<a name="line.414"></a>
-<span class="sourceLineNo">415</span>    return job.waitForCompletion(true) ? 0 : 1;<a name="line.415"></a>
-<span class="sourceLineNo">416</span>  }<a name="line.416"></a>
-<span class="sourceLineNo">417</span>}<a name="line.417"></a>
+<span class="sourceLineNo">062</span><a name="line.62"></a>
+<span class="sourceLineNo">063</span>/**<a name="line.63"></a>
+<span class="sourceLineNo">064</span> * A tool to replay WAL files as a M/R job.<a name="line.64"></a>
+<span class="sourceLineNo">065</span> * The WAL can be replayed for a set of tables or all tables,<a name="line.65"></a>
+<span class="sourceLineNo">066</span> * and a time range can be provided (in milliseconds).<a name="line.66"></a>
+<span class="sourceLineNo">067</span> * The WAL is filtered to the passed set of tables and  the output<a name="line.67"></a>
+<span class="sourceLineNo">068</span> * can optionally be mapped to another set of tables.<a name="line.68"></a>
+<span class="sourceLineNo">069</span> *<a name="line.69"></a>
+<span class="sourceLineNo">070</span> * WAL replay can also generate HFiles for later bulk importing,<a name="line.70"></a>
+<span class="sourceLineNo">071</span> * in that case the WAL is replayed for a single table only.<a name="line.71"></a>
+<span class="sourceLineNo">072</span> */<a name="line.72"></a>
+<span class="sourceLineNo">073</span>@InterfaceAudience.Public<a name="line.73"></a>
+<span class="sourceLineNo">074</span>public class WALPlayer extends Configured implements Tool {<a name="line.74"></a>
+<span class="sourceLineNo">075</span>  private static final Logger LOG = LoggerFactory.getLogger(WALPlayer.class);<a name="line.75"></a>
+<span class="sourceLineNo">076</span>  final static String NAME = "WALPlayer";<a name="line.76"></a>
+<span class="sourceLineNo">077</span>  public final static String BULK_OUTPUT_CONF_KEY = "wal.bulk.output";<a name="line.77"></a>
+<span class="sourceLineNo">078</span>  public final static String TABLES_KEY = "wal.input.tables";<a name="line.78"></a>
+<span class="sourceLineNo">079</span>  public final static String TABLE_MAP_KEY = "wal.input.tablesmap";<a name="line.79"></a>
+<span class="sourceLineNo">080</span>  public final static String INPUT_FILES_SEPARATOR_KEY = "wal.input.separator";<a name="line.80"></a>
+<span class="sourceLineNo">081</span>  public final static String IGNORE_MISSING_FILES = "wal.input.ignore.missing.files";<a name="line.81"></a>
+<span class="sourceLineNo">082</span>  public final static String MULTI_TABLES_SUPPORT = "wal.multi.tables.support";<a name="line.82"></a>
+<span class="sourceLineNo">083</span><a name="line.83"></a>
+<span class="sourceLineNo">084</span>  protected static final String tableSeparator = ";";<a name="line.84"></a>
+<span class="sourceLineNo">085</span><a name="line.85"></a>
+<span class="sourceLineNo">086</span>  private final static String JOB_NAME_CONF_KEY = "mapreduce.job.name";<a name="line.86"></a>
+<span class="sourceLineNo">087</span><a name="line.87"></a>
+<span class="sourceLineNo">088</span>  public WALPlayer() {<a name="line.88"></a>
+<span class="sourceLineNo">089</span>  }<a name="line.89"></a>
+<span class="sourceLineNo">090</span><a name="line.90"></a>
+<span class="sourceLineNo">091</span>  protected WALPlayer(final Configuration c) {<a name="line.91"></a>
+<span class="sourceLineNo">092</span>    super(c);<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>  /**<a name="line.95"></a>
+<span class="sourceLineNo">096</span>   * A mapper that just writes out KeyValues. This one can be used together with<a name="line.96"></a>
+<span class="sourceLineNo">097</span>   * {@link CellSortReducer}<a name="line.97"></a>
+<span class="sourceLineNo">098</span>   */<a name="line.98"></a>
+<span class="sourceLineNo">099</span>  static class WALKeyValueMapper extends Mapper&lt;WALKey, WALEdit, ImmutableBytesWritable, Cell&gt; {<a name="line.99"></a>
+<span class="sourceLineNo">100</span>    private Set&lt;String&gt; tableSet = new HashSet&lt;String&gt;();<a name="line.100"></a>
+<span class="sourceLineNo">101</span>    private boolean multiTableSupport = false;<a name="line.101"></a>
+<span class="sourceLineNo">102</span><a name="line.102"></a>
+<span class="sourceLineNo">103</span>    @Override<a name="line.103"></a>
+<span class="sourceLineNo">104</span>    public void map(WALKey key, WALEdit value, Context context) throws IOException {<a name="line.104"></a>
+<span class="sourceLineNo">105</span>      try {<a name="line.105"></a>
+<span class="sourceLineNo">106</span>        // skip all other tables<a name="line.106"></a>
+<span class="sourceLineNo">107</span>        TableName table = key.getTableName();<a name="line.107"></a>
+<span class="sourceLineNo">108</span>        if (tableSet.contains(table.getNameAsString())) {<a name="line.108"></a>
+<span class="sourceLineNo">109</span>          for (Cell cell : value.getCells()) {<a name="line.109"></a>
+<span class="sourceLineNo">110</span>            if (WALEdit.isMetaEditFamily(cell)) {<a name="line.110"></a>
+<span class="sourceLineNo">111</span>              continue;<a name="line.111"></a>
+<span class="sourceLineNo">112</span>            }<a name="line.112"></a>
+<span class="sourceLineNo">113</span>            byte[] outKey = multiTableSupport<a name="line.113"></a>
+<span class="sourceLineNo">114</span>                ? Bytes.add(table.getName(), Bytes.toBytes(tableSeparator), CellUtil.cloneRow(cell))<a name="line.114"></a>
+<span class="sourceLineNo">115</span>                : CellUtil.cloneRow(cell);<a name="line.115"></a>
+<span class="sourceLineNo">116</span>            context.write(new ImmutableBytesWritable(outKey), new MapReduceExtendedCell(cell));<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>      } catch (InterruptedException e) {<a name="line.119"></a>
+<span class="sourceLineNo">120</span>        LOG.error("Interrupted while emitting Cell", e);<a name="line.120"></a>
+<span class="sourceLineNo">121</span>        Thread.currentThread().interrupt();<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><a name="line.124"></a>
+<span class="sourceLineNo">125</span>    @Override<a name="line.125"></a>
+<span class="sourceLineNo">126</span>    public void setup(Context context) throws IOException {<a name="line.126"></a>
+<span class="sourceLineNo">127</span>      Configuration conf = context.getConfiguration();<a name="line.127"></a>
+<span class="sourceLineNo">128</span>      String[] tables = conf.getStrings(TABLES_KEY);<a name="line.128"></a>
+<span class="sourceLineNo">129</span>      this.multiTableSupport = conf.getBoolean(MULTI_TABLES_SUPPORT, false);<a name="line.129"></a>
+<span class="sourceLineNo">130</span>      for (String table : tables) {<a name="line.130"></a>
+<span class="sourceLineNo">131</span>        tableSet.add(table);<a name="line.131"></a>
+<span class="sourceLineNo">132</span>      }<a name="line.132"></a>
+<span class="sourceLineNo">133</span>    }<a name="line.133"></a>
+<span class="sourceLineNo">134</span>  }<a name="line.134"></a>
+<span class="sourceLineNo">135</span><a name="line.135"></a>
+<span class="sourceLineNo">136</span>  /**<a name="line.136"></a>
+<span class="sourceLineNo">137</span>   * Enum for map metrics.  Keep it out here rather than inside in the Map<a name="line.137"></a>
+<span class="sourceLineNo">138</span>   * inner-class so we can find associated properties.<a name="line.138"></a>
+<span class="sourceLineNo">139</span>   */<a name="line.139"></a>
+<span class="sourceLineNo">140</span>  protected static enum Counter {<a name="line.140"></a>
+<span class="sourceLineNo">141</span>    /** Number of aggregated writes */<a name="line.141"></a>
+<span class="sourceLineNo">142</span>    PUTS,<a name="line.142"></a>
+<span class="sourceLineNo">143</span>    /** Number of aggregated deletes */<a name="line.143"></a>
+<span class="sourceLineNo">144</span>    DELETES,<a name="line.144"></a>
+<span class="sourceLineNo">145</span>    CELLS_READ,<a name="line.145"></a>
+<span class="sourceLineNo">146</span>    CELLS_WRITTEN,<a name="line.146"></a>
+<span class="sourceLineNo">147</span>    WALEDITS<a name="line.147"></a>
+<span class="sourceLineNo">148</span>  }<a name="line.148"></a>
+<span class="sourceLineNo">149</span><a name="line.149"></a>
+<span class="sourceLineNo">150</span>  /**<a name="line.150"></a>
+<span class="sourceLineNo">151</span>   * A mapper that writes out {@link Mutation} to be directly applied to<a name="line.151"></a>
+<span class="sourceLineNo">152</span>   * a running HBase instance.<a name="line.152"></a>
+<span class="sourceLineNo">153</span>   */<a name="line.153"></a>
+<span class="sourceLineNo">154</span>  protected static class WALMapper<a name="line.154"></a>
+<span class="sourceLineNo">155</span>      extends Mapper&lt;WALKey, WALEdit, ImmutableBytesWritable, Mutation&gt; {<a name="line.155"></a>
+<span class="sourceLineNo">156</span>    private Map&lt;TableName, TableName&gt; tables = new TreeMap&lt;&gt;();<a name="line.156"></a>
+<span class="sourceLineNo">157</span><a name="line.157"></a>
+<span class="sourceLineNo">158</span>    @Override<a name="line.158"></a>
+<span class="sourceLineNo">159</span>    public void map(WALKey key, WALEdit value, Context context) throws IOException {<a name="line.159"></a>
+<span class="sourceLineNo">160</span>      context.getCounter(Counter.WALEDITS).increment(1);<a name="line.160"></a>
+<span class="sourceLineNo">161</span>      try {<a name="line.161"></a>
+<span class="sourceLineNo">162</span>        if (tables.isEmpty() || tables.containsKey(key.getTableName())) {<a name="line.162"></a>
+<span class="sourceLineNo">163</span>          TableName targetTable =<a name="line.163"></a>
+<span class="sourceLineNo">164</span>              tables.isEmpty() ? key.getTableName() : tables.get(key.getTableName());<a name="line.164"></a>
+<span class="sourceLineNo">165</span>          ImmutableBytesWritable tableOut = new ImmutableBytesWritable(targetTable.getName());<a name="line.165"></a>
+<span class="sourceLineNo">166</span>          Put put = null;<a name="line.166"></a>
+<span class="sourceLineNo">167</span>          Delete del = null;<a name="line.167"></a>
+<span class="sourceLineNo">168</span>          Cell lastCell = null;<a name="line.168"></a>
+<span class="sourceLineNo">169</span>          for (Cell cell : value.getCells()) {<a name="line.169"></a>
+<span class="sourceLineNo">170</span>            context.getCounter(Counter.CELLS_READ).increment(1);<a name="line.170"></a>
+<span class="sourceLineNo">171</span>            // Filtering WAL meta marker entries.<a name="line.171"></a>
+<span class="sourceLineNo">172</span>            if (WALEdit.isMetaEditFamily(cell)) {<a name="line.172"></a>
+<span class="sourceLineNo">173</span>              continue;<a name="line.173"></a>
+<span class="sourceLineNo">174</span>            }<a name="line.174"></a>
+<span class="sourceLineNo">175</span>            // Allow a subclass filter out this cell.<a name="line.175"></a>
+<span class="sourceLineNo">176</span>            if (filter(context, cell)) {<a name="line.176"></a>
+<span class="sourceLineNo">177</span>              // A WALEdit may contain multiple operations (HBASE-3584) and/or<a name="line.177"></a>
+<span class="sourceLineNo">178</span>              // multiple rows (HBASE-5229).<a name="line.178"></a>
+<span class="sourceLineNo">179</span>              // Aggregate as much as possible into a single Put/Delete<a name="line.179"></a>
+<span class="sourceLineNo">180</span>              // operation before writing to the context.<a name="line.180"></a>
+<span class="sourceLineNo">181</span>              if (lastCell == null || lastCell.getTypeByte() != cell.getTypeByte()<a name="line.181"></a>
+<span class="sourceLineNo">182</span>                  || !CellUtil.matchingRows(lastCell, cell)) {<a name="line.182"></a>
+<span class="sourceLineNo">183</span>                // row or type changed, write out aggregate KVs.<a name="line.183"></a>
+<span class="sourceLineNo">184</span>                if (put != null) {<a name="line.184"></a>
+<span class="sourceLineNo">185</span>                  context.write(tableOut, put);<a name="line.185"></a>
+<span class="sourceLineNo">186</span>                  context.getCounter(Counter.PUTS).increment(1);<a name="line.186"></a>
+<span class="sourceLineNo">187</span>                }<a name="line.187"></a>
+<span class="sourceLineNo">188</span>                if (del != null) {<a name="line.188"></a>
+<span class="sourceLineNo">189</span>                  context.write(tableOut, del);<a name="line.189"></a>
+<span class="sourceLineNo">190</span>                  context.getCounter(Counter.DELETES).increment(1);<a name="line.190"></a>
+<span class="sourceLineNo">191</span>                }<a name="line.191"></a>
+<span class="sourceLineNo">192</span>                if (CellUtil.isDelete(cell)) {<a name="line.192"></a>
+<span class="sourceLineNo">193</span>                  del = new Delete(CellUtil.cloneRow(cell));<a name="line.193"></a>
+<span class="sourceLineNo">194</span>                } else {<a name="line.194"></a>
+<span class="sourceLineNo">195</span>                  put = new Put(CellUtil.cloneRow(cell));<a name="line.195"></a>
+<span class="sourceLineNo">196</span>                }<a name="line.196"></a>
+<span class="sourceLineNo">197</span>              }<a name="line.197"></a>
+<span class="sourceLineNo">198</span>              if (CellUtil.isDelete(cell)) {<a name="line.198"></a>
+<span class="sourceLineNo">199</span>                del.add(cell);<a name="line.199"></a>
+<span class="sourceLineNo">200</span>              } else {<a name="line.200"></a>
+<span class="sourceLineNo">201</span>                put.add(cell);<a name="line.201"></a>
+<span class="sourceLineNo">202</span>              }<a name="line.202"></a>
+<span class="sourceLineNo">203</span>              context.getCounter(Counter.CELLS_WRITTEN).increment(1);<a name="line.203"></a>
+<span class="sourceLineNo">204</span>            }<a name="line.204"></a>
+<span class="sourceLineNo">205</span>            lastCell = cell;<a name="line.205"></a>
+<span class="sourceLineNo">206</span>          }<a name="line.206"></a>
+<span class="sourceLineNo">207</span>          // write residual KVs<a name="line.207"></a>
+<span class="sourceLineNo">208</span>          if (put != null) {<a name="line.208"></a>
+<span class="sourceLineNo">209</span>            context.write(tableOut, put);<a name="line.209"></a>
+<span class="sourceLineNo">210</span>            context.getCounter(Counter.PUTS).increment(1);<a name="line.210"></a>
+<span class="sourceLineNo">211</span>          }<a name="line.211"></a>
+<span class="sourceLineNo">212</span>          if (del != null) {<a name="line.212"></a>
+<span class="sourceLineNo">213</span>            context.getCounter(Counter.DELETES).increment(1);<a name="line.213"></a>
+<span class="sourceLineNo">214</span>            context.write(tableOut, del);<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>      } catch (InterruptedException e) {<a name="line.217"></a>
+<span class="sourceLineNo">218</span>        LOG.error("Interrupted while writing results", e);<a name="line.218"></a>
+<span class="sourceLineNo">219</span>        Thread.currentThread().interrupt();<a name="line.219"></a>
+<span class="sourceLineNo">220</span>      }<a name="line.220"></a>
+<span class="sourceLineNo">221</span>    }<a name="line.221"></a>
+<span class="sourceLineNo">222</span><a name="line.222"></a>
+<span class="sourceLineNo">223</span>    protected boolean filter(Context context, final Cell cell) {<a name="line.223"></a>
+<span class="sourceLineNo">224</span>      return true;<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>    protected void<a name="line.228"></a>
+<span class="sourceLineNo">229</span>        cleanup(Mapper&lt;WALKey, WALEdit, ImmutableBytesWritable, Mutation&gt;.Context context)<a name="line.229"></a>
+<span class="sourceLineNo">230</span>            throws IOException, InterruptedException {<a name="line.230"></a>
+<span class="sourceLineNo">231</span>      super.cleanup(context);<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>    @SuppressWarnings("checkstyle:EmptyBlock")<a name="line.234"></a>
+<span class="sourceLineNo">235</span>    @Override<a name="line.235"></a>
+<span class="sourceLineNo">236</span>    public void setup(Context context) throws IOException {<a name="line.236"></a>
+<span class="sourceLineNo">237</span>      String[] tableMap = context.getConfiguration().getStrings(TABLE_MAP_KEY);<a name="line.237"></a>
+<span class="sourceLineNo">238</span>      String[] tablesToUse = context.getConfiguration().getStrings(TABLES_KEY);<a name="line.238"></a>
+<span class="sourceLineNo">239</span>      if (tableMap == null) {<a name="line.239"></a>
+<span class="sourceLineNo">240</span>        tableMap = tablesToUse;<a name="line.240"></a>
+<span class="sourceLineNo">241</span>      }<a name="line.241"></a>
+<span class="sourceLineNo">242</span>      if (tablesToUse == null) {<a name="line.242"></a>
+<span class="sourceLineNo">243</span>        // Then user wants all tables.<a name="line.243"></a>
+<span class="sourceLineNo">244</span>      } else if (tablesToUse.length != tableMap.length) {<a name="line.244"></a>
+<span class="sourceLineNo">245</span>        // this can only happen when WALMapper is used directly by a class other than WALPlayer<a name="line.245"></a>
+<span class="sourceLineNo">246</span>        throw new IOException("Incorrect table mapping specified .");<a name="line.246"></a>
+<span class="sourceLineNo">247</span>      }<a name="line.247"></a>
+<span class="sourceLineNo">248</span>      int i = 0;<a name="line.248"></a>
+<span class="sourceLineNo">249</span>      if (tablesToUse != null) {<a name="line.249"></a>
+<span class="sourceLineNo">250</span>        for (String table : tablesToUse) {<a name="line.250"></a>
+<span class="sourceLineNo">251</span>          tables.put(TableName.valueOf(table), TableName.valueOf(tableMap[i++]));<a name="line.251"></a>
+<span class="sourceLineNo">252</span>        }<a name="line.252"></a>
+<span class="sourceLineNo">253</span>      }<a name="line.253"></a>
+<span class="sourceLineNo">254</span>    }<a name="line.254"></a>
+<span class="sourceLineNo">255</span>  }<a name="line.255"></a>
+<span class="sourceLineNo">256</span><a name="line.256"></a>
+<span class="sourceLineNo">257</span>  void setupTime(Configuration conf, String option) throws IOException {<a name="line.257"></a>
+<span class="sourceLineNo">258</span>    String val = conf.get(option);<a name="line.258"></a>
+<span class="sourceLineNo">259</span>    if (null == val) {<a name="line.259"></a>
+<span class="sourceLineNo">260</span>      return;<a name="line.260"></a>
+<span class="sourceLineNo">261</span>    }<a name="line.261"></a>
+<span class="sourceLineNo">262</span>    long ms;<a name="line.262"></a>
+<span class="sourceLineNo">263</span>    try {<a name="line.263"></a>
+<span class="sourceLineNo">264</span>      // first try to parse in user friendly form<a name="line.264"></a>
+<span class="sourceLineNo">265</span>      ms = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SS").parse(val).getTime();<a name="line.265"></a>
+<span class="sourceLineNo">266</span>    } catch (ParseException pe) {<a name="line.266"></a>
+<span class="sourceLineNo">267</span>      try {<a name="line.267"></a>
+<span class="sourceLineNo">268</span>        // then see if just a number of ms's was specified<a name="line.268"></a>
+<span class="sourceLineNo">269</span>        ms = Long.parseLong(val);<a name="line.269"></a>
+<span class="sourceLineNo">270</span>      } catch (NumberFormatException nfe) {<a name="line.270"></a>
+<span class="sourceLineNo">271</span>        throw new IOException(<a name="line.271"></a>
+<span class="sourceLineNo">272</span>            option + " must be specified either in the form 2001-02-20T16:35:06.99 "<a name="line.272"></a>
+<span class="sourceLineNo">273</span>                + "or as number of milliseconds");<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>    conf.setLong(option, ms);<a name="line.276"></a>
+<span class="sourceLineNo">277</span>  }<a name="line.277"></a>
+<span class="sourceLineNo">278</span><a name="line.278"></a>
+<span class="sourceLineNo">279</span>  /**<a name="line.279"></a>
+<span class="sourceLineNo">280</span>   * Sets up the actual job.<a name="line.280"></a>
+<span class="sourceLineNo">281</span>   * @param args The command line parameters.<a name="line.281"></a>
+<span class="sourceLineNo">282</span>   * @return The newly created job.<a name="line.282"></a>
+<span class="sourceLineNo">283</span>   * @throws IOException When setting up the job fails.<a name="line.283"></a>
+<span class="sourceLineNo">284</span>   */<a name="line.284"></a>
+<span class="sourceLineNo">285</span>  public Job createSubmittableJob(String[] args) throws IOException {<a name="line.285"></a>
+<span class="sourceLineNo">286</span>    Configuration conf = getConf();<a name="line.286"></a>
+<span class="sourceLineNo">287</span>    setupTime(conf, WALInputFormat.START_TIME_KEY);<a name="line.287"></a>
+<span class="sourceLineNo">288</span>    setupTime(conf, WALInputFormat.END_TIME_KEY);<a name="line.288"></a>
+<span class="sourceLineNo">289</span>    String inputDirs = args[0];<a name="line.289"></a>
+<span class="sourceLineNo">290</span>    String[] tables = args.length == 1? new String [] {}: args[1].split(",");<a name="line.290"></a>
+<span class="sourceLineNo">291</span>    String[] tableMap;<a name="line.291"></a>
+<span class="sourceLineNo">292</span>    if (args.length &gt; 2) {<a name="line.292"></a>
+<span class="sourceLineNo">293</span>      tableMap = args[2].split(",");<a name="line.293"></a>
+<span class="sourceLineNo">294</span>      if (tableMap.length != tables.length) {<a name="line.294"></a>
+<span class="sourceLineNo">295</span>        throw new IOException("The same number of tables and mapping must be provided.");<a name="line.295"></a>
+<span class="sourceLineNo">296</span>      }<a name="line.296"></a>
+<span class="sourceLineNo">297</span>    } else {<a name="line.297"></a>
+<span class="sourceLineNo">298</span>      // if no mapping is specified, map each table to itself<a name="line.298"></a>
+<span class="sourceLineNo">299</span>      tableMap = tables;<a name="line.299"></a>
+<span class="sourceLineNo">300</span>    }<a name="line.300"></a>
+<span class="sourceLineNo">301</span>    conf.setStrings(TABLES_KEY, tables);<a name="line.301"></a>
+<span class="sourceLineNo">302</span>    conf.setStrings(TABLE_MAP_KEY, tableMap);<a name="line.302"></a>
+<span class="sourceLineNo">303</span>    conf.set(FileInputFormat.INPUT_DIR, inputDirs);<a name="line.303"></a>
+<span class="sourceLineNo">304</span>    Job job = Job.getInstance(conf, conf.get(JOB_NAME_CONF_KEY, NAME + "_" +<a name="line.304"></a>
+<span class="sourceLineNo">305</span>      EnvironmentEdgeManager.currentTime()));<a name="line.305"></a>
+<span class="sourceLineNo">306</span>    job.setJarByClass(WALPlayer.class);<a name="line.306"></a>
+<span class="sourceLineNo">307</span><a name="line.307"></a>
+<span class="sourceLineNo">308</span>    job.setInputFormatClass(WALInputFormat.class);<a name="line.308"></a>
+<span class="sourceLineNo">309</span>    job.setMapOutputKeyClass(ImmutableBytesWritable.class);<a name="line.309"></a>
+<span class="sourceLineNo">310</span><a name="line.310"></a>
+<span class="sourceLineNo">311</span>    String hfileOutPath = conf.get(BULK_OUTPUT_CONF_KEY);<a name="line.311"></a>
+<span class="sourceLineNo">312</span>    if (hfileOutPath != null) {<a name="line.312"></a>
+<span class="sourceLineNo">313</span>      LOG.debug("add incremental job :" + hfileOutPath + " from " + inputDirs);<a name="line.313"></a>
+<span class="sourceLineNo">314</span><a name="line.314"></a>
+<span class="sourceLineNo">315</span>      // the bulk HFile case<a name="line.315"></a>
+<span class="sourceLineNo">316</span>      List&lt;TableName&gt; tableNames = getTableNameList(tables);<a name="line.316"></a>
+<span class="sourceLineNo">317</span><a name="line.317"></a>
+<span class="sourceLineNo">318</span>      job.setMapperClass(WALKeyValueMapper.class);<a name="line.318"></a>
+<span class="sourceLineNo">319</span>      job.setReducerClass(CellSortReducer.class);<a name="line.319"></a>
+<span class="sourceLineNo">320</span>      Path outputDir = new Path(hfileOutPath);<a name="line.320"></a>
+<span class="sourceLineNo">321</span>      FileOutputFormat.setOutputPath(job, outputDir);<a name="line.321"></a>
+<span class="sourceLineNo">322</span>      job.setMapOutputValueClass(MapReduceExtendedCell.class);<a name="line.322"></a>
+<span class="sourceLineNo">323</span>      try (Connection conn = ConnectionFactory.createConnection(conf);) {<a name="line.323"></a>
+<span class="sourceLineNo">324</span>        List&lt;TableInfo&gt; tableInfoList = new ArrayList&lt;TableInfo&gt;();<a name="line.324"></a>
+<span class="sourceLineNo">325</span>        for (TableName tableName : tableNames) {<a name="line.325"></a>
+<span class="sourceLineNo">326</span>          Table table = conn.getTable(tableName);<a name="line.326"></a>
+<span class="sourceLineNo">327</span>          RegionLocator regionLocator = conn.getRegionLocator(tableName);<a name="line.327"></a>
+<span class="sourceLineNo">328</span>          tableInfoList.add(new TableInfo(table.getDescriptor(), regionLocator));<a name="line.328"></a>
+<span class="sourceLineNo">329</span>        }<a name="line.329"></a>
+<span class="sourceLineNo">330</span>        MultiTableHFileOutputFormat.configureIncrementalLoad(job, tableInfoList);<a name="line.330"></a>
+<span class="sourceLineNo">331</span>      }<a name="line.331"></a>
+<span class="sourceLineNo">332</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.332"></a>
+<span class="sourceLineNo">333</span>        org.apache.hbase.thirdparty.com.google.common.base.Preconditions.class);<a name="line.333"></a>
+<span class="sourceLineNo">334</span>    } else {<a name="line.334"></a>
+<span class="sourceLineNo">335</span>      // output to live cluster<a name="line.335"></a>
+<span class="sourceLineNo">336</span>      job.setMapperClass(WALMapper.class);<a name="line.336"></a>
+<span class="sourceLineNo">337</span>      job.setOutputFormatClass(MultiTableOutputFormat.class);<a name="line.337"></a>
+<span class="sourceLineNo">338</span>      TableMapReduceUtil.addDependencyJars(job);<a name="line.338"></a>
+<span class="sourceLineNo">339</span>      TableMapReduceUtil.initCredentials(job);<a name="line.339"></a>
+<span class="sourceLineNo">340</span>      // No reducers.<a name="line.340"></a>
+<span class="sourceLineNo">341</span>      job.setNumReduceTasks(0);<a name="line.341"></a>
+<span class="sourceLineNo">342</span>    }<a name="line.342"></a>
+<span class="sourceLineNo">343</span>    String codecCls = WALCellCodec.getWALCellCodecClass(conf).getName();<a name="line.343"></a>
+<span class="sourceLineNo">344</span>    try {<a name="line.344"></a>
+<span class="sourceLineNo">345</span>      TableMapReduceUtil.addDependencyJarsForClasses(job.getConfiguration(),<a name="line.345"></a>
+<span class="sourceLineNo">346</span>        Class.forName(codecCls));<a name="line.346"></a>
+<span class="sourceLineNo">347</span>    } catch (Exception e) {<a name="line.347"></a>
+<span class="sourceLineNo">348</span>      throw new IOException("Cannot determine wal codec class " + codecCls, e);<a name="line.348"></a>
+<span class="sourceLineNo">349</span>    }<a name="line.349"></a>
+<span class="sourceLineNo">350</span>    return job;<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>  private List&lt;TableName&gt; getTableNameList(String[] tables) {<a name="line.353"></a>
+<span class="sourceLineNo">354</span>    List&lt;TableName&gt; list = new ArrayList&lt;TableName&gt;();<a name="line.354"></a>
+<span class="sourceLineNo">355</span>    for (String name : tables) {<a name="line.355"></a>
+<span class="sourceLineNo">356</span>      list.add(TableName.valueOf(name));<a name="line.356"></a>
+<span class="sourceLineNo">357</span>    }<a name="line.357"></a>
+<span class="sourceLineNo">358</span>    return list;<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>  /**<a name="line.361"></a>
+<span class="sourceLineNo">362</span>   * Print usage<a name="line.362"></a>
+<span class="sourceLineNo">363</span>   * @param errorMsg Error message. Can be null.<a name="line.363"></a>
+<span class="sourceLineNo">364</span>   */<a name="line.364"></a>
+<span class="sourceLineNo">365</span>  private void usage(final String errorMsg) {<a name="line.365"></a>
+<span class="sourceLineNo">366</span>    if (errorMsg != null &amp;&amp; errorMsg.length() &gt; 0) {<a name="line.366"></a>
+<span class="sourceLineNo">367</span>      System.err.println("ERROR: " + errorMsg);<a name="line.367"></a>
+<span class="sourceLineNo">368</span>    }<a name="line.368"></a>
+<span class="sourceLineNo">369</span>    System.err.println("Usage: " + NAME + " [options] &lt;WAL inputdir&gt; [&lt;tables&gt; &lt;tableMappings&gt;]");<a name="line.369"></a>
+<span class="sourceLineNo">370</span>    System.err.println(" &lt;WAL inputdir&gt;   directory of WALs to replay.");<a name="line.370"></a>
+<span class="sourceLineNo">371</span>    System.err.println(" &lt;tables&gt;         comma separated list of tables. If no tables specified,");<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    System.err.println("                  all are imported (even hbase:meta if present).");<a name="line.372"></a>
+<span class="sourceLineNo">373</span>    System.err.println(" &lt;tableMappings&gt;  WAL entries can be mapped to a new set of tables by " +<a name="line.373"></a>
+<span class="sourceLineNo">374</span>      "passing");<a name="line.374"></a>
+<span class="sourceLineNo">375</span>    System.err.println("                  &lt;tableMappings&gt;, a comma separated list of target " +<a name="line.375"></a>
+<span class="sourceLineNo">376</span>      "tables.");<a name="line.376"></a>
+<span class="sourceLineNo">377</span>    System.err.println("                  If specified, each table in &lt;tables&gt; must have a " +<a name="line.377"></a>
+<span class="sourceLineNo">378</span>      "mapping.");<a name="line.378"></a>
+<span class="sourceLineNo">379</span>    System.err.println("To generate HFiles to bulk load instead of loading HBase directly, pass:");<a name="line.379"></a>
+<span class="sourceLineNo">380</span>    System.err.println(" -D" + BULK_OUTPUT_CONF_KEY + "=/path/for/output");<a name="line.380"></a>
+<span class="sourceLineNo">381</span>    System.err.println(" Only one table can be specified, and no mapping allowed!");<a name="line.381"></a>
+<span class="sourceLineNo">382</span>    System.err.println("To specify a time range, pass:");<a name="line.382"></a>
+<span class="sourceLineNo">383</span>    System.err.println(" -D" + WALInputFormat.START_TIME_KEY + "=[date|ms]");<a name="line.383"></a>
+<span class="sourceLineNo">384</span>    System.err.println(" -D" + WALInputFormat.END_TIME_KEY + "=[date|ms]");<a name="line.384"></a>
+<span class="sourceLineNo">385</span>    System.err.println(" The start and the end date of timerange (inclusive). The dates can be");<a name="line.385"></a>
+<span class="sourceLineNo">386</span>    System.err.println(" expressed in milliseconds-since-epoch or yyyy-MM-dd'T'HH:mm:ss.SS " +<a name="line.386"></a>
+<span class="sourceLineNo">387</span>      "format.");<a name="line.387"></a>
+<span class="sourceLineNo">388</span>    System.err.println(" E.g. 1234567890120 or 2009-02-13T23:32:30.12");<a name="line.388"></a>
+<span class="sourceLineNo">389</span>    System.err.println("Other options:");<a name="line.389"></a>
+<span class="sourceLineNo">390</span>    System.err.println(" -D" + JOB_NAME_CONF_KEY + "=jobName");<a name="line.390"></a>
+<span class="sourceLineNo">391</span>    System.err.println(" Use the specified mapreduce job name for the wal player");<a name="line.391"></a>
+<span class="sourceLineNo">392</span>    System.err.println(" -Dwal.input.separator=' '");<a name="line.392"></a>
+<span class="sourceLineNo">393</span>    System.err.println(" Change WAL filename separator (WAL dir names use default ','.)");<a name="line.393"></a>
+<span class="sourceLineNo">394</span>    System.err.println("For performance also consider the following options:\n"<a name="line.394"></a>
+<span class="sourceLineNo">395</span>        + "  -Dmapreduce.map.speculative=false\n"<a name="line.395"></a>
+<span class="sourceLineNo">396</span>        + "  -Dmapreduce.reduce.speculative=false");<a name="line.396"></a>
+<span class="sourceLineNo">397</span>  }<a name="line.397"></a>
+<span class="sourceLineNo">398</span><a name="line.398"></a>
+<span class="sourceLineNo">399</span>  /**<a name="line.399"></a>
+<span class="sourceLineNo">400</span>   * Main entry point.<a name="line.400"></a>
+<span class="sourceLineNo">401</span>   * @param args The command line parameters.<a name="line.401"></a>
+<span class="sourceLineNo">402</span>   * @throws Exception When running the job fails.<a name="line.402"></a>
+<span class="sourceLineNo">403</span>   */<a name="line.403"></a>
+<span class="sourceLineNo">404</span>  public static void main(String[] args) throws Exception {<a name="line.404"></a>
+<span class="sourceLineNo">405</span>    int ret = ToolRunner.run(new WALPlayer(HBaseConfiguration.create()), args);<a name="line.405"></a>
+<span class="sourceLineNo">406</span>    System.exit(ret);<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>  @Override<a name="line.409"></a>
+<span class="sourceLineNo">410</span>  public int run(String[] args) throws Exception {<a name="line.410"></a>
+<span class="sourceLineNo">411</span>    if (args.length &lt; 1) {<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      usage("Wrong number of arguments: " + args.length);<a name="line.412"></a>
+<span class="sourceLineNo">413</span>      System.exit(-1);<a name="line.413"></a>
+<span class="sourceLineNo">414</span>    }<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    Job job = createSubmittableJob(args);<a name="line.415"></a>
+<span class="sourceLineNo">416</span>    return job.waitForCompletion(true) ? 0 : 1;<a name="line.416"></a>
+<span class="sourceLineNo">417</span>  }<a name="line.417"></a>
+<span class="sourceLineNo">418</span>}<a name="line.418"></a>
 
 
 
diff --git a/apidocs/src-html/org/apache/hadoop/hbase/rest/client/Client.html b/apidocs/src-html/org/apache/hadoop/hbase/rest/client/Client.html
index b69e3c5..f11f8cc 100644
--- a/apidocs/src-html/org/apache/hadoop/hbase/rest/client/Client.html
+++ b/apidocs/src-html/org/apache/hadoop/hbase/rest/client/Client.html
@@ -52,797 +52,798 @@
 <span class="sourceLineNo">044</span>import org.apache.hadoop.conf.Configuration;<a name="line.44"></a>
 <span class="sourceLineNo">045</span>import org.apache.hadoop.hbase.HBaseConfiguration;<a name="line.45"></a>
 <span class="sourceLineNo">046</span>import org.apache.hadoop.hbase.rest.Constants;<a name="line.46"></a>
-<span class="sourceLineNo">047</span>import org.apache.hadoop.security.authentication.client.AuthenticatedURL;<a name="line.47"></a>
-<span class="sourceLineNo">048</span>import org.apache.hadoop.security.authentication.client.AuthenticationException;<a name="line.48"></a>
-<span class="sourceLineNo">049</span>import org.apache.hadoop.security.authentication.client.KerberosAuthenticator;<a name="line.49"></a>
-<span class="sourceLineNo">050</span>import org.apache.http.Header;<a name="line.50"></a>
-<span class="sourceLineNo">051</span>import org.apache.http.HttpResponse;<a name="line.51"></a>
-<span class="sourceLineNo">052</span>import org.apache.http.HttpStatus;<a name="line.52"></a>
-<span class="sourceLineNo">053</span>import org.apache.http.client.HttpClient;<a name="line.53"></a>
-<span class="sourceLineNo">054</span>import org.apache.http.client.config.RequestConfig;<a name="line.54"></a>
-<span class="sourceLineNo">055</span>import org.apache.http.client.methods.HttpDelete;<a name="line.55"></a>
-<span class="sourceLineNo">056</span>import org.apache.http.client.methods.HttpGet;<a name="line.56"></a>
-<span class="sourceLineNo">057</span>import org.apache.http.client.methods.HttpHead;<a name="line.57"></a>
-<span class="sourceLineNo">058</span>import org.apache.http.client.methods.HttpPost;<a name="line.58"></a>
-<span class="sourceLineNo">059</span>import org.apache.http.client.methods.HttpPut;<a name="line.59"></a>
-<span class="sourceLineNo">060</span>import org.apache.http.client.methods.HttpUriRequest;<a name="line.60"></a>
-<span class="sourceLineNo">061</span>import org.apache.http.entity.InputStreamEntity;<a name="line.61"></a>
-<span class="sourceLineNo">062</span>import org.apache.http.impl.client.HttpClientBuilder;<a name="line.62"></a>
-<span class="sourceLineNo">063</span>import org.apache.http.impl.client.HttpClients;<a name="line.63"></a>
-<span class="sourceLineNo">064</span>import org.apache.http.message.BasicHeader;<a name="line.64"></a>
-<span class="sourceLineNo">065</span>import org.apache.http.ssl.SSLContexts;<a name="line.65"></a>
-<span class="sourceLineNo">066</span>import org.apache.http.util.EntityUtils;<a name="line.66"></a>
-<span class="sourceLineNo">067</span>import org.apache.yetus.audience.InterfaceAudience;<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>/**<a name="line.71"></a>
-<span class="sourceLineNo">072</span> * A wrapper around HttpClient which provides some useful function and<a name="line.72"></a>
-<span class="sourceLineNo">073</span> * semantics for interacting with the REST gateway.<a name="line.73"></a>
-<span class="sourceLineNo">074</span> */<a name="line.74"></a>
-<span class="sourceLineNo">075</span>@InterfaceAudience.Public<a name="line.75"></a>
-<span class="sourceLineNo">076</span>public class Client {<a name="line.76"></a>
-<span class="sourceLineNo">077</span>  public static final Header[] EMPTY_HEADER_ARRAY = new Header[0];<a name="line.77"></a>
-<span class="sourceLineNo">078</span><a name="line.78"></a>
-<span class="sourceLineNo">079</span>  private static final Logger LOG = LoggerFactory.getLogger(Client.class);<a name="line.79"></a>
-<span class="sourceLineNo">080</span><a name="line.80"></a>
-<span class="sourceLineNo">081</span>  private HttpClient httpClient;<a name="line.81"></a>
-<span class="sourceLineNo">082</span>  private Cluster cluster;<a name="line.82"></a>
-<span class="sourceLineNo">083</span>  private Configuration conf;<a name="line.83"></a>
-<span class="sourceLineNo">084</span>  private boolean sslEnabled;<a name="line.84"></a>
-<span class="sourceLineNo">085</span>  private HttpResponse resp;<a name="line.85"></a>
-<span class="sourceLineNo">086</span>  private HttpGet httpGet = null;<a name="line.86"></a>
-<span class="sourceLineNo">087</span><a name="line.87"></a>
-<span class="sourceLineNo">088</span>  private Map&lt;String, String&gt; extraHeaders;<a name="line.88"></a>
-<span class="sourceLineNo">089</span><a name="line.89"></a>
-<span class="sourceLineNo">090</span>  private static final String AUTH_COOKIE = "hadoop.auth";<a name="line.90"></a>
-<span class="sourceLineNo">091</span>  private static final String AUTH_COOKIE_EQ = AUTH_COOKIE + "=";<a name="line.91"></a>
-<span class="sourceLineNo">092</span>  private static final String COOKIE = "Cookie";<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>   * Default Constructor<a name="line.95"></a>
-<span class="sourceLineNo">096</span>   */<a name="line.96"></a>
-<span class="sourceLineNo">097</span>  public Client() {<a name="line.97"></a>
-<span class="sourceLineNo">098</span>    this(null);<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>  private void initialize(Cluster cluster, Configuration conf, boolean sslEnabled,<a name="line.101"></a>
-<span class="sourceLineNo">102</span>      Optional&lt;KeyStore&gt; trustStore) {<a name="line.102"></a>
-<span class="sourceLineNo">103</span>    this.cluster = cluster;<a name="line.103"></a>
-<span class="sourceLineNo">104</span>    this.conf = conf;<a name="line.104"></a>
-<span class="sourceLineNo">105</span>    this.sslEnabled = sslEnabled;<a name="line.105"></a>
-<span class="sourceLineNo">106</span>    extraHeaders = new ConcurrentHashMap&lt;&gt;();<a name="line.106"></a>
-<span class="sourceLineNo">107</span>    String clspath = System.getProperty("java.class.path");<a name="line.107"></a>
-<span class="sourceLineNo">108</span>    LOG.debug("classpath " + clspath);<a name="line.108"></a>
-<span class="sourceLineNo">109</span>    HttpClientBuilder httpClientBuilder = HttpClients.custom();<a name="line.109"></a>
-<span class="sourceLineNo">110</span><a name="line.110"></a>
-<span class="sourceLineNo">111</span>    int connTimeout = this.conf.getInt(Constants.REST_CLIENT_CONN_TIMEOUT,<a name="line.111"></a>
-<span class="sourceLineNo">112</span>      Constants.DEFAULT_REST_CLIENT_CONN_TIMEOUT);<a name="line.112"></a>
-<span class="sourceLineNo">113</span>    int socketTimeout = this.conf.getInt(Constants.REST_CLIENT_SOCKET_TIMEOUT,<a name="line.113"></a>
-<span class="sourceLineNo">114</span>      Constants.DEFAULT_REST_CLIENT_SOCKET_TIMEOUT);<a name="line.114"></a>
-<span class="sourceLineNo">115</span>    RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connTimeout)<a name="line.115"></a>
-<span class="sourceLineNo">116</span>        .setSocketTimeout(socketTimeout).build();<a name="line.116"></a>
-<span class="sourceLineNo">117</span>    httpClientBuilder.setDefaultRequestConfig(requestConfig);<a name="line.117"></a>
-<span class="sourceLineNo">118</span><a name="line.118"></a>
-<span class="sourceLineNo">119</span>    // Since HBASE-25267 we don't use the deprecated DefaultHttpClient anymore.<a name="line.119"></a>
-<span class="sourceLineNo">120</span>    // The new http client would decompress the gzip content automatically.<a name="line.120"></a>
-<span class="sourceLineNo">121</span>    // In order to keep the original behaviour of this public class, we disable<a name="line.121"></a>
-<span class="sourceLineNo">122</span>    // automatic content compression.<a name="line.122"></a>
-<span class="sourceLineNo">123</span>    httpClientBuilder.disableContentCompression();<a name="line.123"></a>
-<span class="sourceLineNo">124</span><a name="line.124"></a>
-<span class="sourceLineNo">125</span>    if(sslEnabled &amp;&amp; trustStore.isPresent()) {<a name="line.125"></a>
-<span class="sourceLineNo">126</span>      try {<a name="line.126"></a>
-<span class="sourceLineNo">127</span>        SSLContext sslcontext =<a name="line.127"></a>
-<span class="sourceLineNo">128</span>          SSLContexts.custom().loadTrustMaterial(trustStore.get(), null).build();<a name="line.128"></a>
-<span class="sourceLineNo">129</span>        httpClientBuilder.setSSLContext(sslcontext);<a name="line.129"></a>
-<span class="sourceLineNo">130</span>      } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {<a name="line.130"></a>
-<span class="sourceLineNo">131</span>        throw new ClientTrustStoreInitializationException("Error while processing truststore", e);<a name="line.131"></a>
-<span class="sourceLineNo">132</span>      }<a name="line.132"></a>
-<span class="sourceLineNo">133</span>    }<a name="line.133"></a>
-<span class="sourceLineNo">134</span><a name="line.134"></a>
-<span class="sourceLineNo">135</span>    this.httpClient = httpClientBuilder.build();<a name="line.135"></a>
-<span class="sourceLineNo">136</span>  }<a name="line.136"></a>
-<span class="sourceLineNo">137</span><a name="line.137"></a>
-<span class="sourceLineNo">138</span>  /**<a name="line.138"></a>
-<span class="sourceLineNo">139</span>   * Constructor<a name="line.139"></a>
-<span class="sourceLineNo">140</span>   * @param cluster the cluster definition<a name="line.140"></a>
-<span class="sourceLineNo">141</span>   */<a name="line.141"></a>
-<span class="sourceLineNo">142</span>  public Client(Cluster cluster) {<a name="line.142"></a>
-<span class="sourceLineNo">143</span>    this(cluster, false);<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>  /**<a name="line.146"></a>
-<span class="sourceLineNo">147</span>   * Constructor<a name="line.147"></a>
-<span class="sourceLineNo">148</span>   * @param cluster the cluster definition<a name="line.148"></a>
-<span class="sourceLineNo">149</span>   * @param sslEnabled enable SSL or not<a name="line.149"></a>
-<span class="sourceLineNo">150</span>   */<a name="line.150"></a>
-<span class="sourceLineNo">151</span>  public Client(Cluster cluster, boolean sslEnabled) {<a name="line.151"></a>
-<span class="sourceLineNo">152</span>    initialize(cluster, HBaseConfiguration.create(), sslEnabled, Optional.empty());<a name="line.152"></a>
-<span class="sourceLineNo">153</span>  }<a name="line.153"></a>
-<span class="sourceLineNo">154</span><a name="line.154"></a>
-<span class="sourceLineNo">155</span>  /**<a name="line.155"></a>
-<span class="sourceLineNo">156</span>   * Constructor<a name="line.156"></a>
-<span class="sourceLineNo">157</span>   * @param cluster the cluster definition<a name="line.157"></a>
-<span class="sourceLineNo">158</span>   * @param conf Configuration<a name="line.158"></a>
-<span class="sourceLineNo">159</span>   * @param sslEnabled enable SSL or not<a name="line.159"></a>
-<span class="sourceLineNo">160</span>   */<a name="line.160"></a>
-<span class="sourceLineNo">161</span>  public Client(Cluster cluster, Configuration conf, boolean sslEnabled) {<a name="line.161"></a>
-<span class="sourceLineNo">162</span>    initialize(cluster, conf, sslEnabled, Optional.empty());<a name="line.162"></a>
-<span class="sourceLineNo">163</span>  }<a name="line.163"></a>
-<span class="sourceLineNo">164</span><a name="line.164"></a>
-<span class="sourceLineNo">165</span>  /**<a name="line.165"></a>
-<span class="sourceLineNo">166</span>   * Constructor, allowing to define custom trust store (only for SSL connections)<a name="line.166"></a>
-<span class="sourceLineNo">167</span>   *<a name="line.167"></a>
-<span class="sourceLineNo">168</span>   * @param cluster the cluster definition<a name="line.168"></a>
-<span class="sourceLineNo">169</span>   * @param trustStorePath custom trust store to use for SSL connections<a name="line.169"></a>
-<span class="sourceLineNo">170</span>   * @param trustStorePassword password to use for custom trust store<a name="line.170"></a>
-<span class="sourceLineNo">171</span>   * @param trustStoreType type of custom trust store<a name="line.171"></a>
-<span class="sourceLineNo">172</span>   *<a name="line.172"></a>
-<span class="sourceLineNo">173</span>   * @throws ClientTrustStoreInitializationException if the trust store file can not be loaded<a name="line.173"></a>
-<span class="sourceLineNo">174</span>   */<a name="line.174"></a>
-<span class="sourceLineNo">175</span>  public Client(Cluster cluster, String trustStorePath, Optional&lt;String&gt; trustStorePassword,<a name="line.175"></a>
-<span class="sourceLineNo">176</span>      Optional&lt;String&gt; trustStoreType) {<a name="line.176"></a>
-<span class="sourceLineNo">177</span>    this(cluster, HBaseConfiguration.create(), trustStorePath, trustStorePassword, trustStoreType);<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>  /**<a name="line.180"></a>
-<span class="sourceLineNo">181</span>   * Constructor, allowing to define custom trust store (only for SSL connections)<a name="line.181"></a>
-<span class="sourceLineNo">182</span>   *<a name="line.182"></a>
-<span class="sourceLineNo">183</span>   * @param cluster the cluster definition<a name="line.183"></a>
-<span class="sourceLineNo">184</span>   * @param conf Configuration<a name="line.184"></a>
-<span class="sourceLineNo">185</span>   * @param trustStorePath custom trust store to use for SSL connections<a name="line.185"></a>
-<span class="sourceLineNo">186</span>   * @param trustStorePassword password to use for custom trust store<a name="line.186"></a>
-<span class="sourceLineNo">187</span>   * @param trustStoreType type of custom trust store<a name="line.187"></a>
-<span class="sourceLineNo">188</span>   * @throws ClientTrustStoreInitializationException if the trust store file can not be loaded<a name="line.188"></a>
-<span class="sourceLineNo">189</span>   */<a name="line.189"></a>
-<span class="sourceLineNo">190</span>  public Client(Cluster cluster, Configuration conf, String trustStorePath,<a name="line.190"></a>
-<span class="sourceLineNo">191</span>      Optional&lt;String&gt; trustStorePassword, Optional&lt;String&gt; trustStoreType) {<a name="line.191"></a>
-<span class="sourceLineNo">192</span><a name="line.192"></a>
-<span class="sourceLineNo">193</span>    char[] password = trustStorePassword.map(String::toCharArray).orElse(null);<a name="line.193"></a>
-<span class="sourceLineNo">194</span>    String type = trustStoreType.orElse(KeyStore.getDefaultType());<a name="line.194"></a>
-<span class="sourceLineNo">195</span><a name="line.195"></a>
-<span class="sourceLineNo">196</span>    KeyStore trustStore;<a name="line.196"></a>
-<span class="sourceLineNo">197</span>    try {<a name="line.197"></a>
-<span class="sourceLineNo">198</span>      trustStore = KeyStore.getInstance(type);<a name="line.198"></a>
-<span class="sourceLineNo">199</span>    } catch (KeyStoreException e) {<a name="line.199"></a>
-<span class="sourceLineNo">200</span>      throw new ClientTrustStoreInitializationException("Invalid trust store type: " + type, e);<a name="line.200"></a>
-<span class="sourceLineNo">201</span>    }<a name="line.201"></a>
-<span class="sourceLineNo">202</span>    try (InputStream inputStream = new BufferedInputStream(<a name="line.202"></a>
-<span class="sourceLineNo">203</span>      Files.newInputStream(new File(trustStorePath).toPath()))) {<a name="line.203"></a>
-<span class="sourceLineNo">204</span>      trustStore.load(inputStream, password);<a name="line.204"></a>
-<span class="sourceLineNo">205</span>    } catch (CertificateException | NoSuchAlgorithmException | IOException e) {<a name="line.205"></a>
-<span class="sourceLineNo">206</span>      throw new ClientTrustStoreInitializationException("Trust store load error: " + trustStorePath,<a name="line.206"></a>
-<span class="sourceLineNo">207</span>        e);<a name="line.207"></a>
-<span class="sourceLineNo">208</span>    }<a name="line.208"></a>
-<span class="sourceLineNo">209</span><a name="line.209"></a>
-<span class="sourceLineNo">210</span>    initialize(cluster, conf, true, Optional.of(trustStore));<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>  /**<a name="line.213"></a>
-<span class="sourceLineNo">214</span>   * Shut down the client. Close any open persistent connections.<a name="line.214"></a>
-<span class="sourceLineNo">215</span>   */<a name="line.215"></a>
-<span class="sourceLineNo">216</span>  public void shutdown() {<a name="line.216"></a>
-<span class="sourceLineNo">217</span>  }<a name="line.217"></a>
-<span class="sourceLineNo">218</span><a name="line.218"></a>
-<span class="sourceLineNo">219</span>  /**<a name="line.219"></a>
-<span class="sourceLineNo">220</span>   * @return the wrapped HttpClient<a name="line.220"></a>
-<span class="sourceLineNo">221</span>   */<a name="line.221"></a>
-<span class="sourceLineNo">222</span>  public HttpClient getHttpClient() {<a name="line.222"></a>
-<span class="sourceLineNo">223</span>    return httpClient;<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>   * Add extra headers.  These extra headers will be applied to all http<a name="line.227"></a>
-<span class="sourceLineNo">228</span>   * methods before they are removed. If any header is not used any more,<a name="line.228"></a>
-<span class="sourceLineNo">229</span>   * client needs to remove it explicitly.<a name="line.229"></a>
-<span class="sourceLineNo">230</span>   */<a name="line.230"></a>
-<span class="sourceLineNo">231</span>  public void addExtraHeader(final String name, final String value) {<a name="line.231"></a>
-<span class="sourceLineNo">232</span>    extraHeaders.put(name, value);<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>  /**<a name="line.235"></a>
-<span class="sourceLineNo">236</span>   * Get an extra header value.<a name="line.236"></a>
-<span class="sourceLineNo">237</span>   */<a name="line.237"></a>
-<span class="sourceLineNo">238</span>  public String getExtraHeader(final String name) {<a name="line.238"></a>
-<span class="sourceLineNo">239</span>    return extraHeaders.get(name);<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>   * Get all extra headers (read-only).<a name="line.243"></a>
-<span class="sourceLineNo">244</span>   */<a name="line.244"></a>
-<span class="sourceLineNo">245</span>  public Map&lt;String, String&gt; getExtraHeaders() {<a name="line.245"></a>
-<span class="sourceLineNo">246</span>    return Collections.unmodifiableMap(extraHeaders);<a name="line.246"></a>
-<span class="sourceLineNo">247</span>  }<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>   * Remove an extra header.<a name="line.250"></a>
-<span class="sourceLineNo">251</span>   */<a name="line.251"></a>
-<span class="sourceLineNo">252</span>  public void removeExtraHeader(final String name) {<a name="line.252"></a>
-<span class="sourceLineNo">253</span>    extraHeaders.remove(name);<a name="line.253"></a>
-<span class="sourceLineNo">254</span>  }<a name="line.254"></a>
-<span class="sourceLineNo">255</span><a name="line.255"></a>
-<span class="sourceLineNo">256</span>  /**<a name="line.256"></a>
-<span class="sourceLineNo">257</span>   * Execute a transaction method given only the path. Will select at random<a name="line.257"></a>
-<span class="sourceLineNo">258</span>   * one of the members of the supplied cluster definition and iterate through<a name="line.258"></a>
-<span class="sourceLineNo">259</span>   * the list until a transaction can be successfully completed. The<a name="line.259"></a>
-<span class="sourceLineNo">260</span>   * definition of success here is a complete HTTP transaction, irrespective<a name="line.260"></a>
-<span class="sourceLineNo">261</span>   * of result code.<a name="line.261"></a>
-<span class="sourceLineNo">262</span>   * @param cluster the cluster definition<a name="line.262"></a>
-<span class="sourceLineNo">263</span>   * @param method the transaction method<a name="line.263"></a>
-<span class="sourceLineNo">264</span>   * @param headers HTTP header values to send<a name="line.264"></a>
-<span class="sourceLineNo">265</span>   * @param path the properly urlencoded path<a name="line.265"></a>
-<span class="sourceLineNo">266</span>   * @return the HTTP response code<a name="line.266"></a>
-<span class="sourceLineNo">267</span>   * @throws IOException<a name="line.267"></a>
-<span class="sourceLineNo">268</span>   */<a name="line.268"></a>
-<span class="sourceLineNo">269</span>  public HttpResponse executePathOnly(Cluster cluster, HttpUriRequest method,<a name="line.269"></a>
-<span class="sourceLineNo">270</span>      Header[] headers, String path) throws IOException {<a name="line.270"></a>
-<span class="sourceLineNo">271</span>    IOException lastException;<a name="line.271"></a>
-<span class="sourceLineNo">272</span>    if (cluster.nodes.size() &lt; 1) {<a name="line.272"></a>
-<span class="sourceLineNo">273</span>      throw new IOException("Cluster is empty");<a name="line.273"></a>
-<span class="sourceLineNo">274</span>    }<a name="line.274"></a>
-<span class="sourceLineNo">275</span>    int start = (int)Math.round((cluster.nodes.size() - 1) * Math.random());<a name="line.275"></a>
-<span class="sourceLineNo">276</span>    int i = start;<a name="line.276"></a>
-<span class="sourceLineNo">277</span>    do {<a name="line.277"></a>
-<span class="sourceLineNo">278</span>      cluster.lastHost = cluster.nodes.get(i);<a name="line.278"></a>
-<span class="sourceLineNo">279</span>      try {<a name="line.279"></a>
-<span class="sourceLineNo">280</span>        StringBuilder sb = new StringBuilder();<a name="line.280"></a>
-<span class="sourceLineNo">281</span>        if (sslEnabled) {<a name="line.281"></a>
-<span class="sourceLineNo">282</span>          sb.append("https://");<a name="line.282"></a>
-<span class="sourceLineNo">283</span>        } else {<a name="line.283"></a>
-<span class="sourceLineNo">284</span>          sb.append("http://");<a name="line.284"></a>
-<span class="sourceLineNo">285</span>        }<a name="line.285"></a>
-<span class="sourceLineNo">286</span>        sb.append(cluster.lastHost);<a name="line.286"></a>
-<span class="sourceLineNo">287</span>        sb.append(path);<a name="line.287"></a>
-<span class="sourceLineNo">288</span>        URI uri = new URI(sb.toString());<a name="line.288"></a>
-<span class="sourceLineNo">289</span>        if (method instanceof HttpPut) {<a name="line.289"></a>
-<span class="sourceLineNo">290</span>          HttpPut put = new HttpPut(uri);<a name="line.290"></a>
-<span class="sourceLineNo">291</span>          put.setEntity(((HttpPut) method).getEntity());<a name="line.291"></a>
-<span class="sourceLineNo">292</span>          put.setHeaders(method.getAllHeaders());<a name="line.292"></a>
-<span class="sourceLineNo">293</span>          method = put;<a name="line.293"></a>
-<span class="sourceLineNo">294</span>        } else if (method instanceof HttpGet) {<a name="line.294"></a>
-<span class="sourceLineNo">295</span>          method = new HttpGet(uri);<a name="line.295"></a>
-<span class="sourceLineNo">296</span>        } else if (method instanceof HttpHead) {<a name="line.296"></a>
-<span class="sourceLineNo">297</span>          method = new HttpHead(uri);<a name="line.297"></a>
-<span class="sourceLineNo">298</span>        } else if (method instanceof HttpDelete) {<a name="line.298"></a>
-<span class="sourceLineNo">299</span>          method = new HttpDelete(uri);<a name="line.299"></a>
-<span class="sourceLineNo">300</span>        } else if (method instanceof HttpPost) {<a name="line.300"></a>
-<span class="sourceLineNo">301</span>          HttpPost post = new HttpPost(uri);<a name="line.301"></a>
-<span class="sourceLineNo">302</span>          post.setEntity(((HttpPost) method).getEntity());<a name="line.302"></a>
-<span class="sourceLineNo">303</span>          post.setHeaders(method.getAllHeaders());<a name="line.303"></a>
-<span class="sourceLineNo">304</span>          method = post;<a name="line.304"></a>
-<span class="sourceLineNo">305</span>        }<a name="line.305"></a>
-<span class="sourceLineNo">306</span>        return executeURI(method, headers, uri.toString());<a name="line.306"></a>
-<span class="sourceLineNo">307</span>      } catch (IOException e) {<a name="line.307"></a>
-<span class="sourceLineNo">308</span>        lastException = e;<a name="line.308"></a>
-<span class="sourceLineNo">309</span>      } catch (URISyntaxException use) {<a name="line.309"></a>
-<span class="sourceLineNo">310</span>        lastException = new IOException(use);<a name="line.310"></a>
-<span class="sourceLineNo">311</span>      }<a name="line.311"></a>
-<span class="sourceLineNo">312</span>    } while (++i != start &amp;&amp; i &lt; cluster.nodes.size());<a name="line.312"></a>
-<span class="sourceLineNo">313</span>    throw lastException;<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>   * Execute a transaction method given a complete URI.<a name="line.317"></a>
-<span class="sourceLineNo">318</span>   * @param method the transaction method<a name="line.318"></a>
-<span class="sourceLineNo">319</span>   * @param headers HTTP header values to send<a name="line.319"></a>
-<span class="sourceLineNo">320</span>   * @param uri a properly urlencoded URI<a name="line.320"></a>
-<span class="sourceLineNo">321</span>   * @return the HTTP response code<a name="line.321"></a>
-<span class="sourceLineNo">322</span>   * @throws IOException<a name="line.322"></a>
-<span class="sourceLineNo">323</span>   */<a name="line.323"></a>
-<span class="sourceLineNo">324</span>  public HttpResponse executeURI(HttpUriRequest method, Header[] headers, String uri)<a name="line.324"></a>
-<span class="sourceLineNo">325</span>      throws IOException {<a name="line.325"></a>
-<span class="sourceLineNo">326</span>    // method.setURI(new URI(uri, true));<a name="line.326"></a>
-<span class="sourceLineNo">327</span>    for (Map.Entry&lt;String, String&gt; e: extraHeaders.entrySet()) {<a name="line.327"></a>
-<span class="sourceLineNo">328</span>      method.addHeader(e.getKey(), e.getValue());<a name="line.328"></a>
-<span class="sourceLineNo">329</span>    }<a name="line.329"></a>
-<span class="sourceLineNo">330</span>    if (headers != null) {<a name="line.330"></a>
-<span class="sourceLineNo">331</span>      for (Header header: headers) {<a name="line.331"></a>
-<span class="sourceLineNo">332</span>        method.addHeader(header);<a name="line.332"></a>
-<span class="sourceLineNo">333</span>      }<a name="line.333"></a>
-<span class="sourceLineNo">334</span>    }<a name="line.334"></a>
-<span class="sourceLineNo">335</span>    long startTime = System.currentTimeMillis();<a name="line.335"></a>
-<span class="sourceLineNo">336</span>    if (resp != null) EntityUtils.consumeQuietly(resp.getEntity());<a name="line.336"></a>
-<span class="sourceLineNo">337</span>    resp = httpClient.execute(method);<a name="line.337"></a>
-<span class="sourceLineNo">338</span>    if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {<a name="line.338"></a>
-<span class="sourceLineNo">339</span>      // Authentication error<a name="line.339"></a>
-<span class="sourceLineNo">340</span>      LOG.debug("Performing negotiation with the server.");<a name="line.340"></a>
-<span class="sourceLineNo">341</span>      negotiate(method, uri);<a name="line.341"></a>
-<span class="sourceLineNo">342</span>      resp = httpClient.execute(method);<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>    long endTime = System.currentTimeMillis();<a name="line.345"></a>
-<span class="sourceLineNo">346</span>    if (LOG.isTraceEnabled()) {<a name="line.346"></a>
-<span class="sourceLineNo">347</span>      LOG.trace(method.getMethod() + " " + uri + " " + resp.getStatusLine().getStatusCode() + " " +<a name="line.347"></a>
-<span class="sourceLineNo">348</span>          resp.getStatusLine().getReasonPhrase() + " in " + (endTime - startTime) + " ms");<a name="line.348"></a>
-<span class="sourceLineNo">349</span>    }<a name="line.349"></a>
-<span class="sourceLineNo">350</span>    return resp;<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>   * Execute a transaction method. Will call either &lt;tt&gt;executePathOnly&lt;/tt&gt;<a name="line.354"></a>
-<span class="sourceLineNo">355</span>   * or &lt;tt&gt;executeURI&lt;/tt&gt; depending on whether a path only is supplied in<a name="line.355"></a>
-<span class="sourceLineNo">356</span>   * 'path', or if a complete URI is passed instead, respectively.<a name="line.356"></a>
-<span class="sourceLineNo">357</span>   * @param cluster the cluster definition<a name="line.357"></a>
-<span class="sourceLineNo">358</span>   * @param method the HTTP method<a name="line.358"></a>
-<span class="sourceLineNo">359</span>   * @param headers HTTP header values to send<a name="line.359"></a>
-<span class="sourceLineNo">360</span>   * @param path the properly urlencoded path or URI<a name="line.360"></a>
-<span class="sourceLineNo">361</span>   * @return the HTTP response code<a name="line.361"></a>
-<span class="sourceLineNo">362</span>   * @throws IOException<a name="line.362"></a>
-<span class="sourceLineNo">363</span>   */<a name="line.363"></a>
-<span class="sourceLineNo">364</span>  public HttpResponse execute(Cluster cluster, HttpUriRequest method, Header[] headers,<a name="line.364"></a>
-<span class="sourceLineNo">365</span>      String path) throws IOException {<a name="line.365"></a>
-<span class="sourceLineNo">366</span>    if (path.startsWith("/")) {<a name="line.366"></a>
-<span class="sourceLineNo">367</span>      return executePathOnly(cluster, method, headers, path);<a name="line.367"></a>
-<span class="sourceLineNo">368</span>    }<a name="line.368"></a>
-<span class="sourceLineNo">369</span>    return executeURI(method, headers, path);<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>  /**<a name="line.372"></a>
-<span class="sourceLineNo">373</span>   * Initiate client side Kerberos negotiation with the server.<a name="line.373"></a>
-<span class="sourceLineNo">374</span>   * @param method method to inject the authentication token into.<a name="line.374"></a>
-<span class="sourceLineNo">375</span>   * @param uri the String to parse as a URL.<a name="line.375"></a>
-<span class="sourceLineNo">376</span>   * @throws IOException if unknown protocol is found.<a name="line.376"></a>
-<span class="sourceLineNo">377</span>   */<a name="line.377"></a>
-<span class="sourceLineNo">378</span>  private void negotiate(HttpUriRequest method, String uri) throws IOException {<a name="line.378"></a>
-<span class="sourceLineNo">379</span>    try {<a name="line.379"></a>
-<span class="sourceLineNo">380</span>      AuthenticatedURL.Token token = new AuthenticatedURL.Token();<a name="line.380"></a>
-<span class="sourceLineNo">381</span>      KerberosAuthenticator authenticator = new KerberosAuthenticator();<a name="line.381"></a>
-<span class="sourceLineNo">382</span>      authenticator.authenticate(new URL(uri), token);<a name="line.382"></a>
-<span class="sourceLineNo">383</span>      // Inject the obtained negotiated token in the method cookie<a name="line.383"></a>
-<span class="sourceLineNo">384</span>      injectToken(method, token);<a name="line.384"></a>
-<span class="sourceLineNo">385</span>    } catch (AuthenticationException e) {<a name="line.385"></a>
-<span class="sourceLineNo">386</span>      LOG.error("Failed to negotiate with the server.", e);<a name="line.386"></a>
-<span class="sourceLineNo">387</span>      throw new IOException(e);<a name="line.387"></a>
-<span class="sourceLineNo">388</span>    }<a name="line.388"></a>
-<span class="sourceLineNo">389</span>  }<a name="line.389"></a>
-<span class="sourceLineNo">390</span><a name="line.390"></a>
-<span class="sourceLineNo">391</span>  /**<a name="line.391"></a>
-<span class="sourceLineNo">392</span>   * Helper method that injects an authentication token to send with the method.<a name="line.392"></a>
-<span class="sourceLineNo">393</span>   * @param method method to inject the authentication token into.<a name="line.393"></a>
-<span class="sourceLineNo">394</span>   * @param token authentication token to inject.<a name="line.394"></a>
-<span class="sourceLineNo">395</span>   */<a name="line.395"></a>
-<span class="sourceLineNo">396</span>  private void injectToken(HttpUriRequest method, AuthenticatedURL.Token token) {<a name="line.396"></a>
-<span class="sourceLineNo">397</span>    String t = token.toString();<a name="line.397"></a>
-<span class="sourceLineNo">398</span>    if (t != null) {<a name="line.398"></a>
-<span class="sourceLineNo">399</span>      if (!t.startsWith("\"")) {<a name="line.399"></a>
-<span class="sourceLineNo">400</span>        t = "\"" + t + "\"";<a name="line.400"></a>
-<span class="sourceLineNo">401</span>      }<a name="line.401"></a>
-<span class="sourceLineNo">402</span>      method.addHeader(COOKIE, AUTH_COOKIE_EQ + t);<a name="line.402"></a>
-<span class="sourceLineNo">403</span>    }<a name="line.403"></a>
-<span class="sourceLineNo">404</span>  }<a name="line.404"></a>
-<span class="sourceLineNo">405</span><a name="line.405"></a>
-<span class="sourceLineNo">406</span>  /**<a name="line.406"></a>
-<span class="sourceLineNo">407</span>   * @return the cluster definition<a name="line.407"></a>
-<span class="sourceLineNo">408</span>   */<a name="line.408"></a>
-<span class="sourceLineNo">409</span>  public Cluster getCluster() {<a name="line.409"></a>
-<span class="sourceLineNo">410</span>    return cluster;<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>  /**<a name="line.413"></a>
-<span class="sourceLineNo">414</span>   * @param cluster the cluster definition<a name="line.414"></a>
-<span class="sourceLineNo">415</span>   */<a name="line.415"></a>
-<span class="sourceLineNo">416</span>  public void setCluster(Cluster cluster) {<a name="line.416"></a>
-<span class="sourceLineNo">417</span>    this.cluster = cluster;<a name="line.417"></a>
-<span class="sourceLineNo">418</span>  }<a name="line.418"></a>
-<span class="sourceLineNo">419</span><a name="line.419"></a>
-<span class="sourceLineNo">420</span>  /**<a name="line.420"></a>
-<span class="sourceLineNo">421</span>   * Send a HEAD request<a name="line.421"></a>
-<span class="sourceLineNo">422</span>   * @param path the path or URI<a name="line.422"></a>
-<span class="sourceLineNo">423</span>   * @return a Response object with response detail<a name="line.423"></a>
-<span class="sourceLineNo">424</span>   * @throws IOException<a name="line.424"></a>
-<span class="sourceLineNo">425</span>   */<a name="line.425"></a>
-<span class="sourceLineNo">426</span>  public Response head(String path) throws IOException {<a name="line.426"></a>
-<span class="sourceLineNo">427</span>    return head(cluster, path, null);<a name="line.427"></a>
-<span class="sourceLineNo">428</span>  }<a name="line.428"></a>
-<span class="sourceLineNo">429</span><a name="line.429"></a>
-<span class="sourceLineNo">430</span>  /**<a name="line.430"></a>
-<span class="sourceLineNo">431</span>   * Send a HEAD request<a name="line.431"></a>
-<span class="sourceLineNo">432</span>   * @param cluster the cluster definition<a name="line.432"></a>
-<span class="sourceLineNo">433</span>   * @param path the path or URI<a name="line.433"></a>
-<span class="sourceLineNo">434</span>   * @param headers the HTTP headers to include in the request<a name="line.434"></a>
-<span class="sourceLineNo">435</span>   * @return a Response object with response detail<a name="line.435"></a>
-<span class="sourceLineNo">436</span>   * @throws IOException<a name="line.436"></a>
-<span class="sourceLineNo">437</span>   */<a name="line.437"></a>
-<span class="sourceLineNo">438</span>  public Response head(Cluster cluster, String path, Header[] headers)<a name="line.438"></a>
-<span class="sourceLineNo">439</span>      throws IOException {<a name="line.439"></a>
-<span class="sourceLineNo">440</span>    HttpHead method = new HttpHead(path);<a name="line.440"></a>
-<span class="sourceLineNo">441</span>    try {<a name="line.441"></a>
-<span class="sourceLineNo">442</span>      HttpResponse resp = execute(cluster, method, null, path);<a name="line.442"></a>
-<span class="sourceLineNo">443</span>      return new Response(resp.getStatusLine().getStatusCode(), resp.getAllHeaders(), null);<a name="line.443"></a>
-<span class="sourceLineNo">444</span>    } finally {<a name="line.444"></a>
-<span class="sourceLineNo">445</span>      method.releaseConnection();<a name="line.445"></a>
-<span class="sourceLineNo">446</span>    }<a name="line.446"></a>
-<span class="sourceLineNo">447</span>  }<a name="line.447"></a>
-<span class="sourceLineNo">448</span><a name="line.448"></a>
-<span class="sourceLineNo">449</span>  /**<a name="line.449"></a>
-<span class="sourceLineNo">450</span>   * Send a GET request<a name="line.450"></a>
-<span class="sourceLineNo">451</span>   * @param path the path or URI<a name="line.451"></a>
-<span class="sourceLineNo">452</span>   * @return a Response object with response detail<a name="line.452"></a>
-<span class="sourceLineNo">453</span>   * @throws IOException<a name="line.453"></a>
-<span class="sourceLineNo">454</span>   */<a name="line.454"></a>
-<span class="sourceLineNo">455</span>  public Response get(String path) throws IOException {<a name="line.455"></a>
-<span class="sourceLineNo">456</span>    return get(cluster, path);<a name="line.456"></a>
-<span class="sourceLineNo">457</span>  }<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>   * Send a GET request<a name="line.460"></a>
-<span class="sourceLineNo">461</span>   * @param cluster the cluster definition<a name="line.461"></a>
-<span class="sourceLineNo">462</span>   * @param path the path or URI<a name="line.462"></a>
-<span class="sourceLineNo">463</span>   * @return a Response object with response detail<a name="line.463"></a>
-<span class="sourceLineNo">464</span>   * @throws IOException<a name="line.464"></a>
-<span class="sourceLineNo">465</span>   */<a name="line.465"></a>
-<span class="sourceLineNo">466</span>  public Response get(Cluster cluster, String path) throws IOException {<a name="line.466"></a>
-<span class="sourceLineNo">467</span>    return get(cluster, path, EMPTY_HEADER_ARRAY);<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>  /**<a name="line.470"></a>
-<span class="sourceLineNo">471</span>   * Send a GET request<a name="line.471"></a>
-<span class="sourceLineNo">472</span>   * @param path the path or URI<a name="line.472"></a>
-<span class="sourceLineNo">473</span>   * @param accept Accept header value<a name="line.473"></a>
-<span class="sourceLineNo">474</span>   * @return a Response object with response detail<a name="line.474"></a>
-<span class="sourceLineNo">475</span>   * @throws IOException<a name="line.475"></a>
-<span class="sourceLineNo">476</span>   */<a name="line.476"></a>
-<span class="sourceLineNo">477</span>  public Response get(String path, String accept) throws IOException {<a name="line.477"></a>
-<span class="sourceLineNo">478</span>    return get(cluster, path, accept);<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>  /**<a name="line.481"></a>
-<span class="sourceLineNo">482</span>   * Send a GET request<a name="line.482"></a>
-<span class="sourceLineNo">483</span>   * @param cluster the cluster definition<a name="line.483"></a>
-<span class="sourceLineNo">484</span>   * @param path the path or URI<a name="line.484"></a>
-<span class="sourceLineNo">485</span>   * @param accept Accept header value<a name="line.485"></a>
-<span class="sourceLineNo">486</span>   * @return a Response object with response detail<a name="line.486"></a>
-<span class="sourceLineNo">487</span>   * @throws IOException<a name="line.487"></a>
-<span class="sourceLineNo">488</span>   */<a name="line.488"></a>
-<span class="sourceLineNo">489</span>  public Response get(Cluster cluster, String path, String accept)<a name="line.489"></a>
-<span class="sourceLineNo">490</span>      throws IOException {<a name="line.490"></a>
-<span class="sourceLineNo">491</span>    Header[] headers = new Header[1];<a name="line.491"></a>
-<span class="sourceLineNo">492</span>    headers[0] = new BasicHeader("Accept", accept);<a name="line.492"></a>
-<span class="sourceLineNo">493</span>    return get(cluster, path, headers);<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>   * Send a GET request<a name="line.497"></a>
-<span class="sourceLineNo">498</span>   * @param path the path or URI<a name="line.498"></a>
-<span class="sourceLineNo">499</span>   * @param headers the HTTP headers to include in the request,<a name="line.499"></a>
-<span class="sourceLineNo">500</span>   * &lt;tt&gt;Accept&lt;/tt&gt; must be supplied<a name="line.500"></a>
-<span class="sourceLineNo">501</span>   * @return a Response object with response detail<a name="line.501"></a>
-<span class="sourceLineNo">502</span>   * @throws IOException<a name="line.502"></a>
-<span class="sourceLineNo">503</span>   */<a name="line.503"></a>
-<span class="sourceLineNo">504</span>  public Response get(String path, Header[] headers) throws IOException {<a name="line.504"></a>
-<span class="sourceLineNo">505</span>    return get(cluster, path, headers);<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>  /**<a name="line.508"></a>
-<span class="sourceLineNo">509</span>   * Returns the response body of the HTTPResponse, if any, as an array of bytes.<a name="line.509"></a>
-<span class="sourceLineNo">510</span>   * If response body is not available or cannot be read, returns &lt;tt&gt;null&lt;/tt&gt;<a name="line.510"></a>
-<span class="sourceLineNo">511</span>   *<a name="line.511"></a>
-<span class="sourceLineNo">512</span>   * Note: This will cause the entire response body to be buffered in memory. A<a name="line.512"></a>
-<span class="sourceLineNo">513</span>   * malicious server may easily exhaust all the VM memory. It is strongly<a name="line.513"></a>
-<span class="sourceLineNo">514</span>   * recommended, to use getResponseAsStream if the content length of the response<a name="line.514"></a>
-<span class="sourceLineNo">515</span>   * is unknown or reasonably large.<a name="line.515"></a>
-<span class="sourceLineNo">516</span>   *<a name="line.516"></a>
-<span class="sourceLineNo">517</span>   * @param resp HttpResponse<a name="line.517"></a>
-<span class="sourceLineNo">518</span>   * @return The response body, null if body is empty<a name="line.518"></a>
-<span class="sourceLineNo">519</span>   * @throws IOException If an I/O (transport) problem occurs while obtaining the<a name="line.519"></a>
-<span class="sourceLineNo">520</span>   * response body.<a name="line.520"></a>
-<span class="sourceLineNo">521</span>   */<a name="line.521"></a>
-<span class="sourceLineNo">522</span>  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value =<a name="line.522"></a>
-<span class="sourceLineNo">523</span>      "NP_LOAD_OF_KNOWN_NULL_VALUE", justification = "null is possible return value")<a name="line.523"></a>
-<span class="sourceLineNo">524</span>  public static byte[] getResponseBody(HttpResponse resp) throws IOException {<a name="line.524"></a>
-<span class="sourceLineNo">525</span>    if (resp.getEntity() == null) return null;<a name="line.525"></a>
-<span class="sourceLineNo">526</span>    try (InputStream instream = resp.getEntity().getContent()) {<a name="line.526"></a>
-<span class="sourceLineNo">527</span>      if (instream != null) {<a name="line.527"></a>
-<span class="sourceLineNo">528</span>        long contentLength = resp.getEntity().getContentLength();<a name="line.528"></a>
-<span class="sourceLineNo">529</span>        if (contentLength &gt; Integer.MAX_VALUE) {<a name="line.529"></a>
-<span class="sourceLineNo">530</span>          //guard integer cast from overflow<a name="line.530"></a>
-<span class="sourceLineNo">531</span>          throw new IOException("Content too large to be buffered: " + contentLength +" bytes");<a name="line.531"></a>
-<span class="sourceLineNo">532</span>        }<a name="line.532"></a>
-<span class="sourceLineNo">533</span>        ByteArrayOutputStream outstream = new ByteArrayOutputStream(<a name="line.533"></a>
-<span class="sourceLineNo">534</span>            contentLength &gt; 0 ? (int) contentLength : 4*1024);<a name="line.534"></a>
-<span class="sourceLineNo">535</span>        byte[] buffer = new byte[4096];<a name="line.535"></a>
-<span class="sourceLineNo">536</span>        int len;<a name="line.536"></a>
-<span class="sourceLineNo">537</span>        while ((len = instream.read(buffer)) &gt; 0) {<a name="line.537"></a>
-<span class="sourceLineNo">538</span>          outstream.write(buffer, 0, len);<a name="line.538"></a>
-<span class="sourceLineNo">539</span>        }<a name="line.539"></a>
-<span class="sourceLineNo">540</span>        outstream.close();<a name="line.540"></a>
-<span class="sourceLineNo">541</span>        return outstream.toByteArray();<a name="line.541"></a>
-<span class="sourceLineNo">542</span>      }<a name="line.542"></a>
-<span class="sourceLineNo">543</span>      return null;<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">546</span><a name="line.546"></a>
-<span class="sourceLineNo">547</span>  /**<a name="line.547"></a>
-<span class="sourceLineNo">548</span>   * Send a GET request<a name="line.548"></a>
-<span class="sourceLineNo">549</span>   * @param c the cluster definition<a name="line.549"></a>
-<span class="sourceLineNo">550</span>   * @param path the path or URI<a name="line.550"></a>
-<span class="sourceLineNo">551</span>   * @param headers the HTTP headers to include in the request<a name="line.551"></a>
-<span class="sourceLineNo">552</span>   * @return a Response object with response detail<a name="line.552"></a>
-<span class="sourceLineNo">553</span>   * @throws IOException<a name="line.553"></a>
-<span class="sourceLineNo">554</span>   */<a name="line.554"></a>
-<span class="sourceLineNo">555</span>  public Response get(Cluster c, String path, Header[] headers)<a name="line.555"></a>
-<span class="sourceLineNo">556</span>      throws IOException {<a name="line.556"></a>
-<span class="sourceLineNo">557</span>    if (httpGet != null) {<a name="line.557"></a>
-<span class="sourceLineNo">558</span>      httpGet.releaseConnection();<a name="line.558"></a>
-<span class="sourceLineNo">559</span>    }<a name="line.559"></a>
-<span class="sourceLineNo">560</span>    httpGet = new HttpGet(path);<a name="line.560"></a>
-<span class="sourceLineNo">561</span>    HttpResponse resp = execute(c, httpGet, headers, path);<a name="line.561"></a>
-<span class="sourceLineNo">562</span>    return new Response(resp.getStatusLine().getStatusCode(), resp.getAllHeaders(),<a name="line.562"></a>
-<span class="sourceLineNo">563</span>        resp, resp.getEntity() == null ? null : resp.getEntity().getContent());<a name="line.563"></a>
-<span class="sourceLineNo">564</span>  }<a name="line.564"></a>
-<span class="sourceLineNo">565</span><a name="line.565"></a>
-<span class="sourceLineNo">566</span>  /**<a name="line.566"></a>
-<span class="sourceLineNo">567</span>   * Send a PUT request<a name="line.567"></a>
-<span class="sourceLineNo">568</span>   * @param path the path or URI<a name="line.568"></a>
-<span class="sourceLineNo">569</span>   * @param contentType the content MIME type<a name="line.569"></a>
-<span class="sourceLineNo">570</span>   * @param content the content bytes<a name="line.570"></a>
-<span class="sourceLineNo">571</span>   * @return a Response object with response detail<a name="line.571"></a>
-<span class="sourceLineNo">572</span>   * @throws IOException<a name="line.572"></a>
-<span class="sourceLineNo">573</span>   */<a name="line.573"></a>
-<span class="sourceLineNo">574</span>  public Response put(String path, String contentType, byte[] content)<a name="line.574"></a>
-<span class="sourceLineNo">575</span>      throws IOException {<a name="line.575"></a>
-<span class="sourceLineNo">576</span>    return put(cluster, path, contentType, content);<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>
-<span class="sourceLineNo">579</span>  /**<a name="line.579"></a>
-<span class="sourceLineNo">580</span>   * Send a PUT request<a name="line.580"></a>
-<span class="sourceLineNo">581</span>   * @param path the path or URI<a name="line.581"></a>
-<span class="sourceLineNo">582</span>   * @param contentType the content MIME type<a name="line.582"></a>
-<span class="sourceLineNo">583</span>   * @param content the content bytes<a name="line.583"></a>
-<span class="sourceLineNo">584</span>   * @param extraHdr extra Header to send<a name="line.584"></a>
-<span class="sourceLineNo">585</span>   * @return a Response object with response detail<a name="line.585"></a>
-<span class="sourceLineNo">586</span>   * @throws IOException<a name="line.586"></a>
-<span class="sourceLineNo">587</span>   */<a name="line.587"></a>
-<span class="sourceLineNo">588</span>  public Response put(String path, String contentType, byte[] content, Header extraHdr)<a name="line.588"></a>
-<span class="sourceLineNo">589</span>      throws IOException {<a name="line.589"></a>
-<span class="sourceLineNo">590</span>    return put(cluster, path, contentType, content, extraHdr);<a name="line.590"></a>
-<span class="sourceLineNo">591</span>  }<a name="line.591"></a>
-<span class="sourceLineNo">592</span><a name="line.592"></a>
-<span class="sourceLineNo">593</span>  /**<a name="line.593"></a>
-<span class="sourceLineNo">594</span>   * Send a PUT request<a name="line.594"></a>
-<span class="sourceLineNo">595</span>   * @param cluster the cluster definition<a name="line.595"></a>
-<span class="sourceLineNo">596</span>   * @param path the path or URI<a name="line.596"></a>
-<span class="sourceLineNo">597</span>   * @param contentType the content MIME type<a name="line.597"></a>
-<span class="sourceLineNo">598</span>   * @param content the content bytes<a name="line.598"></a>
-<span class="sourceLineNo">599</span>   * @return a Response object with response detail<a name="line.599"></a>
-<span class="sourceLineNo">600</span>   * @throws IOException for error<a name="line.600"></a>
-<span class="sourceLineNo">601</span>   */<a name="line.601"></a>
-<span class="sourceLineNo">602</span>  public Response put(Cluster cluster, String path, String contentType,<a name="line.602"></a>
-<span class="sourceLineNo">603</span>      byte[] content) throws IOException {<a name="line.603"></a>
-<span class="sourceLineNo">604</span>    Header[] headers = new Header[1];<a name="line.604"></a>
-<span class="sourceLineNo">605</span>    headers[0] = new BasicHeader("Content-Type", contentType);<a name="line.605"></a>
-<span class="sourceLineNo">606</span>    return put(cluster, path, headers, content);<a name="line.606"></a>
-<span class="sourceLineNo">607</span>  }<a name="line.607"></a>
-<span class="sourceLineNo">608</span><a name="line.608"></a>
-<span class="sourceLineNo">609</span>  /**<a name="line.609"></a>
-<span class="sourceLineNo">610</span>   * Send a PUT request<a name="line.610"></a>
-<span class="sourceLineNo">611</span>   * @param cluster the cluster definition<a name="line.611"></a>
-<span class="sourceLineNo">612</span>   * @param path the path or URI<a name="line.612"></a>
-<span class="sourceLineNo">613</span>   * @param contentType the content MIME type<a name="line.613"></a>
-<span class="sourceLineNo">614</span>   * @param content the content bytes<a name="line.614"></a>
-<span class="sourceLineNo">615</span>   * @param extraHdr additional Header to send<a name="line.615"></a>
-<span class="sourceLineNo">616</span>   * @return a Response object with response detail<a name="line.616"></a>
-<span class="sourceLineNo">617</span>   * @throws IOException for error<a name="line.617"></a>
-<span class="sourceLineNo">618</span>   */<a name="line.618"></a>
-<span class="sourceLineNo">619</span>  public Response put(Cluster cluster, String path, String contentType,<a name="line.619"></a>
-<span class="sourceLineNo">620</span>      byte[] content, Header extraHdr) throws IOException {<a name="line.620"></a>
-<span class="sourceLineNo">621</span>    int cnt = extraHdr == null ? 1 : 2;<a name="line.621"></a>
-<span class="sourceLineNo">622</span>    Header[] headers = new Header[cnt];<a name="line.622"></a>
-<span class="sourceLineNo">623</span>    headers[0] = new BasicHeader("Content-Type", contentType);<a name="line.623"></a>
-<span class="sourceLineNo">624</span>    if (extraHdr != null) {<a name="line.624"></a>
-<span class="sourceLineNo">625</span>      headers[1] = extraHdr;<a name="line.625"></a>
-<span class="sourceLineNo">626</span>    }<a name="line.626"></a>
-<span class="sourceLineNo">627</span>    return put(cluster, path, headers, content);<a name="line.627"></a>
-<span class="sourceLineNo">628</span>  }<a name="line.628"></a>
-<span class="sourceLineNo">629</span><a name="line.629"></a>
-<span class="sourceLineNo">630</span>  /**<a name="line.630"></a>
-<span class="sourceLineNo">631</span>   * Send a PUT request<a name="line.631"></a>
-<span class="sourceLineNo">632</span>   * @param path the path or URI<a name="line.632"></a>
-<span class="sourceLineNo">633</span>   * @param headers the HTTP headers to include, &lt;tt&gt;Content-Type&lt;/tt&gt; must be<a name="line.633"></a>
-<span class="sourceLineNo">634</span>   * supplied<a name="line.634"></a>
-<span class="sourceLineNo">635</span>   * @param content the content bytes<a name="line.635"></a>
-<span class="sourceLineNo">636</span>   * @return a Response object with response detail<a name="line.636"></a>
-<span class="sourceLineNo">637</span>   * @throws IOException<a name="line.637"></a>
-<span class="sourceLineNo">638</span>   */<a name="line.638"></a>
-<span class="sourceLineNo">639</span>  public Response put(String path, Header[] headers, byte[] content)<a name="line.639"></a>
-<span class="sourceLineNo">640</span>      throws IOException {<a name="line.640"></a>
-<span class="sourceLineNo">641</span>    return put(cluster, path, headers, content);<a name="line.641"></a>
-<span class="sourceLineNo">642</span>  }<a name="line.642"></a>
-<span class="sourceLineNo">643</span><a name="line.643"></a>
-<span class="sourceLineNo">644</span>  /**<a name="line.644"></a>
-<span class="sourceLineNo">645</span>   * Send a PUT request<a name="line.645"></a>
-<span class="sourceLineNo">646</span>   * @param cluster the cluster definition<a name="line.646"></a>
-<span class="sourceLineNo">647</span>   * @param path the path or URI<a name="line.647"></a>
-<span class="sourceLineNo">648</span>   * @param headers the HTTP headers to include, &lt;tt&gt;Content-Type&lt;/tt&gt; must be<a name="line.648"></a>
-<span class="sourceLineNo">649</span>   * supplied<a name="line.649"></a>
-<span class="sourceLineNo">650</span>   * @param content the content bytes<a name="line.650"></a>
-<span class="sourceLineNo">651</span>   * @return a Response object with response detail<a name="line.651"></a>
-<span class="sourceLineNo">652</span>   * @throws IOException<a name="line.652"></a>
-<span class="sourceLineNo">653</span>   */<a name="line.653"></a>
-<span class="sourceLineNo">654</span>  public Response put(Cluster cluster, String path, Header[] headers,<a name="line.654"></a>
-<span class="sourceLineNo">655</span>      byte[] content) throws IOException {<a name="line.655"></a>
-<span class="sourceLineNo">656</span>    HttpPut method = new HttpPut(path);<a name="line.656"></a>
-<span class="sourceLineNo">657</span>    try {<a name="line.657"></a>
-<span class="sourceLineNo">658</span>      method.setEntity(new InputStreamEntity(new ByteArrayInputStream(content), content.length));<a name="line.658"></a>
-<span class="sourceLineNo">659</span>      HttpResponse resp = execute(cluster, method, headers, path);<a name="line.659"></a>
-<span class="sourceLineNo">660</span>      headers = resp.getAllHeaders();<a name="line.660"></a>
-<span class="sourceLineNo">661</span>      content = getResponseBody(resp);<a name="line.661"></a>
-<span class="sourceLineNo">662</span>      return new Response(resp.getStatusLine().getStatusCode(), headers, content);<a name="line.662"></a>
-<span class="sourceLineNo">663</span>    } finally {<a name="line.663"></a>
-<span class="sourceLineNo">664</span>      method.releaseConnection();<a name="line.664"></a>
-<span class="sourceLineNo">665</span>    }<a name="line.665"></a>
-<span class="sourceLineNo">666</span>  }<a name="line.666"></a>
-<span class="sourceLineNo">667</span><a name="line.667"></a>
-<span class="sourceLineNo">668</span>  /**<a name="line.668"></a>
-<span class="sourceLineNo">669</span>   * Send a POST request<a name="line.669"></a>
-<span class="sourceLineNo">670</span>   * @param path the path or URI<a name="line.670"></a>
-<span class="sourceLineNo">671</span>   * @param contentType the content MIME type<a name="line.671"></a>
-<span class="sourceLineNo">672</span>   * @param content the content bytes<a name="line.672"></a>
-<span class="sourceLineNo">673</span>   * @return a Response object with response detail<a name="line.673"></a>
-<span class="sourceLineNo">674</span>   * @throws IOException<a name="line.674"></a>
-<span class="sourceLineNo">675</span>   */<a name="line.675"></a>
-<span class="sourceLineNo">676</span>  public Response post(String path, String contentType, byte[] content)<a name="line.676"></a>
-<span class="sourceLineNo">677</span>      throws IOException {<a name="line.677"></a>
-<span class="sourceLineNo">678</span>    return post(cluster, path, contentType, content);<a name="line.678"></a>
-<span class="sourceLineNo">679</span>  }<a name="line.679"></a>
-<span class="sourceLineNo">680</span><a name="line.680"></a>
-<span class="sourceLineNo">681</span>  /**<a name="line.681"></a>
-<span class="sourceLineNo">682</span>   * Send a POST request<a name="line.682"></a>
-<span class="sourceLineNo">683</span>   * @param path the path or URI<a name="line.683"></a>
-<span class="sourceLineNo">684</span>   * @param contentType the content MIME type<a name="line.684"></a>
-<span class="sourceLineNo">685</span>   * @param content the content bytes<a name="line.685"></a>
-<span class="sourceLineNo">686</span>   * @param extraHdr additional Header to send<a name="line.686"></a>
-<span class="sourceLineNo">687</span>   * @return a Response object with response detail<a name="line.687"></a>
-<span class="sourceLineNo">688</span>   * @throws IOException<a name="line.688"></a>
-<span class="sourceLineNo">689</span>   */<a name="line.689"></a>
-<span class="sourceLineNo">690</span>  public Response post(String path, String contentType, byte[] content, Header extraHdr)<a name="line.690"></a>
-<span class="sourceLineNo">691</span>      throws IOException {<a name="line.691"></a>
-<span class="sourceLineNo">692</span>    return post(cluster, path, contentType, content, extraHdr);<a name="line.692"></a>
-<span class="sourceLineNo">693</span>  }<a name="line.693"></a>
-<span class="sourceLineNo">694</span><a name="line.694"></a>
-<span class="sourceLineNo">695</span>  /**<a name="line.695"></a>
-<span class="sourceLineNo">696</span>   * Send a POST request<a name="line.696"></a>
-<span class="sourceLineNo">697</span>   * @param cluster the cluster definition<a name="line.697"></a>
-<span class="sourceLineNo">698</span>   * @param path the path or URI<a name="line.698"></a>
-<span class="sourceLineNo">699</span>   * @param contentType the content MIME type<a name="line.699"></a>
-<span class="sourceLineNo">700</span>   * @param content the content bytes<a name="line.700"></a>
-<span class="sourceLineNo">701</span>   * @return a Response object with response detail<a name="line.701"></a>
-<span class="sourceLineNo">702</span>   * @throws IOException for error<a name="line.702"></a>
-<span class="sourceLineNo">703</span>   */<a name="line.703"></a>
-<span class="sourceLineNo">704</span>  public Response post(Cluster cluster, String path, String contentType,<a name="line.704"></a>
-<span class="sourceLineNo">705</span>      byte[] content) throws IOException {<a name="line.705"></a>
-<span class="sourceLineNo">706</span>    Header[] headers = new Header[1];<a name="line.706"></a>
-<span class="sourceLineNo">707</span>    headers[0] = new BasicHeader("Content-Type", contentType);<a name="line.707"></a>
-<span class="sourceLineNo">708</span>    return post(cluster, path, headers, content);<a name="line.708"></a>
-<span class="sourceLineNo">709</span>  }<a name="line.709"></a>
-<span class="sourceLineNo">710</span><a name="line.710"></a>
-<span class="sourceLineNo">711</span>  /**<a name="line.711"></a>
-<span class="sourceLineNo">712</span>   * Send a POST request<a name="line.712"></a>
-<span class="sourceLineNo">713</span>   * @param cluster the cluster definition<a name="line.713"></a>
-<span class="sourceLineNo">714</span>   * @param path the path or URI<a name="line.714"></a>
-<span class="sourceLineNo">715</span>   * @param contentType the content MIME type<a name="line.715"></a>
-<span class="sourceLineNo">716</span>   * @param content the content bytes<a name="line.716"></a>
-<span class="sourceLineNo">717</span>   * @param extraHdr additional Header to send<a name="line.717"></a>
-<span class="sourceLineNo">718</span>   * @return a Response object with response detail<a name="line.718"></a>
-<span class="sourceLineNo">719</span>   * @throws IOException for error<a name="line.719"></a>
-<span class="sourceLineNo">720</span>   */<a name="line.720"></a>
-<span class="sourceLineNo">721</span>  public Response post(Cluster cluster, String path, String contentType,<a name="line.721"></a>
-<span class="sourceLineNo">722</span>      byte[] content, Header extraHdr) throws IOException {<a name="line.722"></a>
-<span class="sourceLineNo">723</span>    int cnt = extraHdr == null ? 1 : 2;<a name="line.723"></a>
-<span class="sourceLineNo">724</span>    Header[] headers = new Header[cnt];<a name="line.724"></a>
-<span class="sourceLineNo">725</span>    headers[0] = new BasicHeader("Content-Type", contentType);<a name="line.725"></a>
-<span class="sourceLineNo">726</span>    if (extraHdr != null) {<a name="line.726"></a>
-<span class="sourceLineNo">727</span>      headers[1] = extraHdr;<a name="line.727"></a>
-<span class="sourceLineNo">728</span>    }<a name="line.728"></a>
-<span class="sourceLineNo">729</span>    return post(cluster, path, headers, content);<a name="line.729"></a>
-<span class="sourceLineNo">730</span>  }<a name="line.730"></a>
-<span class="sourceLineNo">731</span><a name="line.731"></a>
-<span class="sourceLineNo">732</span>  /**<a name="line.732"></a>
-<span class="sourceLineNo">733</span>   * Send a POST request<a name="line.733"></a>
-<span class="sourceLineNo">734</span>   * @param path the path or URI<a name="line.734"></a>
-<span class="sourceLineNo">735</span>   * @param headers the HTTP headers to include, &lt;tt&gt;Content-Type&lt;/tt&gt; must be<a name="line.735"></a>
-<span class="sourceLineNo">736</span>   * supplied<a name="line.736"></a>
-<span class="sourceLineNo">737</span>   * @param content the content bytes<a name="line.737"></a>
-<span class="sourceLineNo">738</span>   * @return a Response object with response detail<a name="line.738"></a>
-<span class="sourceLineNo">739</span>   * @throws IOException<a name="line.739"></a>
-<span class="sourceLineNo">740</span>   */<a name="line.740"></a>
-<span class="sourceLineNo">741</span>  public Response post(String path, Header[] headers, byte[] content)<a name="line.741"></a>
-<span class="sourceLineNo">742</span>      throws IOException {<a name="line.742"></a>
-<span class="sourceLineNo">743</span>    return post(cluster, path, headers, content);<a name="line.743"></a>
-<span class="sourceLineNo">744</span>  }<a name="line.744"></a>
-<span class="sourceLineNo">745</span><a name="line.745"></a>
-<span class="sourceLineNo">746</span>  /**<a name="line.746"></a>
-<span class="sourceLineNo">747</span>   * Send a POST request<a name="line.747"></a>
-<span class="sourceLineNo">748</span>   * @param cluster the cluster definition<a name="line.748"></a>
-<span class="sourceLineNo">749</span>   * @param path the path or URI<a name="line.749"></a>
-<span class="sourceLineNo">750</span>   * @param headers the HTTP headers to include, &lt;tt&gt;Content-Type&lt;/tt&gt; must be<a name="line.750"></a>
-<span class="sourceLineNo">751</span>   * supplied<a name="line.751"></a>
-<span class="sourceLineNo">752</span>   * @param content the content bytes<a name="line.752"></a>
-<span class="sourceLineNo">753</span>   * @return a Response object with response detail<a name="line.753"></a>
-<span class="sourceLineNo">754</span>   * @throws IOException<a name="line.754"></a>
-<span class="sourceLineNo">755</span>   */<a name="line.755"></a>
-<span class="sourceLineNo">756</span>  public Response post(Cluster cluster, String path, Header[] headers,<a name="line.756"></a>
-<span class="sourceLineNo">757</span>      byte[] content) throws IOException {<a name="line.757"></a>
-<span class="sourceLineNo">758</span>    HttpPost method = new HttpPost(path);<a name="line.758"></a>
-<span class="sourceLineNo">759</span>    try {<a name="line.759"></a>
-<span class="sourceLineNo">760</span>      method.setEntity(new InputStreamEntity(new ByteArrayInputStream(content), content.length));<a name="line.760"></a>
-<span class="sourceLineNo">761</span>      HttpResponse resp = execute(cluster, method, headers, path);<a name="line.761"></a>
-<span class="sourceLineNo">762</span>      headers = resp.getAllHeaders();<a name="line.762"></a>
-<span class="sourceLineNo">763</span>      content = getResponseBody(resp);<a name="line.763"></a>
-<span class="sourceLineNo">764</span>      return new Response(resp.getStatusLine().getStatusCode(), headers, content);<a name="line.764"></a>
-<span class="sourceLineNo">765</span>    } finally {<a name="line.765"></a>
-<span class="sourceLineNo">766</span>      method.releaseConnection();<a name="line.766"></a>
-<span class="sourceLineNo">767</span>    }<a name="line.767"></a>
-<span class="sourceLineNo">768</span>  }<a name="line.768"></a>
-<span class="sourceLineNo">769</span><a name="line.769"></a>
-<span class="sourceLineNo">770</span>  /**<a name="line.770"></a>
-<span class="sourceLineNo">771</span>   * Send a DELETE request<a name="line.771"></a>
-<span class="sourceLineNo">772</span>   * @param path the path or URI<a name="line.772"></a>
-<span class="sourceLineNo">773</span>   * @return a Response object with response detail<a name="line.773"></a>
-<span class="sourceLineNo">774</span>   * @throws IOException<a name="line.774"></a>
-<span class="sourceLineNo">775</span>   */<a name="line.775"></a>
-<span class="sourceLineNo">776</span>  public Response delete(String path) throws IOException {<a name="line.776"></a>
-<span class="sourceLineNo">777</span>    return delete(cluster, path);<a name="line.777"></a>
-<span class="sourceLineNo">778</span>  }<a name="line.778"></a>
-<span class="sourceLineNo">779</span><a name="line.779"></a>
-<span class="sourceLineNo">780</span>  /**<a name="line.780"></a>
-<span class="sourceLineNo">781</span>   * Send a DELETE request<a name="line.781"></a>
-<span class="sourceLineNo">782</span>   * @param path the path or URI<a name="line.782"></a>
-<span class="sourceLineNo">783</span>   * @param extraHdr additional Header to send<a name="line.783"></a>
-<span class="sourceLineNo">784</span>   * @return a Response object with response detail<a name="line.784"></a>
-<span class="sourceLineNo">785</span>   * @throws IOException<a name="line.785"></a>
-<span class="sourceLineNo">786</span>   */<a name="line.786"></a>
-<span class="sourceLineNo">787</span>  public Response delete(String path, Header extraHdr) throws IOException {<a name="line.787"></a>
-<span class="sourceLineNo">788</span>    return delete(cluster, path, extraHdr);<a name="line.788"></a>
-<span class="sourceLineNo">789</span>  }<a name="line.789"></a>
-<span class="sourceLineNo">790</span><a name="line.790"></a>
-<span class="sourceLineNo">791</span>  /**<a name="line.791"></a>
-<span class="sourceLineNo">792</span>   * Send a DELETE request<a name="line.792"></a>
-<span class="sourceLineNo">793</span>   * @param cluster the cluster definition<a name="line.793"></a>
-<span class="sourceLineNo">794</span>   * @param path the path or URI<a name="line.794"></a>
-<span class="sourceLineNo">795</span>   * @return a Response object with response detail<a name="line.795"></a>
-<span class="sourceLineNo">796</span>   * @throws IOException for error<a name="line.796"></a>
-<span class="sourceLineNo">797</span>   */<a name="line.797"></a>
-<span class="sourceLineNo">798</span>  public Response delete(Cluster cluster, String path) throws IOException {<a name="line.798"></a>
-<span class="sourceLineNo">799</span>    HttpDelete method = new HttpDelete(path);<a name="line.799"></a>
-<span class="sourceLineNo">800</span>    try {<a name="line.800"></a>
-<span class="sourceLineNo">801</span>      HttpResponse resp = execute(cluster, method, null, path);<a name="line.801"></a>
-<span class="sourceLineNo">802</span>      Header[] headers = resp.getAllHeaders();<a name="line.802"></a>
-<span class="sourceLineNo">803</span>      byte[] content = getResponseBody(resp);<a name="line.803"></a>
-<span class="sourceLineNo">804</span>      return new Response(resp.getStatusLine().getStatusCode(), headers, content);<a name="line.804"></a>
-<span class="sourceLineNo">805</span>    } finally {<a name="line.805"></a>
-<span class="sourceLineNo">806</span>      method.releaseConnection();<a name="line.806"></a>
-<span class="sourceLineNo">807</span>    }<a name="line.807"></a>
-<span class="sourceLineNo">808</span>  }<a name="line.808"></a>
-<span class="sourceLineNo">809</span><a name="line.809"></a>
-<span class="sourceLineNo">810</span>  /**<a name="line.810"></a>
-<span class="sourceLineNo">811</span>   * Send a DELETE request<a name="line.811"></a>
-<span class="sourceLineNo">812</span>   * @param cluster the cluster definition<a name="line.812"></a>
-<span class="sourceLineNo">813</span>   * @param path the path or URI<a name="line.813"></a>
-<span class="sourceLineNo">814</span>   * @return a Response object with response detail<a name="line.814"></a>
-<span class="sourceLineNo">815</span>   * @throws IOException for error<a name="line.815"></a>
-<span class="sourceLineNo">816</span>   */<a name="line.816"></a>
-<span class="sourceLineNo">817</span>  public Response delete(Cluster cluster, String path, Header extraHdr) throws IOException {<a name="line.817"></a>
-<span class="sourceLineNo">818</span>    HttpDelete method = new HttpDelete(path);<a name="line.818"></a>
-<span class="sourceLineNo">819</span>    try {<a name="line.819"></a>
-<span class="sourceLineNo">820</span>      Header[] headers = { extraHdr };<a name="line.820"></a>
-<span class="sourceLineNo">821</span>      HttpResponse resp = execute(cluster, method, headers, path);<a name="line.821"></a>
-<span class="sourceLineNo">822</span>      headers = resp.getAllHeaders();<a name="line.822"></a>
-<span class="sourceLineNo">823</span>      byte[] content = getResponseBody(resp);<a name="line.823"></a>
-<span class="sourceLineNo">824</span>      return new Response(resp.getStatusLine().getStatusCode(), headers, content);<a name="line.824"></a>
-<span class="sourceLineNo">825</span>    } finally {<a name="line.825"></a>
-<span class="sourceLineNo">826</span>      method.releaseConnection();<a name="line.826"></a>
-<span class="sourceLineNo">827</span>    }<a name="line.827"></a>
-<span class="sourceLineNo">828</span>  }<a name="line.828"></a>
-<span class="sourceLineNo">829</span><a name="line.829"></a>
+<span class="sourceLineNo">047</span>import org.apache.hadoop.hbase.util.EnvironmentEdgeManager;<a name="line.47"></a>
+<span class="sourceLineNo">048</span>import org.apache.hadoop.security.authentication.client.AuthenticatedURL;<a name="line.48"></a>
+<span class="sourceLineNo">049</span>import org.apache.hadoop.security.authentication.client.AuthenticationException;<a name="line.49"></a>
+<span class="sourceLineNo">050</span>import org.apache.hadoop.security.authentication.client.KerberosAuthenticator;<a name="line.50"></a>
+<span class="sourceLineNo">051</span>import org.apache.http.Header;<a name="line.51"></a>
+<span class="sourceLineNo">052</span>import org.apache.http.HttpResponse;<a name="line.52"></a>
+<span class="sourceLineNo">053</span>import org.apache.http.HttpStatus;<a name="line.53"></a>
+<span class="sourceLineNo">054</span>import org.apache.http.client.HttpClient;<a name="line.54"></a>
+<span class="sourceLineNo">055</span>import org.apache.http.client.config.RequestConfig;<a name="line.55"></a>
+<span class="sourceLineNo">056</span>import org.apache.http.client.methods.HttpDelete;<a name="line.56"></a>
+<span class="sourceLineNo">057</span>import org.apache.http.client.methods.HttpGet;<a name="line.57"></a>
+<span class="sourceLineNo">058</span>import org.apache.http.client.methods.HttpHead;<a name="line.58"></a>
+<span class="sourceLineNo">059</span>import org.apache.http.client.methods.HttpPost;<a name="line.59"></a>
+<span class="sourceLineNo">060</span>import org.apache.http.client.methods.HttpPut;<a name="line.60"></a>
+<span class="sourceLineNo">061</span>import org.apache.http.client.methods.HttpUriRequest;<a name="line.61"></a>
+<span class="sourceLineNo">062</span>import org.apache.http.entity.InputStreamEntity;<a name="line.62"></a>
+<span class="sourceLineNo">063</span>import org.apache.http.impl.client.HttpClientBuilder;<a name="line.63"></a>
+<span class="sourceLineNo">064</span>import org.apache.http.impl.client.HttpClients;<a name="line.64"></a>
+<span class="sourceLineNo">065</span>import org.apache.http.message.BasicHeader;<a name="line.65"></a>
+<span class="sourceLineNo">066</span>import org.apache.http.ssl.SSLContexts;<a name="line.66"></a>
+<span class="sourceLineNo">067</span>import org.apache.http.util.EntityUtils;<a name="line.67"></a>
+<span class="sourceLineNo">068</span>import org.apache.yetus.audience.InterfaceAudience;<a name="line.68"></a>
+<span class="sourceLineNo">069</span>import org.slf4j.Logger;<a name="line.69"></a>
+<span class="sourceLineNo">070</span>import org.slf4j.LoggerFactory;<a name="line.70"></a>
+<span class="sourceLineNo">071</span><a name="line.71"></a>
+<span class="sourceLineNo">072</span>/**<a name="line.72"></a>
+<span class="sourceLineNo">073</span> * A wrapper around HttpClient which provides some useful function and<a name="line.73"></a>
+<span class="sourceLineNo">074</span> * semantics for interacting with the REST gateway.<a name="line.74"></a>
+<span class="sourceLineNo">075</span> */<a name="line.75"></a>
+<span class="sourceLineNo">076</span>@InterfaceAudience.Public<a name="line.76"></a>
+<span class="sourceLineNo">077</span>public class Client {<a name="line.77"></a>
+<span class="sourceLineNo">078</span>  public static final Header[] EMPTY_HEADER_ARRAY = new Header[0];<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(Client.class);<a name="line.80"></a>
+<span class="sourceLineNo">081</span><a name="line.81"></a>
+<span class="sourceLineNo">082</span>  private HttpClient httpClient;<a name="line.82"></a>
+<span class="sourceLineNo">083</span>  private Cluster cluster;<a name="line.83"></a>
+<span class="sourceLineNo">084</span>  private Configuration conf;<a name="line.84"></a>
+<span class="sourceLineNo">085</span>  private boolean sslEnabled;<a name="line.85"></a>
+<span class="sourceLineNo">086</span>  private HttpResponse resp;<a name="line.86"></a>
+<span class="sourceLineNo">087</span>  private HttpGet httpGet = null;<a name="line.87"></a>
+<span class="sourceLineNo">088</span><a name="line.88"></a>
+<span class="sourceLineNo">089</span>  private Map&lt;String, String&gt; extraHeaders;<a name="line.89"></a>
+<span class="sourceLineNo">090</span><a name="line.90"></a>
+<span class="sourceLineNo">091</span>  private static final String AUTH_COOKIE = "hadoop.auth";<a name="line.91"></a>
+<span class="sourceLineNo">092</span>  private static final String AUTH_COOKIE_EQ = AUTH_COOKIE + "=";<a name="line.92"></a>
+<span class="sourceLineNo">093</span>  private static final String COOKIE = "Cookie";<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>   * Default Constructor<a name="line.96"></a>
+<span class="sourceLineNo">097</span>   */<a name="line.97"></a>
+<span class="sourceLineNo">098</span>  public Client() {<a name="line.98"></a>
+<span class="sourceLineNo">099</span>    this(null);<a name="line.99"></a>
+<span class="sourceLineNo">100</span>  }<a name="line.100"></a>
+<span class="sourceLineNo">101</span><a name="line.101"></a>
+<span class="sourceLineNo">102</span>  private void initialize(Cluster cluster, Configuration conf, boolean sslEnabled,<a name="line.102"></a>
+<span class="sourceLineNo">103</span>      Optional&lt;KeyStore&gt; trustStore) {<a name="line.103"></a>
+<span class="sourceLineNo">104</span>    this.cluster = cluster;<a name="line.104"></a>
+<span class="sourceLineNo">105</span>    this.conf = conf;<a name="line.105"></a>
+<span class="sourceLineNo">106</span>    this.sslEnabled = sslEnabled;<a name="line.106"></a>
+<span class="sourceLineNo">107</span>    extraHeaders = new ConcurrentHashMap&lt;&gt;();<a name="line.107"></a>
+<span class="sourceLineNo">108</span>    String clspath = System.getProperty("java.class.path");<a name="line.108"></a>
+<span class="sourceLineNo">109</span>    LOG.debug("classpath " + clspath);<a name="line.109"></a>
+<span class="sourceLineNo">110</span>    HttpClientBuilder httpClientBuilder = HttpClients.custom();<a name="line.110"></a>
+<span class="sourceLineNo">111</span><a name="line.111"></a>
+<span class="sourceLineNo">112</span>    int connTimeout = this.conf.getInt(Constants.REST_CLIENT_CONN_TIMEOUT,<a name="line.112"></a>
+<span class="sourceLineNo">113</span>      Constants.DEFAULT_REST_CLIENT_CONN_TIMEOUT);<a name="line.113"></a>
+<span class="sourceLineNo">114</span>    int socketTimeout = this.conf.getInt(Constants.REST_CLIENT_SOCKET_TIMEOUT,<a name="line.114"></a>
+<span class="sourceLineNo">115</span>      Constants.DEFAULT_REST_CLIENT_SOCKET_TIMEOUT);<a name="line.115"></a>
+<span class="sourceLineNo">116</span>    RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(connTimeout)<a name="line.116"></a>
+<span class="sourceLineNo">117</span>        .setSocketTimeout(socketTimeout).build();<a name="line.117"></a>
+<span class="sourceLineNo">118</span>    httpClientBuilder.setDefaultRequestConfig(requestConfig);<a name="line.118"></a>
+<span class="sourceLineNo">119</span><a name="line.119"></a>
+<span class="sourceLineNo">120</span>    // Since HBASE-25267 we don't use the deprecated DefaultHttpClient anymore.<a name="line.120"></a>
+<span class="sourceLineNo">121</span>    // The new http client would decompress the gzip content automatically.<a name="line.121"></a>
+<span class="sourceLineNo">122</span>    // In order to keep the original behaviour of this public class, we disable<a name="line.122"></a>
+<span class="sourceLineNo">123</span>    // automatic content compression.<a name="line.123"></a>
+<span class="sourceLineNo">124</span>    httpClientBuilder.disableContentCompression();<a name="line.124"></a>
+<span class="sourceLineNo">125</span><a name="line.125"></a>
+<span class="sourceLineNo">126</span>    if(sslEnabled &amp;&amp; trustStore.isPresent()) {<a name="line.126"></a>
+<span class="sourceLineNo">127</span>      try {<a name="line.127"></a>
+<span class="sourceLineNo">128</span>        SSLContext sslcontext =<a name="line.128"></a>
+<span class="sourceLineNo">129</span>          SSLContexts.custom().loadTrustMaterial(trustStore.get(), null).build();<a name="line.129"></a>
+<span class="sourceLineNo">130</span>        httpClientBuilder.setSSLContext(sslcontext);<a name="line.130"></a>
+<span class="sourceLineNo">131</span>      } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) {<a name="line.131"></a>
+<span class="sourceLineNo">132</span>        throw new ClientTrustStoreInitializationException("Error while processing truststore", e);<a name="line.132"></a>
+<span class="sourceLineNo">133</span>      }<a name="line.133"></a>
+<span class="sourceLineNo">134</span>    }<a name="line.134"></a>
+<span class="sourceLineNo">135</span><a name="line.135"></a>
+<span class="sourceLineNo">136</span>    this.httpClient = httpClientBuilder.build();<a name="line.136"></a>
+<span class="sourceLineNo">137</span>  }<a name="line.137"></a>
+<span class="sourceLineNo">138</span><a name="line.138"></a>
+<span class="sourceLineNo">139</span>  /**<a name="line.139"></a>
+<span class="sourceLineNo">140</span>   * Constructor<a name="line.140"></a>
+<span class="sourceLineNo">141</span>   * @param cluster the cluster definition<a name="line.141"></a>
+<span class="sourceLineNo">142</span>   */<a name="line.142"></a>
+<span class="sourceLineNo">143</span>  public Client(Cluster cluster) {<a name="line.143"></a>
+<span class="sourceLineNo">144</span>    this(cluster, false);<a name="line.144"></a>
+<span class="sourceLineNo">145</span>  }<a name="line.145"></a>
+<span class="sourceLineNo">146</span><a name="line.146"></a>
+<span class="sourceLineNo">147</span>  /**<a name="line.147"></a>
+<span class="sourceLineNo">148</span>   * Constructor<a name="line.148"></a>
+<span class="sourceLineNo">149</span>   * @param cluster the cluster definition<a name="line.149"></a>
+<span class="sourceLineNo">150</span>   * @param sslEnabled enable SSL or not<a name="line.150"></a>
+<span class="sourceLineNo">151</span>   */<a name="line.151"></a>
+<span class="sourceLineNo">152</span>  public Client(Cluster cluster, boolean sslEnabled) {<a name="line.152"></a>
+<span class="sourceLineNo">153</span>    initialize(cluster, HBaseConfiguration.create(), sslEnabled, Optional.empty());<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>   * Constructor<a name="line.157"></a>
+<span class="sourceLineNo">158</span>   * @param cluster the cluster definition<a name="line.158"></a>
+<span class="sourceLineNo">159</span>   * @param conf Configuration<a name="line.159"></a>
+<span class="sourceLineNo">160</span>   * @param sslEnabled enable SSL or not<a name="line.160"></a>
+<span class="sourceLineNo">161</span>   */<a name="line.161"></a>
+<span class="sourceLineNo">162</span>  public Client(Cluster cluster, Configuration conf, boolean sslEnabled) {<a name="line.162"></a>
+<span class="sourceLineNo">163</span>    initialize(cluster, conf, sslEnabled, Optional.empty());<a name="line.163"></a>
+<span class="sourceLineNo">164</span>  }<a name="line.164"></a>
+<span class="sourceLineNo">165</span><a name="line.165"></a>
+<span class="sourceLineNo">166</span>  /**<a name="line.166"></a>
+<span class="sourceLineNo">167</span>   * Constructor, allowing to define custom trust store (only for SSL connections)<a name="line.167"></a>
+<span class="sourceLineNo">168</span>   *<a name="line.168"></a>
+<span class="sourceLineNo">169</span>   * @param cluster the cluster definition<a name="line.169"></a>
+<span class="sourceLineNo">170</span>   * @param trustStorePath custom trust store to use for SSL connections<a name="line.170"></a>
+<span class="sourceLineNo">171</span>   * @param trustStorePassword password to use for custom trust store<a name="line.171"></a>
+<span class="sourceLineNo">172</span>   * @param trustStoreType type of custom trust store<a name="line.172"></a>
+<span class="sourceLineNo">173</span>   *<a name="line.173"></a>
+<span class="sourceLineNo">174</span>   * @throws ClientTrustStoreInitializationException if the trust store file can not be loaded<a name="line.174"></a>
+<span class="sourceLineNo">175</span>   */<a name="line.175"></a>
+<span class="sourceLineNo">176</span>  public Client(Cluster cluster, String trustStorePath, Optional&lt;String&gt; trustStorePassword,<a name="line.176"></a>
+<span class="sourceLineNo">177</span>      Optional&lt;String&gt; trustStoreType) {<a name="line.177"></a>
+<span class="sourceLineNo">178</span>    this(cluster, HBaseConfiguration.create(), trustStorePath, trustStorePassword, trustStoreType);<a name="line.178"></a>
+<span class="sourceLineNo">179</span>  }<a name="line.179"></a>
+<span class="sourceLineNo">180</span><a name="line.180"></a>
+<span class="sourceLineNo">181</span>  /**<a name="line.181"></a>
+<span class="sourceLineNo">182</span>   * Constructor, allowing to define custom trust store (only for SSL connections)<a name="line.182"></a>
+<span class="sourceLineNo">183</span>   *<a name="line.183"></a>
+<span class="sourceLineNo">184</span>   * @param cluster the cluster definition<a name="line.184"></a>
+<span class="sourceLineNo">185</span>   * @param conf Configuration<a name="line.185"></a>
+<span class="sourceLineNo">186</span>   * @param trustStorePath custom trust store to use for SSL connections<a name="line.186"></a>
+<span class="sourceLineNo">187</span>   * @param trustStorePassword password to use for custom trust store<a name="line.187"></a>
+<span class="sourceLineNo">188</span>   * @param trustStoreType type of custom trust store<a name="line.188"></a>
+<span class="sourceLineNo">189</span>   * @throws ClientTrustStoreInitializationException if the trust store file can not be loaded<a name="line.189"></a>
+<span class="sourceLineNo">190</span>   */<a name="line.190"></a>
+<span class="sourceLineNo">191</span>  public Client(Cluster cluster, Configuration conf, String trustStorePath,<a name="line.191"></a>
+<span class="sourceLineNo">192</span>      Optional&lt;String&gt; trustStorePassword, Optional&lt;String&gt; trustStoreType) {<a name="line.192"></a>
+<span class="sourceLineNo">193</span><a name="line.193"></a>
+<span class="sourceLineNo">194</span>    char[] password = trustStorePassword.map(String::toCharArray).orElse(null);<a name="line.194"></a>
+<span class="sourceLineNo">195</span>    String type = trustStoreType.orElse(KeyStore.getDefaultType());<a name="line.195"></a>
+<span class="sourceLineNo">196</span><a name="line.196"></a>
+<span class="sourceLineNo">197</span>    KeyStore trustStore;<a name="line.197"></a>
+<span class="sourceLineNo">198</span>    try {<a name="line.198"></a>
+<span class="sourceLineNo">199</span>      trustStore = KeyStore.getInstance(type);<a name="line.199"></a>
+<span class="sourceLineNo">200</span>    } catch (KeyStoreException e) {<a name="line.200"></a>
+<span class="sourceLineNo">201</span>      throw new ClientTrustStoreInitializationException("Invalid trust store type: " + type, e);<a name="line.201"></a>
+<span class="sourceLineNo">202</span>    }<a name="line.202"></a>
+<span class="sourceLineNo">203</span>    try (InputStream inputStream = new BufferedInputStream(<a name="line.203"></a>
+<span class="sourceLineNo">204</span>      Files.newInputStream(new File(trustStorePath).toPath()))) {<a name="line.204"></a>
+<span class="sourceLineNo">205</span>      trustStore.load(inputStream, password);<a name="line.205"></a>
+<span class="sourceLineNo">206</span>    } catch (CertificateException | NoSuchAlgorithmException | IOException e) {<a name="line.206"></a>
+<span class="sourceLineNo">207</span>      throw new ClientTrustStoreInitializationException("Trust store load error: " + trustStorePath,<a name="line.207"></a>
+<span class="sourceLineNo">208</span>        e);<a name="line.208"></a>
+<span class="sourceLineNo">209</span>    }<a name="line.209"></a>
+<span class="sourceLineNo">210</span><a name="line.210"></a>
+<span class="sourceLineNo">211</span>    initialize(cluster, conf, true, Optional.of(trustStore));<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>   * Shut down the client. Close any open persistent connections.<a name="line.215"></a>
+<span class="sourceLineNo">216</span>   */<a name="line.216"></a>
+<span class="sourceLineNo">217</span>  public void shutdown() {<a name="line.217"></a>
+<span class="sourceLineNo">218</span>  }<a name="line.218"></a>
+<span class="sourceLineNo">219</span><a name="line.219"></a>
+<span class="sourceLineNo">220</span>  /**<a name="line.220"></a>
+<span class="sourceLineNo">221</span>   * @return the wrapped HttpClient<a name="line.221"></a>
+<span class="sourceLineNo">222</span>   */<a name="line.222"></a>
+<span class="sourceLineNo">223</span>  public HttpClient getHttpClient() {<a name="line.223"></a>
+<span class="sourceLineNo">224</span>    return httpClient;<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>  /**<a name="line.227"></a>
+<span class="sourceLineNo">228</span>   * Add extra headers.  These extra headers will be applied to all http<a name="line.228"></a>
+<span class="sourceLineNo">229</span>   * methods before they are removed. If any header is not used any more,<a name="line.229"></a>
+<span class="sourceLineNo">230</span>   * client needs to remove it explicitly.<a name="line.230"></a>
+<span class="sourceLineNo">231</span>   */<a name="line.231"></a>
+<span class="sourceLineNo">232</span>  public void addExtraHeader(final String name, final String value) {<a name="line.232"></a>
+<span class="sourceLineNo">233</span>    extraHeaders.put(name, value);<a name="line.233"></a>
+<span class="sourceLineNo">234</span>  }<a name="line.234"></a>
+<span class="sourceLineNo">235</span><a name="line.235"></a>
+<span class="sourceLineNo">236</span>  /**<a name="line.236"></a>
+<span class="sourceLineNo">237</span>   * Get an extra header value.<a name="line.237"></a>
+<span class="sourceLineNo">238</span>   */<a name="line.238"></a>
+<span class="sourceLineNo">239</span>  public String getExtraHeader(final String name) {<a name="line.239"></a>
+<span class="sourceLineNo">240</span>    return extraHeaders.get(name);<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>   * Get all extra headers (read-only).<a name="line.244"></a>
+<span class="sourceLineNo">245</span>   */<a name="line.245"></a>
+<span class="sourceLineNo">246</span>  public Map&lt;String, String&gt; getExtraHeaders() {<a name="line.246"></a>
+<span class="sourceLineNo">247</span>    return Collections.unmodifiableMap(extraHeaders);<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>  /**<a name="line.250"></a>
+<span class="sourceLineNo">251</span>   * Remove an extra header.<a name="line.251"></a>
+<span class="sourceLineNo">252</span>   */<a name="line.252"></a>
+<span class="sourceLineNo">253</span>  public void removeExtraHeader(final String name) {<a name="line.253"></a>
+<span class="sourceLineNo">254</span>    extraHeaders.remove(name);<a name="line.254"></a>
+<span class="sourceLineNo">255</span>  }<a name="line.255"></a>
+<span class="sourceLineNo">256</span><a name="line.256"></a>
+<span class="sourceLineNo">257</span>  /**<a name="line.257"></a>
+<span class="sourceLineNo">258</span>   * Execute a transaction method given only the path. Will select at random<a name="line.258"></a>
+<span class="sourceLineNo">259</span>   * one of the members of the supplied cluster definition and iterate through<a name="line.259"></a>
+<span class="sourceLineNo">260</span>   * the list until a transaction can be successfully completed. The<a name="line.260"></a>
+<span class="sourceLineNo">261</span>   * definition of success here is a complete HTTP transaction, irrespective<a name="line.261"></a>
+<span class="sourceLineNo">262</span>   * of result code.<a name="line.262"></a>
+<span class="sourceLineNo">263</span>   * @param cluster the cluster definition<a name="line.263"></a>
+<span class="sourceLineNo">264</span>   * @param method the transaction method<a name="line.264"></a>
+<span class="sourceLineNo">265</span>   * @param headers HTTP header values to send<a name="line.265"></a>
+<span class="sourceLineNo">266</span>   * @param path the properly urlencoded path<a name="line.266"></a>
+<span class="sourceLineNo">267</span>   * @return the HTTP response code<a name="line.267"></a>
+<span class="sourceLineNo">268</span>   * @throws IOException<a name="line.268"></a>
+<span class="sourceLineNo">269</span>   */<a name="line.269"></a>
+<span class="sourceLineNo">270</span>  public HttpResponse executePathOnly(Cluster cluster, HttpUriRequest method,<a name="line.270"></a>
+<span class="sourceLineNo">271</span>      Header[] headers, String path) throws IOException {<a name="line.271"></a>
+<span class="sourceLineNo">272</span>    IOException lastException;<a name="line.272"></a>
+<span class="sourceLineNo">273</span>    if (cluster.nodes.size() &lt; 1) {<a name="line.273"></a>
+<span class="sourceLineNo">274</span>      throw new IOException("Cluster is empty");<a name="line.274"></a>
+<span class="sourceLineNo">275</span>    }<a name="line.275"></a>
+<span class="sourceLineNo">276</span>    int start = (int)Math.round((cluster.nodes.size() - 1) * Math.random());<a name="line.276"></a>
+<span class="sourceLineNo">277</span>    int i = start;<a name="line.277"></a>
+<span class="sourceLineNo">278</span>    do {<a name="line.278"></a>
+<span class="sourceLineNo">279</span>      cluster.lastHost = cluster.nodes.get(i);<a name="line.279"></a>
+<span class="sourceLineNo">280</span>      try {<a name="line.280"></a>
+<span class="sourceLineNo">281</span>        StringBuilder sb = new StringBuilder();<a name="line.281"></a>
+<span class="sourceLineNo">282</span>        if (sslEnabled) {<a name="line.282"></a>
+<span class="sourceLineNo">283</span>          sb.append("https://");<a name="line.283"></a>
+<span class="sourceLineNo">284</span>        } else {<a name="line.284"></a>
+<span class="sourceLineNo">285</span>          sb.append("http://");<a name="line.285"></a>
+<span class="sourceLineNo">286</span>        }<a name="line.286"></a>
+<span class="sourceLineNo">287</span>        sb.append(cluster.lastHost);<a name="line.287"></a>
+<span class="sourceLineNo">288</span>        sb.append(path);<a name="line.288"></a>
+<span class="sourceLineNo">289</span>        URI uri = new URI(sb.toString());<a name="line.289"></a>
+<span class="sourceLineNo">290</span>        if (method instanceof HttpPut) {<a name="line.290"></a>
+<span class="sourceLineNo">291</span>          HttpPut put = new HttpPut(uri);<a name="line.291"></a>
+<span class="sourceLineNo">292</span>          put.setEntity(((HttpPut) method).getEntity());<a name="line.292"></a>
+<span class="sourceLineNo">293</span>          put.setHeaders(method.getAllHeaders());<a name="line.293"></a>
+<span class="sourceLineNo">294</span>          method = put;<a name="line.294"></a>
+<span class="sourceLineNo">295</span>        } else if (method instanceof HttpGet) {<a name="line.295"></a>
+<span class="sourceLineNo">296</span>          method = new HttpGet(uri);<a name="line.296"></a>
+<span class="sourceLineNo">297</span>        } else if (method instanceof HttpHead) {<a name="line.297"></a>
+<span class="sourceLineNo">298</span>          method = new HttpHead(uri);<a name="line.298"></a>
+<span class="sourceLineNo">299</span>        } else if (method instanceof HttpDelete) {<a name="line.299"></a>
+<span class="sourceLineNo">300</span>          method = new HttpDelete(uri);<a name="line.300"></a>
+<span class="sourceLineNo">301</span>        } else if (method instanceof HttpPost) {<a name="line.301"></a>
+<span class="sourceLineNo">302</span>          HttpPost post = new HttpPost(uri);<a name="line.302"></a>
+<span class="sourceLineNo">303</span>          post.setEntity(((HttpPost) method).getEntity());<a name="line.303"></a>
+<span class="sourceLineNo">304</span>          post.setHeaders(method.getAllHeaders());<a name="line.304"></a>
+<span class="sourceLineNo">305</span>          method = post;<a name="line.305"></a>
+<span class="sourceLineNo">306</span>        }<a name="line.306"></a>
+<span class="sourceLineNo">307</span>        return executeURI(method, headers, uri.toString());<a name="line.307"></a>
+<span class="sourceLineNo">308</span>      } catch (IOException e) {<a name="line.308"></a>
+<span class="sourceLineNo">309</span>        lastException = e;<a name="line.309"></a>
+<span class="sourceLineNo">310</span>      } catch (URISyntaxException use) {<a name="line.310"></a>
+<span class="sourceLineNo">311</span>        lastException = new IOException(use);<a name="line.311"></a>
+<span class="sourceLineNo">312</span>      }<a name="line.312"></a>
+<span class="sourceLineNo">313</span>    } while (++i != start &amp;&amp; i &lt; cluster.nodes.size());<a name="line.313"></a>
+<span class="sourceLineNo">314</span>    throw lastException;<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>   * Execute a transaction method given a complete URI.<a name="line.318"></a>
+<span class="sourceLineNo">319</span>   * @param method the transaction method<a name="line.319"></a>
+<span class="sourceLineNo">320</span>   * @param headers HTTP header values to send<a name="line.320"></a>
+<span class="sourceLineNo">321</span>   * @param uri a properly urlencoded URI<a name="line.321"></a>
+<span class="sourceLineNo">322</span>   * @return the HTTP response code<a name="line.322"></a>
+<span class="sourceLineNo">323</span>   * @throws IOException<a name="line.323"></a>
+<span class="sourceLineNo">324</span>   */<a name="line.324"></a>
+<span class="sourceLineNo">325</span>  public HttpResponse executeURI(HttpUriRequest method, Header[] headers, String uri)<a name="line.325"></a>
+<span class="sourceLineNo">326</span>      throws IOException {<a name="line.326"></a>
+<span class="sourceLineNo">327</span>    // method.setURI(new URI(uri, true));<a name="line.327"></a>
+<span class="sourceLineNo">328</span>    for (Map.Entry&lt;String, String&gt; e: extraHeaders.entrySet()) {<a name="line.328"></a>
+<span class="sourceLineNo">329</span>      method.addHeader(e.getKey(), e.getValue());<a name="line.329"></a>
+<span class="sourceLineNo">330</span>    }<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    if (headers != null) {<a name="line.331"></a>
+<span class="sourceLineNo">332</span>      for (Header header: headers) {<a name="line.332"></a>
+<span class="sourceLineNo">333</span>        method.addHeader(header);<a name="line.333"></a>
+<span class="sourceLineNo">334</span>      }<a name="line.334"></a>
+<span class="sourceLineNo">335</span>    }<a name="line.335"></a>
+<span class="sourceLineNo">336</span>    long startTime = EnvironmentEdgeManager.currentTime();<a name="line.336"></a>
+<span class="sourceLineNo">337</span>    if (resp != null) EntityUtils.consumeQuietly(resp.getEntity());<a name="line.337"></a>
+<span class="sourceLineNo">338</span>    resp = httpClient.execute(method);<a name="line.338"></a>
+<span class="sourceLineNo">339</span>    if (resp.getStatusLine().getStatusCode() == HttpStatus.SC_UNAUTHORIZED) {<a name="line.339"></a>
+<span class="sourceLineNo">340</span>      // Authentication error<a name="line.340"></a>
+<span class="sourceLineNo">341</span>      LOG.debug("Performing negotiation with the server.");<a name="line.341"></a>
+<span class="sourceLineNo">342</span>      negotiate(method, uri);<a name="line.342"></a>
+<span class="sourceLineNo">343</span>      resp = httpClient.execute(method);<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>    long endTime = EnvironmentEdgeManager.currentTime();<a name="line.346"></a>
+<span class="sourceLineNo">347</span>    if (LOG.isTraceEnabled()) {<a name="line.347"></a>
+<span class="sourceLineNo">348</span>      LOG.trace(method.getMethod() + " " + uri + " " + resp.getStatusLine().getStatusCode() + " " +<a name="line.348"></a>
+<span class="sourceLineNo">349</span>          resp.getStatusLine().getReasonPhrase() + " in " + (endTime - startTime) + " ms");<a name="line.349"></a>
+<span class="sourceLineNo">350</span>    }<a name="line.350"></a>
+<span class="sourceLineNo">351</span>    return resp;<a name="line.351"></a>
+<span class="sourceLineNo">352</span>  }<a name="line.352"></a>
+<span class="sourceLineNo">353</span><a name="line.353"></a>
+<span class="sourceLineNo">354</span>  /**<a name="line.354"></a>
+<span class="sourceLineNo">355</span>   * Execute a transaction method. Will call either &lt;tt&gt;executePathOnly&lt;/tt&gt;<a name="line.355"></a>
+<span class="sourceLineNo">356</span>   * or &lt;tt&gt;executeURI&lt;/tt&gt; depending on whether a path only is supplied in<a name="line.356"></a>
+<span class="sourceLineNo">357</span>   * 'path', or if a complete URI is passed instead, respectively.<a name="line.357"></a>
+<span class="sourceLineNo">358</span>   * @param cluster the cluster definition<a name="line.358"></a>
+<span class="sourceLineNo">359</span>   * @param method the HTTP method<a name="line.359"></a>
+<span class="sourceLineNo">360</span>   * @param headers HTTP header values to send<a name="line.360"></a>
+<span class="sourceLineNo">361</span>   * @param path the properly urlencoded path or URI<a name="line.361"></a>
+<span class="sourceLineNo">362</span>   * @return the HTTP response code<a name="line.362"></a>
+<span class="sourceLineNo">363</span>   * @throws IOException<a name="line.363"></a>
+<span class="sourceLineNo">364</span>   */<a name="line.364"></a>
+<span class="sourceLineNo">365</span>  public HttpResponse execute(Cluster cluster, HttpUriRequest method, Header[] headers,<a name="line.365"></a>
+<span class="sourceLineNo">366</span>      String path) throws IOException {<a name="line.366"></a>
+<span class="sourceLineNo">367</span>    if (path.startsWith("/")) {<a name="line.367"></a>
+<span class="sourceLineNo">368</span>      return executePathOnly(cluster, method, headers, path);<a name="line.368"></a>
+<span class="sourceLineNo">369</span>    }<a name="line.369"></a>
+<span class="sourceLineNo">370</span>    return executeURI(method, headers, path);<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>  /**<a name="line.373"></a>
+<span class="sourceLineNo">374</span>   * Initiate client side Kerberos negotiation with the server.<a name="line.374"></a>
+<span class="sourceLineNo">375</span>   * @param method method to inject the authentication token into.<a name="line.375"></a>
+<span class="sourceLineNo">376</span>   * @param uri the String to parse as a URL.<a name="line.376"></a>
+<span class="sourceLineNo">377</span>   * @throws IOException if unknown protocol is found.<a name="line.377"></a>
+<span class="sourceLineNo">378</span>   */<a name="line.378"></a>
+<span class="sourceLineNo">379</span>  private void negotiate(HttpUriRequest method, String uri) throws IOException {<a name="line.379"></a>
+<span class="sourceLineNo">380</span>    try {<a name="line.380"></a>
+<span class="sourceLineNo">381</span>      AuthenticatedURL.Token token = new AuthenticatedURL.Token();<a name="line.381"></a>
+<span class="sourceLineNo">382</span>      KerberosAuthenticator authenticator = new KerberosAuthenticator();<a name="line.382"></a>
+<span class="sourceLineNo">383</span>      authenticator.authenticate(new URL(uri), token);<a name="line.383"></a>
+<span class="sourceLineNo">384</span>      // Inject the obtained negotiated token in the method cookie<a name="line.384"></a>
+<span class="sourceLineNo">385</span>      injectToken(method, token);<a name="line.385"></a>
+<span class="sourceLineNo">386</span>    } catch (AuthenticationException e) {<a name="line.386"></a>
+<span class="sourceLineNo">387</span>      LOG.error("Failed to negotiate with the server.", e);<a name="line.387"></a>
+<span class="sourceLineNo">388</span>      throw new IOException(e);<a name="line.388"></a>
+<span class="sourceLineNo">389</span>    }<a name="line.389"></a>
+<span class="sourceLineNo">390</span>  }<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>   * Helper method that injects an authentication token to send with the method.<a name="line.393"></a>
+<span class="sourceLineNo">394</span>   * @param method method to inject the authentication token into.<a name="line.394"></a>
+<span class="sourceLineNo">395</span>   * @param token authentication token to inject.<a name="line.395"></a>
+<span class="sourceLineNo">396</span>   */<a name="line.396"></a>
+<span class="sourceLineNo">397</span>  private void injectToken(HttpUriRequest method, AuthenticatedURL.Token token) {<a name="line.397"></a>
+<span class="sourceLineNo">398</span>    String t = token.toString();<a name="line.398"></a>
+<span class="sourceLineNo">399</span>    if (t != null) {<a name="line.399"></a>
+<span class="sourceLineNo">400</span>      if (!t.startsWith("\"")) {<a name="line.400"></a>
+<span class="sourceLineNo">401</span>        t = "\"" + t + "\"";<a name="line.401"></a>
+<span class="sourceLineNo">402</span>      }<a name="line.402"></a>
+<span class="sourceLineNo">403</span>      method.addHeader(COOKIE, AUTH_COOKIE_EQ + t);<a name="line.403"></a>
+<span class="sourceLineNo">404</span>    }<a name="line.404"></a>
+<span class="sourceLineNo">405</span>  }<a name="line.405"></a>
+<span class="sourceLineNo">406</span><a name="line.406"></a>
+<span class="sourceLineNo">407</span>  /**<a name="line.407"></a>
+<span class="sourceLineNo">408</span>   * @return the cluster definition<a name="line.408"></a>
+<span class="sourceLineNo">409</span>   */<a name="line.409"></a>
+<span class="sourceLineNo">410</span>  public Cluster getCluster() {<a name="line.410"></a>
+<span class="sourceLineNo">411</span>    return cluster;<a name="line.411"></a>
+<span class="sourceLineNo">412</span>  }<a name="line.412"></a>
+<span class="sourceLineNo">413</span><a name="line.413"></a>
+<span class="sourceLineNo">414</span>  /**<a name="line.414"></a>
+<span class="sourceLineNo">415</span>   * @param cluster the cluster definition<a name="line.415"></a>
+<span class="sourceLineNo">416</span>   */<a name="line.416"></a>
+<span class="sourceLineNo">417</span>  public void setCluster(Cluster cluster) {<a name="line.417"></a>
+<span class="sourceLineNo">418</span>    this.cluster = cluster;<a name="line.418"></a>
+<span class="sourceLineNo">419</span>  }<a name="line.419"></a>
+<span class="sourceLineNo">420</span><a name="line.420"></a>
+<span class="sourceLineNo">421</span>  /**<a name="line.421"></a>
+<span class="sourceLineNo">422</span>   * Send a HEAD request<a name="line.422"></a>
+<span class="sourceLineNo">423</span>   * @param path the path or URI<a name="line.423"></a>
+<span class="sourceLineNo">424</span>   * @return a Response object with response detail<a name="line.424"></a>
+<span class="sourceLineNo">425</span>   * @throws IOException<a name="line.425"></a>
+<span class="sourceLineNo">426</span>   */<a name="line.426"></a>
+<span class="sourceLineNo">427</span>  public Response head(String path) throws IOException {<a name="line.427"></a>
+<span class="sourceLineNo">428</span>    return head(cluster, path, null);<a name="line.428"></a>
+<span class="sourceLineNo">429</span>  }<a name="line.429"></a>
+<span class="sourceLineNo">430</span><a name="line.430"></a>
+<span class="sourceLineNo">431</span>  /**<a name="line.431"></a>
+<span class="sourceLineNo">432</span>   * Send a HEAD request<a name="line.432"></a>
+<span class="sourceLineNo">433</span>   * @param cluster the cluster definition<a name="line.433"></a>
+<span class="sourceLineNo">434</span>   * @param path the path or URI<a name="line.434"></a>
+<span class="sourceLineNo">435</span>   * @param headers the HTTP headers to include in the request<a name="line.435"></a>
+<span class="sourceLineNo">436</span>   * @return a Response object with response detail<a name="line.436"></a>
+<span class="sourceLineNo">437</span>   * @throws IOException<a name="line.437"></a>
+<span class="sourceLineNo">438</span>   */<a name="line.438"></a>
+<span class="sourceLineNo">439</span>  public Response head(Cluster cluster, String path, Header[] headers)<a name="line.439"></a>
+<span class="sourceLineNo">440</span>      throws IOException {<a name="line.440"></a>
+<span class="sourceLineNo">441</span>    HttpHead method = new HttpHead(path);<a name="line.441"></a>
+<span class="sourceLineNo">442</span>    try {<a name="line.442"></a>
+<span class="sourceLineNo">443</span>      HttpResponse resp = execute(cluster, method, null, path);<a name="line.443"></a>
+<span class="sourceLineNo">444</span>      return new Response(resp.getStatusLine().getStatusCode(), resp.getAllHeaders(), null);<a name="line.444"></a>
+<span class="sourceLineNo">445</span>    } finally {<a name="line.445"></a>
+<span class="sourceLineNo">446</span>      method.releaseConnection();<a name="line.446"></a>
+<span class="sourceLineNo">447</span>    }<a name="line.447"></a>
+<span class="sourceLineNo">448</span>  }<a name="line.448"></a>
+<span class="sourceLineNo">449</span><a name="line.449"></a>
+<span class="sourceLineNo">450</span>  /**<a name="line.450"></a>
+<span class="sourceLineNo">451</span>   * Send a GET request<a name="line.451"></a>
+<span class="sourceLineNo">452</span>   * @param path the path or URI<a name="line.452"></a>
+<span class="sourceLineNo">453</span>   * @return a Response object with response detail<a name="line.453"></a>
+<span class="sourceLineNo">454</span>   * @throws IOException<a name="line.454"></a>
+<span class="sourceLineNo">455</span>   */<a name="line.455"></a>
+<span class="sourceLineNo">456</span>  public Response get(String path) throws IOException {<a name="line.456"></a>
+<span class="sourceLineNo">457</span>    return get(cluster, path);<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>  /**<a name="line.460"></a>
+<span class="sourceLineNo">461</span>   * Send a GET request<a name="line.461"></a>
+<span class="sourceLineNo">462</span>   * @param cluster the cluster definition<a name="line.462"></a>
+<span class="sourceLineNo">463</span>   * @param path the path or URI<a name="line.463"></a>
+<span class="sourceLineNo">464</span>   * @return a Response object with response detail<a name="line.464"></a>
+<span class="sourceLineNo">465</span>   * @throws IOException<a name="line.465"></a>
+<span class="sourceLineNo">466</span>   */<a name="line.466"></a>
+<span class="sourceLineNo">467</span>  public Response get(Cluster cluster, String path) throws IOException {<a name="line.467"></a>
+<span class="sourceLineNo">468</span>    return get(cluster, path, EMPTY_HEADER_ARRAY);<a name="line.468"></a>
+<span class="sourceLineNo">469</span>  }<a name="line.469"></a>
+<span class="sourceLineNo">470</span><a name="line.470"></a>
+<span class="sourceLineNo">471</span>  /**<a name="line.471"></a>
+<span class="sourceLineNo">472</span>   * Send a GET request<a name="line.472"></a>
+<span class="sourceLineNo">473</span>   * @param path the path or URI<a name="line.473"></a>
+<span class="sourceLineNo">474</span>   * @param accept Accept header value<a name="line.474"></a>
+<span class="sourceLineNo">475</span>   * @return a Response object with response detail<a name="line.475"></a>
+<span class="sourceLineNo">476</span>   * @throws IOException<a name="line.476"></a>
+<span class="sourceLineNo">477</span>   */<a name="line.477"></a>
+<span class="sourceLineNo">478</span>  public Response get(String path, String accept) throws IOException {<a name="line.478"></a>
+<span class="sourceLineNo">479</span>    return get(cluster, path, accept);<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>   * Send a GET request<a name="line.483"></a>
+<span class="sourceLineNo">484</span>   * @param cluster the cluster definition<a name="line.484"></a>
+<span class="sourceLineNo">485</span>   * @param path the path or URI<a name="line.485"></a>
+<span class="sourceLineNo">486</span>   * @param accept Accept header value<a name="line.486"></a>
+<span class="sourceLineNo">487</span>   * @return a Response object with response detail<a name="line.487"></a>
+<span class="sourceLineNo">488</span>   * @throws IOException<a name="line.488"></a>
+<span class="sourceLineNo">489</span>   */<a name="line.489"></a>
+<span class="sourceLineNo">490</span>  public Response get(Cluster cluster, String path, String accept)<a name="line.490"></a>
+<span class="sourceLineNo">491</span>      throws IOException {<a name="line.491"></a>
+<span class="sourceLineNo">492</span>    Header[] headers = new Header[1];<a name="line.492"></a>
+<span class="sourceLineNo">493</span>    headers[0] = new BasicHeader("Accept", accept);<a name="line.493"></a>
+<span class="sourceLineNo">494</span>    return get(cluster, path, headers);<a name="line.494"></a>
+<span class="sourceLineNo">495</span>  }<a name="line.495"></a>
+<span class="sourceLineNo">496</span><a name="line.496"></a>
+<span class="sourceLineNo">497</span>  /**<a name="line.497"></a>
+<span class="sourceLineNo">498</span>   * Send a GET request<a name="line.498"></a>
+<span class="sourceLineNo">499</span>   * @param path the path or URI<a name="line.499"></a>
+<span class="sourceLineNo">500</span>   * @param headers the HTTP headers to include in the request,<a name="line.500"></a>
+<span class="sourceLineNo">501</span>   * &lt;tt&gt;Accept&lt;/tt&gt; must be supplied<a name="line.501"></a>
+<span class="sourceLineNo">502</span>   * @return a Response object with response detail<a name="line.502"></a>
+<span class="sourceLineNo">503</span>   * @throws IOException<a name="line.503"></a>
+<span class="sourceLineNo">504</span>   */<a name="line.504"></a>
+<span class="sourceLineNo">505</span>  public Response get(String path, Header[] headers) throws IOException {<a name="line.505"></a>
+<span class="sourceLineNo">506</span>    return get(cluster, path, headers);<a name="line.506"></a>
+<span class="sourceLineNo">507</span>  }<a name="line.507"></a>
+<span class="sourceLineNo">508</span><a name="line.508"></a>
+<span class="sourceLineNo">509</span>  /**<a name="line.509"></a>
+<span class="sourceLineNo">510</span>   * Returns the response body of the HTTPResponse, if any, as an array of bytes.<a name="line.510"></a>
+<span class="sourceLineNo">511</span>   * If response body is not available or cannot be read, returns &lt;tt&gt;null&lt;/tt&gt;<a name="line.511"></a>
+<span class="sourceLineNo">512</span>   *<a name="line.512"></a>
+<span class="sourceLineNo">513</span>   * Note: This will cause the entire response body to be buffered in memory. A<a name="line.513"></a>
+<span class="sourceLineNo">514</span>   * malicious server may easily exhaust all the VM memory. It is strongly<a name="line.514"></a>
+<span class="sourceLineNo">515</span>   * recommended, to use getResponseAsStream if the content length of the response<a name="line.515"></a>
+<span class="sourceLineNo">516</span>   * is unknown or reasonably large.<a name="line.516"></a>
+<span class="sourceLineNo">517</span>   *<a name="line.517"></a>
+<span class="sourceLineNo">518</span>   * @param resp HttpResponse<a name="line.518"></a>
+<span class="sourceLineNo">519</span>   * @return The response body, null if body is empty<a name="line.519"></a>
+<span class="sourceLineNo">520</span>   * @throws IOException If an I/O (transport) problem occurs while obtaining the<a name="line.520"></a>
+<span class="sourceLineNo">521</span>   * response body.<a name="line.521"></a>
+<span class="sourceLineNo">522</span>   */<a name="line.522"></a>
+<span class="sourceLineNo">523</span>  @edu.umd.cs.findbugs.annotations.SuppressWarnings(value =<a name="line.523"></a>
+<span class="sourceLineNo">524</span>      "NP_LOAD_OF_KNOWN_NULL_VALUE", justification = "null is possible return value")<a name="line.524"></a>
+<span class="sourceLineNo">525</span>  public static byte[] getResponseBody(HttpResponse resp) throws IOException {<a name="line.525"></a>
+<span class="sourceLineNo">526</span>    if (resp.getEntity() == null) return null;<a name="line.526"></a>
+<span class="sourceLineNo">527</span>    try (InputStream instream = resp.getEntity().getContent()) {<a name="line.527"></a>
+<span class="sourceLineNo">528</span>      if (instream != null) {<a name="line.528"></a>
+<span class="sourceLineNo">529</span>        long contentLength = resp.getEntity().getContentLength();<a name="line.529"></a>
+<span class="sourceLineNo">530</span>        if (contentLength &gt; Integer.MAX_VALUE) {<a name="line.530"></a>
+<span class="sourceLineNo">531</span>          //guard integer cast from overflow<a name="line.531"></a>
+<span class="sourceLineNo">532</span>          throw new IOException("Content too large to be buffered: " + contentLength +" bytes");<a name="line.532"></a>
+<span class="sourceLineNo">533</span>        }<a name="line.533"></a>
+<span class="sourceLineNo">534</span>        ByteArrayOutputStream outstream = new ByteArrayOutputStream(<a name="line.534"></a>
+<span class="sourceLineNo">535</span>            contentLength &gt; 0 ? (int) contentLength : 4*1024);<a name="line.535"></a>
+<span class="sourceLineNo">536</span>        byte[] buffer = new byte[4096];<a name="line.536"></a>
+<span class="sourceLineNo">537</span>        int len;<a name="line.537"></a>
+<span class="sourceLineNo">538</span>        while ((len = instream.read(buffer)) &gt; 0) {<a name="line.538"></a>
+<span class="sourceLineNo">539</span>          outstream.write(buffer, 0, len);<a name="line.539"></a>
+<span class="sourceLineNo">540</span>        }<a name="line.540"></a>
+<span class="sourceLineNo">541</span>        outstream.close();<a name="line.541"></a>
+<span class="sourceLineNo">542</span>        return outstream.toByteArray();<a name="line.542"></a>
+<span class="sourceLineNo">543</span>      }<a name="line.543"></a>
+<span class="sourceLineNo">544</span>      return null;<a name="line.544"></a>
+<span class="sourceLineNo">545</span>    }<a name="line.545"></a>
+<span class="sourceLineNo">546</span>  }<a name="line.546"></a>
+<span class="sourceLineNo">547</span><a name="line.547"></a>
+<span class="sourceLineNo">548</span>  /**<a name="line.548"></a>
+<span class="sourceLineNo">549</span>   * Send a GET request<a name="line.549"></a>
+<span class="sourceLineNo">550</span>   * @param c the cluster definition<a name="line.550"></a>
+<span class="sourceLineNo">551</span>   * @param path the path or URI<a name="line.551"></a>
+<span class="sourceLineNo">552</span>   * @param headers the HTTP headers to include in the request<a name="line.552"></a>
+<span class="sourceLineNo">553</span>   * @return a Response object with response detail<a name="line.553"></a>
+<span class="sourceLineNo">554</span>   * @throws IOException<a name="line.554"></a>
+<span class="sourceLineNo">555</span>   */<a name="line.555"></a>
+<span class="sourceLineNo">556</span>  public Response get(Cluster c, String path, Header[] headers)<a name="line.556"></a>
+<span class="sourceLineNo">557</span>      throws IOException {<a name="line.557"></a>
+<span class="sourceLineNo">558</span>    if (httpGet != null) {<a name="line.558"></a>
+<span class="sourceLineNo">559</span>      httpGet.releaseConnection();<a name="line.559"></a>
+<span class="sourceLineNo">560</span>    }<a name="line.560"></a>
+<span class="sourceLineNo">561</span>    httpGet = new HttpGet(path);<a name="line.561"></a>
+<span class="sourceLineNo">562</span>    HttpResponse resp = execute(c, httpGet, headers, path);<a name="line.562"></a>
+<span class="sourceLineNo">563</span>    return new Response(resp.getStatusLine().getStatusCode(), resp.getAllHeaders(),<a name="line.563"></a>
+<span class="sourceLineNo">564</span>        resp, resp.getEntity() == null ? null : resp.getEntity().getContent());<a name="line.564"></a>
+<span class="sourceLineNo">565</span>  }<a name="line.565"></a>
+<span class="sourceLineNo">566</span><a name="line.566"></a>
+<span class="sourceLineNo">567</span>  /**<a name="line.567"></a>
+<span class="sourceLineNo">568</span>   * Send a PUT request<a name="line.568"></a>
+<span class="sourceLineNo">569</span>   * @param path the path or URI<a name="line.569"></a>
+<span class="sourceLineNo">570</span>   * @param contentType the content MIME type<a name="line.570"></a>
+<span class="sourceLineNo">571</span>   * @param content the content bytes<a name="line.571"></a>
+<span class="sourceLineNo">572</span>   * @return a Response object with response detail<a name="line.572"></a>
+<span class="sourceLineNo">573</span>   * @throws IOException<a name="line.573"></a>
+<span class="sourceLineNo">574</span>   */<a name="line.574"></a>
+<span class="sourceLineNo">575</span>  public Response put(String path, String contentType, byte[] content)<a name="line.575"></a>
+<span class="sourceLineNo">576</span>      throws IOException {<a name="line.576"></a>
+<span class="sourceLineNo">577</span>    return put(cluster, path, contentType, content);<a name="line.577"></a>
+<span class="sourceLineNo">578</span>  }<a name="line.578"></a>
+<span class="sourceLineNo">579</span><a name="line.579"></a>
+<span class="sourceLineNo">580</span>  /**<a name="line.580"></a>
+<span class="sourceLineNo">581</span>   * Send a PUT request<a name="line.581"></a>
+<span class="sourceLineNo">582</span>   * @param path the path or URI<a name="line.582"></a>
+<span class="sourceLineNo">583</span>   * @param contentType the content MIME type<a name="line.583"></a>
+<span class="sourceLineNo">584</span>   * @param content the content bytes<a name="line.584"></a>
+<span class="sourceLineNo">585</span>   * @param extraHdr extra Header to send<a name="line.585"></a>
+<span class="sourceLineNo">586</span>   * @return a Response object with response detail<a name="line.586"></a>
+<span class="sourceLineNo">587</span>   * @throws IOException<a name="line.587"></a>
+<span class="sourceLineNo">588</span>   */<a name="line.588"></a>
+<span class="sourceLineNo">589</span>  public Response put(String path, String contentType, byte[] content, Header extraHdr)<a name="line.589"></a>
+<span class="sourceLineNo">590</span>      throws IOException {<a name="line.590"></a>
+<span class="sourceLineNo">591</span>    return put(cluster, path, contentType, content, extraHdr);<a name="line.591"></a>
+<span class="sourceLineNo">592</span>  }<a name="line.592"></a>
+<span class="sourceLineNo">593</span><a name="line.593"></a>
+<span class="sourceLineNo">594</span>  /**<a name="line.594"></a>
+<span class="sourceLineNo">595</span>   * Send a PUT request<a name="line.595"></a>
+<span class="sourceLineNo">596</span>   * @param cluster the cluster definition<a name="line.596"></a>
+<span class="sourceLineNo">597</span>   * @param path the path or URI<a name="line.597"></a>
+<span class="sourceLineNo">598</spa