http://git-wip-us.apache.org/repos/asf/hbase-site/blob/495ddb86/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/querymatcher/ScanQueryMatcher.MatchCode.html
----------------------------------------------------------------------
diff --git 
a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/querymatcher/ScanQueryMatcher.MatchCode.html
 
b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/querymatcher/ScanQueryMatcher.MatchCode.html
index cf26433..07c9f18 100644
--- 
a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/querymatcher/ScanQueryMatcher.MatchCode.html
+++ 
b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/querymatcher/ScanQueryMatcher.MatchCode.html
@@ -298,122 +298,135 @@
 <span class="sourceLineNo">290</span>  public abstract boolean 
moreRowsMayExistAfter(Cell cell);<a name="line.290"></a>
 <span class="sourceLineNo">291</span><a name="line.291"></a>
 <span class="sourceLineNo">292</span>  public Cell getKeyForNextColumn(Cell 
cell) {<a name="line.292"></a>
-<span class="sourceLineNo">293</span>    ColumnCount nextColumn = 
columns.getColumnHint();<a name="line.293"></a>
-<span class="sourceLineNo">294</span>    if (nextColumn == null) {<a 
name="line.294"></a>
-<span class="sourceLineNo">295</span>      return 
CellUtil.createLastOnRowCol(cell);<a name="line.295"></a>
-<span class="sourceLineNo">296</span>    } else {<a name="line.296"></a>
-<span class="sourceLineNo">297</span>      return 
CellUtil.createFirstOnRowCol(cell, nextColumn.getBuffer(), 
nextColumn.getOffset(),<a name="line.297"></a>
-<span class="sourceLineNo">298</span>        nextColumn.getLength());<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><a name="line.301"></a>
-<span class="sourceLineNo">302</span>  /**<a name="line.302"></a>
-<span class="sourceLineNo">303</span>   * @param nextIndexed the key of the 
next entry in the block index (if any)<a name="line.303"></a>
-<span class="sourceLineNo">304</span>   * @param currentCell The Cell we're 
using to calculate the seek key<a name="line.304"></a>
-<span class="sourceLineNo">305</span>   * @return result of the compare 
between the indexed key and the key portion of the passed cell<a 
name="line.305"></a>
-<span class="sourceLineNo">306</span>   */<a name="line.306"></a>
-<span class="sourceLineNo">307</span>  public int compareKeyForNextRow(Cell 
nextIndexed, Cell currentCell) {<a name="line.307"></a>
-<span class="sourceLineNo">308</span>    return 
rowComparator.compareKeyBasedOnColHint(nextIndexed, currentCell, 0, 0, null, 0, 
0,<a name="line.308"></a>
-<span class="sourceLineNo">309</span>      HConstants.OLDEST_TIMESTAMP, 
Type.Minimum.getCode());<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>   * @param nextIndexed the key of the 
next entry in the block index (if any)<a name="line.313"></a>
-<span class="sourceLineNo">314</span>   * @param currentCell The Cell we're 
using to calculate the seek key<a name="line.314"></a>
-<span class="sourceLineNo">315</span>   * @return result of the compare 
between the indexed key and the key portion of the passed cell<a 
name="line.315"></a>
-<span class="sourceLineNo">316</span>   */<a name="line.316"></a>
-<span class="sourceLineNo">317</span>  public int compareKeyForNextColumn(Cell 
nextIndexed, Cell currentCell) {<a name="line.317"></a>
-<span class="sourceLineNo">318</span>    ColumnCount nextColumn = 
columns.getColumnHint();<a name="line.318"></a>
-<span class="sourceLineNo">319</span>    if (nextColumn == null) {<a 
name="line.319"></a>
-<span class="sourceLineNo">320</span>      return 
rowComparator.compareKeyBasedOnColHint(nextIndexed, currentCell, 0, 0, null, 0, 
0,<a name="line.320"></a>
-<span class="sourceLineNo">321</span>        HConstants.OLDEST_TIMESTAMP, 
Type.Minimum.getCode());<a name="line.321"></a>
-<span class="sourceLineNo">322</span>    } else {<a name="line.322"></a>
-<span class="sourceLineNo">323</span>      return 
rowComparator.compareKeyBasedOnColHint(nextIndexed, currentCell,<a 
name="line.323"></a>
-<span class="sourceLineNo">324</span>        currentCell.getFamilyOffset(), 
currentCell.getFamilyLength(), nextColumn.getBuffer(),<a name="line.324"></a>
-<span class="sourceLineNo">325</span>        nextColumn.getOffset(), 
nextColumn.getLength(), HConstants.LATEST_TIMESTAMP,<a name="line.325"></a>
-<span class="sourceLineNo">326</span>        Type.Maximum.getCode());<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>   * @return the Filter<a 
name="line.331"></a>
-<span class="sourceLineNo">332</span>   */<a name="line.332"></a>
-<span class="sourceLineNo">333</span>  public abstract Filter getFilter();<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>   * Delegate to {@link 
Filter#getNextCellHint(Cell)}. If no filter, return {@code null}.<a 
name="line.336"></a>
-<span class="sourceLineNo">337</span>   */<a name="line.337"></a>
-<span class="sourceLineNo">338</span>  public abstract Cell 
getNextKeyHint(Cell cell) throws IOException;<a name="line.338"></a>
-<span class="sourceLineNo">339</span><a name="line.339"></a>
-<span class="sourceLineNo">340</span>  @Override<a name="line.340"></a>
-<span class="sourceLineNo">341</span>  public void beforeShipped() throws 
IOException {<a name="line.341"></a>
-<span class="sourceLineNo">342</span>    if (this.currentRow != null) {<a 
name="line.342"></a>
-<span class="sourceLineNo">343</span>      this.currentRow = 
CellUtil.createFirstOnRow(CellUtil.copyRow(this.currentRow));<a 
name="line.343"></a>
-<span class="sourceLineNo">344</span>    }<a name="line.344"></a>
-<span class="sourceLineNo">345</span>    if (columns != null) {<a 
name="line.345"></a>
-<span class="sourceLineNo">346</span>      columns.beforeShipped();<a 
name="line.346"></a>
-<span class="sourceLineNo">347</span>    }<a name="line.347"></a>
-<span class="sourceLineNo">348</span>  }<a name="line.348"></a>
-<span class="sourceLineNo">349</span><a name="line.349"></a>
-<span class="sourceLineNo">350</span>  protected static Cell 
createStartKeyFromRow(byte[] startRow, ScanInfo scanInfo) {<a 
name="line.350"></a>
-<span class="sourceLineNo">351</span>    return 
CellUtil.createFirstDeleteFamilyCellOnRow(startRow, scanInfo.getFamily());<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>  protected static Pair&lt;DeleteTracker, 
ColumnTracker&gt; getTrackers(RegionCoprocessorHost host,<a name="line.354"></a>
-<span class="sourceLineNo">355</span>      NavigableSet&lt;byte[]&gt; columns, 
ScanInfo scanInfo, long oldestUnexpiredTS, Scan userScan)<a name="line.355"></a>
-<span class="sourceLineNo">356</span>      throws IOException {<a 
name="line.356"></a>
-<span class="sourceLineNo">357</span>    int resultMaxVersion = 
scanInfo.getMaxVersions();<a name="line.357"></a>
-<span class="sourceLineNo">358</span>    int maxVersionToCheck = 
resultMaxVersion;<a name="line.358"></a>
-<span class="sourceLineNo">359</span>    if (userScan != null) {<a 
name="line.359"></a>
-<span class="sourceLineNo">360</span>      if (userScan.isRaw()) {<a 
name="line.360"></a>
-<span class="sourceLineNo">361</span>        resultMaxVersion = 
userScan.getMaxVersions();<a name="line.361"></a>
-<span class="sourceLineNo">362</span>      } else {<a name="line.362"></a>
-<span class="sourceLineNo">363</span>        resultMaxVersion = 
Math.min(userScan.getMaxVersions(), scanInfo.getMaxVersions());<a 
name="line.363"></a>
-<span class="sourceLineNo">364</span>      }<a name="line.364"></a>
-<span class="sourceLineNo">365</span>      maxVersionToCheck = 
userScan.hasFilter() ? scanInfo.getMaxVersions() : resultMaxVersion;<a 
name="line.365"></a>
-<span class="sourceLineNo">366</span>    }<a name="line.366"></a>
-<span class="sourceLineNo">367</span><a name="line.367"></a>
-<span class="sourceLineNo">368</span>    DeleteTracker deleteTracker;<a 
name="line.368"></a>
-<span class="sourceLineNo">369</span>    if (scanInfo.isNewVersionBehavior() 
&amp;&amp; (userScan == null || !userScan.isRaw())) {<a name="line.369"></a>
-<span class="sourceLineNo">370</span>      deleteTracker = new 
NewVersionBehaviorTracker(columns, scanInfo.getMinVersions(),<a 
name="line.370"></a>
-<span class="sourceLineNo">371</span>          scanInfo.getMaxVersions(), 
resultMaxVersion, oldestUnexpiredTS);<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    } else {<a name="line.372"></a>
-<span class="sourceLineNo">373</span>      deleteTracker = new 
ScanDeleteTracker();<a name="line.373"></a>
-<span class="sourceLineNo">374</span>    }<a name="line.374"></a>
-<span class="sourceLineNo">375</span>    if (host != null) {<a 
name="line.375"></a>
-<span class="sourceLineNo">376</span>      deleteTracker = 
host.postInstantiateDeleteTracker(deleteTracker);<a name="line.376"></a>
-<span class="sourceLineNo">377</span>      if (deleteTracker instanceof 
VisibilityScanDeleteTracker &amp;&amp; scanInfo.isNewVersionBehavior()) {<a 
name="line.377"></a>
-<span class="sourceLineNo">378</span>        deleteTracker = new 
VisibilityNewVersionBehaivorTracker(columns, scanInfo.getMinVersions(),<a 
name="line.378"></a>
-<span class="sourceLineNo">379</span>            scanInfo.getMaxVersions(), 
resultMaxVersion, oldestUnexpiredTS);<a name="line.379"></a>
-<span class="sourceLineNo">380</span>      }<a name="line.380"></a>
-<span class="sourceLineNo">381</span>    }<a name="line.381"></a>
-<span class="sourceLineNo">382</span><a name="line.382"></a>
-<span class="sourceLineNo">383</span>    ColumnTracker columnTracker;<a 
name="line.383"></a>
-<span class="sourceLineNo">384</span><a name="line.384"></a>
-<span class="sourceLineNo">385</span>    if (deleteTracker instanceof 
NewVersionBehaviorTracker) {<a name="line.385"></a>
-<span class="sourceLineNo">386</span>      columnTracker = 
(NewVersionBehaviorTracker) deleteTracker;<a name="line.386"></a>
-<span class="sourceLineNo">387</span>    } else if (columns == null || 
columns.size() == 0) {<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      columnTracker = new 
ScanWildcardColumnTracker(scanInfo.getMinVersions(), maxVersionToCheck,<a 
name="line.388"></a>
-<span class="sourceLineNo">389</span>          oldestUnexpiredTS);<a 
name="line.389"></a>
-<span class="sourceLineNo">390</span>    } else {<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      columnTracker = new 
ExplicitColumnTracker(columns, scanInfo.getMinVersions(),<a name="line.391"></a>
-<span class="sourceLineNo">392</span>        maxVersionToCheck, 
oldestUnexpiredTS);<a name="line.392"></a>
-<span class="sourceLineNo">393</span>    }<a name="line.393"></a>
-<span class="sourceLineNo">394</span>    return new 
Pair&lt;&gt;(deleteTracker, columnTracker);<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>  // Used only for testing purposes<a 
name="line.397"></a>
-<span class="sourceLineNo">398</span>  static MatchCode 
checkColumn(ColumnTracker columnTracker, byte[] bytes, int offset, int 
length,<a name="line.398"></a>
-<span class="sourceLineNo">399</span>      long ttl, byte type, boolean 
ignoreCount) throws IOException {<a name="line.399"></a>
-<span class="sourceLineNo">400</span>    KeyValue kv = 
KeyValueUtil.createFirstOnRow(HConstants.EMPTY_BYTE_ARRAY, 0, 0,<a 
name="line.400"></a>
-<span class="sourceLineNo">401</span>      HConstants.EMPTY_BYTE_ARRAY, 0, 0, 
bytes, offset, length);<a name="line.401"></a>
-<span class="sourceLineNo">402</span>    MatchCode matchCode = 
columnTracker.checkColumn(kv, type);<a name="line.402"></a>
-<span class="sourceLineNo">403</span>    if (matchCode == MatchCode.INCLUDE) 
{<a name="line.403"></a>
-<span class="sourceLineNo">404</span>      return 
columnTracker.checkVersions(kv, ttl, type, ignoreCount);<a name="line.404"></a>
-<span class="sourceLineNo">405</span>    }<a name="line.405"></a>
-<span class="sourceLineNo">406</span>    return matchCode;<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">293</span>    // We aren't sure whether any 
DeleteFamily cells exist, so we can't skip to next column.<a 
name="line.293"></a>
+<span class="sourceLineNo">294</span>    // TODO: Current way disable us to 
seek to next column quickly. Is there any better solution?<a 
name="line.294"></a>
+<span class="sourceLineNo">295</span>    // see HBASE-18471 for more details<a 
name="line.295"></a>
+<span class="sourceLineNo">296</span>    // see 
TestFromClientSide3#testScanAfterDeletingSpecifiedRow<a name="line.296"></a>
+<span class="sourceLineNo">297</span>    // see 
TestFromClientSide3#testScanAfterDeletingSpecifiedRowV2<a name="line.297"></a>
+<span class="sourceLineNo">298</span>    if (cell.getQualifierLength() == 0) 
{<a name="line.298"></a>
+<span class="sourceLineNo">299</span>      Cell nextKey = 
CellUtil.createNextOnRowCol(cell);<a name="line.299"></a>
+<span class="sourceLineNo">300</span>      if (nextKey != cell) {<a 
name="line.300"></a>
+<span class="sourceLineNo">301</span>        return nextKey;<a 
name="line.301"></a>
+<span class="sourceLineNo">302</span>      }<a name="line.302"></a>
+<span class="sourceLineNo">303</span>      // The cell is at the end of 
row/family/qualifier, so it is impossible to find any DeleteFamily cells.<a 
name="line.303"></a>
+<span class="sourceLineNo">304</span>      // Let us seek to next column.<a 
name="line.304"></a>
+<span class="sourceLineNo">305</span>    }<a name="line.305"></a>
+<span class="sourceLineNo">306</span>    ColumnCount nextColumn = 
columns.getColumnHint();<a name="line.306"></a>
+<span class="sourceLineNo">307</span>    if (nextColumn == null) {<a 
name="line.307"></a>
+<span class="sourceLineNo">308</span>      return 
CellUtil.createLastOnRowCol(cell);<a name="line.308"></a>
+<span class="sourceLineNo">309</span>    } else {<a name="line.309"></a>
+<span class="sourceLineNo">310</span>      return 
CellUtil.createFirstOnRowCol(cell, nextColumn.getBuffer(), 
nextColumn.getOffset(),<a name="line.310"></a>
+<span class="sourceLineNo">311</span>        nextColumn.getLength());<a 
name="line.311"></a>
+<span class="sourceLineNo">312</span>    }<a name="line.312"></a>
+<span class="sourceLineNo">313</span>  }<a name="line.313"></a>
+<span class="sourceLineNo">314</span><a name="line.314"></a>
+<span class="sourceLineNo">315</span>  /**<a name="line.315"></a>
+<span class="sourceLineNo">316</span>   * @param nextIndexed the key of the 
next entry in the block index (if any)<a name="line.316"></a>
+<span class="sourceLineNo">317</span>   * @param currentCell The Cell we're 
using to calculate the seek key<a name="line.317"></a>
+<span class="sourceLineNo">318</span>   * @return result of the compare 
between the indexed key and the key portion of the passed cell<a 
name="line.318"></a>
+<span class="sourceLineNo">319</span>   */<a name="line.319"></a>
+<span class="sourceLineNo">320</span>  public int compareKeyForNextRow(Cell 
nextIndexed, Cell currentCell) {<a name="line.320"></a>
+<span class="sourceLineNo">321</span>    return 
rowComparator.compareKeyBasedOnColHint(nextIndexed, currentCell, 0, 0, null, 0, 
0,<a name="line.321"></a>
+<span class="sourceLineNo">322</span>      HConstants.OLDEST_TIMESTAMP, 
Type.Minimum.getCode());<a name="line.322"></a>
+<span class="sourceLineNo">323</span>  }<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>   * @param nextIndexed the key of the 
next entry in the block index (if any)<a name="line.326"></a>
+<span class="sourceLineNo">327</span>   * @param currentCell The Cell we're 
using to calculate the seek key<a name="line.327"></a>
+<span class="sourceLineNo">328</span>   * @return result of the compare 
between the indexed key and the key portion of the passed cell<a 
name="line.328"></a>
+<span class="sourceLineNo">329</span>   */<a name="line.329"></a>
+<span class="sourceLineNo">330</span>  public int compareKeyForNextColumn(Cell 
nextIndexed, Cell currentCell) {<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    ColumnCount nextColumn = 
columns.getColumnHint();<a name="line.331"></a>
+<span class="sourceLineNo">332</span>    if (nextColumn == null) {<a 
name="line.332"></a>
+<span class="sourceLineNo">333</span>      return 
rowComparator.compareKeyBasedOnColHint(nextIndexed, currentCell, 0, 0, null, 0, 
0,<a name="line.333"></a>
+<span class="sourceLineNo">334</span>        HConstants.OLDEST_TIMESTAMP, 
Type.Minimum.getCode());<a name="line.334"></a>
+<span class="sourceLineNo">335</span>    } else {<a name="line.335"></a>
+<span class="sourceLineNo">336</span>      return 
rowComparator.compareKeyBasedOnColHint(nextIndexed, currentCell,<a 
name="line.336"></a>
+<span class="sourceLineNo">337</span>        currentCell.getFamilyOffset(), 
currentCell.getFamilyLength(), nextColumn.getBuffer(),<a name="line.337"></a>
+<span class="sourceLineNo">338</span>        nextColumn.getOffset(), 
nextColumn.getLength(), HConstants.LATEST_TIMESTAMP,<a name="line.338"></a>
+<span class="sourceLineNo">339</span>        Type.Maximum.getCode());<a 
name="line.339"></a>
+<span class="sourceLineNo">340</span>    }<a name="line.340"></a>
+<span class="sourceLineNo">341</span>  }<a name="line.341"></a>
+<span class="sourceLineNo">342</span><a name="line.342"></a>
+<span class="sourceLineNo">343</span>  /**<a name="line.343"></a>
+<span class="sourceLineNo">344</span>   * @return the Filter<a 
name="line.344"></a>
+<span class="sourceLineNo">345</span>   */<a name="line.345"></a>
+<span class="sourceLineNo">346</span>  public abstract Filter getFilter();<a 
name="line.346"></a>
+<span class="sourceLineNo">347</span><a name="line.347"></a>
+<span class="sourceLineNo">348</span>  /**<a name="line.348"></a>
+<span class="sourceLineNo">349</span>   * Delegate to {@link 
Filter#getNextCellHint(Cell)}. If no filter, return {@code null}.<a 
name="line.349"></a>
+<span class="sourceLineNo">350</span>   */<a name="line.350"></a>
+<span class="sourceLineNo">351</span>  public abstract Cell 
getNextKeyHint(Cell cell) throws IOException;<a name="line.351"></a>
+<span class="sourceLineNo">352</span><a name="line.352"></a>
+<span class="sourceLineNo">353</span>  @Override<a name="line.353"></a>
+<span class="sourceLineNo">354</span>  public void beforeShipped() throws 
IOException {<a name="line.354"></a>
+<span class="sourceLineNo">355</span>    if (this.currentRow != null) {<a 
name="line.355"></a>
+<span class="sourceLineNo">356</span>      this.currentRow = 
CellUtil.createFirstOnRow(CellUtil.copyRow(this.currentRow));<a 
name="line.356"></a>
+<span class="sourceLineNo">357</span>    }<a name="line.357"></a>
+<span class="sourceLineNo">358</span>    if (columns != null) {<a 
name="line.358"></a>
+<span class="sourceLineNo">359</span>      columns.beforeShipped();<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>  protected static Cell 
createStartKeyFromRow(byte[] startRow, ScanInfo scanInfo) {<a 
name="line.363"></a>
+<span class="sourceLineNo">364</span>    return 
CellUtil.createFirstDeleteFamilyCellOnRow(startRow, scanInfo.getFamily());<a 
name="line.364"></a>
+<span class="sourceLineNo">365</span>  }<a name="line.365"></a>
+<span class="sourceLineNo">366</span><a name="line.366"></a>
+<span class="sourceLineNo">367</span>  protected static Pair&lt;DeleteTracker, 
ColumnTracker&gt; getTrackers(RegionCoprocessorHost host,<a name="line.367"></a>
+<span class="sourceLineNo">368</span>      NavigableSet&lt;byte[]&gt; columns, 
ScanInfo scanInfo, long oldestUnexpiredTS, Scan userScan)<a name="line.368"></a>
+<span class="sourceLineNo">369</span>      throws IOException {<a 
name="line.369"></a>
+<span class="sourceLineNo">370</span>    int resultMaxVersion = 
scanInfo.getMaxVersions();<a name="line.370"></a>
+<span class="sourceLineNo">371</span>    int maxVersionToCheck = 
resultMaxVersion;<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    if (userScan != null) {<a 
name="line.372"></a>
+<span class="sourceLineNo">373</span>      if (userScan.isRaw()) {<a 
name="line.373"></a>
+<span class="sourceLineNo">374</span>        resultMaxVersion = 
userScan.getMaxVersions();<a name="line.374"></a>
+<span class="sourceLineNo">375</span>      } else {<a name="line.375"></a>
+<span class="sourceLineNo">376</span>        resultMaxVersion = 
Math.min(userScan.getMaxVersions(), scanInfo.getMaxVersions());<a 
name="line.376"></a>
+<span class="sourceLineNo">377</span>      }<a name="line.377"></a>
+<span class="sourceLineNo">378</span>      maxVersionToCheck = 
userScan.hasFilter() ? scanInfo.getMaxVersions() : resultMaxVersion;<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>    DeleteTracker deleteTracker;<a 
name="line.381"></a>
+<span class="sourceLineNo">382</span>    if (scanInfo.isNewVersionBehavior() 
&amp;&amp; (userScan == null || !userScan.isRaw())) {<a name="line.382"></a>
+<span class="sourceLineNo">383</span>      deleteTracker = new 
NewVersionBehaviorTracker(columns, scanInfo.getMinVersions(),<a 
name="line.383"></a>
+<span class="sourceLineNo">384</span>          scanInfo.getMaxVersions(), 
resultMaxVersion, oldestUnexpiredTS);<a name="line.384"></a>
+<span class="sourceLineNo">385</span>    } else {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>      deleteTracker = new 
ScanDeleteTracker();<a name="line.386"></a>
+<span class="sourceLineNo">387</span>    }<a name="line.387"></a>
+<span class="sourceLineNo">388</span>    if (host != null) {<a 
name="line.388"></a>
+<span class="sourceLineNo">389</span>      deleteTracker = 
host.postInstantiateDeleteTracker(deleteTracker);<a name="line.389"></a>
+<span class="sourceLineNo">390</span>      if (deleteTracker instanceof 
VisibilityScanDeleteTracker &amp;&amp; scanInfo.isNewVersionBehavior()) {<a 
name="line.390"></a>
+<span class="sourceLineNo">391</span>        deleteTracker = new 
VisibilityNewVersionBehaivorTracker(columns, scanInfo.getMinVersions(),<a 
name="line.391"></a>
+<span class="sourceLineNo">392</span>            scanInfo.getMaxVersions(), 
resultMaxVersion, oldestUnexpiredTS);<a name="line.392"></a>
+<span class="sourceLineNo">393</span>      }<a name="line.393"></a>
+<span class="sourceLineNo">394</span>    }<a name="line.394"></a>
+<span class="sourceLineNo">395</span><a name="line.395"></a>
+<span class="sourceLineNo">396</span>    ColumnTracker columnTracker;<a 
name="line.396"></a>
+<span class="sourceLineNo">397</span><a name="line.397"></a>
+<span class="sourceLineNo">398</span>    if (deleteTracker instanceof 
NewVersionBehaviorTracker) {<a name="line.398"></a>
+<span class="sourceLineNo">399</span>      columnTracker = 
(NewVersionBehaviorTracker) deleteTracker;<a name="line.399"></a>
+<span class="sourceLineNo">400</span>    } else if (columns == null || 
columns.size() == 0) {<a name="line.400"></a>
+<span class="sourceLineNo">401</span>      columnTracker = new 
ScanWildcardColumnTracker(scanInfo.getMinVersions(), maxVersionToCheck,<a 
name="line.401"></a>
+<span class="sourceLineNo">402</span>          oldestUnexpiredTS);<a 
name="line.402"></a>
+<span class="sourceLineNo">403</span>    } else {<a name="line.403"></a>
+<span class="sourceLineNo">404</span>      columnTracker = new 
ExplicitColumnTracker(columns, scanInfo.getMinVersions(),<a name="line.404"></a>
+<span class="sourceLineNo">405</span>        maxVersionToCheck, 
oldestUnexpiredTS);<a name="line.405"></a>
+<span class="sourceLineNo">406</span>    }<a name="line.406"></a>
+<span class="sourceLineNo">407</span>    return new 
Pair&lt;&gt;(deleteTracker, columnTracker);<a name="line.407"></a>
+<span class="sourceLineNo">408</span>  }<a name="line.408"></a>
+<span class="sourceLineNo">409</span><a name="line.409"></a>
+<span class="sourceLineNo">410</span>  // Used only for testing purposes<a 
name="line.410"></a>
+<span class="sourceLineNo">411</span>  static MatchCode 
checkColumn(ColumnTracker columnTracker, byte[] bytes, int offset, int 
length,<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      long ttl, byte type, boolean 
ignoreCount) throws IOException {<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    KeyValue kv = 
KeyValueUtil.createFirstOnRow(HConstants.EMPTY_BYTE_ARRAY, 0, 0,<a 
name="line.413"></a>
+<span class="sourceLineNo">414</span>      HConstants.EMPTY_BYTE_ARRAY, 0, 0, 
bytes, offset, length);<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    MatchCode matchCode = 
columnTracker.checkColumn(kv, type);<a name="line.415"></a>
+<span class="sourceLineNo">416</span>    if (matchCode == MatchCode.INCLUDE) 
{<a name="line.416"></a>
+<span class="sourceLineNo">417</span>      return 
columnTracker.checkVersions(kv, ttl, type, ignoreCount);<a name="line.417"></a>
+<span class="sourceLineNo">418</span>    }<a name="line.418"></a>
+<span class="sourceLineNo">419</span>    return matchCode;<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>
 
 
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/495ddb86/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/querymatcher/ScanQueryMatcher.html
----------------------------------------------------------------------
diff --git 
a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/querymatcher/ScanQueryMatcher.html
 
b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/querymatcher/ScanQueryMatcher.html
index cf26433..07c9f18 100644
--- 
a/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/querymatcher/ScanQueryMatcher.html
+++ 
b/devapidocs/src-html/org/apache/hadoop/hbase/regionserver/querymatcher/ScanQueryMatcher.html
@@ -298,122 +298,135 @@
 <span class="sourceLineNo">290</span>  public abstract boolean 
moreRowsMayExistAfter(Cell cell);<a name="line.290"></a>
 <span class="sourceLineNo">291</span><a name="line.291"></a>
 <span class="sourceLineNo">292</span>  public Cell getKeyForNextColumn(Cell 
cell) {<a name="line.292"></a>
-<span class="sourceLineNo">293</span>    ColumnCount nextColumn = 
columns.getColumnHint();<a name="line.293"></a>
-<span class="sourceLineNo">294</span>    if (nextColumn == null) {<a 
name="line.294"></a>
-<span class="sourceLineNo">295</span>      return 
CellUtil.createLastOnRowCol(cell);<a name="line.295"></a>
-<span class="sourceLineNo">296</span>    } else {<a name="line.296"></a>
-<span class="sourceLineNo">297</span>      return 
CellUtil.createFirstOnRowCol(cell, nextColumn.getBuffer(), 
nextColumn.getOffset(),<a name="line.297"></a>
-<span class="sourceLineNo">298</span>        nextColumn.getLength());<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><a name="line.301"></a>
-<span class="sourceLineNo">302</span>  /**<a name="line.302"></a>
-<span class="sourceLineNo">303</span>   * @param nextIndexed the key of the 
next entry in the block index (if any)<a name="line.303"></a>
-<span class="sourceLineNo">304</span>   * @param currentCell The Cell we're 
using to calculate the seek key<a name="line.304"></a>
-<span class="sourceLineNo">305</span>   * @return result of the compare 
between the indexed key and the key portion of the passed cell<a 
name="line.305"></a>
-<span class="sourceLineNo">306</span>   */<a name="line.306"></a>
-<span class="sourceLineNo">307</span>  public int compareKeyForNextRow(Cell 
nextIndexed, Cell currentCell) {<a name="line.307"></a>
-<span class="sourceLineNo">308</span>    return 
rowComparator.compareKeyBasedOnColHint(nextIndexed, currentCell, 0, 0, null, 0, 
0,<a name="line.308"></a>
-<span class="sourceLineNo">309</span>      HConstants.OLDEST_TIMESTAMP, 
Type.Minimum.getCode());<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>   * @param nextIndexed the key of the 
next entry in the block index (if any)<a name="line.313"></a>
-<span class="sourceLineNo">314</span>   * @param currentCell The Cell we're 
using to calculate the seek key<a name="line.314"></a>
-<span class="sourceLineNo">315</span>   * @return result of the compare 
between the indexed key and the key portion of the passed cell<a 
name="line.315"></a>
-<span class="sourceLineNo">316</span>   */<a name="line.316"></a>
-<span class="sourceLineNo">317</span>  public int compareKeyForNextColumn(Cell 
nextIndexed, Cell currentCell) {<a name="line.317"></a>
-<span class="sourceLineNo">318</span>    ColumnCount nextColumn = 
columns.getColumnHint();<a name="line.318"></a>
-<span class="sourceLineNo">319</span>    if (nextColumn == null) {<a 
name="line.319"></a>
-<span class="sourceLineNo">320</span>      return 
rowComparator.compareKeyBasedOnColHint(nextIndexed, currentCell, 0, 0, null, 0, 
0,<a name="line.320"></a>
-<span class="sourceLineNo">321</span>        HConstants.OLDEST_TIMESTAMP, 
Type.Minimum.getCode());<a name="line.321"></a>
-<span class="sourceLineNo">322</span>    } else {<a name="line.322"></a>
-<span class="sourceLineNo">323</span>      return 
rowComparator.compareKeyBasedOnColHint(nextIndexed, currentCell,<a 
name="line.323"></a>
-<span class="sourceLineNo">324</span>        currentCell.getFamilyOffset(), 
currentCell.getFamilyLength(), nextColumn.getBuffer(),<a name="line.324"></a>
-<span class="sourceLineNo">325</span>        nextColumn.getOffset(), 
nextColumn.getLength(), HConstants.LATEST_TIMESTAMP,<a name="line.325"></a>
-<span class="sourceLineNo">326</span>        Type.Maximum.getCode());<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>   * @return the Filter<a 
name="line.331"></a>
-<span class="sourceLineNo">332</span>   */<a name="line.332"></a>
-<span class="sourceLineNo">333</span>  public abstract Filter getFilter();<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>   * Delegate to {@link 
Filter#getNextCellHint(Cell)}. If no filter, return {@code null}.<a 
name="line.336"></a>
-<span class="sourceLineNo">337</span>   */<a name="line.337"></a>
-<span class="sourceLineNo">338</span>  public abstract Cell 
getNextKeyHint(Cell cell) throws IOException;<a name="line.338"></a>
-<span class="sourceLineNo">339</span><a name="line.339"></a>
-<span class="sourceLineNo">340</span>  @Override<a name="line.340"></a>
-<span class="sourceLineNo">341</span>  public void beforeShipped() throws 
IOException {<a name="line.341"></a>
-<span class="sourceLineNo">342</span>    if (this.currentRow != null) {<a 
name="line.342"></a>
-<span class="sourceLineNo">343</span>      this.currentRow = 
CellUtil.createFirstOnRow(CellUtil.copyRow(this.currentRow));<a 
name="line.343"></a>
-<span class="sourceLineNo">344</span>    }<a name="line.344"></a>
-<span class="sourceLineNo">345</span>    if (columns != null) {<a 
name="line.345"></a>
-<span class="sourceLineNo">346</span>      columns.beforeShipped();<a 
name="line.346"></a>
-<span class="sourceLineNo">347</span>    }<a name="line.347"></a>
-<span class="sourceLineNo">348</span>  }<a name="line.348"></a>
-<span class="sourceLineNo">349</span><a name="line.349"></a>
-<span class="sourceLineNo">350</span>  protected static Cell 
createStartKeyFromRow(byte[] startRow, ScanInfo scanInfo) {<a 
name="line.350"></a>
-<span class="sourceLineNo">351</span>    return 
CellUtil.createFirstDeleteFamilyCellOnRow(startRow, scanInfo.getFamily());<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>  protected static Pair&lt;DeleteTracker, 
ColumnTracker&gt; getTrackers(RegionCoprocessorHost host,<a name="line.354"></a>
-<span class="sourceLineNo">355</span>      NavigableSet&lt;byte[]&gt; columns, 
ScanInfo scanInfo, long oldestUnexpiredTS, Scan userScan)<a name="line.355"></a>
-<span class="sourceLineNo">356</span>      throws IOException {<a 
name="line.356"></a>
-<span class="sourceLineNo">357</span>    int resultMaxVersion = 
scanInfo.getMaxVersions();<a name="line.357"></a>
-<span class="sourceLineNo">358</span>    int maxVersionToCheck = 
resultMaxVersion;<a name="line.358"></a>
-<span class="sourceLineNo">359</span>    if (userScan != null) {<a 
name="line.359"></a>
-<span class="sourceLineNo">360</span>      if (userScan.isRaw()) {<a 
name="line.360"></a>
-<span class="sourceLineNo">361</span>        resultMaxVersion = 
userScan.getMaxVersions();<a name="line.361"></a>
-<span class="sourceLineNo">362</span>      } else {<a name="line.362"></a>
-<span class="sourceLineNo">363</span>        resultMaxVersion = 
Math.min(userScan.getMaxVersions(), scanInfo.getMaxVersions());<a 
name="line.363"></a>
-<span class="sourceLineNo">364</span>      }<a name="line.364"></a>
-<span class="sourceLineNo">365</span>      maxVersionToCheck = 
userScan.hasFilter() ? scanInfo.getMaxVersions() : resultMaxVersion;<a 
name="line.365"></a>
-<span class="sourceLineNo">366</span>    }<a name="line.366"></a>
-<span class="sourceLineNo">367</span><a name="line.367"></a>
-<span class="sourceLineNo">368</span>    DeleteTracker deleteTracker;<a 
name="line.368"></a>
-<span class="sourceLineNo">369</span>    if (scanInfo.isNewVersionBehavior() 
&amp;&amp; (userScan == null || !userScan.isRaw())) {<a name="line.369"></a>
-<span class="sourceLineNo">370</span>      deleteTracker = new 
NewVersionBehaviorTracker(columns, scanInfo.getMinVersions(),<a 
name="line.370"></a>
-<span class="sourceLineNo">371</span>          scanInfo.getMaxVersions(), 
resultMaxVersion, oldestUnexpiredTS);<a name="line.371"></a>
-<span class="sourceLineNo">372</span>    } else {<a name="line.372"></a>
-<span class="sourceLineNo">373</span>      deleteTracker = new 
ScanDeleteTracker();<a name="line.373"></a>
-<span class="sourceLineNo">374</span>    }<a name="line.374"></a>
-<span class="sourceLineNo">375</span>    if (host != null) {<a 
name="line.375"></a>
-<span class="sourceLineNo">376</span>      deleteTracker = 
host.postInstantiateDeleteTracker(deleteTracker);<a name="line.376"></a>
-<span class="sourceLineNo">377</span>      if (deleteTracker instanceof 
VisibilityScanDeleteTracker &amp;&amp; scanInfo.isNewVersionBehavior()) {<a 
name="line.377"></a>
-<span class="sourceLineNo">378</span>        deleteTracker = new 
VisibilityNewVersionBehaivorTracker(columns, scanInfo.getMinVersions(),<a 
name="line.378"></a>
-<span class="sourceLineNo">379</span>            scanInfo.getMaxVersions(), 
resultMaxVersion, oldestUnexpiredTS);<a name="line.379"></a>
-<span class="sourceLineNo">380</span>      }<a name="line.380"></a>
-<span class="sourceLineNo">381</span>    }<a name="line.381"></a>
-<span class="sourceLineNo">382</span><a name="line.382"></a>
-<span class="sourceLineNo">383</span>    ColumnTracker columnTracker;<a 
name="line.383"></a>
-<span class="sourceLineNo">384</span><a name="line.384"></a>
-<span class="sourceLineNo">385</span>    if (deleteTracker instanceof 
NewVersionBehaviorTracker) {<a name="line.385"></a>
-<span class="sourceLineNo">386</span>      columnTracker = 
(NewVersionBehaviorTracker) deleteTracker;<a name="line.386"></a>
-<span class="sourceLineNo">387</span>    } else if (columns == null || 
columns.size() == 0) {<a name="line.387"></a>
-<span class="sourceLineNo">388</span>      columnTracker = new 
ScanWildcardColumnTracker(scanInfo.getMinVersions(), maxVersionToCheck,<a 
name="line.388"></a>
-<span class="sourceLineNo">389</span>          oldestUnexpiredTS);<a 
name="line.389"></a>
-<span class="sourceLineNo">390</span>    } else {<a name="line.390"></a>
-<span class="sourceLineNo">391</span>      columnTracker = new 
ExplicitColumnTracker(columns, scanInfo.getMinVersions(),<a name="line.391"></a>
-<span class="sourceLineNo">392</span>        maxVersionToCheck, 
oldestUnexpiredTS);<a name="line.392"></a>
-<span class="sourceLineNo">393</span>    }<a name="line.393"></a>
-<span class="sourceLineNo">394</span>    return new 
Pair&lt;&gt;(deleteTracker, columnTracker);<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>  // Used only for testing purposes<a 
name="line.397"></a>
-<span class="sourceLineNo">398</span>  static MatchCode 
checkColumn(ColumnTracker columnTracker, byte[] bytes, int offset, int 
length,<a name="line.398"></a>
-<span class="sourceLineNo">399</span>      long ttl, byte type, boolean 
ignoreCount) throws IOException {<a name="line.399"></a>
-<span class="sourceLineNo">400</span>    KeyValue kv = 
KeyValueUtil.createFirstOnRow(HConstants.EMPTY_BYTE_ARRAY, 0, 0,<a 
name="line.400"></a>
-<span class="sourceLineNo">401</span>      HConstants.EMPTY_BYTE_ARRAY, 0, 0, 
bytes, offset, length);<a name="line.401"></a>
-<span class="sourceLineNo">402</span>    MatchCode matchCode = 
columnTracker.checkColumn(kv, type);<a name="line.402"></a>
-<span class="sourceLineNo">403</span>    if (matchCode == MatchCode.INCLUDE) 
{<a name="line.403"></a>
-<span class="sourceLineNo">404</span>      return 
columnTracker.checkVersions(kv, ttl, type, ignoreCount);<a name="line.404"></a>
-<span class="sourceLineNo">405</span>    }<a name="line.405"></a>
-<span class="sourceLineNo">406</span>    return matchCode;<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">293</span>    // We aren't sure whether any 
DeleteFamily cells exist, so we can't skip to next column.<a 
name="line.293"></a>
+<span class="sourceLineNo">294</span>    // TODO: Current way disable us to 
seek to next column quickly. Is there any better solution?<a 
name="line.294"></a>
+<span class="sourceLineNo">295</span>    // see HBASE-18471 for more details<a 
name="line.295"></a>
+<span class="sourceLineNo">296</span>    // see 
TestFromClientSide3#testScanAfterDeletingSpecifiedRow<a name="line.296"></a>
+<span class="sourceLineNo">297</span>    // see 
TestFromClientSide3#testScanAfterDeletingSpecifiedRowV2<a name="line.297"></a>
+<span class="sourceLineNo">298</span>    if (cell.getQualifierLength() == 0) 
{<a name="line.298"></a>
+<span class="sourceLineNo">299</span>      Cell nextKey = 
CellUtil.createNextOnRowCol(cell);<a name="line.299"></a>
+<span class="sourceLineNo">300</span>      if (nextKey != cell) {<a 
name="line.300"></a>
+<span class="sourceLineNo">301</span>        return nextKey;<a 
name="line.301"></a>
+<span class="sourceLineNo">302</span>      }<a name="line.302"></a>
+<span class="sourceLineNo">303</span>      // The cell is at the end of 
row/family/qualifier, so it is impossible to find any DeleteFamily cells.<a 
name="line.303"></a>
+<span class="sourceLineNo">304</span>      // Let us seek to next column.<a 
name="line.304"></a>
+<span class="sourceLineNo">305</span>    }<a name="line.305"></a>
+<span class="sourceLineNo">306</span>    ColumnCount nextColumn = 
columns.getColumnHint();<a name="line.306"></a>
+<span class="sourceLineNo">307</span>    if (nextColumn == null) {<a 
name="line.307"></a>
+<span class="sourceLineNo">308</span>      return 
CellUtil.createLastOnRowCol(cell);<a name="line.308"></a>
+<span class="sourceLineNo">309</span>    } else {<a name="line.309"></a>
+<span class="sourceLineNo">310</span>      return 
CellUtil.createFirstOnRowCol(cell, nextColumn.getBuffer(), 
nextColumn.getOffset(),<a name="line.310"></a>
+<span class="sourceLineNo">311</span>        nextColumn.getLength());<a 
name="line.311"></a>
+<span class="sourceLineNo">312</span>    }<a name="line.312"></a>
+<span class="sourceLineNo">313</span>  }<a name="line.313"></a>
+<span class="sourceLineNo">314</span><a name="line.314"></a>
+<span class="sourceLineNo">315</span>  /**<a name="line.315"></a>
+<span class="sourceLineNo">316</span>   * @param nextIndexed the key of the 
next entry in the block index (if any)<a name="line.316"></a>
+<span class="sourceLineNo">317</span>   * @param currentCell The Cell we're 
using to calculate the seek key<a name="line.317"></a>
+<span class="sourceLineNo">318</span>   * @return result of the compare 
between the indexed key and the key portion of the passed cell<a 
name="line.318"></a>
+<span class="sourceLineNo">319</span>   */<a name="line.319"></a>
+<span class="sourceLineNo">320</span>  public int compareKeyForNextRow(Cell 
nextIndexed, Cell currentCell) {<a name="line.320"></a>
+<span class="sourceLineNo">321</span>    return 
rowComparator.compareKeyBasedOnColHint(nextIndexed, currentCell, 0, 0, null, 0, 
0,<a name="line.321"></a>
+<span class="sourceLineNo">322</span>      HConstants.OLDEST_TIMESTAMP, 
Type.Minimum.getCode());<a name="line.322"></a>
+<span class="sourceLineNo">323</span>  }<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>   * @param nextIndexed the key of the 
next entry in the block index (if any)<a name="line.326"></a>
+<span class="sourceLineNo">327</span>   * @param currentCell The Cell we're 
using to calculate the seek key<a name="line.327"></a>
+<span class="sourceLineNo">328</span>   * @return result of the compare 
between the indexed key and the key portion of the passed cell<a 
name="line.328"></a>
+<span class="sourceLineNo">329</span>   */<a name="line.329"></a>
+<span class="sourceLineNo">330</span>  public int compareKeyForNextColumn(Cell 
nextIndexed, Cell currentCell) {<a name="line.330"></a>
+<span class="sourceLineNo">331</span>    ColumnCount nextColumn = 
columns.getColumnHint();<a name="line.331"></a>
+<span class="sourceLineNo">332</span>    if (nextColumn == null) {<a 
name="line.332"></a>
+<span class="sourceLineNo">333</span>      return 
rowComparator.compareKeyBasedOnColHint(nextIndexed, currentCell, 0, 0, null, 0, 
0,<a name="line.333"></a>
+<span class="sourceLineNo">334</span>        HConstants.OLDEST_TIMESTAMP, 
Type.Minimum.getCode());<a name="line.334"></a>
+<span class="sourceLineNo">335</span>    } else {<a name="line.335"></a>
+<span class="sourceLineNo">336</span>      return 
rowComparator.compareKeyBasedOnColHint(nextIndexed, currentCell,<a 
name="line.336"></a>
+<span class="sourceLineNo">337</span>        currentCell.getFamilyOffset(), 
currentCell.getFamilyLength(), nextColumn.getBuffer(),<a name="line.337"></a>
+<span class="sourceLineNo">338</span>        nextColumn.getOffset(), 
nextColumn.getLength(), HConstants.LATEST_TIMESTAMP,<a name="line.338"></a>
+<span class="sourceLineNo">339</span>        Type.Maximum.getCode());<a 
name="line.339"></a>
+<span class="sourceLineNo">340</span>    }<a name="line.340"></a>
+<span class="sourceLineNo">341</span>  }<a name="line.341"></a>
+<span class="sourceLineNo">342</span><a name="line.342"></a>
+<span class="sourceLineNo">343</span>  /**<a name="line.343"></a>
+<span class="sourceLineNo">344</span>   * @return the Filter<a 
name="line.344"></a>
+<span class="sourceLineNo">345</span>   */<a name="line.345"></a>
+<span class="sourceLineNo">346</span>  public abstract Filter getFilter();<a 
name="line.346"></a>
+<span class="sourceLineNo">347</span><a name="line.347"></a>
+<span class="sourceLineNo">348</span>  /**<a name="line.348"></a>
+<span class="sourceLineNo">349</span>   * Delegate to {@link 
Filter#getNextCellHint(Cell)}. If no filter, return {@code null}.<a 
name="line.349"></a>
+<span class="sourceLineNo">350</span>   */<a name="line.350"></a>
+<span class="sourceLineNo">351</span>  public abstract Cell 
getNextKeyHint(Cell cell) throws IOException;<a name="line.351"></a>
+<span class="sourceLineNo">352</span><a name="line.352"></a>
+<span class="sourceLineNo">353</span>  @Override<a name="line.353"></a>
+<span class="sourceLineNo">354</span>  public void beforeShipped() throws 
IOException {<a name="line.354"></a>
+<span class="sourceLineNo">355</span>    if (this.currentRow != null) {<a 
name="line.355"></a>
+<span class="sourceLineNo">356</span>      this.currentRow = 
CellUtil.createFirstOnRow(CellUtil.copyRow(this.currentRow));<a 
name="line.356"></a>
+<span class="sourceLineNo">357</span>    }<a name="line.357"></a>
+<span class="sourceLineNo">358</span>    if (columns != null) {<a 
name="line.358"></a>
+<span class="sourceLineNo">359</span>      columns.beforeShipped();<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>  protected static Cell 
createStartKeyFromRow(byte[] startRow, ScanInfo scanInfo) {<a 
name="line.363"></a>
+<span class="sourceLineNo">364</span>    return 
CellUtil.createFirstDeleteFamilyCellOnRow(startRow, scanInfo.getFamily());<a 
name="line.364"></a>
+<span class="sourceLineNo">365</span>  }<a name="line.365"></a>
+<span class="sourceLineNo">366</span><a name="line.366"></a>
+<span class="sourceLineNo">367</span>  protected static Pair&lt;DeleteTracker, 
ColumnTracker&gt; getTrackers(RegionCoprocessorHost host,<a name="line.367"></a>
+<span class="sourceLineNo">368</span>      NavigableSet&lt;byte[]&gt; columns, 
ScanInfo scanInfo, long oldestUnexpiredTS, Scan userScan)<a name="line.368"></a>
+<span class="sourceLineNo">369</span>      throws IOException {<a 
name="line.369"></a>
+<span class="sourceLineNo">370</span>    int resultMaxVersion = 
scanInfo.getMaxVersions();<a name="line.370"></a>
+<span class="sourceLineNo">371</span>    int maxVersionToCheck = 
resultMaxVersion;<a name="line.371"></a>
+<span class="sourceLineNo">372</span>    if (userScan != null) {<a 
name="line.372"></a>
+<span class="sourceLineNo">373</span>      if (userScan.isRaw()) {<a 
name="line.373"></a>
+<span class="sourceLineNo">374</span>        resultMaxVersion = 
userScan.getMaxVersions();<a name="line.374"></a>
+<span class="sourceLineNo">375</span>      } else {<a name="line.375"></a>
+<span class="sourceLineNo">376</span>        resultMaxVersion = 
Math.min(userScan.getMaxVersions(), scanInfo.getMaxVersions());<a 
name="line.376"></a>
+<span class="sourceLineNo">377</span>      }<a name="line.377"></a>
+<span class="sourceLineNo">378</span>      maxVersionToCheck = 
userScan.hasFilter() ? scanInfo.getMaxVersions() : resultMaxVersion;<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>    DeleteTracker deleteTracker;<a 
name="line.381"></a>
+<span class="sourceLineNo">382</span>    if (scanInfo.isNewVersionBehavior() 
&amp;&amp; (userScan == null || !userScan.isRaw())) {<a name="line.382"></a>
+<span class="sourceLineNo">383</span>      deleteTracker = new 
NewVersionBehaviorTracker(columns, scanInfo.getMinVersions(),<a 
name="line.383"></a>
+<span class="sourceLineNo">384</span>          scanInfo.getMaxVersions(), 
resultMaxVersion, oldestUnexpiredTS);<a name="line.384"></a>
+<span class="sourceLineNo">385</span>    } else {<a name="line.385"></a>
+<span class="sourceLineNo">386</span>      deleteTracker = new 
ScanDeleteTracker();<a name="line.386"></a>
+<span class="sourceLineNo">387</span>    }<a name="line.387"></a>
+<span class="sourceLineNo">388</span>    if (host != null) {<a 
name="line.388"></a>
+<span class="sourceLineNo">389</span>      deleteTracker = 
host.postInstantiateDeleteTracker(deleteTracker);<a name="line.389"></a>
+<span class="sourceLineNo">390</span>      if (deleteTracker instanceof 
VisibilityScanDeleteTracker &amp;&amp; scanInfo.isNewVersionBehavior()) {<a 
name="line.390"></a>
+<span class="sourceLineNo">391</span>        deleteTracker = new 
VisibilityNewVersionBehaivorTracker(columns, scanInfo.getMinVersions(),<a 
name="line.391"></a>
+<span class="sourceLineNo">392</span>            scanInfo.getMaxVersions(), 
resultMaxVersion, oldestUnexpiredTS);<a name="line.392"></a>
+<span class="sourceLineNo">393</span>      }<a name="line.393"></a>
+<span class="sourceLineNo">394</span>    }<a name="line.394"></a>
+<span class="sourceLineNo">395</span><a name="line.395"></a>
+<span class="sourceLineNo">396</span>    ColumnTracker columnTracker;<a 
name="line.396"></a>
+<span class="sourceLineNo">397</span><a name="line.397"></a>
+<span class="sourceLineNo">398</span>    if (deleteTracker instanceof 
NewVersionBehaviorTracker) {<a name="line.398"></a>
+<span class="sourceLineNo">399</span>      columnTracker = 
(NewVersionBehaviorTracker) deleteTracker;<a name="line.399"></a>
+<span class="sourceLineNo">400</span>    } else if (columns == null || 
columns.size() == 0) {<a name="line.400"></a>
+<span class="sourceLineNo">401</span>      columnTracker = new 
ScanWildcardColumnTracker(scanInfo.getMinVersions(), maxVersionToCheck,<a 
name="line.401"></a>
+<span class="sourceLineNo">402</span>          oldestUnexpiredTS);<a 
name="line.402"></a>
+<span class="sourceLineNo">403</span>    } else {<a name="line.403"></a>
+<span class="sourceLineNo">404</span>      columnTracker = new 
ExplicitColumnTracker(columns, scanInfo.getMinVersions(),<a name="line.404"></a>
+<span class="sourceLineNo">405</span>        maxVersionToCheck, 
oldestUnexpiredTS);<a name="line.405"></a>
+<span class="sourceLineNo">406</span>    }<a name="line.406"></a>
+<span class="sourceLineNo">407</span>    return new 
Pair&lt;&gt;(deleteTracker, columnTracker);<a name="line.407"></a>
+<span class="sourceLineNo">408</span>  }<a name="line.408"></a>
+<span class="sourceLineNo">409</span><a name="line.409"></a>
+<span class="sourceLineNo">410</span>  // Used only for testing purposes<a 
name="line.410"></a>
+<span class="sourceLineNo">411</span>  static MatchCode 
checkColumn(ColumnTracker columnTracker, byte[] bytes, int offset, int 
length,<a name="line.411"></a>
+<span class="sourceLineNo">412</span>      long ttl, byte type, boolean 
ignoreCount) throws IOException {<a name="line.412"></a>
+<span class="sourceLineNo">413</span>    KeyValue kv = 
KeyValueUtil.createFirstOnRow(HConstants.EMPTY_BYTE_ARRAY, 0, 0,<a 
name="line.413"></a>
+<span class="sourceLineNo">414</span>      HConstants.EMPTY_BYTE_ARRAY, 0, 0, 
bytes, offset, length);<a name="line.414"></a>
+<span class="sourceLineNo">415</span>    MatchCode matchCode = 
columnTracker.checkColumn(kv, type);<a name="line.415"></a>
+<span class="sourceLineNo">416</span>    if (matchCode == MatchCode.INCLUDE) 
{<a name="line.416"></a>
+<span class="sourceLineNo">417</span>      return 
columnTracker.checkVersions(kv, ttl, type, ignoreCount);<a name="line.417"></a>
+<span class="sourceLineNo">418</span>    }<a name="line.418"></a>
+<span class="sourceLineNo">419</span>    return matchCode;<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>
 
 
 

http://git-wip-us.apache.org/repos/asf/hbase-site/blob/495ddb86/devapidocs/src-html/org/apache/hadoop/hbase/security/visibility/DefaultVisibilityLabelServiceImpl.html
----------------------------------------------------------------------
diff --git 
a/devapidocs/src-html/org/apache/hadoop/hbase/security/visibility/DefaultVisibilityLabelServiceImpl.html
 
b/devapidocs/src-html/org/apache/hadoop/hbase/security/visibility/DefaultVisibilityLabelServiceImpl.html
index 45aa6ec..cdac426 100644
--- 
a/devapidocs/src-html/org/apache/hadoop/hbase/security/visibility/DefaultVisibilityLabelServiceImpl.html
+++ 
b/devapidocs/src-html/org/apache/hadoop/hbase/security/visibility/DefaultVisibilityLabelServiceImpl.html
@@ -559,169 +559,173 @@
 <span class="sourceLineNo">551</span>  @Override<a name="line.551"></a>
 <span class="sourceLineNo">552</span>  public boolean 
matchVisibility(List&lt;Tag&gt; putVisTags, Byte putTagsFormat, List&lt;Tag&gt; 
deleteVisTags,<a name="line.552"></a>
 <span class="sourceLineNo">553</span>      Byte deleteTagsFormat) throws 
IOException {<a name="line.553"></a>
-<span class="sourceLineNo">554</span>    if ((deleteTagsFormat != null 
&amp;&amp; deleteTagsFormat == SORTED_ORDINAL_SERIALIZATION_FORMAT)<a 
name="line.554"></a>
-<span class="sourceLineNo">555</span>        &amp;&amp; (putTagsFormat == null 
|| putTagsFormat == SORTED_ORDINAL_SERIALIZATION_FORMAT)) {<a 
name="line.555"></a>
-<span class="sourceLineNo">556</span>      if (putVisTags.isEmpty()) {<a 
name="line.556"></a>
-<span class="sourceLineNo">557</span>        // Early out if there are no tags 
in the cell<a name="line.557"></a>
-<span class="sourceLineNo">558</span>        return false;<a 
name="line.558"></a>
-<span class="sourceLineNo">559</span>      }<a name="line.559"></a>
-<span class="sourceLineNo">560</span>      if (putTagsFormat == null) {<a 
name="line.560"></a>
-<span class="sourceLineNo">561</span>        return 
matchUnSortedVisibilityTags(putVisTags, deleteVisTags);<a name="line.561"></a>
-<span class="sourceLineNo">562</span>      } else {<a name="line.562"></a>
-<span class="sourceLineNo">563</span>        return 
matchOrdinalSortedVisibilityTags(putVisTags, deleteVisTags);<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>    throw new IOException("Unexpected tag 
format passed for comparison, deleteTagsFormat : "<a name="line.566"></a>
-<span class="sourceLineNo">567</span>        + deleteTagsFormat + ", 
putTagsFormat : " + putTagsFormat);<a name="line.567"></a>
-<span class="sourceLineNo">568</span>  }<a name="line.568"></a>
-<span class="sourceLineNo">569</span><a name="line.569"></a>
-<span class="sourceLineNo">570</span>  /**<a name="line.570"></a>
-<span class="sourceLineNo">571</span>   * @param putVisTags Visibility tags in 
Put Mutation<a name="line.571"></a>
-<span class="sourceLineNo">572</span>   * @param deleteVisTags Visibility tags 
in Delete Mutation<a name="line.572"></a>
-<span class="sourceLineNo">573</span>   * @return true when all the visibility 
tags in Put matches with visibility tags in Delete.<a name="line.573"></a>
-<span class="sourceLineNo">574</span>   * This is used when, at least one set 
of tags are not sorted based on the label ordinal.<a name="line.574"></a>
-<span class="sourceLineNo">575</span>   */<a name="line.575"></a>
-<span class="sourceLineNo">576</span>  private static boolean 
matchUnSortedVisibilityTags(List&lt;Tag&gt; putVisTags,<a name="line.576"></a>
-<span class="sourceLineNo">577</span>      List&lt;Tag&gt; deleteVisTags) 
throws IOException {<a name="line.577"></a>
-<span class="sourceLineNo">578</span>    return 
compareTagsOrdinals(sortTagsBasedOnOrdinal(putVisTags),<a name="line.578"></a>
-<span class="sourceLineNo">579</span>        
sortTagsBasedOnOrdinal(deleteVisTags));<a name="line.579"></a>
-<span class="sourceLineNo">580</span>  }<a name="line.580"></a>
-<span class="sourceLineNo">581</span><a name="line.581"></a>
-<span class="sourceLineNo">582</span>  /**<a name="line.582"></a>
-<span class="sourceLineNo">583</span>   * @param putVisTags Visibility tags in 
Put Mutation<a name="line.583"></a>
-<span class="sourceLineNo">584</span>   * @param deleteVisTags Visibility tags 
in Delete Mutation<a name="line.584"></a>
-<span class="sourceLineNo">585</span>   * @return true when all the visibility 
tags in Put matches with visibility tags in Delete.<a name="line.585"></a>
-<span class="sourceLineNo">586</span>   * This is used when both the set of 
tags are sorted based on the label ordinal.<a name="line.586"></a>
-<span class="sourceLineNo">587</span>   */<a name="line.587"></a>
-<span class="sourceLineNo">588</span>  private static boolean 
matchOrdinalSortedVisibilityTags(List&lt;Tag&gt; putVisTags,<a 
name="line.588"></a>
-<span class="sourceLineNo">589</span>      List&lt;Tag&gt; deleteVisTags) {<a 
name="line.589"></a>
-<span class="sourceLineNo">590</span>    boolean matchFound = false;<a 
name="line.590"></a>
-<span class="sourceLineNo">591</span>    // If the size does not match. 
Definitely we are not comparing the equal tags.<a name="line.591"></a>
-<span class="sourceLineNo">592</span>    if ((deleteVisTags.size()) == 
putVisTags.size()) {<a name="line.592"></a>
-<span class="sourceLineNo">593</span>      for (Tag tag : deleteVisTags) {<a 
name="line.593"></a>
-<span class="sourceLineNo">594</span>        matchFound = false;<a 
name="line.594"></a>
-<span class="sourceLineNo">595</span>        for (Tag givenTag : putVisTags) 
{<a name="line.595"></a>
-<span class="sourceLineNo">596</span>          if (TagUtil.matchingValue(tag, 
givenTag)) {<a name="line.596"></a>
-<span class="sourceLineNo">597</span>            matchFound = true;<a 
name="line.597"></a>
-<span class="sourceLineNo">598</span>            break;<a name="line.598"></a>
-<span class="sourceLineNo">599</span>          }<a name="line.599"></a>
-<span class="sourceLineNo">600</span>        }<a name="line.600"></a>
-<span class="sourceLineNo">601</span>        if (!matchFound) break;<a 
name="line.601"></a>
-<span class="sourceLineNo">602</span>      }<a name="line.602"></a>
-<span class="sourceLineNo">603</span>    }<a name="line.603"></a>
-<span class="sourceLineNo">604</span>    return matchFound;<a 
name="line.604"></a>
-<span class="sourceLineNo">605</span>  }<a name="line.605"></a>
-<span class="sourceLineNo">606</span><a name="line.606"></a>
-<span class="sourceLineNo">607</span>  private static 
List&lt;List&lt;Integer&gt;&gt; sortTagsBasedOnOrdinal(List&lt;Tag&gt; tags) 
throws IOException {<a name="line.607"></a>
-<span class="sourceLineNo">608</span>    List&lt;List&lt;Integer&gt;&gt; 
fullTagsList = new ArrayList&lt;&gt;();<a name="line.608"></a>
-<span class="sourceLineNo">609</span>    for (Tag tag : tags) {<a 
name="line.609"></a>
-<span class="sourceLineNo">610</span>      if (tag.getType() == 
VISIBILITY_TAG_TYPE) {<a name="line.610"></a>
-<span class="sourceLineNo">611</span>        
getSortedTagOrdinals(fullTagsList, tag);<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>    return fullTagsList;<a 
name="line.614"></a>
-<span class="sourceLineNo">615</span>  }<a name="line.615"></a>
-<span class="sourceLineNo">616</span><a name="line.616"></a>
-<span class="sourceLineNo">617</span>  private static void 
getSortedTagOrdinals(List&lt;List&lt;Integer&gt;&gt; fullTagsList, Tag tag)<a 
name="line.617"></a>
-<span class="sourceLineNo">618</span>      throws IOException {<a 
name="line.618"></a>
-<span class="sourceLineNo">619</span>    List&lt;Integer&gt; 
tagsOrdinalInSortedOrder = new ArrayList&lt;&gt;();<a name="line.619"></a>
-<span class="sourceLineNo">620</span>    int offset = tag.getValueOffset();<a 
name="line.620"></a>
-<span class="sourceLineNo">621</span>    int endOffset = offset + 
tag.getValueLength();<a name="line.621"></a>
-<span class="sourceLineNo">622</span>    while (offset &lt; endOffset) {<a 
name="line.622"></a>
-<span class="sourceLineNo">623</span>      Pair&lt;Integer, Integer&gt; result 
= TagUtil.readVIntValuePart(tag, offset);<a name="line.623"></a>
-<span class="sourceLineNo">624</span>      
tagsOrdinalInSortedOrder.add(result.getFirst());<a name="line.624"></a>
-<span class="sourceLineNo">625</span>      offset += result.getSecond();<a 
name="line.625"></a>
-<span class="sourceLineNo">626</span>    }<a name="line.626"></a>
-<span class="sourceLineNo">627</span>    
Collections.sort(tagsOrdinalInSortedOrder);<a name="line.627"></a>
-<span class="sourceLineNo">628</span>    
fullTagsList.add(tagsOrdinalInSortedOrder);<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>  /*<a name="line.631"></a>
-<span class="sourceLineNo">632</span>   * @return true when all the visibility 
tags in Put matches with visibility tags in Delete.<a name="line.632"></a>
-<span class="sourceLineNo">633</span>   */<a name="line.633"></a>
-<span class="sourceLineNo">634</span>  private static boolean 
compareTagsOrdinals(List&lt;List&lt;Integer&gt;&gt; putVisTags,<a 
name="line.634"></a>
-<span class="sourceLineNo">635</span>      List&lt;List&lt;Integer&gt;&gt; 
deleteVisTags) {<a name="line.635"></a>
-<span class="sourceLineNo">636</span>    boolean matchFound = false;<a 
name="line.636"></a>
-<span class="sourceLineNo">637</span>    if (deleteVisTags.size() == 
putVisTags.size()) {<a name="line.637"></a>
-<span class="sourceLineNo">638</span>      for (List&lt;Integer&gt; 
deleteTagOrdinals : deleteVisTags) {<a name="line.638"></a>
-<span class="sourceLineNo">639</span>        matchFound = false;<a 
name="line.639"></a>
-<span class="sourceLineNo">640</span>        for (List&lt;Integer&gt; 
tagOrdinals : putVisTags) {<a name="line.640"></a>
-<span class="sourceLineNo">641</span>          if 
(deleteTagOrdinals.equals(tagOrdinals)) {<a name="line.641"></a>
-<span class="sourceLineNo">642</span>            matchFound = true;<a 
name="line.642"></a>
-<span class="sourceLineNo">643</span>            break;<a name="line.643"></a>
-<span class="sourceLineNo">644</span>          }<a name="line.644"></a>
-<span class="sourceLineNo">645</span>        }<a name="line.645"></a>
-<span class="sourceLineNo">646</span>        if (!matchFound) break;<a 
name="line.646"></a>
-<span class="sourceLineNo">647</span>      }<a name="line.647"></a>
-<span class="sourceLineNo">648</span>    }<a name="line.648"></a>
-<span class="sourceLineNo">649</span>    return matchFound;<a 
name="line.649"></a>
-<span class="sourceLineNo">650</span>  }<a name="line.650"></a>
-<span class="sourceLineNo">651</span><a name="line.651"></a>
-<span class="sourceLineNo">652</span>  @Override<a name="line.652"></a>
-<span class="sourceLineNo">653</span>  public byte[] 
encodeVisibilityForReplication(final List&lt;Tag&gt; tags, final Byte 
serializationFormat)<a name="line.653"></a>
-<span class="sourceLineNo">654</span>      throws IOException {<a 
name="line.654"></a>
-<span class="sourceLineNo">655</span>    if (tags.size() &gt; 0<a 
name="line.655"></a>
-<span class="sourceLineNo">656</span>        &amp;&amp; (serializationFormat 
== null ||<a name="line.656"></a>
-<span class="sourceLineNo">657</span>        serializationFormat == 
SORTED_ORDINAL_SERIALIZATION_FORMAT)) {<a name="line.657"></a>
-<span class="sourceLineNo">658</span>      return 
createModifiedVisExpression(tags);<a name="line.658"></a>
-<span class="sourceLineNo">659</span>    }<a name="line.659"></a>
-<span class="sourceLineNo">660</span>    return null;<a name="line.660"></a>
-<span class="sourceLineNo">661</span>  }<a name="line.661"></a>
-<span class="sourceLineNo">662</span><a name="line.662"></a>
-<span class="sourceLineNo">663</span>  /**<a name="line.663"></a>
-<span class="sourceLineNo">664</span>   * @param tags<a name="line.664"></a>
-<span class="sourceLineNo">665</span>   *          - all the visibility tags 
associated with the current Cell<a name="line.665"></a>
-<span class="sourceLineNo">666</span>   * @return - the modified visibility 
expression as byte[]<a name="line.666"></a>
-<span class="sourceLineNo">667</span>   */<a name="line.667"></a>
-<span class="sourceLineNo">668</span>  private byte[] 
createModifiedVisExpression(final List&lt;Tag&gt; tags)<a name="line.668"></a>
-<span class="sourceLineNo">669</span>      throws IOException {<a 
name="line.669"></a>
-<span class="sourceLineNo">670</span>    StringBuilder visibilityString = new 
StringBuilder();<a name="line.670"></a>
-<span class="sourceLineNo">671</span>    for (Tag tag : tags) {<a 
name="line.671"></a>
-<span class="sourceLineNo">672</span>      if (tag.getType() == 
TagType.VISIBILITY_TAG_TYPE) {<a name="line.672"></a>
-<span class="sourceLineNo">673</span>        if (visibilityString.length() != 
0) {<a name="line.673"></a>
-<span class="sourceLineNo">674</span>          
visibilityString.append(VisibilityConstants.CLOSED_PARAN).append(<a 
name="line.674"></a>
-<span class="sourceLineNo">675</span>              
VisibilityConstants.OR_OPERATOR);<a name="line.675"></a>
-<span class="sourceLineNo">676</span>        }<a name="line.676"></a>
-<span class="sourceLineNo">677</span>        int offset = 
tag.getValueOffset();<a name="line.677"></a>
-<span class="sourceLineNo">678</span>        int endOffset = offset + 
tag.getValueLength();<a name="line.678"></a>
-<span class="sourceLineNo">679</span>        boolean expressionStart = true;<a 
name="line.679"></a>
-<span class="sourceLineNo">680</span>        while (offset &lt; endOffset) {<a 
name="line.680"></a>
-<span class="sourceLineNo">681</span>          Pair&lt;Integer, Integer&gt; 
result = TagUtil.readVIntValuePart(tag, offset);<a name="line.681"></a>
-<span class="sourceLineNo">682</span>          int currLabelOrdinal = 
result.getFirst();<a name="line.682"></a>
-<span class="sourceLineNo">683</span>          if (currLabelOrdinal &lt; 0) 
{<a name="line.683"></a>
-<span class="sourceLineNo">684</span>            int temp = 
-currLabelOrdinal;<a name="line.684"></a>
-<span class="sourceLineNo">685</span>            String label = 
this.labelsCache.getLabel(temp);<a name="line.685"></a>
-<span class="sourceLineNo">686</span>            if (expressionStart) {<a 
name="line.686"></a>
-<span class="sourceLineNo">687</span>              // Quote every label in 
case of unicode characters if present<a name="line.687"></a>
-<span class="sourceLineNo">688</span>              
visibilityString.append(VisibilityConstants.OPEN_PARAN)<a name="line.688"></a>
-<span class="sourceLineNo">689</span>                  
.append(VisibilityConstants.NOT_OPERATOR).append(CellVisibility.quote(label));<a
 name="line.689"></a>
-<span class="sourceLineNo">690</span>            } else {<a 
name="line.690"></a>
-<span class="sourceLineNo">691</span>              
visibilityString.append(VisibilityConstants.AND_OPERATOR)<a name="line.691"></a>
-<span class="sourceLineNo">692</span>                  
.append(VisibilityConstants.NOT_OPERATOR).append(CellVisibility.quote(label));<a
 name="line.692"></a>
-<span class="sourceLineNo">693</span>            }<a name="line.693"></a>
-<span class="sourceLineNo">694</span>          } else {<a name="line.694"></a>
-<span class="sourceLineNo">695</span>            String label = 
this.labelsCache.getLabel(currLabelOrdinal);<a name="line.695"></a>
-<span class="sourceLineNo">696</span>            if (expressionStart) {<a 
name="line.696"></a>
-<span class="sourceLineNo">697</span>              
visibilityString.append(VisibilityConstants.OPEN_PARAN).append(<a 
name="line.697"></a>
-<span class="sourceLineNo">698</span>                  
CellVisibility.quote(label));<a name="line.698"></a>
-<span class="sourceLineNo">699</span>            } else {<a 
name="line.699"></a>
-<span class="sourceLineNo">700</span>              
visibilityString.append(VisibilityConstants.AND_OPERATOR).append(<a 
name="line.700"></a>
-<span class="sourceLineNo">701</span>                  
CellVisibility.quote(label));<a name="line.701"></a>
-<span class="sourceLineNo">702</span>            }<a name="line.702"></a>
-<span class="sourceLineNo">703</span>          }<a name="line.703"></a>
-<span class="sourceLineNo">704</span>          expressionStart = false;<a 
name="line.704"></a>
-<span class="sourceLineNo">705</span>          offset += result.getSecond();<a 
name="line.705"></a>
-<span class="sourceLineNo">706</span>        }<a name="line.706"></a>
-<span class="sourceLineNo">707</span>      }<a name="line.707"></a>
-<span class="sourceLineNo">708</span>    }<a name="line.708"></a>
-<span class="sourceLineNo">709</span>    if (visibilityString.length() != 0) 
{<a name="line.709"></a>
-<span class="sourceLineNo">710</span>      
visibilityString.append(VisibilityConstants.CLOSED_PARAN);<a 
name="line.710"></a>
-<span class="sourceLineNo">711</span>      // Return the string formed as 
byte[]<a name="line.711"></a>
-<span class="sourceLineNo">712</span>      return 
Bytes.toBytes(visibilityString.toString());<a name="line.712"></a>
-<span class="sourceLineNo">713</span>    }<a name="line.713"></a>
-<span class="sourceLineNo">714</span>    return null;<a name="line.714"></a>
-<span class="sourceLineNo">715</span>  }<a name="line.715"></a>
-<span class="sourceLineNo">716</span>}<a name="line.716"></a>
+<span class="sourceLineNo">554</span>    // Early out if there are no tags in 
both of cell and delete<a name="line.554"></a>
+<span class="sourceLineNo">555</span>    if (putVisTags.isEmpty() &amp;&amp; 
deleteVisTags.isEmpty()) {<a name="line.555"></a>
+<span class="sourceLineNo">556</span>      return true;<a name="line.556"></a>
+<span class="sourceLineNo">557</span>    }<a name="line.557"></a>
+<span class="sourceLineNo">558</span>    // Early out if one of the tags is 
empty<a name="line.558"></a>
+<span class="sourceLineNo">559</span>    if (putVisTags.isEmpty() ^ 
deleteVisTags.isEmpty()) {<a name="line.559"></a>
+<span class="sourceLineNo">560</span>      return false;<a name="line.560"></a>
+<span class="sourceLineNo">561</span>    }<a name="line.561"></a>
+<span class="sourceLineNo">562</span>    if ((deleteTagsFormat != null 
&amp;&amp; deleteTagsFormat == SORTED_ORDINAL_SERIALIZATION_FORMAT)<a 
name="line.562"></a>
+<span class="sourceLineNo">563</span>        &amp;&amp; (putTagsFormat == null 
|| putTagsFormat == SORTED_ORDINAL_SERIALIZATION_FORMAT)) {<a 
name="line.563"></a>
+<span class="sourceLineNo">564</span>      if (putTagsFormat == null) {<a 
name="line.564"></a>
+<span class="sourceLineNo">565</span>        return 
matchUnSortedVisibilityTags(putVisTags, deleteVisTags);<a name="line.565"></a>
+<span class="sourceLineNo">566</span>      } else {<a name="line.566"></a>
+<span class="sourceLineNo">567</span>        return 
matchOrdinalSortedVisibilityTags(putVisTags, deleteVisTags);<a 
name="line.567"></a>
+<span class="sourceLineNo">568</span>      }<a name="line.568"></a>
+<span class="sourceLineNo">569</span>    }<a name="line.569"></a>
+<span class="sourceLineNo">570</span>    throw new IOException("Unexpected tag 
format passed for comparison, deleteTagsFormat : "<a name="line.570"></a>
+<span class="sourceLineNo">571</span>        + deleteTagsFormat + ", 
putTagsFormat : " + putTagsFormat);<a name="line.571"></a>
+<span class="sourceLineNo">572</span>  }<a name="line.572"></a>
+<span class="sourceLineNo">573</span><a name="line.573"></a>
+<span class="sourceLineNo">574</span>  /**<a name="line.574"></a>
+<span class="sourceLineNo">575</span>   * @param putVisTags Visibility tags in 
Put Mutation<a name="line.575"></a>
+<span class="sourceLineNo">576</span>   * @param deleteVisTags Visibility tags 
in Delete Mutation<a name="line.576"></a>
+<span class="sourceLineNo">577</span>   * @return true when all the visibility 
tags in Put matches with visibility tags in Delete.<a name="line.577"></a>
+<span class="sourceLineNo">578</span>   * This is used when, at least one set 
of tags are not sorted based on the label ordinal.<a name="line.578"></a>
+<span class="sourceLineNo">579</span>   */<a name="line.579"></a>
+<span class="sourceLineNo">580</span>  private static boolean 
matchUnSortedVisibilityTags(List&lt;Tag&gt; putVisTags,<a name="line.580"></a>
+<span class="sourceLineNo">581</span>      List&lt;Tag&gt; deleteVisTags) 
throws IOException {<a name="line.581"></a>
+<span class="sourceLineNo">582</span>    return 
compareTagsOrdinals(sortTagsBasedOnOrdinal(putVisTags),<a name="line.582"></a>
+<span class="sourceLineNo">583</span>        
sortTagsBasedOnOrdinal(deleteVisTags));<a name="line.583"></a>
+<span class="sourceLineNo">584</span>  }<a name="line.584"></a>
+<span class="sourceLineNo">585</span><a name="line.585"></a>
+<span class="sourceLineNo">586</span>  /**<a name="line.586"></a>
+<span class="sourceLineNo">587</span>   * @param putVisTags Visibility tags in 
Put Mutation<a name="line.587"></a>
+<span class="sourceLineNo">588</span>   * @param deleteVisTags Visibility tags 
in Delete Mutation<a name="line.588"></a>
+<span class="sourceLineNo">589</span>   * @return true when all the visibility 
tags in Put matches with visibility tags in Delete.<a name="line.589"></a>
+<span class="sourceLineNo">590</span>   * This is used when both the set of 
tags are sorted based on the label ordinal.<a name="line.590"></a>
+<span class="sourceLineNo">591</span>   */<a name="line.591"></a>
+<span class="sourceLineNo">592</span>  private static boolean 
matchOrdinalSortedVisibilityTags(List&lt;Tag&gt; putVisTags,<a 
name="line.592"></a>
+<span class="sourceLineNo">593</span>      List&lt;Tag&gt; deleteVisTags) {<a 
name="line.593"></a>
+<span class="sourceLineNo">594</span>    boolean matchFound = false;<a 
name="line.594"></a>
+<span class="sourceLineNo">595</span>    // If the size does not match. 
Definitely we are not comparing the equal tags.<a name="line.595"></a>
+<span class="sourceLineNo">596</span>    if ((deleteVisTags.size()) == 
putVisTags.size()) {<a name="line.596"></a>
+<span class="sourceLineNo">597</span>      for (Tag tag : deleteVisTags) {<a 
name="line.597"></a>
+<span class="sourceLineNo">598</span>        matchFound = false;<a 
name="line.598"></a>
+<span class="sourceLineNo">599</span>        for (Tag givenTag : putVisTags) 
{<a name="line.599"></a>
+<span class="sourceLineNo">600</span>          if (TagUtil.matchingValue(tag, 
givenTag)) {<a name="line.600"></a>
+<span class="sourceLineNo">601</span>            matchFound = true;<a 
name="line.601"></a>
+<span class="sourceLineNo">602</span>            break;<a name="line.602"></a>
+<span class="sourceLineNo">603</span>          }<a name="line.603"></a>
+<span class="sourceLineNo">604</span>        }<a name="line.604"></a>
+<span class="sourceLineNo">605</span>        if (!matchFound) break;<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>    return matchFound;<a 
name="line.608"></a>
+<span class="sourceLineNo">609</span>  }<a name="line.609"></a>
+<span class="sourceLineNo">610</span><a name="line.610"></a>
+<span class="sourceLineNo">611</span>  private static 
List&lt;List&lt;Integer&gt;&gt; sortTagsBasedOnOrdinal(List&lt;Tag&gt; tags) 
throws IOException {<a name="line.611"></a>
+<span class="sourceLineNo">612</span>    List&lt;List&lt;Integer&gt;&gt; 
fullTagsList = new ArrayList&lt;&gt;();<a name="line.612"></a>
+<span class="sourceLineNo">613</span>    for (Tag tag : tags) {<a 
name="line.613"></a>
+<span class="sourceLineNo">614</span>      if (tag.getType() == 
VISIBILITY_TAG_TYPE) {<a name="line.614"></a>
+<span class="sourceLineNo">615</span>        
getSortedTagOrdinals(fullTagsList, tag);<a name="line.615"></a>
+<span class="sourceLineNo">616</span>      }<a name="line.616"></a>
+<span class="sourceLineNo">617</span>    }<a name="line.617"></a>
+<span class="sourceLineNo">618</span>    return fullTagsList;<a 
name="line.618"></a>
+<span class="sourceLineNo">619</span>  }<a name="line.619"></a>
+<span class="sourceLineNo">620</span><a name="line.620"></a>
+<span class="sourceLineNo">621</span>  private static void 
getSortedTagOrdinals(List&lt;List&lt;Integer&gt;&gt; fullTagsList, Tag tag)<a 
name="line.621"></a>
+<span class="sourceLineNo">622</span>      throws IOException {<a 
name="line.622"></a>
+<span class="sourceLineNo">623</span>    List&lt;Integer&gt; 
tagsOrdinalInSortedOrder = new ArrayList&lt;&gt;();<a name="line.623"></a>
+<span class="sourceLineNo">624</span>    int offset = tag.getValueOffset();<a 
name="line.624"></a>
+<span class="sourceLineNo">625</span>    int endOffset = offset + 
tag.getValueLength();<a name="line.625"></a>
+<span class="sourceLineNo">626</span>    while (offset &lt; endOffset) {<a 
name="line.626"></a>
+<span class="sourceLineNo">627</span>      Pair&lt;Integer, Integer&gt; result 
= TagUtil.readVIntValuePart(tag, offset);<a name="line.627"></a>
+<span class="sourceLineNo">628</span>      
tagsOrdinalInSortedOrder.add(result.getFirst());<a name="line.628"></a>
+<span class="sourceLineNo">629</span>      offset += result.getSecond();<a 
name="line.629"></a>
+<span class="sourceLineNo">630</span>    }<a name="line.630"></a>
+<span class="sourceLineNo">631</span>    
Collections.sort(tagsOrdinalInSortedOrder);<a name="line.631"></a>
+<span class="sourceLineNo">632</span>    
fullTagsList.add(tagsOrdinalInSortedOrder);<a name="line.632"></a>
+<span class="sourceLineNo">633</span>  }<a name="line.633"></a>
+<span class="sourceLineNo">634</span><a name="line.634"></a>
+<span class="sourceLineNo">635</span>  /*<a name="line.635"></a>
+<span class="sourceLineNo">636</span>   * @return true when all the visibility 
tags in Put matches with visibility tags in Delete.<a name="line.636"></a>
+<span class="sourceLineNo">637</span>   */<a name="line.637"></a>
+<span class="sourceLineNo">638</span>  private static boolean 
compareTagsOrdinals(List&lt;List&lt;Integer&gt;&gt; putVisTags,<a 
name="line.638"></a>
+<span class="sourceLineNo">639</span>      List&lt;List&lt;Integer&gt;&gt; 
deleteVisTags) {<a name="line.639"></a>
+<span class="sourceLineNo">640</span>    boolean matchFound = false;<a 
name="line.640"></a>
+<span class="sourceLineNo">641</span>    if (deleteVisTags.size() == 
putVisTags.size()) {<a name="line.641"></a>
+<span class="sourceLineNo">642</span>      for (List&lt;Integer&gt; 
deleteTagOrdinals : deleteVisTags) {<a name="line.642"></a>
+<span class="sourceLineNo">643</span>        matchFound = false;<a 
name="line.643"></a>
+<span class="sourceLineNo">644</span>        for (List&lt;Integer&gt; 
tagOrdinals : putVisTags) {<a name="line.644"></a>
+<span class="sourceLineNo">645</span>          if 
(deleteTagOrdinals.equals(tagOrdinals)) {<a name="line.645"></a>
+<span class="sourceLineNo">646</span>            matchFound = true;<a 
name="line.646"></a>
+<span class="sourceLineNo">647</span>            break;<a name="line.647"></a>
+<span class="sourceLineNo">648</span>          }<a name="line.648"></a>
+<span class="sourceLineNo">649</span>        }<a name="line.649"></a>
+<span class="sourceLineNo">650</span>        if (!matchFound) break;<a 
name="line.650"></a>
+<span class="sourceLineNo">651</span>      }<a name="line.651"></a>
+<span class="sourceLineNo">652</span>    }<a name="line.652"></a>
+<span class="sourceLineNo">653</span>    return matchFound;<a 
name="line.653"></a>
+<span class="sourceLineNo">654</span>  }<a name="line.654"></a>
+<span class="sourceLineNo">655</span><a name="line.655"></a>
+<span class="sourceLineNo">656</span>  @Override<a name="line.656"></a>
+<span class="sourceLineNo">657</span>  public byte[] 
encodeVisibilityForReplication(final List&lt;Tag&gt; tags, final Byte 
serializationFormat)<a name="line.657"></a>
+<span class="sourceLineNo">658</span>      throws IOException {<a 
name="line.658"></a>
+<span class="sourceLineNo">659</span>    if (tags.size() &gt; 0<a 
name="line.659"></a>
+<span class="sourceLineNo">660</span>        &amp;&amp; (serializationFormat 
== null ||<a name="line.660"></a>
+<span class="sourceLineNo">661</span>        serializationFormat == 
SORTED_ORDINAL_SERIALIZATION_FORMAT)) {<a name="line.661"></a>
+<span class="sourceLineNo">662</span>      return 
createModifiedVisExpression(tags);<a name="line.662"></a>
+<span class="sourceLineNo">663</span>    }<a name="line.663"></a>
+<span class="sourceLineNo">664</span>    return null;<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>   * @param tags<a name="line.668"></a>
+<span class="sourceLineNo">669</span>   *          - all the visibility tags 
associated with the current Cell<a name="line.669"></a>
+<span class="sourceLineNo">670</span>   * @return - the modified visibility 
expression as byte[]<a name="line.670"></a>
+<span class="sourceLineNo">671</span>   */<a name="line.671"></a>
+<span class="sourceLineNo">672</span>  private byte[] 
createModifiedVisExpression(final List&lt;Tag&gt; tags)<a name="line.672"></a>
+<span class="sourceLineNo">673</span>      throws IOException {<a 
name="line.673"></a>
+<span class="sourceLineNo">674</span>    StringBuilder visibilityString = new 
StringBuilder();<a name="line.674"></a>
+<span class="sourceLineNo">675</span>    for (Tag tag : tags) {<a 
name="line.675"></a>
+<span class="sourceLineNo">676</span>      if (tag.getType() == 
TagType.VISIBILITY_TAG_TYPE) {<a name="line.676"></a>
+<span class="sourceLineNo">677</span>        if (visibilityString.length() != 
0) {<a name="line.677"></a>
+<span class="sourceLineNo">678</span>          
visibilityString.append(VisibilityConstants.CLOSED_PARAN).append(<a 
name="line.678"></a>
+<span class="sourceLineNo">679</span>              
VisibilityConstants.OR_OPERATOR);<a name="line.679"></a>
+<span class="sourceLineNo">680</span>        }<a name="line.680"></a>
+<span class="sourceLineNo">681</span>        int offset = 
tag.getValueOffset();<a name="line.681"></a>
+<span class="sourceLineNo">682</span>        int endOffset = offset + 
tag.getValueLength();<a name="line.682"></a>
+<span class="sourceLineNo">683</span>        boolean expressionStart = true;<a 
name="line.683"></a>
+<span class="sourceLineNo">684</span>        while (offset &lt; endOffset) {<a 
name="line.684"></a>
+<span class="sourceLineNo">685</span>          Pair&lt;Integer, Integer&gt; 
result = TagUtil.readVIntValuePart(tag, offset);<a name="line.685"></a>
+<span class="sourceLineNo">686</span>          int currLabelOrdinal = 
result.getFirst();<a name="line.686"></a>
+<span class="sourceLineNo">687</span>          if (currLabelOrdinal &lt; 0) 
{<a name="line.687"></a>
+<span class="sourceLineNo">688</span>            int temp = 
-currLabelOrdinal;<a name="line.688"></a>
+<span class="sourceLineNo">689</span>            String label = 
this.labelsCache.getLabel(temp);<a name="line.689"></a>
+<span class="sourceLineNo">690</span>            if (expressionStart) {<a 
name="line.690"></a>
+<span class="sourceLineNo">691</span>              // Quote every label in 
case of unicode characters if present<a name="line.691"></a>
+<span class="sourceLineNo">692</span>              
visibilityString.append(VisibilityConstants.OPEN_PARAN)<a name="line.692"></a>
+<span class="sourceLineNo">693</span>                  
.append(VisibilityConstants.NOT_OPERATOR).append(CellVisibility.quote(label));<a
 name="line.693"></a>
+<span class="sourceLineNo">694</span>            } else {<a 
name="line.694"></a>
+<span class="sourceLineNo">695</span>              
visibilityString.append(VisibilityConstants.AND_OPERATOR)<a name="line.695"></a>
+<span class="sourceLineNo">696</span>                  
.append(VisibilityConstants.NOT_OPERATOR).append(CellVisibility.quote(label));<a
 name="line.696"></a>
+<span class="sourceLineNo">697</span>            }<a name="line.697"></a>
+<span class="sourceLineNo">698</span>          } else {<a name="line.698"></a>
+<span class="sourceLineNo">699</span>            String label = 
this.labelsCache.getLabel(currLabelOrdinal);<a name="line.699"></a>
+<span class="sourceLineNo">700</span>            if (expressionStart) {<a 
name="line.700"></a>
+<span class="sourceLineNo">701</span>              
visibilityString.append(VisibilityConstants.OPEN_PARAN).append(<a 
name="line.701"></a>
+<span class="sourceLineNo">702</span>                  
CellVisibility.quote(label));<a name="line.702"></a>
+<span class="sourceLineNo">703</span>            } else {<a 
name="line.703"></a>
+<span class="sourceLineNo">704</span>              
visibilityString.append(VisibilityConstants.AND_OPERATOR).append(<a 
name="line.704"></a>
+<span class="sourceLineNo">705</span>                  
CellVisibility.quote(label));<a name="line.705"></a>
+<span class="sourceLineNo">706</span>            }<a name="line.706"></a>
+<span class="sourceLineNo">707</span>          }<a name="line.707"></a>
+<span class="sourceLineNo">708</span>          expressionStart = false;<a 
name="line.708"></a>
+<span class="sourceLineNo">709</span>          offset += result.getSecond();<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>    }<a name="line.712"></a>
+<span class="sourceLineNo">713</span>    if (visibilityString.length() != 0) 
{<a name="line.713"></a>
+<span class="sourceLineNo">714</span>      
visibilityString.append(VisibilityConstants.CLOSED_PARAN);<a 
name="line.714"></a>
+<span class="sourceLineNo">715</span>      // Return the string formed as 
byte[]<a name="line.715"></a>
+<span class="sourceLineNo">716</span>      return 
Bytes.toBytes(visibilityString.toString());<a name="line.716"></a>
+<span class="sourceLineNo">717</span>    }<a name="line.717"></a>
+<span class="sourceLineNo">718</span>    return null;<a name="line.718"></a>
+<span class="sourceLineNo">719</span>  }<a name="line.719"></a>
+<span class="sourceLineNo">720</span>}<a name="line.720"></a>
 
 
 

Reply via email to